mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Massive cleanup. We are starting afresh
This commit is contained in:
1 parent
3ae731da30
commit
15d0ae5faf
125 files changed
+1772
-25013
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
DS_Store
|
||||
.DS_Store
|
||||
node_modules
|
||||
.next
|
||||
out
|
||||
|
||||
@@ -1,24 +1,3 @@
|
||||
# Supabase
|
||||
|
||||
Supercharge PostgreSQL. [https://supabase.io](https://supabase.io)
|
||||
|
||||
## About
|
||||
|
||||
Supabase provide opensource tools that make PostgreSQL even better.
|
||||
|
||||
## Docs
|
||||
|
||||
All of our documeentation is stored in this repo as a single source of truth. You can view it online at [https://supabase.io/docs/-/about](https://supabase.io/docs/-/about).
|
||||
|
||||
## Development
|
||||
|
||||
This is monorepo. As much as we love `npm`, we have decided to use `yarn` to manage the separate workspaces.
|
||||
|
||||
```bash
|
||||
yarn # installs all dependencies for all workspaces.
|
||||
yarn workspaces dev # runs "dev" command in all workspaces.
|
||||
yarn workspace @supabase/web dev # runs "dev" command in the "web" workspace.
|
||||
|
||||
yarn workspace @supabase/web add package # installs "package" in the "web" workspace
|
||||
yarn workspace @supabase/web remove package # removes "package" in the "web" workspace
|
||||
```
|
||||
[Supabase](https://supabase.io)
|
||||
@@ -0,0 +1,3 @@
|
||||
# App
|
||||
|
||||
@todo
|
||||
@@ -0,0 +1 @@
|
||||
@todo
|
||||
@@ -0,0 +1 @@
|
||||
@todo
|
||||
@@ -1,8 +0,0 @@
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_DB=db
|
||||
POSTGRES_HOST=db
|
||||
POSTGRES_PORT=5432
|
||||
PGRST_DB_URI=postgres://postgres:postgres@db:5432/postgres
|
||||
PGRST_DB_SCHEMA=public
|
||||
PGRST_DB_ANON_ROLE=postgres
|
||||
@@ -1,17 +0,0 @@
|
||||
# Docker and React Realtime example
|
||||
|
||||
A How-To guide for using Realtime with React and Docker.
|
||||
|
||||
Online documentation: [https://supabase.io/docs/realtime/guide-docker-react](https://supabase.io/docs/realtime/guide-docker-nextjs)
|
||||
|
||||
## Usage
|
||||
|
||||
1. Clone this repo
|
||||
2. Run `docker-compose up`
|
||||
3. Open two browser tabs to [http://localhost:3000](http://localhost:3000)
|
||||
4. Add a user in one tab, and it will add a user in another
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
If you make changes to this repo, please ensure you update the online documentation too.
|
||||
@@ -1,23 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
@@ -1,68 +0,0 @@
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
|
||||
### `yarn build` fails to minify
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
||||
-13333
File diff suppressed because it is too large.
Load diff
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "^16.11.0",
|
||||
"react-scripts": "3.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,43 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
@@ -1,22 +0,0 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #09d3ac;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import React, { useState } from 'react'
|
||||
import axios from 'axios'
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const [firstName, setFirstName] = useState('')
|
||||
const [userList, setUserList] = useState([{ first_name: 'Paul' }])
|
||||
|
||||
const onAddUserClicked = async () => {
|
||||
try {
|
||||
addUser(firstName)
|
||||
setFirstName('')
|
||||
} catch (error) {
|
||||
console.log('error', error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<div><input value={firstName} type="text" onChange={e => setFirstName(e.target.value)}/></div>
|
||||
<div><button onClick={onAddUserClicked}>Add User</button></div>
|
||||
<div>{userList.map(user => <p key={user.first_name}>{user.first_name}</p>)}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
const addUser = async (first_name) => {
|
||||
let url = `${window.location.host}:3000/users`
|
||||
console.log('url', url)
|
||||
return axios.post(url, { first_name })
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(<App />, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||
monospace;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 170.96 159.93"><defs><style>.cls-1{fill:#09d3ac;}</style></defs><path class="cls-1" d="M141.35,73.27c0-6.89-8.11-13-20.58-16.73,3-12.67,1.69-22.75-4.28-26.16a9.55,9.55,0,0,0-4.79-1.2c-5.57,0-12.61,3.89-19.72,10.62-7.11-6.68-14.13-10.55-19.69-10.55a9.46,9.46,0,0,0-4.86,1.22c-5.94,3.42-7.17,13.44-4.21,26.05-12.41,3.71-20.48,9.77-20.5,16.63s8.12,13,20.59,16.72c-3,12.68-1.7,22.75,4.28,26.16a9.41,9.41,0,0,0,4.78,1.2c5.58,0,12.62-3.89,19.73-10.62,7.1,6.68,14.12,10.55,19.69,10.55a9.59,9.59,0,0,0,4.86-1.22c5.94-3.42,7.16-13.44,4.21-26C133.27,86.18,141.34,80.12,141.35,73.27ZM96.56,42.06c8.19-7.33,13.31-8.12,15.13-8.12h0a4.71,4.71,0,0,1,2.42.58c2.86,1.63,4,7.38,3.09,15a56.73,56.73,0,0,1-1,5.79,97.7,97.7,0,0,0-12.58-2.07,98.47,98.47,0,0,0-8.24-10.08C95.75,42.79,96.15,42.42,96.56,42.06ZM71.77,78.94c.78,1.5,1.61,3,2.47,4.51S76,86.49,77,88c-2.71-.39-5.34-.88-7.84-1.46C69.86,84,70.75,81.5,71.77,78.94ZM69,59.9c2.53-.59,5.18-1.08,7.93-1.46-1,1.48-1.86,3-2.76,4.59s-1.69,3-2.46,4.52Q70.18,63.65,69,59.9Zm5.21,13.34q1.86-3.93,4.09-7.86c1.5-2.62,3.11-5.17,4.77-7.61,2.91-.22,5.91-.34,9-.33s6,.12,8.89.35c1.66,2.42,3.25,5,4.75,7.55s2.88,5.22,4.12,7.83c-1.23,2.62-2.6,5.25-4.08,7.85s-3.11,5.18-4.77,7.62c-2.91.23-5.91.34-9,.34s-6-.13-8.89-.36c-1.66-2.42-3.26-4.94-4.76-7.55S75.5,75.85,74.25,73.24Zm32.86-14.77c2.72.38,5.35.87,7.84,1.45-.74,2.47-1.62,5-2.64,7.55-.79-1.5-1.61-3-2.48-4.51S108,59.93,107.11,58.47Zm2.76,24.92q1.29-2.27,2.46-4.53c1,2.6,2,5.16,2.7,7.66-2.52.59-5.17,1.07-7.92,1.45Q108.52,85.75,109.87,83.39ZM92,46.56c1.8,1.92,3.57,4,5.3,6.23-1.71-.07-3.46-.12-5.23-.12s-3.58,0-5.33.12C88.45,50.57,90.2,48.48,92,46.56Zm-22.18-12A4.82,4.82,0,0,1,72.29,34a13.11,13.11,0,0,1,5.19,1.31,39.07,39.07,0,0,1,10,6.78l1.17,1.07a98.49,98.49,0,0,0-8.16,10,98.88,98.88,0,0,0-12.65,2.06c-.44-1.94-.8-3.84-1-5.67C65.8,42,67,36.24,69.81,34.6ZM64.53,85.26a58.75,58.75,0,0,1-5.54-2c-7.1-3-11.5-6.85-11.5-10.14S51.91,66,59,63.05a57.63,57.63,0,0,1,5.44-1.94A97.93,97.93,0,0,0,69,73.25,98.72,98.72,0,0,0,64.53,85.26Zm23,19.1c-8.19,7.33-13.31,8.11-15.14,8.11a4.69,4.69,0,0,1-2.42-.58c-2.86-1.63-4-7.38-3.09-15a56.07,56.07,0,0,1,1-5.78,99.51,99.51,0,0,0,12.58,2.06,97.17,97.17,0,0,0,8.24,10.08Zm4.57-4.51c-1.8-1.92-3.57-4-5.31-6.23,1.72.08,3.47.12,5.24.12s3.58,0,5.33-.11C95.63,95.85,93.87,97.93,92.09,99.85Zm22.18,12a4.82,4.82,0,0,1-2.48.59c-1.82,0-7-.8-15.16-8.1l-1.17-1.07a98.44,98.44,0,0,0,8.15-10,97,97,0,0,0,12.66-2.06c.44,1.94.79,3.84,1,5.67C118.27,104.42,117.12,110.18,114.27,111.81Zm10.8-28.44c-1.71.7-3.52,1.35-5.44,1.93a98.54,98.54,0,0,0-4.57-12.14,98.1,98.1,0,0,0,4.49-12,58.75,58.75,0,0,1,5.54,2c7.09,3,11.5,6.85,11.49,10.14S132.17,80.42,125.07,83.37ZM92,82.39a9.18,9.18,0,1,0-9.17-9.19A9.17,9.17,0,0,0,92,82.39ZM31,17.88V128.53H153.07V17.88ZM148.3,123.77H35.78V22.65H148.3Zm-85-33.9c-3,12.68-1.7,22.75,4.28,26.16a9.41,9.41,0,0,0,4.78,1.2c5.58,0,12.62-3.89,19.73-10.62,7.1,6.68,14.12,10.55,19.69,10.55a9.59,9.59,0,0,0,4.86-1.22c5.94-3.42,7.16-13.44,4.21-26,12.41-3.72,20.48-9.78,20.49-16.63s-8.11-13-20.58-16.73c3-12.67,1.69-22.75-4.28-26.16a9.55,9.55,0,0,0-4.79-1.2c-5.57,0-12.61,3.89-19.72,10.62-7.11-6.68-14.13-10.55-19.69-10.55a9.46,9.46,0,0,0-4.86,1.22c-5.94,3.42-7.17,13.44-4.21,26.05-12.41,3.71-20.48,9.77-20.5,16.63S50.84,86.13,63.31,89.87Zm24.21,14.49c-8.19,7.33-13.31,8.11-15.14,8.11a4.69,4.69,0,0,1-2.42-.58c-2.86-1.63-4-7.38-3.09-15a56.07,56.07,0,0,1,1-5.78,99.51,99.51,0,0,0,12.58,2.06,97.17,97.17,0,0,0,8.24,10.08Zm24.79-36.89c-.79-1.5-1.61-3-2.48-4.51s-1.8-3-2.72-4.49c2.72.38,5.35.87,7.84,1.45C114.21,62.39,113.33,64.92,112.31,67.47Zm2.72,19c-2.52.59-5.17,1.07-7.92,1.45q1.41-2.22,2.76-4.58t2.46-4.53C113.37,81.46,114.28,84,115,86.52Zm-5.21-13.35c-1.23,2.62-2.6,5.25-4.08,7.85s-3.11,5.18-4.77,7.62c-2.91.23-5.91.34-9,.34s-6-.13-8.89-.36c-1.66-2.42-3.26-4.94-4.76-7.55s-2.87-5.22-4.12-7.83q1.86-3.93,4.09-7.86c1.5-2.62,3.11-5.17,4.77-7.61,2.91-.22,5.91-.34,9-.33s6,.12,8.89.35c1.66,2.42,3.25,5,4.75,7.55S108.58,70.56,109.82,73.17ZM77,88c-2.71-.39-5.34-.88-7.84-1.46.74-2.46,1.63-5,2.65-7.55.78,1.5,1.61,3,2.47,4.51S76,86.49,77,88ZM74.21,63c-.87,1.5-1.69,3-2.46,4.52Q70.18,63.65,69,59.9c2.53-.59,5.18-1.08,7.93-1.46C76,59.92,75.11,61.45,74.21,63ZM92.09,99.85c-1.8-1.92-3.57-4-5.31-6.23,1.72.08,3.47.12,5.24.12s3.58,0,5.33-.11C95.63,95.85,93.87,97.93,92.09,99.85Zm22.18,12a4.82,4.82,0,0,1-2.48.59c-1.82,0-7-.8-15.16-8.1l-1.17-1.07a98.44,98.44,0,0,0,8.15-10,97,97,0,0,0,12.66-2.06c.44,1.94.79,3.84,1,5.67C118.27,104.42,117.12,110.18,114.27,111.81Zm5.28-50.66a58.75,58.75,0,0,1,5.54,2c7.09,3,11.5,6.85,11.49,10.14s-4.41,7.16-11.51,10.11c-1.71.7-3.52,1.35-5.44,1.93a98.54,98.54,0,0,0-4.57-12.14A98.1,98.1,0,0,0,119.55,61.15Zm-23-19.09c8.19-7.33,13.31-8.12,15.13-8.12h0a4.71,4.71,0,0,1,2.42.58c2.86,1.63,4,7.38,3.09,15a56.73,56.73,0,0,1-1,5.79,97.7,97.7,0,0,0-12.58-2.07,98.47,98.47,0,0,0-8.24-10.08C95.75,42.79,96.15,42.42,96.56,42.06ZM92,46.56c1.8,1.92,3.57,4,5.3,6.23-1.71-.07-3.46-.12-5.23-.12s-3.58,0-5.33.12C88.45,50.57,90.2,48.48,92,46.56Line truncated
|
||||
|
Before Width: | Height: | Size: 8.0 KiB |
@@ -1,135 +0,0 @@
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
# docker-compose.yml
|
||||
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
app:
|
||||
image: node:10.15.0
|
||||
command: bash -c "npm install && npm start"
|
||||
volumes:
|
||||
- ./app:/usr/src/app
|
||||
working_dir: /usr/src/app
|
||||
depends_on:
|
||||
- realtime
|
||||
ports:
|
||||
- "80:3000"
|
||||
realtime:
|
||||
image: supabase/realtime
|
||||
ports:
|
||||
- "4000:4000"
|
||||
env_file: .env.sample
|
||||
depends_on:
|
||||
- db
|
||||
rest:
|
||||
image: postgrest/postgrest
|
||||
restart: always
|
||||
ports:
|
||||
- "3000:3000"
|
||||
env_file: .env.sample
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
image: supabase/packaged
|
||||
command: postgres -c wal_level=logical # Start with streaming enabled
|
||||
ports:
|
||||
- "6543:5432" # Use 6543 to avoid host port collisions
|
||||
env_file: .env.sample
|
||||
volumes:
|
||||
- ./schema:/docker-entrypoint-initdb.d
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
-- Create a table of users
|
||||
create table "public"."quotes" (
|
||||
"id" bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"first_name" text null,
|
||||
"last_name" text null,
|
||||
"inserted_at" timestamp without time zone not null default(now() at time zone 'utc'),
|
||||
"updated_at" timestamp without time zone not null default (now() at time zone 'utc')
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
@todo
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "supabase-monorepo",
|
||||
"private": true,
|
||||
"description": "Supabase Monorepo",
|
||||
"repository": "https://github.com/supabase/monorepo",
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"nohoist": [
|
||||
"**/bulma",
|
||||
"**/bulma/**"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0",
|
||||
"yarn": "1.x"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn run build:web",
|
||||
"build:web": "yarn workspace @supabase/web build",
|
||||
"deploy:web": "yarn workspace @supabase/web deploy",
|
||||
"deploy:realtime-js": "yarn workspace @supabase/realtime-js deploy",
|
||||
"dev": "concurrently --kill-others-on-fail \"yarn dev:web\" ",
|
||||
"dev:web": "yarn workspace @supabase/web dev",
|
||||
"test:pg-admin-js": "yarn workspace @supabase/pg-admin-js test",
|
||||
"test:realtime-js": "yarn workspace @supabase/realtime-js test"
|
||||
},
|
||||
"dependencies": {
|
||||
"concurrently": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"now": "^16.3.1",
|
||||
"prettier": "^1.18.2",
|
||||
"esm": "3.2.25",
|
||||
"jsdoc-test": "0.0.10",
|
||||
"mocha": "6.2.2"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
# RealtimeJS
|
||||
|
||||
Realtime PostgreSQL.
|
||||
|
||||
## Docs
|
||||
|
||||
View online at [https://supabase.io/docs/-/about](https://supabase.io/docs/-/about).
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "@supabase/pg-admin-js",
|
||||
"version": "0.1.0",
|
||||
"description": "Manage your PG Database.",
|
||||
"repository": "https://github.com/supabase/monorepo",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"deploy": "npm version patch; npm publish --access=public",
|
||||
"test": "mocha --require esm \"test/**/*_spec.js\""
|
||||
},
|
||||
"keywords": [
|
||||
"supabase",
|
||||
"postgresql",
|
||||
"postgres"
|
||||
],
|
||||
"author": "@kiwicopple",
|
||||
"license": "Apache-2.0",
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
"knex": "^0.20.1",
|
||||
"pg": "^7.4.3"
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import * as constants from '../utils/constants.js'
|
||||
import * as postgres from '../utils/postgres.js'
|
||||
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var getAllSql = fs.readFileSync(path.join(__dirname, '../sql/getAllConfig.sql')).toString()
|
||||
|
||||
/**
|
||||
* Gets all the config for a
|
||||
* @param {Object} config The database config
|
||||
* @param {string} config.host
|
||||
* @param {string} config.user
|
||||
* @param {string} config.password
|
||||
* @param {string} config.database
|
||||
* @param {number} config.port
|
||||
* @param {Object} options
|
||||
* @param {string} options.schema
|
||||
*
|
||||
* @example
|
||||
* await getAll()
|
||||
* //=>
|
||||
* [
|
||||
* {
|
||||
* name: 'autovacuum',
|
||||
* setting: 'on',
|
||||
* unit: null,
|
||||
* category: 'Autovacuum',
|
||||
* short_desc: 'Starts the autovacuum subprocess.',
|
||||
* extra_desc: null,
|
||||
* context: 'sighup',
|
||||
* vartype: 'bool',
|
||||
* source: 'default',
|
||||
* min_val: null,
|
||||
* max_val: null,
|
||||
* enumvals: null,
|
||||
* boot_val: 'on',
|
||||
* reset_val: 'on',
|
||||
* sourcefile: null,
|
||||
* sourceline: null,
|
||||
* pending_restart: false
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
export const getAll = async (config = {}) => {
|
||||
const dbConfig = { ...constants.POSTGRES_CONFIG, ...config }
|
||||
const conn = await postgres.connect(dbConfig)
|
||||
const results = await postgres.runQuery(conn, getAllSql)
|
||||
postgres.disconnect(conn)
|
||||
return results.rows
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import * as constants from '../utils/constants.js'
|
||||
import * as postgres from '../utils/postgres.js'
|
||||
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var getAllSql = fs.readFileSync(path.join(__dirname, '../sql/getAllPLugins.sql')).toString()
|
||||
|
||||
/**
|
||||
* Queries a given schema for all the tables
|
||||
* @param {Object} config The database config
|
||||
* @param {Object} config The database config
|
||||
* @param {string} config.host
|
||||
* @param {string} config.user
|
||||
* @param {string} config.password
|
||||
* @param {string} config.database
|
||||
* @param {number} config.port
|
||||
*
|
||||
* @example
|
||||
* await getAll()
|
||||
* //=>
|
||||
* [
|
||||
* { name: 'plpgsql', version: '1.0', schema: 'pg_catalog', description: 'PL/pgSQL procedural language' }
|
||||
* ]
|
||||
*/
|
||||
export const getAll = async (config = {}, options = {}) => {
|
||||
const dbConfig = { ...constants.POSTGRES_CONFIG, ...config }
|
||||
const conn = await postgres.connect(dbConfig)
|
||||
const results = await postgres.runQuery(conn, getAllSql)
|
||||
postgres.disconnect(conn)
|
||||
return results.rows
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import * as constants from '../utils/constants.js'
|
||||
import * as postgres from '../utils/postgres.js'
|
||||
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var getAllSql = fs.readFileSync(path.join(__dirname, '../sql/getAllTables.sql')).toString()
|
||||
|
||||
/**
|
||||
* Queries a given schema for all the tables
|
||||
* @param {Object} config The database config
|
||||
* @param {string} config.host
|
||||
* @param {string} config.user
|
||||
* @param {string} config.password
|
||||
* @param {string} config.database
|
||||
* @param {number} config.port
|
||||
* @param {Object} options
|
||||
* @param {string} options.schema The database schema containing the tables. Defaults to 'public'
|
||||
*
|
||||
* @example
|
||||
* await getAll()
|
||||
* //=>
|
||||
* [
|
||||
* { table_schema: 'public', table_name: 'users' }
|
||||
* ]
|
||||
*/
|
||||
export const getAll = async (config = {}, options = {}) => {
|
||||
const dbConfig = { ...constants.POSTGRES_CONFIG, ...config }
|
||||
const schema = options.schema || constants.DEFAULT_SCHEMA
|
||||
const conn = await postgres.connect(dbConfig)
|
||||
const results = await postgres.runQuery(conn, getAllSql, [schema])
|
||||
postgres.disconnect(conn)
|
||||
return results.rows
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import * as constants from '../utils/constants.js'
|
||||
import * as postgres from '../utils/postgres.js'
|
||||
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var getAllSql = fs.readFileSync(path.join(__dirname, '../sql/getAllTypes.sql')).toString()
|
||||
|
||||
/**
|
||||
* Queries a given schema for all the tables
|
||||
* @param {Object} config The database config
|
||||
* @param {Object} config The database config
|
||||
* @param {string} config.host
|
||||
* @param {string} config.user
|
||||
* @param {string} config.password
|
||||
* @param {string} config.database
|
||||
* @param {number} config.port
|
||||
*
|
||||
* @example
|
||||
* await getAll()
|
||||
* //=>
|
||||
* [
|
||||
* { name: 'boolean', internal_name: 'bool', size: '1', enums: '{}', description: 'boolean, \'true\'/\'false\'' },
|
||||
* { name: 'smallint', internal_name: 'int2', size: '2', enums: '{}', description: '-32 thousand to 32 thousand, 2-byte storage' }
|
||||
* ]
|
||||
*/
|
||||
export const getAll = async (config = {}, options = {}) => {
|
||||
const dbConfig = { ...constants.POSTGRES_CONFIG, ...config }
|
||||
const conn = await postgres.connect(dbConfig)
|
||||
const results = await postgres.runQuery(conn, getAllSql)
|
||||
postgres.disconnect(conn)
|
||||
return results.rows
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import * as constants from '../utils/constants.js'
|
||||
import * as postgres from '../utils/postgres.js'
|
||||
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var getAllSql = fs.readFileSync(path.join(__dirname, '../sql/getAllViews.sql')).toString()
|
||||
|
||||
/**
|
||||
* Queries a given schema for all the tables
|
||||
* @param {Object} config The database config
|
||||
* @param {string} config.host
|
||||
* @param {string} config.user
|
||||
* @param {string} config.password
|
||||
* @param {string} config.database
|
||||
* @param {number} config.port
|
||||
* @param {Object} options
|
||||
* @param {string} options.schema The database schema containing the tables. Defaults to 'public'
|
||||
*
|
||||
* @example
|
||||
* await getAll()
|
||||
* //=>
|
||||
* [
|
||||
* {
|
||||
* table_schema: 'information_schema',
|
||||
* table_name: 'attributes',
|
||||
* check_option: 'NONE',
|
||||
* is_updatable: 'NO',
|
||||
* is_insertable_into: 'NO',
|
||||
* is_trigger_updatable: 'NO',
|
||||
* is_trigger_deletable: 'NO',
|
||||
* is_trigger_insertable_into: 'NO',
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
export const getAll = async (config = {}, options = {}) => {
|
||||
const dbConfig = { ...constants.POSTGRES_CONFIG, ...config }
|
||||
const schema = options.schema || constants.DEFAULT_SCHEMA
|
||||
const conn = await postgres.connect(dbConfig)
|
||||
const results = await postgres.runQuery(conn, getAllSql, [schema])
|
||||
postgres.disconnect(conn)
|
||||
return results.rows
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import * as tables from './api/tables'
|
||||
|
||||
export { tables }
|
||||
@@ -1,13 +0,0 @@
|
||||
select
|
||||
table_schema,
|
||||
table_name,
|
||||
column_name,
|
||||
column_default,
|
||||
is_nullable::boolean,
|
||||
data_type,
|
||||
udt_name as format,
|
||||
col_description((table_schema || '."' || table_name || '"')::regclass, ordinal_position)
|
||||
|
||||
from information_schema.columns
|
||||
where table_schema = ?
|
||||
order by table_schema, table_name, ordinal_position
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
SELECT
|
||||
name,
|
||||
setting,
|
||||
unit,
|
||||
category,
|
||||
short_desc,
|
||||
extra_desc,
|
||||
context,
|
||||
vartype,
|
||||
source,
|
||||
min_val,
|
||||
max_val,
|
||||
enumvals,
|
||||
boot_val,
|
||||
reset_val,
|
||||
sourcefile,
|
||||
sourceline,
|
||||
pending_restart
|
||||
|
||||
FROM pg_settings
|
||||
ORDER BY name;
|
||||
@@ -1,26 +0,0 @@
|
||||
select
|
||||
coalesce(table_schema, referenced_schema) as table_schema,
|
||||
coalesce(table_name, referenced_table) as table_name,
|
||||
coalesce(column_name, referenced_column) as column_name,
|
||||
constraint_schema,
|
||||
constraint_name,
|
||||
constraint_type,
|
||||
check_clause,
|
||||
referenced_schema,
|
||||
referenced_table,
|
||||
referenced_column
|
||||
|
||||
from information_schema.table_constraints
|
||||
natural full join information_schema.key_column_usage
|
||||
natural full join information_schema.check_constraints
|
||||
inner join (
|
||||
select
|
||||
table_schema as referenced_schema,
|
||||
table_name as referenced_table,
|
||||
column_name as referenced_column,
|
||||
constraint_name
|
||||
from information_schema.constraint_column_usage
|
||||
) as referenced_columns using (constraint_name)
|
||||
|
||||
where constraint_schema = ?
|
||||
order by table_schema, table_name, ordinal_position
|
||||
@@ -1,12 +0,0 @@
|
||||
SELECT
|
||||
tc.table_schema,
|
||||
tc.constraint_name,
|
||||
tc.table_name,
|
||||
kcu.column_name,
|
||||
ccu.table_schema AS foreign_table_schema,
|
||||
ccu.table_name AS foreign_table_name,
|
||||
ccu.column_name AS foreign_column_name
|
||||
FROM information_schema.table_constraints AS tc
|
||||
JOIN information_schema.key_column_usage AS kcu USING (constraint_schema, constraint_name)
|
||||
JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
|
||||
where tc.table_schema = ? and tc.constraint_type = 'FOREIGN KEY';
|
||||
@@ -1,11 +0,0 @@
|
||||
SELECT
|
||||
e.extname AS "name",
|
||||
e.extversion AS "version",
|
||||
n.nspname AS "schema",
|
||||
c.description AS "description"
|
||||
|
||||
FROM
|
||||
pg_catalog.pg_extension e
|
||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
|
||||
LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass
|
||||
ORDER BY 1;
|
||||
@@ -1,16 +0,0 @@
|
||||
select
|
||||
table_schema,
|
||||
table_name,
|
||||
column_name,
|
||||
sequence_name,
|
||||
start_value,
|
||||
minimum_value,
|
||||
increment
|
||||
|
||||
from information_schema.columns
|
||||
inner join information_schema.sequences on (
|
||||
table_schema = sequence_schema and
|
||||
pg_get_serial_sequence(table_schema || '."' || table_name || '"', column_name) = sequence_schema || '.' || sequence_name
|
||||
)
|
||||
where sequence_schema = ?
|
||||
order by table_schema, table_name, ordinal_position
|
||||
@@ -1,7 +0,0 @@
|
||||
select
|
||||
table_schema,
|
||||
table_name
|
||||
|
||||
from information_schema.tables
|
||||
where table_schema = ? and table_type = 'BASE TABLE'
|
||||
order by table_schema, table_name;
|
||||
@@ -1,30 +0,0 @@
|
||||
SELECT
|
||||
pg_catalog.Format_type ( t.oid, NULL ) AS name,
|
||||
t.typname AS internal_name,
|
||||
CASE
|
||||
WHEN t.typrelid != 0 THEN Cast ( 'tuple' AS pg_catalog.TEXT )
|
||||
WHEN t.typlen < 0 THEN Cast ( 'var' AS pg_catalog.TEXT )
|
||||
ELSE Cast ( t.typlen AS pg_catalog.TEXT )
|
||||
END AS size,
|
||||
array (
|
||||
select e.enumlabel
|
||||
FROM pg_catalog.pg_enum e
|
||||
WHERE e.enumtypid = t.oid
|
||||
ORDER BY e.oid
|
||||
) AS enums,
|
||||
pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description
|
||||
FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n
|
||||
ON n.oid = t.typnamespace
|
||||
WHERE (
|
||||
t.typrelid = 0
|
||||
OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid )
|
||||
)
|
||||
and NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_catalog.pg_type el
|
||||
WHERE el.oid = t.typelem AND el.typarray = t.oid
|
||||
)
|
||||
-- AND n.nspname = ?
|
||||
-- AND n.nspname not in ('information_schema', 'pg_catalog')
|
||||
AND pg_catalog.pg_type_is_visible ( t.oid )
|
||||
ORDER BY 1, 2;
|
||||
@@ -1,13 +0,0 @@
|
||||
select
|
||||
table_schema,
|
||||
table_name,
|
||||
check_option,
|
||||
is_updatable,
|
||||
is_insertable_into,
|
||||
is_trigger_updatable,
|
||||
is_trigger_deletable,
|
||||
is_trigger_insertable_into
|
||||
|
||||
from information_schema.views
|
||||
where table_schema = ?
|
||||
-- and table_schema not in ('information_schema', 'pg_catalog')
|
||||
@@ -1,13 +0,0 @@
|
||||
export const POSTGRES_HOST = 'localhost'
|
||||
export const POSTGRES_USER = 'postgres'
|
||||
export const POSTGRES_PASSWORD = 'postgres'
|
||||
export const POSTGRES_DATABASE = 'postgres'
|
||||
export const POSTGRES_PORT = 5432
|
||||
export const DEFAULT_SCHEMA = 'public'
|
||||
export const POSTGRES_CONFIG = {
|
||||
host: POSTGRES_HOST,
|
||||
user: POSTGRES_USER,
|
||||
password: POSTGRES_PASSWORD,
|
||||
database: POSTGRES_DATABASE,
|
||||
port: POSTGRES_PORT,
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import knex from 'knex'
|
||||
|
||||
export function connect(config) {
|
||||
return knex({ client: 'pg', connection: config })
|
||||
}
|
||||
|
||||
export async function disconnect(conn) {
|
||||
let cb = () => { return true }
|
||||
conn.destroy(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a SQL string against the database
|
||||
* @param conn an open Knex connection
|
||||
* @param {string} query The SQL query
|
||||
* @param {sting[]} params An optional array of paramaters to feed into the query
|
||||
*/
|
||||
export function runQuery(conn, query, params = {}) {
|
||||
return conn.raw(query, params)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import assert from 'assert'
|
||||
|
||||
export function compareKeys (first, second) {
|
||||
Object.keys(first).map(key => assert(Object.keys(second).includes(key)))
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import * as config from '../src/api/config.js'
|
||||
import { compareKeys } from './_helpers'
|
||||
|
||||
describe('Config', function() {
|
||||
it('getAll() should return all settings', async () => {
|
||||
let res = await config.getAll()
|
||||
|
||||
// Check that we have a result
|
||||
assert(Array.isArray(res))
|
||||
|
||||
// Compare one of the values
|
||||
const valid = {
|
||||
name: 'autovacuum',
|
||||
setting: 'on',
|
||||
unit: null,
|
||||
category: 'Autovacuum',
|
||||
short_desc: 'Starts the autovacuum subprocess.',
|
||||
extra_desc: null,
|
||||
context: 'sighup',
|
||||
vartype: 'bool',
|
||||
source: 'default',
|
||||
min_val: null,
|
||||
max_val: null,
|
||||
enumvals: null,
|
||||
boot_val: 'on',
|
||||
reset_val: 'on',
|
||||
sourcefile: null,
|
||||
sourceline: null,
|
||||
pending_restart: false,
|
||||
}
|
||||
const compare = res.find(setting => setting.name === valid.name)
|
||||
compareKeys(valid, compare)
|
||||
})
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
// See https://github.com/supabase/monorepo/issues/3
|
||||
|
||||
// import doctest from 'jsdoc-test'
|
||||
|
||||
// describe('Run doctests', () => {
|
||||
// doctest('src/api/tables.js')
|
||||
// })
|
||||
@@ -1,22 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import * as types from '../src/api/plugins'
|
||||
import { compareKeys } from './_helpers'
|
||||
|
||||
describe('Plugins', function() {
|
||||
it('getAll() should return an array of tables', async () => {
|
||||
let res = await types.getAll('public')
|
||||
|
||||
// Check that we have a result
|
||||
assert(Array.isArray(res))
|
||||
|
||||
// Compare one of the values
|
||||
const valid = {
|
||||
name: 'plpgsql',
|
||||
version: '1.0',
|
||||
schema: 'pg_catalog',
|
||||
description: 'PL/pgSQL procedural language',
|
||||
}
|
||||
const compare = res.find(setting => setting.name === valid.name)
|
||||
compareKeys(valid, compare)
|
||||
})
|
||||
})
|
||||
@@ -1,11 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import * as tables from '../src/api/tables.js'
|
||||
|
||||
describe('Tables', function() {
|
||||
it('getAll() should return an array of tables', async () => {
|
||||
let res = await tables.getAll()
|
||||
|
||||
// Check that we have a result
|
||||
assert(Array.isArray(res))
|
||||
})
|
||||
})
|
||||
@@ -1,23 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import * as types from '../src/api/types.js'
|
||||
import { compareKeys } from './_helpers'
|
||||
|
||||
describe('Types', function() {
|
||||
it('getAll() should return an array of tables', async () => {
|
||||
let res = await types.getAll('public')
|
||||
|
||||
// Check that we have a result
|
||||
assert(Array.isArray(res))
|
||||
|
||||
// Compare one of the values
|
||||
const valid = {
|
||||
name: 'smallint',
|
||||
internal_name: 'int2',
|
||||
size: '2',
|
||||
enums: '{}',
|
||||
description: '-32 thousand to 32 thousand, 2-byte storage',
|
||||
}
|
||||
const compare = res.find(setting => setting.name === valid.name)
|
||||
compareKeys(valid, compare)
|
||||
})
|
||||
})
|
||||
@@ -1,26 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import * as views from '../src/api/views.js'
|
||||
import { compareKeys } from './_helpers'
|
||||
|
||||
describe('Views', function() {
|
||||
it('getAll() should return an array of tables', async () => {
|
||||
let res = await views.getAll({}, { schema: 'information_schema' })
|
||||
|
||||
// Check that we have a result
|
||||
assert(Array.isArray(res))
|
||||
|
||||
// Compare one of the values
|
||||
const valid = {
|
||||
table_schema: 'information_schema',
|
||||
table_name: 'attributes',
|
||||
check_option: 'NONE',
|
||||
is_updatable: 'NO',
|
||||
is_insertable_into: 'NO',
|
||||
is_trigger_updatable: 'NO',
|
||||
is_trigger_deletable: 'NO',
|
||||
is_trigger_insertable_into: 'NO',
|
||||
}
|
||||
const compare = res.find(setting => setting.name === valid.name)
|
||||
compareKeys(valid, compare)
|
||||
})
|
||||
})
|
||||
@@ -1,8 +0,0 @@
|
||||
# RealtimeJS
|
||||
|
||||
Realtime PostgreSQL.
|
||||
|
||||
## Docs
|
||||
|
||||
View online at [https://supabase.io/docs/-/about](https://supabase.io/docs/-/about).
|
||||
|
||||
Generated
-68
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"name": "@supabase/realtime-js",
|
||||
"version": "0.1.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "12.12.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz",
|
||||
"integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
||||
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
|
||||
},
|
||||
"phoenix-channels": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/phoenix-channels/-/phoenix-channels-1.0.0.tgz",
|
||||
"integrity": "sha1-TeOno0J0g97/xJCNj+yscl2wbWo=",
|
||||
"requires": {
|
||||
"websocket": "^1.0.24"
|
||||
}
|
||||
},
|
||||
"typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"requires": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"version": "1.0.30",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.30.tgz",
|
||||
"integrity": "sha512-aO6klgaTdSMkhfl5VVJzD5fm+Srhh5jLYbS15+OiI1sN6h/RU/XW6WN9J1uVIpUKNmsTvT3Hs35XAFjn9NMfOw==",
|
||||
"requires": {
|
||||
"debug": "^2.2.0",
|
||||
"nan": "^2.14.0",
|
||||
"typedarray-to-buffer": "^3.1.5",
|
||||
"yaeti": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "@supabase/realtime-js",
|
||||
"version": "0.1.4",
|
||||
"description": "Listen to realtime updates to your PostgreSQL database.",
|
||||
"repository": "https://github.com/supabase/monorepo",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"deploy": "npm version patch; npm publish --access=public",
|
||||
"test": "mocha --require esm \"test/**/*_spec.js\""
|
||||
},
|
||||
"keywords": [
|
||||
"supabase",
|
||||
"realtime"
|
||||
],
|
||||
"author": "@kiwicopple",
|
||||
"license": "Apache-2.0",
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^12.6.8",
|
||||
"phoenix-channels": "^1.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
import { Socket } from 'phoenix-channels'
|
||||
|
||||
export default class Realtime {
|
||||
constructor(apiSocket){
|
||||
this.socket = new Socket(apiSocket)
|
||||
this.channel = this.socket.channel('realtime')
|
||||
this.listeners = []
|
||||
|
||||
this.socket.onOpen(() => {
|
||||
console.log('Socket connected')
|
||||
})
|
||||
this.socket.onClose(() => {
|
||||
console.log('Socket disconnected')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts socket and all of its channels/ listeners
|
||||
*
|
||||
* @param {Array} listeners
|
||||
* @param {Object} listeners[n]
|
||||
* @param {String} listener.channel The name of channel
|
||||
* @param {Function} listener.callback The callback function to fire when the channel receives a change
|
||||
*/
|
||||
start(listeners) {
|
||||
this.socket.connect()
|
||||
if (this.channel.state !== 'joined'){
|
||||
this.channel
|
||||
.join()
|
||||
.receive('ok', resp => console.log('Joined Realtime successfully', resp))
|
||||
.receive('error', resp => console.log('Unable to join', resp))
|
||||
.receive('timeout', () => console.log('Networking issue. Still waiting...'))
|
||||
|
||||
listeners.forEach( listener => {
|
||||
this.addListener(listener)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops socket and all of its channels/ listeners
|
||||
*/
|
||||
stop(){
|
||||
this.listeners.forEach(({ channel, callback }) => {
|
||||
this.channel.off(channel, callback)
|
||||
})
|
||||
this.socket.disconnect()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the socket and activates it
|
||||
*
|
||||
* @param {Object} listener
|
||||
* @param {String} listener.channel The name of channel
|
||||
* @param {Function} listener.callback The callback function to fire when the channel receives a change
|
||||
*
|
||||
* @example
|
||||
* addListener({channel: 'shout', callback: () => {}})
|
||||
*/
|
||||
addListener(listener){
|
||||
this.listeners.push(listener)
|
||||
let { channel, callback } = listener
|
||||
|
||||
this.channel.on(channel, callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in String channel to:
|
||||
* 1. turn channel off
|
||||
* 2. remove specific listener from this.listener
|
||||
*
|
||||
* @param {String} channel
|
||||
*
|
||||
* @example
|
||||
* removeListener('shout')
|
||||
*/
|
||||
removeListener(channel){
|
||||
this.channel.off(channel)
|
||||
|
||||
let updatedListeners = this.listeners.filter(listener => {
|
||||
let channelName = listener.channel
|
||||
return channelName !== channel
|
||||
})
|
||||
this.listeners = updatedListeners
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import * as mapper from './mapper'
|
||||
import Realtime from './Realtime'
|
||||
|
||||
export {
|
||||
mapper,
|
||||
Realtime
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
// # Lifted from epgsql (src/epgsql_binary.erl), this module licensed under
|
||||
// # 3-clause BSD found here: https://raw.githubusercontent.com/epgsql/epgsql/devel/LICENSE
|
||||
//
|
||||
// {:bool, 16, 1000},
|
||||
// {:bpchar, 1042, 1014},
|
||||
// {:bytea, 17, 1001},
|
||||
// {:char, 18, 1002},
|
||||
// {:cidr, 650, 651},
|
||||
// {:date, 1082, 1182},
|
||||
// {:daterange, 3912, 3913},
|
||||
// {:float4, 700, 1021},
|
||||
// {:float8, 701, 1022},
|
||||
// {:geometry, 17063, 17071},
|
||||
// {:hstore, 16935, 16940},
|
||||
// {:inet, 869, 1041},
|
||||
// {:int2, 21, 1005},
|
||||
// {:int4, 23, 1007},
|
||||
// {:int4range, 3904, 3905},
|
||||
// {:int8, 20, 1016},
|
||||
// {:int8range, 3926, 3927},
|
||||
// {:interval, 1186, 1187},
|
||||
// {:json, 114, 199},
|
||||
// {:jsonb, 3802, 3807},
|
||||
// {:macaddr, 829, 1040},
|
||||
// {:macaddr8, 774, 775},
|
||||
// {:point, 600, 1017},
|
||||
// {:text, 25, 1009},
|
||||
// {:time, 1083, 1183},
|
||||
// {:timestamp, 1114, 1115},
|
||||
// {:timestamptz, 1184, 1185},
|
||||
// {:timetz, 1266, 1270},
|
||||
// {:tsrange, 3908, 3909},
|
||||
// {:tstzrange, 3910, 3911},
|
||||
// {:uuid, 2950, 2951},
|
||||
// {:varchar, 1043, 1015}
|
||||
|
||||
/**
|
||||
* Takes an array of columns and an object of string values then converts each string value
|
||||
* to its mapped type
|
||||
* @param {{name: String, type: String}[]} columns
|
||||
* @param {Object} records
|
||||
* @param {Object} options The map of various options that can be applied to the mapper
|
||||
* @param {Array} options.skipTypes The array of types that should not be converted
|
||||
*
|
||||
* @example
|
||||
* convertChangeData([{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {'Paul', '33'}, {})
|
||||
* //=>
|
||||
* { first_name: 'Paul', age: 33 }
|
||||
*/
|
||||
export const convertChangeData = (columns, records, options = {}) => {
|
||||
let result = {}
|
||||
let skipTypes = typeof options.skipTypes !== 'undefined' ? options.skipTypes : []
|
||||
Object.entries(records).map(([key, value]) => {
|
||||
result[key] = convertColumn(key, columns, records, skipTypes)
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the value of an individual column
|
||||
* @param {String} columnName The column that you want to convert
|
||||
* @param {{name: String, type: String}[]} columns All of the columns
|
||||
* @param {Object} records The map of string values
|
||||
* @param {Array} skipTypes An array of types that should not be converted
|
||||
* @return {object} Useless information
|
||||
*
|
||||
* @example
|
||||
* convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], ['Paul', '33'], [])
|
||||
* //=>
|
||||
* 33
|
||||
*
|
||||
* @example
|
||||
* convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], ['Paul', '33'], ['int4'])
|
||||
* //=>
|
||||
* "33"
|
||||
*/
|
||||
export const convertColumn = (columnName, columns, records, skipTypes) => {
|
||||
let column = columns.find(x => x.name == columnName)
|
||||
if(skipTypes.includes(column.type)) return noop(records[columnName])
|
||||
else return convertCell(column.type, records[columnName])
|
||||
}
|
||||
|
||||
/**
|
||||
* If the value of the cell is `null`, returns null.
|
||||
* Otherwise converts the string value to the correct type.
|
||||
* @param {String} type A postgres column type
|
||||
* @param {String} stringValue The cell value
|
||||
*
|
||||
* @example
|
||||
* convertCell('bool', 'true')
|
||||
* //=>
|
||||
* true
|
||||
*
|
||||
* @example
|
||||
* convertCell('int8', '10')
|
||||
* //=>
|
||||
* 10
|
||||
*/
|
||||
export const convertCell = (type, stringValue) => {
|
||||
try {
|
||||
if (stringValue === null) return null
|
||||
|
||||
// If not null, convert to correct type.
|
||||
switch (type) {
|
||||
case 'bool':
|
||||
return toBoolean(stringValue)
|
||||
case 'bpchar':
|
||||
return noop(stringValue)
|
||||
case 'bytea':
|
||||
return noop(stringValue)
|
||||
case 'char':
|
||||
return noop(stringValue)
|
||||
case 'cidr':
|
||||
return noop(stringValue)
|
||||
case 'date':
|
||||
return toDate(stringValue)
|
||||
case 'daterange':
|
||||
return toDateRange(stringValue)
|
||||
case 'float4':
|
||||
return toFloat(stringValue)
|
||||
case 'float8':
|
||||
return toFloat(stringValue)
|
||||
case 'geometry':
|
||||
return noop(stringValue)
|
||||
case 'hstore':
|
||||
return noop(stringValue)
|
||||
case 'inet':
|
||||
return noop(stringValue)
|
||||
case 'int2':
|
||||
return toInt(stringValue)
|
||||
case 'int4':
|
||||
return toInt(stringValue)
|
||||
case 'int4range':
|
||||
return toIntRange(stringValue)
|
||||
case 'int8':
|
||||
return toInt(stringValue)
|
||||
case 'int8range':
|
||||
return toIntRange(stringValue)
|
||||
case 'interval':
|
||||
return noop(stringValue)
|
||||
case 'json':
|
||||
return toJson(stringValue)
|
||||
case 'jsonb':
|
||||
return toJson(stringValue)
|
||||
case 'macaddr':
|
||||
return noop(stringValue)
|
||||
case 'macaddr8':
|
||||
return noop(stringValue)
|
||||
case 'point':
|
||||
return noop(stringValue)
|
||||
case 'text':
|
||||
return noop(stringValue)
|
||||
case 'time':
|
||||
return noop(stringValue)
|
||||
case 'timestamp':
|
||||
return toDate(stringValue)
|
||||
case 'timestamptz':
|
||||
return toDate(stringValue)
|
||||
case 'timetz':
|
||||
return noop(stringValue)
|
||||
case 'tsrange':
|
||||
return noop(stringValue)
|
||||
case 'tstzrange':
|
||||
return noop(stringValue)
|
||||
case 'uuid':
|
||||
return noop(stringValue)
|
||||
case 'varchar':
|
||||
return noop(stringValue)
|
||||
default:
|
||||
// Unhandled and custom types will always return as strings
|
||||
return noop(stringValue)
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Could not convert cell of type ${type} and value ${stringValue}`)
|
||||
return stringValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes back the raw string value
|
||||
*/
|
||||
const noop = stringValue => {
|
||||
return stringValue
|
||||
}
|
||||
const toBoolean = stringValue => {
|
||||
switch (stringValue) {
|
||||
case 't':
|
||||
return true
|
||||
case 'f':
|
||||
return false
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
const toDate = stringValue => {
|
||||
return new Date(stringValue)
|
||||
}
|
||||
const toDateRange = stringValue => {
|
||||
let arr = JSON.parse(stringValue)
|
||||
return [new Date(arr[0]), new Date(arr[1])]
|
||||
}
|
||||
const toFloat = stringValue => {
|
||||
return parseFloat(stringValue)
|
||||
}
|
||||
const toInt = stringValue => {
|
||||
return parseInt(stringValue)
|
||||
}
|
||||
const toIntRange = stringValue => {
|
||||
let arr = JSON.parse(stringValue)
|
||||
return [parseInt(arr[0]), parseInt(arr[1])]
|
||||
}
|
||||
const toJson = stringValue => {
|
||||
return JSON.parse(stringValue)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import doctest from 'jsdoc-test'
|
||||
|
||||
describe('Run doctests', () => {
|
||||
doctest('src/mapper.js')
|
||||
})
|
||||
@@ -1,10 +0,0 @@
|
||||
# Supabase
|
||||
|
||||
Landing page for [supabase.io](supabase.io).
|
||||
|
||||
|
||||
## Deployment
|
||||
|
||||
This site is deployed as a STATIC site on Netlify. This means that pages must be listed in `next.config.js`. To update the site on Netlify, just push to `master`.
|
||||
|
||||
See the [NextJS](https://nextjs.org/learn/excel/static-html-export/exporting-other-pages) docs for more details.
|
||||
@@ -1,18 +0,0 @@
|
||||
module.exports = function(api) {
|
||||
api.cache(true)
|
||||
return {
|
||||
presets: ['next/babel'],
|
||||
plugins: [
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
[
|
||||
'module-resolver',
|
||||
{
|
||||
root: ['./'],
|
||||
alias: {
|
||||
'~': '.',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import SignUpForm from '~/components/SignUpForm'
|
||||
import WidthWrapper from '~/components/WidthWrapper'
|
||||
import {version} from '~/package.json'
|
||||
|
||||
export default function Footer({ isFullwidth }) {
|
||||
return (
|
||||
<footer className="footer p-b-md">
|
||||
<WidthWrapper isFullwidth={isFullwidth}>
|
||||
<div className="columns">
|
||||
<div className="column">
|
||||
<h3 className="title is-3 ">
|
||||
<img src="/supabase-logo.svg" alt="Supabase" width="180" />
|
||||
</h3>
|
||||
<SignUpForm />
|
||||
</div>
|
||||
<div className="column is-3"></div>
|
||||
<div className="column is-2">
|
||||
<p className="heading">Products</p>
|
||||
<p>
|
||||
<Link href="/docs">
|
||||
<a className="">Docs</a>
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<div className="column is-2">
|
||||
<p className="heading">Company</p>
|
||||
<p>
|
||||
<a href="https://github.com/supabase/monorepo" target="_blank">
|
||||
Github
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div className="level">
|
||||
<div className="level-left ">
|
||||
<div className="level-item ">
|
||||
<small className="has-text-weight-bold">© Supabase. v{version}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="level-right">
|
||||
<div className="level-item">
|
||||
<a className="is-size-7 m-r-md">Terms of Use</a>·
|
||||
<a className="is-size-7 m-l-md">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidthWrapper>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<div style={{ textAlign: 'center', width: 800, padding: 100, margin: 'auto' }}>
|
||||
We haven't come up with a cool loading component yet. Consider this this shittiest easter egg you've ever found.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import WidthWrapper from '~/components/WidthWrapper'
|
||||
|
||||
export default function Navbar({ isFullwidth }) {
|
||||
const [mobileActive, setMobileActive] = useState(false)
|
||||
|
||||
|
||||
return (
|
||||
<nav className="navbar" role="navigation" aria-label="main navigation">
|
||||
<WidthWrapper isFullwidth={isFullwidth}>
|
||||
<div className="navbar-brand">
|
||||
<Link href="/">
|
||||
<a className="navbar-item has-text-weight-bold">
|
||||
<img src="/supabase-logo.svg" alt="Supabase" />
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<a
|
||||
role="button"
|
||||
className="navbar-burger burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navbarBasicExample"
|
||||
onClick={() => setMobileActive(!mobileActive)}
|
||||
>
|
||||
<span aria-hidden="true" />
|
||||
<span aria-hidden="true" />
|
||||
<span aria-hidden="true" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbarBasicExample" className={`navbar-menu ${mobileActive ? 'is-active' : ''}`}>
|
||||
<div className="navbar-start"></div>
|
||||
|
||||
<div className="navbar-end p-r-sm">
|
||||
<div className="navbar-item">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/-/about`}>
|
||||
<a className="">Docs</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidthWrapper>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Navbar({ }) {
|
||||
const router = useRouter()
|
||||
let { category } = router.query
|
||||
return (
|
||||
<nav className="tabs m-none">
|
||||
<ul>
|
||||
<li className={category == '-' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/-/about`}>
|
||||
<a className="">Supabase</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={category == 'packaged' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/packaged/introduction`}>
|
||||
<a className="">Packaged</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={category == 'admin-api' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/admin-api/introduction`}>
|
||||
<a className="">Admin API</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={category == 'realtime' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/realtime/introduction`}>
|
||||
<a className="">Realtime</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={category == 'restful' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/restful/introduction`}>
|
||||
<a className="">Restful</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={category == 'graphql' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/graphql/introduction`}>
|
||||
<a className="">GraphQL</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={category == 'baseless' ? 'is-active' : ''}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/baseless/introduction`}>
|
||||
<a className="">Baseless</a>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
export default function SignUpForm() {
|
||||
const [email, setEmail] = useState('')
|
||||
return (
|
||||
<form
|
||||
action="https://gmail.us5.list-manage.com/subscribe/post?u=c6785f4e1c9c77f231e367f6e&id=18cccc8b62"
|
||||
method="post"
|
||||
id="mc-embedded-subscribe-form"
|
||||
name="mc-embedded-subscribe-form"
|
||||
className="field is-grouped"
|
||||
target="_blank"
|
||||
noValidate
|
||||
>
|
||||
<p className="control is-expanded">
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
name="EMAIL"
|
||||
className="input email"
|
||||
id="mce-EMAIL"
|
||||
placeholder="your@email.com"
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</p>
|
||||
<div style={{ position: 'absolute', left: '-5000px' }} aria-hidden="true">
|
||||
<input type="text" name="b_c6785f4e1c9c77f231e367f6e_18cccc8b62" tabIndex="-1" />
|
||||
</div>
|
||||
<div className="control">
|
||||
<input
|
||||
type="submit"
|
||||
value="Early Sign Up"
|
||||
name="subscribe"
|
||||
id="mc-embedded-subscribe"
|
||||
className="button is-primary"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export default function WidthWrapper({ isFullwidth, children }) {
|
||||
if (!isFullwidth) return <div className="section container p-b-none p-t-none">{children}</div>
|
||||
else return <>{children}</>
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import '~/styles/style.scss'
|
||||
import Navbar from '../Navbar'
|
||||
import NavbarDocs from '../NavbarDocs'
|
||||
import Footer from '../Footer'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
export default function DocsLayout(props) {
|
||||
const [sidebarVisible, toggleSidebar] = useState(false)
|
||||
const { sidebar } = props
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Supabase | Docs</title>
|
||||
</Head>
|
||||
<div className="">
|
||||
<Navbar isFullwidth={true} />
|
||||
<NavbarDocs />
|
||||
<div className="columns m-none is-gapless">
|
||||
<div
|
||||
className="DocsMenuColumn docs-subnav column is-narrow is-hidden-mobile"
|
||||
style={{ width: 250 }}
|
||||
>
|
||||
{Sidebar(sidebar, () => toggleSidebar(false))}
|
||||
</div>
|
||||
<div className="column">{props.children}</div>
|
||||
</div>
|
||||
<Footer isFullwidth={true} />
|
||||
|
||||
<nav
|
||||
className="navbar is-fixed-bottom has-background-dark is-hidden-tablet"
|
||||
role="navigation"
|
||||
aria-label="sub navigation"
|
||||
>
|
||||
<a className="navbar-brand" onClick={() => toggleSidebar(!sidebarVisible)}>
|
||||
<div className="navbar-item">
|
||||
<h5 className="title is-5">Menu</h5>
|
||||
</div>
|
||||
|
||||
<span
|
||||
role="button"
|
||||
className={sidebarVisible ? 'navbar-burger is-active' : 'navbar-burger'}
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<div className={sidebarVisible ? 'navbar-menu is-active' : 'navbar-menu'}>
|
||||
<div className="navbar-end docs-subnav">
|
||||
{Sidebar(sidebar, () => toggleSidebar(false))}
|
||||
<div className="p-md">
|
||||
<a className="button is-fullwidth" onClick={() => toggleSidebar(!sidebarVisible)}>
|
||||
Hide
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const Sidebar = (sidebar, onMenuItemClicked) => {
|
||||
const router = useRouter()
|
||||
let { category, slug } = router.query
|
||||
return Object.entries(sidebar || []).map(([heading, pages]) => {
|
||||
return (
|
||||
<div key={heading}>
|
||||
<p className="menu-label">{heading}</p>
|
||||
<ul className="menu-list">
|
||||
{pages.map(page => (
|
||||
<li key={page.slug}>
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/${category}/${page.slug}`}>
|
||||
<a
|
||||
className={slug == page.slug ? 'is-active' : ''}
|
||||
onClick={() => onMenuItemClicked(page)}
|
||||
>
|
||||
{page.title}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import '~/styles/style.scss'
|
||||
import Navbar from '../Navbar'
|
||||
import Footer from '../Footer'
|
||||
import Head from 'next/head'
|
||||
|
||||
export default function MainLayout(props) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Supabase</title>
|
||||
</Head>
|
||||
<div className="">
|
||||
<Navbar />
|
||||
{props.children}
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
# Hello World
|
||||
|
||||
This is a sample blog post, using markdown.
|
||||
|
||||
I also has a [link to the homepage](/)
|
||||
@@ -1,25 +0,0 @@
|
||||
import Link from 'next/link'
|
||||
export const metadata = {
|
||||
title: 'Supabase',
|
||||
description: 'Supercharge PostgreSQL.',
|
||||
sidebarLabel: 'About'
|
||||
}
|
||||
|
||||
### Single source of truth
|
||||
|
||||
This is the single source of truth for Supabase documentation and information.
|
||||
|
||||
We are a lean open-source company. To make things easier you you (and us) all documentation is in this single repository.
|
||||
|
||||
### Contributions
|
||||
|
||||
Like what we're doing and want to help? We'll go out of our way to help you help us.
|
||||
|
||||
Whether you're a first time open source contributor or a veteran, we'd love your [contribution.](/docs/-/contributing)
|
||||
|
||||
### In Production
|
||||
|
||||
Here are some companies that use Supabase in production.
|
||||
|
||||
- [Nimbus for Work](https://nimbusforwork.com)
|
||||
- Want to add your company? Submit a PR.
|
||||
@@ -1,16 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Contributing',
|
||||
description: 'Supabase Contribution Guidelines.'
|
||||
}
|
||||
|
||||
### Want to contribute?
|
||||
|
||||
So ... we're even looking for contributions on our contributions guidelines.
|
||||
|
||||
Supabase is thinking in public. Everything is online, no matter how raw the current state.
|
||||
|
||||
We'll make this awesome, we promise. But if you can't wait then why not jump into our github and:
|
||||
|
||||
- submit an issue
|
||||
- create a pull request
|
||||
- try one of our products and give feedback
|
||||
@@ -1,34 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Admin API',
|
||||
description: 'SQL is awesome, but sometimes not so awesome for beginners.',
|
||||
sidebarLabel: 'Getting Started'
|
||||
}
|
||||
|
||||
|
||||
### Coming soon
|
||||
|
||||
We're busy making Realtime awesome right now, and we'll get around to this as soon as we can.
|
||||
|
||||
### What it is
|
||||
|
||||
Superbase Admin API is a RESTful interface for interacting with your database schema (listing tables, views, settings, etc).
|
||||
|
||||
### How it works
|
||||
|
||||
We took all the common SQL commands that we think you'd need, and we put a RESTful interface in front of them.
|
||||
|
||||
|
||||
### What it isn't
|
||||
|
||||
It's not for interacting with your data - it for querying the schema (tables, views) and database (settings).
|
||||
|
||||
### Features
|
||||
|
||||
- 100% open source
|
||||
- Built with JS, can be used on the client (web, mobile)
|
||||
|
||||
### Benefits
|
||||
|
||||
- Familiar
|
||||
- Quick
|
||||
- and Dirty
|
||||
@@ -1,29 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Schemas',
|
||||
description:
|
||||
'A database contains one or more named schemas, which in turn contain tables. Schemas also contain other kinds of named objects, including data types, functions, and operators.',
|
||||
}
|
||||
|
||||
### Introduction
|
||||
|
||||
A database contains one or more named schemas, which in turn contain tables. Schemas also contain other kinds of named objects, including data types, functions, and operators.
|
||||
Read more about schemas [here](https://www.postgresql.org/docs/current/ddl-schemas.html).
|
||||
|
||||
|
||||
### GET
|
||||
|
||||
Request a list of schemas
|
||||
|
||||
```
|
||||
curl \
|
||||
https://fakeurl.com
|
||||
```
|
||||
|
||||
### POST
|
||||
|
||||
Create a new schema
|
||||
|
||||
```
|
||||
curl \
|
||||
https://fakeurl.com
|
||||
```
|
||||
@@ -1,17 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Tables',
|
||||
description:
|
||||
'Something about tables.',
|
||||
}
|
||||
|
||||
### Introduction
|
||||
|
||||
Something about tables
|
||||
|
||||
|
||||
### Request a list of tables
|
||||
|
||||
```
|
||||
curl \
|
||||
https://fakeurl.com
|
||||
```
|
||||
@@ -1,14 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Baseless',
|
||||
description: 'We\'re building a serverless PostgreSQL so you can get started in seconds. Export your database to a fully native PostgreSQL instance at any time.'
|
||||
}
|
||||
|
||||
### Motivation
|
||||
|
||||
Relational databases are great but the set up can be cumbersome for quick prototyping and small products.
|
||||
Additionally, even a small Postgres database can cost you $5/month.
|
||||
We want to provide developers with the fastest and cheapest route to market using PostgreSQL.
|
||||
|
||||
### Coming soon
|
||||
|
||||
We're busy making Realtime awesome right now, and we'll get around to this as soon as we can.
|
||||
@@ -1,8 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'GraphQL',
|
||||
description: 'Extend your database with a fully functional GraphQL API, without a line of code.'
|
||||
}
|
||||
|
||||
### Coming soon
|
||||
|
||||
We're busy making Realtime awesome right now, and we'll get around to this as soon as we can.
|
||||
@@ -1,40 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Packaged PostgreSQL',
|
||||
description: 'PostgreSQL is easy, we\'re just making it slightly easier.',
|
||||
sidebarLabel: 'Getting Started'
|
||||
}
|
||||
|
||||
### Coming soon
|
||||
|
||||
We're busy making Realtime awesome right now, and we'll get around to this as soon as we can.
|
||||
|
||||
|
||||
### What it is
|
||||
|
||||
Supabase Packaged is simply PostgreSQL, with all the common plugins you may need as well as a few bells-and-whistles we think you may need.
|
||||
We wrap it all up to make it easy to deploy to various platforms.
|
||||
|
||||
### How it works
|
||||
|
||||
It's pretty simple, we just PostgreSQL and various other tools into packages for usage with:
|
||||
|
||||
- Containers: Docker & Kubernetes
|
||||
- More coming soon
|
||||
|
||||
|
||||
### What it isn't
|
||||
|
||||
It's not a replacement for your full production instance.
|
||||
|
||||
### Features
|
||||
|
||||
- 100% open source
|
||||
- Restful Admin interface for interacting with your database schema (listing tables, views, settings, etc)
|
||||
- Master replication enabled by default
|
||||
- Plugins: PostGIS, TimescaleDb, wal2json
|
||||
|
||||
### Benefits
|
||||
|
||||
- Get up and running quickly
|
||||
- Try out PostgreSQL plugins without having to go through painful installations
|
||||
- Best practices implemented out-of-the-box
|
||||
@@ -1,6 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'With Docker and NextJs',
|
||||
description: 'A How-To guide for using Realtime with NextJs.'
|
||||
}
|
||||
|
||||
> Draft
|
||||
@@ -1,38 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Realtime',
|
||||
description: 'Listen to your database updates, inserts, and deletes over websockets.',
|
||||
sidebarLabel: 'Overview'
|
||||
}
|
||||
|
||||
### What it is
|
||||
|
||||
Supabase Realtime is an elixir server that allows you to listen to PostgreSQL inserts/updates/deletes over websockets.
|
||||
|
||||
### Where it is
|
||||
|
||||
All code is hosted at [https://github.com/supabase/realtime](https://github.com/supabase/realtime).
|
||||
|
||||
### How it works
|
||||
|
||||
Realtime listens to PostgreSQL's replication functionality and converts the byte stream into JSON. It then broadcasts the JSON over websockets.
|
||||
|
||||
It is built with [Phoenix](https://phoenixframework.org/), an Elixir framework that's incredibly scalable.
|
||||
|
||||
### What it isn't
|
||||
|
||||
- Supabase Realtime is a passive listen/broadcast system. You don't use it to make updates to your database.
|
||||
- We don't (yet) intend to build client-side databases that can do all the offline conflict resolution that other services like Firebase provide.
|
||||
|
||||
### Features
|
||||
|
||||
- 100% open source under the Apache 2.0 License
|
||||
- Accessible by mobile and web
|
||||
- Works without wal2json :)
|
||||
|
||||
### Benefits
|
||||
|
||||
- You own your data. Realtime can be pointed at any PostgreSQL database that has replication enabled.
|
||||
- Build chat apps and other systems that require realtime functionality.
|
||||
- Listening to data changes on client side solves stale data problems and update collisions.
|
||||
- Many systems that give you realtime functionality require you to update via the same interface that the listener is on. Supabase is source agnostic. Update your database from anywhere and you'll still get the changes.
|
||||
- Scale the realtime servers without putting any additional load on your DB. All you need is one connection to your database, and you can handle thousands (or [millions](https://phoenixframework.org/blog/the-road-to-2-million-websocket-connections)) or users
|
||||
@@ -1,37 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Quick start',
|
||||
description: 'From zero to Realtime in 5 minutes.'
|
||||
}
|
||||
|
||||
> Draft
|
||||
|
||||
### Introduction
|
||||
|
||||
You can find the code for this @todo
|
||||
|
||||
## Running the server
|
||||
|
||||
The easiest way to use this is to set up a docker compose:
|
||||
|
||||
```yml
|
||||
# docker-compose.yml
|
||||
version: '3'
|
||||
services:
|
||||
realtime:
|
||||
image: supabase/realtime
|
||||
ports:
|
||||
- "4000:4000"
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DB=db
|
||||
- POSTGRES_HOST=localhost
|
||||
- POSTGRES_PORT=5432
|
||||
db:
|
||||
image: supabase/packaged
|
||||
ports:
|
||||
- "5432:5432"
|
||||
```
|
||||
|
||||
Once you are set up you can run `docker-compose up`
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Realtime JS',
|
||||
description: 'How to use the JS client.'
|
||||
}
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install --save @supabase/realtime-js
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
#### Connect to the server
|
||||
|
||||
```js
|
||||
import { Socket } = '@supabase/realtime-js'
|
||||
|
||||
var API_SOCKET = process.env.SOCKET_URL
|
||||
var socket = new Socket(API_SOCKET)
|
||||
var realtimeChannel = this.socket.channel('realtime')
|
||||
|
||||
socket.connect()
|
||||
if (realtimeChannel.state !== 'joined') {
|
||||
realtimeChannel
|
||||
.join()
|
||||
.receive('ok', resp => console.log('Joined successfully', resp))
|
||||
.receive('error', resp => console.log('Unable to join', resp))
|
||||
.receive('timeout', () => console.log('Networking issue. Still waiting...'))
|
||||
|
||||
// Listen to all changes in the database
|
||||
realtimeChannel.on('shout', payload => {
|
||||
console.log('Update received!', payload)
|
||||
})
|
||||
}
|
||||
```
|
||||
@@ -1,61 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Realtime Server',
|
||||
description: 'Guide for using the realtime server.'
|
||||
}
|
||||
|
||||
|
||||
## Database preparation
|
||||
|
||||
We have tried to keep the requirements to use this as simple as possible. However there are still *some* things that you need to enable on your Postgres database (namely, replication).
|
||||
|
||||
**1. Enable replication**
|
||||
|
||||
Make sure your database has replication turned on:
|
||||
|
||||
```bash
|
||||
SHOW wal_level; # This should be "logical"
|
||||
SHOW max_replication_slots; # You need at least one free slot for Supabase
|
||||
```
|
||||
|
||||
**2. Listen to all table changes**
|
||||
|
||||
Create a publication for Supabase to listen to on all of your tables.
|
||||
|
||||
```bash
|
||||
CREATE PUBLICATION supabase_realtime FOR ALL TABLES;
|
||||
```
|
||||
|
||||
**3. (Optional) Receive old data**
|
||||
|
||||
If you want to receive the data the previous data (i.e. what the fields were *before* updates), then you need to set each table to have a full replica identity:
|
||||
|
||||
```bash
|
||||
ALTER TABLE YOUR_TABLE_NAME replica identity full; # Change YOUR_TABLE_NAME
|
||||
```
|
||||
|
||||
|
||||
## Running the server
|
||||
|
||||
The easiest way to use this is to set up a docker compose:
|
||||
|
||||
```yml
|
||||
# docker-compose.yml
|
||||
version: '3'
|
||||
services:
|
||||
realtime:
|
||||
image: supabase/realtime
|
||||
ports:
|
||||
- "4000:4000"
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DB=postgres
|
||||
- POSTGRES_HOST=localhost
|
||||
- POSTGRES_PORT=5432
|
||||
```
|
||||
|
||||
Once you are set up you can run `docker-compose up`
|
||||
|
||||
## Next steps
|
||||
|
||||
Now that your server is running you can connect to it via one of the client libraries
|
||||
@@ -1,9 +0,0 @@
|
||||
export const metadata = {
|
||||
title: 'Restful',
|
||||
description: 'Add a fully documented Restful API, simply by introspecting the schema.',
|
||||
sidebarLabel: 'Getting Started'
|
||||
}
|
||||
|
||||
### Coming soon
|
||||
|
||||
We're busy making Realtime awesome right now, and we'll get around to this as soon as we can.
|
||||
@@ -1,37 +0,0 @@
|
||||
const withPlugins = require('next-compose-plugins')
|
||||
|
||||
// Next Config
|
||||
const nextConfig = {
|
||||
experimental: { publicDirectory: true },
|
||||
}
|
||||
|
||||
// CSS
|
||||
const withCSS = require('@zeit/next-css')
|
||||
const withCssConfig = {}
|
||||
|
||||
// SASS
|
||||
const withSass = require('@zeit/next-sass')
|
||||
const withSassConfig = {
|
||||
sassLoaderOptions: {
|
||||
includePaths: ['./', 'absolute/path/b'],
|
||||
},
|
||||
}
|
||||
|
||||
// Markdown
|
||||
const rehypePrism = require('@mapbox/rehype-prism')
|
||||
const withMDX = require('@zeit/next-mdx')({
|
||||
extension: /\.(md|mdx)?$/,
|
||||
options: {
|
||||
rehypePlugins: [rehypePrism],
|
||||
},
|
||||
})
|
||||
const withMdxConfig = {}
|
||||
|
||||
module.exports = withPlugins(
|
||||
[
|
||||
[withCSS, withCssConfig],
|
||||
[withSass, withSassConfig],
|
||||
[withMDX, withMdxConfig],
|
||||
],
|
||||
nextConfig
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "supabase",
|
||||
"version": 2,
|
||||
"scope": "supabase"
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "@supabase/web",
|
||||
"version": "0.1.25",
|
||||
"description": "Supabase Main Website",
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"deploy": "yarn version && now --prod",
|
||||
"dev": "next",
|
||||
"export": "next export",
|
||||
"start": "next start",
|
||||
"static": "next build && next export"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mapbox/rehype-prism": "^0.3.1",
|
||||
"@mdx-js/loader": "^1.3.1",
|
||||
"@zeit/next-css": "^1.0.1",
|
||||
"@zeit/next-mdx": "^1.2.0",
|
||||
"@zeit/next-sass": "^1.0.0",
|
||||
"bulma": "^0.7.5",
|
||||
"next": "^9.0.5-canary.2",
|
||||
"next-compose-plugins": "^2.2.0",
|
||||
"node-sass": "^4.7.2",
|
||||
"prismjs": "^1.17.1",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.4.4",
|
||||
"babel-plugin-module-resolver": "^3.2.0"
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import Document, { Head, Main, NextScript } from 'next/document'
|
||||
export default class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="shortcut icon" type="image/png" href="/favicon.png" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/prism-tomorrow.css" />
|
||||
<title>Supabase</title>
|
||||
</head>
|
||||
<Head />
|
||||
<body className="has-navbar-fixed-bottom ">
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import MainLayout from '~/components/layouts/MainLayout'
|
||||
// import MDXDocument, { metadata } from '~/pages/posts/post.mdx'
|
||||
export default () => (
|
||||
<>
|
||||
<MainLayout>
|
||||
<div className="section container">
|
||||
<div className="content">
|
||||
{/* <MDXDocument /> */}
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
</>
|
||||
)
|
||||
@@ -1,16 +0,0 @@
|
||||
// index.js
|
||||
import React from 'react'
|
||||
import Layout from '~/components/layouts/MainLayout'
|
||||
import NavbarDocs from '~/components//NavbarDocs'
|
||||
|
||||
export default () => (
|
||||
<Layout>
|
||||
<div className="section container">
|
||||
<NavbarDocs />
|
||||
<div className="content">
|
||||
<h1>Docs</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
@@ -1,126 +0,0 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import Layout from '~/components/layouts/DocsLayout'
|
||||
import Loading from '~/components/Loading'
|
||||
import Link from 'next/link'
|
||||
|
||||
const importReducer = ctx => {
|
||||
let keys = ctx.keys()
|
||||
let values = keys.map(ctx)
|
||||
return keys.reduce((o, k, i) => {
|
||||
o[k] = values[i]
|
||||
return o
|
||||
}, {})
|
||||
}
|
||||
|
||||
// Import all docs
|
||||
var Docs = []
|
||||
Docs['-'] = importReducer(require.context('../../../content/docs/-', true, /.mdx$/))
|
||||
Docs['packaged'] = importReducer(require.context('../../../content/docs/packaged', true, /.mdx$/))
|
||||
Docs['admin-api'] = importReducer(require.context('../../../content/docs/admin-api', true, /.mdx$/))
|
||||
Docs['realtime'] = importReducer(require.context('../../../content/docs/realtime', true, /.mdx$/))
|
||||
Docs['restful'] = importReducer(require.context('../../../content/docs/restful', true, /.mdx$/))
|
||||
Docs['graphql'] = importReducer(require.context('../../../content/docs/graphql', true, /.mdx$/))
|
||||
Docs['baseless'] = importReducer(require.context('../../../content/docs/baseless', true, /.mdx$/))
|
||||
|
||||
// Set up all sidebars
|
||||
var Sidebars = []
|
||||
Sidebars['-'] = {
|
||||
Introduction: ['about', 'contributing'],
|
||||
}
|
||||
Sidebars['packaged'] = {
|
||||
Introduction: ['introduction'],
|
||||
}
|
||||
Sidebars['admin-api'] = {
|
||||
Introduction: ['introduction'],
|
||||
API: ['schemas', 'tables'],
|
||||
}
|
||||
Sidebars['realtime'] = {
|
||||
Introduction: ['introduction', 'quick-start'],
|
||||
Reference: ['realtime-server', 'realtime-js'],
|
||||
Guides: ['docker-nextjs'],
|
||||
}
|
||||
Sidebars['restful'] = {
|
||||
Introduction: ['introduction'],
|
||||
}
|
||||
Sidebars['graphql'] = {
|
||||
Introduction: ['introduction'],
|
||||
}
|
||||
Sidebars['baseless'] = {
|
||||
Introduction: ['introduction'],
|
||||
}
|
||||
|
||||
const CategoryDocs = props => {
|
||||
const router = useRouter()
|
||||
if (!router.query.category || !router.query.slug) return <Loading />
|
||||
|
||||
const { category, slug } = router.query
|
||||
const categoryDocs = Docs[category]
|
||||
const categorySidebar = enrichSidebar(Sidebars[category], categoryDocs)
|
||||
const documentation = categoryDocs[`./${slug}.mdx`]
|
||||
const Content = documentation.default
|
||||
const { metadata } = documentation
|
||||
const { title, description } = metadata
|
||||
const pages = Object.values(Sidebars[category]) // array of arrays
|
||||
const pageArray = pages.concat.apply([], pages) // flatten
|
||||
const sidebarIndex = pageArray.indexOf(slug)
|
||||
const nextDocSlug = pageArray[sidebarIndex + 1]
|
||||
const nextDoc = nextDocSlug ? categoryDocs[`./${nextDocSlug}.mdx`] : null
|
||||
const previousDocSlug = pageArray[sidebarIndex - 1]
|
||||
const previousDoc = previousDocSlug ? categoryDocs[`./${previousDocSlug}.mdx`] : null
|
||||
|
||||
return (
|
||||
<Layout sidebar={categorySidebar} activeCategory={category}>
|
||||
<div className="has-background-dark">
|
||||
<div className="content w-m-800 p-md p-t-xl p-b-xl m-b-lg">
|
||||
<h1 className="title">{title}</h1>
|
||||
<p className="subtitle">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content w-m-800 p-md">
|
||||
<Content />
|
||||
</div>
|
||||
<div className="w-m-800 p-md p-b-lg">
|
||||
<nav className="columns reverse-row-order">
|
||||
<div className="column ">
|
||||
{!!nextDoc && (
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/${category}/${nextDocSlug}`}>
|
||||
<a className="box p-md">
|
||||
<p className="heading has-text-grey">Next</p>
|
||||
<p>{nextDoc.metadata.sidebarLabel || nextDoc.metadata.title}</p>
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<div className="column is-hidden-mobile "></div>
|
||||
<div className="column">
|
||||
{!!previousDoc && (
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/${category}/${previousDocSlug}`}>
|
||||
<a className="box p-md has-text-right">
|
||||
<p className="heading has-text-grey">Previous</p>
|
||||
<p>{previousDoc.metadata.sidebarLabel || previousDoc.metadata.title}</p>
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default CategoryDocs
|
||||
|
||||
/**
|
||||
* Fills the sidebar array with relevant metadata,
|
||||
*/
|
||||
const enrichSidebar = (sidebar, categoryDocs) => {
|
||||
return Object.keys(sidebar).reduce((acc, heading) => {
|
||||
acc[heading] = sidebar[heading].map(slug => {
|
||||
const documentation = categoryDocs[`./${slug}.mdx`]
|
||||
const { metadata } = documentation
|
||||
const { title, sidebarLabel } = metadata
|
||||
return { slug, title: sidebarLabel || title }
|
||||
})
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
import MainLayout from '~/components/layouts/MainLayout'
|
||||
import Link from 'next/link'
|
||||
import SignUpForm from '~/components/SignUpForm'
|
||||
|
||||
|
||||
export default class Home extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<MainLayout>
|
||||
<div className="section container">
|
||||
<div className="columns">
|
||||
<div className="column" style={{ maxWidth: 450 }}>
|
||||
<h1 className="title is-1">Supabase</h1>
|
||||
<p className="subtitle">Supercharge PostgreSQL.</p>
|
||||
<SignUpForm />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="section container m-b-lg">
|
||||
<a name="pricing" id="pricing" />
|
||||
<h3 className="title is-3 has-underline ">Products</h3>
|
||||
<p className="subtitle">
|
||||
Extend your existing Postgres Database with opensource products.
|
||||
</p>
|
||||
<div className="columns is-multiline">
|
||||
<div className="column is-4">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/realtime/introduction`}>
|
||||
<a className="box deep-hover" style={{ height: '100%' }}>
|
||||
<h4 className="title is-4">Realtime</h4>
|
||||
<p>Listen to your database updates, inserts, and deletes over websockets.</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/restful/introduction`}>
|
||||
<a className="box deep-hover" style={{ height: '100%' }}>
|
||||
<h4 className="title is-4">Restful</h4>
|
||||
<p>Add a fully documented Restful API, simply by introspecting the schema.</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/graphql/introduction`}>
|
||||
<a className="box deep-hover" style={{ height: '100%' }}>
|
||||
<h4 className="title is-4">GraphQL</h4>
|
||||
<p>Extend your database with a fully functional GraphQL API, without a line of code.</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="section container m-b-lg">
|
||||
<a name="pricing" id="pricing" />
|
||||
<h3 className="title is-3 has-underline ">Launch</h3>
|
||||
<p className="subtitle">
|
||||
Whether you're a DB expert or just a beginner, Supabase makes it ridiculously easy to
|
||||
get started with PostgreSQL.
|
||||
</p>
|
||||
<div className="columns is-multiline">
|
||||
<div className="column is-4">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/packaged/introduction`}>
|
||||
<a className="box deep-hover" style={{ height: '100%' }}>
|
||||
<h4 className="title is-4">Packaged PostgreSQL</h4>
|
||||
<p>
|
||||
We've packaged PostgreSQL with a bunch of plugins and goodies that we think
|
||||
you'll like.
|
||||
</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/admin-api/introduction`}>
|
||||
<a className="box deep-hover" style={{ height: '100%' }}>
|
||||
<h4 className="title is-4">Admin API</h4>
|
||||
<p>Manage your PostgreSQL database with a well documented Restful API.</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="column is-4">
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/baseless/introduction`}>
|
||||
<a className="box deep-hover" style={{ height: '100%' }}>
|
||||
<h4 className="title is-4">Baseless</h4>
|
||||
<p>
|
||||
We're building a serverless PostgreSQL so you can get started in seconds. Export
|
||||
your database to a fully native PostgreSQL instance at any time.
|
||||
</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import MainLayout from '~/components/layouts/MainLayout'
|
||||
import Link from 'next/link'
|
||||
export default class Thanks extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<MainLayout>
|
||||
<div className="section container m-t-xxl m-b-xxl ">
|
||||
<div className="columns is-centered">
|
||||
<div className="column" style={{ maxWidth: 450 }}>
|
||||
<h1 className="title is-1">Thanks!</h1>
|
||||
<p className="subtitle">You're super early.</p>
|
||||
<p className="">We've put you on the early-bird list.</p>
|
||||
<p className="">
|
||||
If you're feeling really brave, why don't you check out our{' '}
|
||||
<Link href={`/docs/[category]/[slug]`} as={`/docs/-/about`}>
|
||||
<a className="">docs</a>
|
||||
</Link>{' '}
|
||||
and start using our free & opensource products?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
Note that including this file in DocsLayout.js (even with a CSS loader)
|
||||
seems to break the documentation links, but only in production.
|
||||
Steps to replicate:
|
||||
|
||||
- Uncomment the CSS loader from next.config.js
|
||||
- Add `import '~/styles/prism-tomorrow.css'` to DocsLayout.js
|
||||
- Run in dev: Go to homepage -> click on a links to the docs -> success
|
||||
- Deploy to Prod
|
||||
- Run in prod: Go to homepage -> click on a links to the docs -> location doesn't change
|
||||
*/
|
||||
|
||||
/**
|
||||
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
|
||||
* Based on https://github.com/chriskempson/tomorrow-theme
|
||||
* @author Rose Pritchard
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: #ccc;
|
||||
background: none;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #2d2d2d;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.block-comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.token.tag,
|
||||
.token.attr-name,
|
||||
.token.namespace,
|
||||
.token.deleted {
|
||||
color: #e2777a;
|
||||
}
|
||||
|
||||
.token.function-name {
|
||||
color: #6196cc;
|
||||
}
|
||||
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.function {
|
||||
color: #f08d49;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.class-name,
|
||||
.token.constant,
|
||||
.token.symbol {
|
||||
color: #f8c555;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.important,
|
||||
.token.atrule,
|
||||
.token.keyword,
|
||||
.token.builtin {
|
||||
color: #cc99cd;
|
||||
}
|
||||
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.attr-value,
|
||||
.token.regex,
|
||||
.token.variable {
|
||||
color: #7ec699;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url {
|
||||
color: #67cdcc;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: green;
|
||||
}
|
||||
@@ -1,360 +0,0 @@
|
||||
@charset "utf-8";
|
||||
@import url(https://cdn.rawgit.com/kiwicopple/quick-font/master/css/circular.css);
|
||||
@import url(https://use.fontawesome.com/releases/v5.6.3/css/all.css);
|
||||
|
||||
/// BULMA
|
||||
|
||||
// Set your brand colors
|
||||
// $green: #45d092;
|
||||
$green: #45d092;
|
||||
$blue: #0069ff;
|
||||
$yellow: #f8c945;
|
||||
$orange: #ec6e2d;
|
||||
$grey-900: #1f1f1f;
|
||||
$grey-800: #2a2a2a;
|
||||
$grey-700: #3b3b3b;
|
||||
$grey-600: #4c4c4c;
|
||||
$grey-500: #5e5e5e;
|
||||
$grey-400: #6f6f6f;
|
||||
$grey-300: #7f7f7f;
|
||||
$grey-200: #8f8f8f;
|
||||
$grey-100: #eeeeee;
|
||||
$background: $grey-900;
|
||||
$background: $grey-900;
|
||||
$border-color: $grey-400;
|
||||
$primary: $green;
|
||||
$link: $green;
|
||||
|
||||
$shadow: 0 0 5px 5px rgba(0, 0, 0, 0.3);
|
||||
$shadow-shallow: 0 0 3px 3px rgba(0, 0, 0, 0.2);
|
||||
$text-shallow: 0 0 3px rgba(0, 0, 0, 0.3);
|
||||
|
||||
// Typography
|
||||
$family-sans-serif: 'Circular', BlinkMacSystemFont, -apple-system, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Helvetica', 'Arial',
|
||||
sans-serif;
|
||||
$body-size: 0.9rem;
|
||||
|
||||
$text: $grey-100;
|
||||
$text-light: $grey-100;
|
||||
$text-strong: $grey-100;
|
||||
$title-color: $text;
|
||||
$subtitle-color: $text;
|
||||
$text-invert: $grey-900;
|
||||
|
||||
$link: $primary;
|
||||
$link-invert: $text;
|
||||
$link-hover: $text;
|
||||
$link-visited: $primary;
|
||||
// $link-hover-border: $grey-100;
|
||||
// $link-focus: $grey-100;
|
||||
// $link-focus-border: $grey-100;
|
||||
// $link-active: $grey-100;
|
||||
// $link-active-border: $grey-100;
|
||||
|
||||
// Navbar
|
||||
$navbar-background-color: $background;
|
||||
$navbar-item-color: $text;
|
||||
$navbar-item-hover-color: $primary;
|
||||
$navbar-item-hover-background-color: $background;
|
||||
$navbar-dropdown-background-color: $grey-800;
|
||||
$navbar-dropdown-item-hover-color: $primary;
|
||||
$navbar-dropdown-boxed-shadow: $shadow;
|
||||
$navbar-dropdown-arrow: $text;
|
||||
$navbar-divider-background-color: $border-color;
|
||||
|
||||
// Footer
|
||||
$footer-background-color: $background;
|
||||
|
||||
// Forms
|
||||
$input-background-color: $background;
|
||||
$input-color: $text;
|
||||
$input-border-color: $border-color;
|
||||
$label-color: $text;
|
||||
|
||||
// Buttons
|
||||
$button-color: $text;
|
||||
$button-background-color: $background;
|
||||
$button-border-color: $border-color;
|
||||
$button-hover-color: $text;
|
||||
|
||||
// Box
|
||||
$box-background-color: $grey-800;
|
||||
$box-color: #fff;
|
||||
$box-shadow: $shadow-shallow;
|
||||
|
||||
// Modal
|
||||
$modal-card-body-background-color: $background;
|
||||
$modal-card-title-color: $text;
|
||||
.modal-card-head,
|
||||
.modal-card-foot {
|
||||
background: $background !important;
|
||||
}
|
||||
|
||||
// Dropdown
|
||||
$dropdown-content-background-color: $grey-600;
|
||||
$dropdown-item-color: $text;
|
||||
$dropdown-item-hover-color: $text;
|
||||
$dropdown-item-active-color: $background;
|
||||
|
||||
// Menu
|
||||
$menu-item-hover-color: $primary;
|
||||
$menu-item-active-color: $text-invert;
|
||||
|
||||
// Menu
|
||||
$tabs-border-bottom-color: $border-color;
|
||||
$tabs-link-color: $grey-200;
|
||||
|
||||
// Import only what you need from Bulma
|
||||
@import '../node_modules/bulma/bulma.sass';
|
||||
|
||||
// SPACING CSS - see usage: https://github.com/jgthms/bulma/issues/451#issuecomment-331758839
|
||||
$sizeUnit: rem;
|
||||
$marginKey: 'm';
|
||||
$paddingKey: 'p';
|
||||
$separator: '-';
|
||||
$sizes: (
|
||||
('none', 0),
|
||||
('xxs', 0.125),
|
||||
('xs', 0.25),
|
||||
('sm', 0.5),
|
||||
('md', 1),
|
||||
('lg', 2),
|
||||
('xl', 4),
|
||||
('xxl', 8)
|
||||
);
|
||||
$positions: (('t', 'top'), ('r', 'right'), ('b', 'bottom'), ('l', 'left'));
|
||||
|
||||
@function sizeValue($key, $value) {
|
||||
@return if($key == 'none', 0, $value + $sizeUnit);
|
||||
}
|
||||
|
||||
@each $size in $sizes {
|
||||
$sizeKey: nth($size, 1);
|
||||
$sizeValue: nth($size, 2);
|
||||
.#{$marginKey}#{$separator}#{$sizeKey} {
|
||||
margin: sizeValue($sizeKey, $sizeValue) !important;
|
||||
}
|
||||
.#{$paddingKey}#{$separator}#{$sizeKey} {
|
||||
padding: sizeValue($sizeKey, $sizeValue) !important;
|
||||
}
|
||||
@each $position in $positions {
|
||||
$posKey: nth($position, 1);
|
||||
$posValue: nth($position, 2);
|
||||
.#{$marginKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} {
|
||||
margin-#{$posValue}: sizeValue($sizeKey, $sizeValue) !important;
|
||||
}
|
||||
.#{$paddingKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} {
|
||||
padding-#{$posValue}: sizeValue($sizeKey, $sizeValue) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
// end spacing
|
||||
|
||||
$widths: (
|
||||
('100', 100),
|
||||
('200', 200),
|
||||
('300', 300),
|
||||
('400', 400),
|
||||
('500', 500),
|
||||
('600', 600),
|
||||
('700', 700),
|
||||
('800', 800),
|
||||
('900', 900),
|
||||
('1000', 1000),
|
||||
('1100', 1100),
|
||||
('1200', 1200)
|
||||
);
|
||||
|
||||
@each $width in $widths {
|
||||
$widthKey: nth($width, 1);
|
||||
$widthValue: nth($width, 2);
|
||||
.w-#{$widthKey} {
|
||||
width: #{$widthValue}px !important;
|
||||
margin: 0 auto;
|
||||
}
|
||||
// Set max widths
|
||||
.w-m-#{$widthKey} {
|
||||
max-width: #{$widthValue}px !important;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Custom CSS
|
||||
//
|
||||
html,
|
||||
body {
|
||||
background: $background;
|
||||
color: $text;
|
||||
}
|
||||
::selection {
|
||||
background: $primary;
|
||||
color: $text-invert;
|
||||
}
|
||||
::-moz-selection {
|
||||
background: $primary;
|
||||
color: $text-invert;
|
||||
}
|
||||
hr {
|
||||
border: 1px solid $border-color;
|
||||
}
|
||||
|
||||
// Navbar
|
||||
.navbar-item {
|
||||
a {
|
||||
color: $text;
|
||||
&:hover {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 1023px) {
|
||||
.navbar {
|
||||
.section.container {
|
||||
padding: 00px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
box-shadow: inset 0px 5px 5px 0px rgba(0, 0, 0, 0.3);
|
||||
.heading {
|
||||
color: $grey-200;
|
||||
}
|
||||
a {
|
||||
color: $text;
|
||||
&:hover {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
.has-flex-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.has-flex-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.half-and-half {
|
||||
overflow: auto;
|
||||
div {
|
||||
width: 50% !important;
|
||||
float: left;
|
||||
}
|
||||
div:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
table tr th,
|
||||
p,
|
||||
strong {
|
||||
color: $text;
|
||||
}
|
||||
|
||||
a {
|
||||
box-shadow: inset 0 -3px 0 -1px $primary;
|
||||
transition: box-shadow 0.15s ease-in-out;
|
||||
color: $text;
|
||||
padding-bottom: 2px;
|
||||
&:hover {
|
||||
box-shadow: inset 0 -30px 0 -1px $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
hr.is-title-accent {
|
||||
margin-top: 5px;
|
||||
max-width: 100px;
|
||||
}
|
||||
h1.has-underline,
|
||||
h2.has-underline,
|
||||
h3.has-underline {
|
||||
&::after {
|
||||
content: '\2501';
|
||||
display: block;
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
.has-shadow {
|
||||
box-shadow: $shadow;
|
||||
}
|
||||
.has-border-primary {
|
||||
border: 1px solid $primary !important;
|
||||
}
|
||||
.DocsMenuColumn {
|
||||
border-right: 1px solid $border-color !important;
|
||||
}
|
||||
.docs-subnav {
|
||||
.menu-label {
|
||||
padding: 1rem 1rem 0 1rem;
|
||||
}
|
||||
.menu-list {
|
||||
li a {
|
||||
border-radius: 0;
|
||||
border-left: 3px solid $background;
|
||||
color: $grey-200;
|
||||
|
||||
&.is-active {
|
||||
background: none;
|
||||
color: $text;
|
||||
border-left: 3px solid $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.button {
|
||||
text-shadow: $text-shallow;
|
||||
font-weight: bold;
|
||||
&.is-primary {
|
||||
// color: $background;
|
||||
&.has-shadow {
|
||||
box-shadow: 1px 1px 5px 5px rgba($primary, 0);
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
&:hover {
|
||||
color: $background;
|
||||
box-shadow: 1px 1px 5px 5px rgba($primary, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.is-dark {
|
||||
color: $grey-200 !important;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
}
|
||||
pre {
|
||||
background: $grey-700;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 30px;
|
||||
padding: 0px;
|
||||
padding-left: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
code {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
white-space: pre;
|
||||
background: $grey-700;
|
||||
color: $text;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.has-overflow-scroll {
|
||||
overflow: auto;
|
||||
}
|
||||
.deep-hover {
|
||||
transition: all 0.2s ease;
|
||||
&:hover {
|
||||
box-shadow: 0 30px 60px 0 rgba(0, 0, 0, 0.5), 0 0 0 1px $primary !important;
|
||||
}
|
||||
}
|
||||
@media only screen and (min-width: 769px) {
|
||||
.reverse-row-order {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
build
|
||||
.docusaurus
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
# Supabase
|
||||
|
||||
Supabase Web
|
||||
Loaded 100 of 125 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user