Merge branch 'master' into fix-hard-coded-error

This commit is contained in:
Hieu Pham authored and GitHub committed 2022-01-12 14:24:41 +07:00
commit a6cf32c951
38 files changed
+1525 -609

No files matched your search

+7
View File
@@ -4,6 +4,7 @@
* [Installing Dependencies](#Installing-Dependencies)
* [Building Supabase](#Building-Supabase)
* [Start a Development Server](#Start-a-Development-Server)
* [Build in Public](#Build-in-Public)
## Development Setup
@@ -148,3 +149,9 @@ To debug code, and to see changes in real time, it is often useful to have a loc
```
For more information on Supabase Studio, see the [Supabase Studio readme](./studio/README.md).
## Build in Public
Videos of building supabase made in public.
- [Contributing to open source as a beginner - Supabase](https://youtu.be/OAqhsylUuWg) - [@imskr](https://github.com/imskr)
+61
View File
@@ -0,0 +1,61 @@
---
id: careers-developer-success
slug: developer-success
title: Developer Success Engineer
description: Supabase is hiring Developer Success Engineers
---
import Roles from '@site/docs/careers/snippets/roles.mdx'
import About from '@site/docs/careers/snippets/about.mdx'
import Team from '@site/docs/careers/snippets/team.mdx'
import Apply from '@site/docs/careers/snippets/apply.mdx'
import Process from '@site/docs/careers/snippets/process.mdx'
## About the role
Supabase is hiring Developer Success Engineers. Help us build the easiest database platform in the world.
### Responsibilities
- Focused on unblocking developers, backlog of issues.
- Priority focus on Enterprise customers.
- Help high-value customers with implementation and monitoring.
- Build internal tools for support team.
- Produce tests and documentation to mitigate recurring support tickets.
- Triage/clean/close issues on any of our repos.
- Work with the community on all of our channels: GitHub, Discord, and Email.
## About you
- 2+ years experience in engineering or a highly technical support role.
- You must love remote work.
- You possess exceptional communication skills.
- Availability to work within a weekend and on-call rota.
## Bonus if you:
- Are a Polyglot developer, with some skill in NodeJS/Javascript.
- Have PostgreSQL experience.
## About Supabase
<About />{' '}
## About the team
<Team />{' '}
## Apply
<Apply />{' '}
## Process
<Process />{' '}
## All roles
<Roles />{' '}
+67
View File
@@ -0,0 +1,67 @@
---
id: careers-growth-marketer
slug: growth-marketer
title: Growth Marketer.
description: Supabase is hiring a Growth Marketer
---
import Roles from '@site/docs/careers/snippets/roles.mdx'
import About from '@site/docs/careers/snippets/about.mdx'
import Team from '@site/docs/careers/snippets/team.mdx'
import Apply from '@site/docs/careers/snippets/apply.mdx'
import Process from '@site/docs/careers/snippets/process.mdx'
## About the role
Supabase is looking for a growth marketer to help continue to raise awareness of Supabase within the developer community. This role will require working across the entire customer lifecycle helping shape programs that drive awareness, activation, engagement, and expansion. In this role you will play a key role in establishing and operating the marketing and growth strategies for supabase by working cross-functionally with our engineering and growth teams to ensure we have the best possible marketing strategy and execution.
The ideal candidate has experience helping grow products which enable developers. You should be both strategic and highly execution focussed.
**Some of the things you will be doing:**
- Planning and executing the Supabase marketing strategy
- Designing and executing on industry specific marketing campaigns
- Help promote and amplify all things Supabase: events, hackathons, our DevRel team profiles, launch week
- Outbound to co-ordinate and schedule events & conferences that we can participate in
- Outbound to find channels for content distribution (written, video, podcasts, interviews etc)
- Outbound to find partnership opportunities with code schools & 3rd parties for content co-creation
- Understand whats driving our user acquisition funnel and assets required to increase activation
- Monitor and measure our entire portfolio of assets and communicating the results of our marketing efforts internally so we understand what is most effective
- Create enterprise grade marketing materials that we can start to distribute from our own website and across other channels such as LinkedIn and DZone
- Find interesting case study opportunities and help turn them into content we can distribute across different segments
- Liaise and work with our incredible DevRel team to help them identify opportunities and amplify their efforts
- work with our amazing team of community writers to help find topics to write about
- Scope out and action our SEO strategy
- Help running email campaigns
- Community management
## Skills and Experience
- Building marketing funnels and running outbound campaigns
- Creating and managing social media campaigns
- Marketing to software developers & developer tooling space
- Marketing collateral aimed at enterprise and cloud native customers
- Metrics driven & an experimental mindset
- Marketing automation and CRM tools
- Experience with analytics platforms
- SEO experience
## About Supabase
<About />{' '}
## About the team
<Team />{' '}
## Apply
<Apply />{' '}
## Process
<Process />{' '}
## All roles
<Roles />{' '}
+21
View File
@@ -13,6 +13,13 @@
</div>
</a>
<a className="card" href="/careers/growth-marketer" style={{marginBottom: 10}}>
<div className="card__body">
<h3>Growth Marketer</h3>
<p>Get our tools in front of the next billion developers.</p>
</div>
</a>
<a className="card" href="/careers/auth-engineers" style={{marginBottom: 10}}>
<div className="card__body">
<h3>Auth Engineers</h3>
@@ -60,4 +67,18 @@
<h3>Full-stack Engineers</h3>
<p>Build our Dashboard, tools, and tests.</p>
</div>
</a>
<a className="card" href="/careers/technical-recruiter" style={{marginBottom: 10}}>
<div className="card__body">
<h3>Technical recruiter</h3>
<p>Take the lead on our technical recruitment.</p>
</div>
</a>
<a className="card" href="/careers/developer-success" style={{marginBottom: 10}}>
<div className="card__body">
<h3>Developer Success Engineer</h3>
<p>Build the easiest database platform in the world.</p>
</div>
</a>
@@ -0,0 +1,60 @@
---
id: careers-technical-recruiter
slug: technical-recruiter
title: Technical Recruiter
description: Supabase is hiring Technical Recruiters
---
import Roles from '@site/docs/careers/snippets/roles.mdx'
import About from '@site/docs/careers/snippets/about.mdx'
import Team from '@site/docs/careers/snippets/team.mdx'
import Apply from '@site/docs/careers/snippets/apply.mdx'
import Process from '@site/docs/careers/snippets/process.mdx'
## About the role
#### Key Responsibilities:
- Be accountable for implementing inclusive recruiting practices and finding ways to engage more under-represented talent for technical roles
- Ability to understand and communicate the business' current technical challenges to entice candidates who are driven by solving interesting problems
- Accountable to starting a candidate search project from scratch through requirement gathering, job posting, sourcing, networking, previous applicants follow-ups etc
#### Requirements:
- Minimum 2+ years technical recruiting experience across the full hiring process from sourcing to the offer stage
- Technical knowledge of different coding languages/technical stacks/terminology
- You have expertise in filling Engineering, Infrastructure, Data Science, and other technical roles.
- Self motivated Technical Recruiter that enjoys working in a fun, fast paced environment!
- A solid understanding of what makes a great candidate experience
- You enjoy reaching out to others and learning what drives them in their career
- You are not afraid to own all parts of an operation in a remote setting
- Ability to communicate effectively and effortlessly with candidates and internal stakeholders of all career levels
- Excellent interpersonal skills, resourcefulness, and follow-up
#### Candidate Nice to Haves
- A continuous improvement mindset with an iterative approach to making things better. Whether it's your interview technique, pipeline optimization or anything else that you discover.
- Fluency with Greenhouse or other Applicant Tracking Systems, as well as various sourcing platforms (e.g., LinkedIn, Github, Work at a Startup, etc)
- You're Comfortable coordinating all candidate touch points
- You can plan out batch days & other projects to drive excellence for our candidate experience and quality of interviews
## About Supabase
<About />{' '}
## About the team
<Team />{' '}
## Apply
<Apply />{' '}
## Process
<Process />{' '}
## All roles
<Roles />{' '}
+484 -302
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -10,7 +10,7 @@
"@docusaurus/core": "^2.0.0-alpha.63",
"@docusaurus/preset-classic": "^2.0.0-alpha.63",
"@kiwicopple/prism-react-renderer": "github:kiwicopple/prism-react-renderer",
"mermaid": "^8.6.4",
"mermaid": "^8.13.8",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-inlinesvg": "^2.0.1"
+2 -2
View File
@@ -3,8 +3,8 @@
POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password
JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long
ANON_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYyNzIwODU0MCwiZXhwIjoxOTc0MzYzNzQwfQ.zcaQfHd3VA7XgJmdGfmV86OLVJT9s2MTmSy-e69BpUY
SERVICE_ROLE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaWF0IjoxNjI3MjA4NTQwLCJleHAiOjE5NzQzNjM3NDB9.pkT3PNpO4DtO45Ac5HK_TKCx8sGLgNtV__pr_ZrRSAU
ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q
# Auth
+1 -1
View File
@@ -80,7 +80,7 @@ services:
restart: unless-stopped
environment:
PGRST_DB_URI: postgres://postgres:${POSTGRES_PASSWORD}@db:5432/postgres
PGRST_DB_SCHEMA: public,storage
PGRST_DB_SCHEMAS: public,storage
PGRST_DB_ANON_ROLE: anon
PGRST_JWT_SECRET: ${JWT_SECRET}
PGRST_DB_USE_LEGACY_GUCS: "false"
+2 -2
View File
@@ -6,10 +6,10 @@ _format_version: "1.1"
consumers:
- username: anon
keyauth_credentials:
- key: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYyNzIwODU0MCwiZXhwIjoxOTc0MzYzNzQwfQ.zcaQfHd3VA7XgJmdGfmV86OLVJT9s2MTmSy-e69BpUY
- key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
- username: service_role
keyauth_credentials:
- key: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaWF0IjoxNjI3MjA4NTQwLCJleHAiOjE5NzQzNjM3NDB9.pkT3PNpO4DtO45Ac5HK_TKCx8sGLgNtV__pr_ZrRSAU
- key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q
###
### Access Control List
+3 -2
View File
@@ -3,5 +3,6 @@ POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password
SUPABASE_URL=http://localhost:8000
SUPABASE_REST_URL=http://localhost:8000/rest/v1/
SUPABASE_ANON_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYyNzIwODU0MCwiZXhwIjoxOTc0MzYzNzQwfQ.zcaQfHd3VA7XgJmdGfmV86OLVJT9s2MTmSy-e69BpUY
SUPABASE_SERVICE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaWF0IjoxNjI3MjA4NTQwLCJleHAiOjE5NzQzNjM3NDB9.pkT3PNpO4DtO45Ac5HK_TKCx8sGLgNtV__pr_ZrRSAU
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q
@@ -100,42 +100,44 @@ const LogPanel: FC<Props> = ({
</div>
<div className="flex items-center gap-x-4">
{/* wrap with form so that if user presses enter, the search value will submit automatically */}
<form
id="log-panel-search"
onSubmit={(e) => {
// prevent redirection
e.preventDefault()
onSearch(search)
}}
>
<Input
size="tiny"
icon={<IconSearch size={16} />}
placeholder="Search events"
onChange={(e) => setSearch(e.target.value)}
value={search}
actions={[
search && (
<IconX
key="clear-search"
{!isCustomQuery && (
<form
id="log-panel-search"
onSubmit={(e) => {
// prevent redirection
e.preventDefault()
onSearch(search)
}}
>
<Input
size="tiny"
icon={<IconSearch size={16} />}
placeholder="Search events"
onChange={(e) => setSearch(e.target.value)}
value={search}
actions={[
search && (
<IconX
key="clear-search"
size="tiny"
className="cursor-pointer mx-1"
title="Clear search"
onClick={() => setSearch('')}
/>
),
<Button
key="go"
size="tiny"
className="cursor-pointer mx-1"
title="Clear search"
onClick={() => setSearch('')}
/>
),
<Button
key="go"
size="tiny"
title="Go"
type="secondary"
onClick={() => onSearch(search)}
>
Go
</Button>,
]}
/>
</form>
title="Go"
type="secondary"
onClick={() => onSearch(search)}
>
Go
</Button>,
]}
/>
</form>
)}
</div>
</div>
</div>
@@ -7,6 +7,7 @@ import {
Popover,
Typography,
} from '@supabase/ui'
import { useRouter } from 'next/router'
import { FC } from 'react'
import Link from 'next/link'
import Image from 'next/image'
@@ -16,6 +17,10 @@ import SVG from 'react-inlinesvg'
interface Props {}
const HelpPopover: FC<Props> = () => {
const router = useRouter()
const projectRef = router.query.ref
const supportUrl = `/support/new${projectRef ? `?ref=${projectRef}` : ''}`
return (
<Popover
className="w-80"
@@ -34,7 +39,7 @@ const HelpPopover: FC<Props> = () => {
hosted services.
</p>
</Typography.Text>
<Link href="/support/new">
<Link href={supportUrl}>
<Button className="sbui-default-button--dark-white" icon={<IconMail />}>
Contact support team
</Button>
@@ -16,7 +16,7 @@ export async function fetchVercelProjects({
url = `${url}?${query}`
}
const response = await get(url, {
headers: { Authorization: `Bearer ${vercelToken}` },
headers: { vercel_authorization: `Bearer ${vercelToken}` },
})
if (response.error != null) {
return { error: `Retrieve vercel projects failed. ${response.error?.message}` }
@@ -48,7 +48,7 @@ export async function fetchVercelProject({
url = `${url}?${query}`
}
const data = await get(url, {
headers: { Authorization: `Bearer ${vercelToken}` },
headers: { vercel_authorization: `Bearer ${vercelToken}` },
})
if (data.error != null) {
return { error: `Retrieve vercel project failed. ${data.error.message}` }
@@ -74,7 +74,7 @@ export async function fetchVercelProjectEnvs({
url = `${url}?${query}`
}
const response = await get(url, {
headers: { Authorization: `Bearer ${vercelToken}` },
headers: { vercel_authorization: `Bearer ${vercelToken}` },
})
if (response.error != null) {
return { error: `Retrieve vercel project envs failed. ${response.error?.message}` }
@@ -114,7 +114,7 @@ export async function createVercelEnv({
url,
{ key, value, type, target },
{
headers: { Authorization: `Bearer ${vercelToken}` },
headers: { vercel_authorization: `Bearer ${vercelToken}` },
}
)
}
+1 -1
View File
@@ -83,7 +83,7 @@ function checkRedirectTo(
redirectIfFound?: boolean
) {
if (loading) return false
if (router.asPath == redirectTo) return false
if (router.pathname == redirectTo) return false
// If redirectTo is set, redirect if the user was not found.
if (redirectTo && !redirectIfFound && !profile) return true
+42 -2
View File
@@ -1,6 +1,6 @@
import React from 'react'
import { observer } from 'mobx-react-lite'
import { IconMoon, IconSun, Select, Typography } from '@supabase/ui'
import { IconMoon, IconSun, Select, Typography, Input } from '@supabase/ui'
import { useProfile, useStore, withAuth } from 'hooks'
import { post } from 'lib/common/fetch'
@@ -32,8 +32,10 @@ export default withAuth(User)
const ProfileCard = observer(() => {
const { ui } = useStore()
const { mutateProfile } = useProfile()
const user = ui.profile
console.log('User', user?.username, user?.primary_email)
const updateUser = async (model: any) => {
try {
const updatedUser = await post(`${API_URL}/profile/update`, model)
@@ -51,6 +53,9 @@ const ProfileCard = observer(() => {
return (
<article className="p-4 max-w-4xl">
<section>
<GithubProfile />
</section>
<section className="">
{/* @ts-ignore */}
<SchemaFormPanel
@@ -77,6 +82,41 @@ const ProfileCard = observer(() => {
)
})
const GithubProfile = observer(() => {
const { ui } = useStore()
return (
<Panel
title={[
<Typography.Title key="panel-title" level={5} className="mb-0">
Account Information
</Typography.Title>,
]}
>
<Panel.Content>
<div className="space-y-2">
<Input
readOnly
disabled
label="Username"
layout="horizontal"
value=""
placeholder={ui.profile?.username ?? ''}
/>
<Input
readOnly
disabled
label="Email"
layout="horizontal"
value=""
placeholder={ui.profile?.primary_email ?? ''}
/>
</div>
</Panel.Content>
</Panel>
)
})
const ThemeSettings = observer(() => {
const { ui } = useStore()
+48 -4
View File
@@ -1,19 +1,21 @@
import { NextPage } from 'next'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { NextRouter, useRouter } from 'next/router'
import { isUndefined } from 'lodash'
import { Typography } from '@supabase/ui'
import { Project } from 'types'
import { useProfile, useStore, withAuth } from 'hooks'
import { post, delete_ } from 'lib/common/fetch'
import { API_URL, IS_PLATFORM, PROJECT_STATUS, STRIPE_PRODUCT_IDS } from 'lib/constants'
import { API_URL, IS_PLATFORM, PROJECT_STATUS } from 'lib/constants'
import { AccountLayout } from 'components/layouts'
import { auth } from 'lib/gotrue'
import Landing from 'components/interfaces/Home/Landing'
import ProjectList from 'components/interfaces/Home/ProjectList'
import OrganizationDropdown from 'components/to-be-cleaned/Dropdown/OrganizationDropdown'
import TextConfirmModal from 'components/to-be-cleaned/ModalsDeprecated/TextConfirmModal'
import Connecting from 'components/ui/Loading'
const Home: NextPage = () => {
const { app, ui } = useStore()
@@ -26,7 +28,23 @@ const Home: NextPage = () => {
const [selectedProjectToDelete, setSelectedProjectToDelete] = useState<Project>()
if (!profile) {
return <Landing />
return <UnauthorizedLanding />
} else {
const isRedirect = isRedirectFromThirdPartyService(router)
if (isRedirect) {
const queryParams = (router.query as any) || {}
const params = new URLSearchParams(queryParams)
if (router.query?.next?.includes('https://vercel.com')) {
router.push(`/vercel/integrate?${params.toString()}`)
}
if (router.query?.next?.includes('new-project')) {
router.push('/new/project')
}
if (router.query['x-amzn-marketplace-token'] != undefined) {
router.push(`/account/associate?${params.toString()}`)
}
return <Connecting />
}
}
const onSelectDeleteProject = async (project: Project) => {
@@ -103,3 +121,29 @@ const Home: NextPage = () => {
)
}
export default withAuth(observer(Home))
// detect for redirect from 3rd party service like vercel, aws...
function isRedirectFromThirdPartyService(router: NextRouter) {
return router.query.next !== undefined || router.query['x-amzn-marketplace-token'] !== undefined
}
const UnauthorizedLanding = () => {
const router = useRouter()
const autoLogin = isRedirectFromThirdPartyService(router)
useEffect(() => {
if (autoLogin) {
const queryParams = (router.query as any) || {}
const params = new URLSearchParams(queryParams)
// trigger github signIn
auth.signIn(
{ provider: 'github' },
{
redirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}?${params.toString()}`,
}
)
}
}, [])
return autoLogin ? <Connecting /> : <Landing />
}
+5 -7
View File
@@ -1,7 +1,7 @@
import { useState } from 'react'
import { observer } from 'mobx-react-lite'
import { Button, Typography } from '@supabase/ui'
import Router from 'next/router'
import { useRouter } from 'next/router'
import { API_URL } from 'lib/constants'
import { useStore, withAuth } from 'hooks'
@@ -15,6 +15,8 @@ import Panel from 'components/to-be-cleaned/Panel'
*/
const Wizard = () => {
const { ui, app } = useStore()
const router = useRouter()
const [orgName, setOrgName] = useState('')
const [newOrgLoading, setNewOrgLoading] = useState(false)
@@ -49,11 +51,7 @@ const Wizard = () => {
} else {
const org = response
app.onOrgAdded(org)
// Router.push('/new/[slug]', `/new/${org.slug}`)
// Using window.location.href for now as organization metadata needs to refresh
// We do not get is_owner nor stripe_customer_id from the response here
window.location.href = `/new/${org.slug}`
router.push(`/new/${org.slug}`)
}
}
@@ -70,7 +68,7 @@ const Wizard = () => {
]}
footer={[
<div key="panel-footer" className="flex items-center w-full justify-between">
<Button type="default" onClick={() => Router.push('/')}>
<Button type="default" onClick={() => router.push('/')}>
Cancel
</Button>
<div className="space-x-3">
+8 -3
View File
@@ -198,6 +198,8 @@ const Settings = () => {
className="mb-4"
label={authConfig.properties.MAILER_AUTOCONFIRM.title}
onChange={(value) => {
// If MAILER_AUTOCONFIRM is set to true, it means we are disabling email confirmations.
// "Enable email confirmations" should be toggled off.
handleToggle('MAILER_AUTOCONFIRM', !value)
}}
checked={!model.MAILER_AUTOCONFIRM}
@@ -335,10 +337,13 @@ const Settings = () => {
<UIToggle
layout="horizontal"
label={authConfig.properties.SMS_AUTOCONFIRM.title}
onChange={() => {
handleToggle('SMS_AUTOCONFIRM')
onChange={(value) => {
// If SMS_AUTOCONFIRM is set to true, it means we are disabling phone confirmations.
// "Enable phone confirmations" should be toggled off.
handleToggle('SMS_AUTOCONFIRM', !value)
}}
checked={model.SMS_AUTOCONFIRM}
//
checked={!model.SMS_AUTOCONFIRM}
descriptionText={authConfig.properties.SMS_AUTOCONFIRM.help}
/>
</>
@@ -188,6 +188,7 @@ const ResetDbPassword: FC<any> = () => {
} else {
ui.setNotification({ category: 'error', message: 'Failed to reset password' })
}
setIsUpdatingPassword(false)
}
}
@@ -279,9 +280,6 @@ const DownloadCertificate: FC<any> = ({ createdAt }) => {
}
const GeneralSettings: FC<any> = ({ projectRef }) => {
const { ui } = useStore()
const isOwner = ui.selectedOrganization?.is_owner
const { data, error }: any = useSWR(`${API_URL}/props/project/${projectRef}/settings`, get)
if (data?.error || error) {
@@ -378,7 +376,7 @@ const GeneralSettings: FC<any> = ({ projectRef }) => {
</Panel.Content>
</Panel>
</section>
{isOwner && <ResetDbPassword />}
<ResetDbPassword />
<DownloadCertificate createdAt={connectionInfo.inserted_at} />
</div>
<div>
@@ -3,7 +3,15 @@ import React, { useEffect, useRef, useState } from 'react'
import { NextPage } from 'next'
import { useRouter } from 'next/router'
import { observer } from 'mobx-react-lite'
import { Typography, IconLoader, IconAlertCircle, IconRewind, Button, IconInfo } from '@supabase/ui'
import {
Typography,
IconLoader,
IconAlertCircle,
IconRewind,
Button,
IconInfo,
Card,
} from '@supabase/ui'
import { withAuth } from 'hooks'
import { get } from 'lib/common/fetch'
@@ -72,6 +80,9 @@ export const LogPage: NextPage = () => {
if (prevPageData === null) {
// reduce interval window limit by using the timestamp of the last log
queryParams = genQueryParams(params)
} else if (prevPageData.data.length === 0) {
// no rows returned, indicates that no more data to retrieve and append.
return null
} else {
const len = prevPageData.data.length
const { timestamp: tsLimit }: LogData = prevPageData.data[len - 1]
@@ -84,18 +95,16 @@ export const LogPage: NextPage = () => {
}
const {
data = [],
error: swrError,
isValidating,
mutate,
size,
setSize,
} = useSWRInfinite<Logs>(getKeyLogs, get, { revalidateOnFocus: false })
// const { data, isValidating, mutate } = useSWR<Logs>(logUrl, get, { revalidateOnFocus: false })
let logData: LogData[] = []
let error: null | string = null
let error: null | string = swrError ? swrError.message : null
data.forEach((response: Logs) => {
if (response && response.data) {
if (!error && response && response.data) {
logData = [...logData, ...response.data]
}
if (!error && response && response.error) {
@@ -145,10 +154,12 @@ export const LogPage: NextPage = () => {
...prev,
where: isSelectQuery ? '' : editorValue,
sql: isSelectQuery ? editorValue : '',
search_query: ''
}))
}
const handleSearch = (v: string) => {
setParams((prev) => ({ ...prev, search_query: v || '' }))
setParams((prev) => ({ ...prev, search_query: v || '', where: '', sql: '' }))
setEditorValue('')
}
return (
@@ -220,9 +231,16 @@ export const LogPage: NextPage = () => {
</div>
)}
{error && (
<div className="flex w-full h-full justify-center items-center space-x-2 mx-auto">
<IconAlertCircle size={16} />
<Typography.Text type="secondary">Sorry! Could not fetch data</Typography.Text>
<div className="flex w-full h-full justify-center items-center mx-auto">
<Card className="flex flex-col gap-y-2">
<div className="flex flex-row gap-x-2 py-2">
<IconAlertCircle size={16} />
<Typography.Text type="secondary">
Sorry! An error occured when fetching data.
</Typography.Text>
</div>
<Typography.Text type="warning">{error}</Typography.Text>
</Card>
</div>
)}
<LogTable data={logData} isCustomQuery={mode === 'custom'} />
+11 -1
View File
@@ -12,11 +12,13 @@ import {
} from '@supabase/ui'
import SVG from 'react-inlinesvg'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { API_URL } from 'lib/constants'
import { useStore, withAuth } from 'hooks'
import { post } from 'lib/common/fetch'
import { Project } from 'types'
import { isUndefined } from 'lodash'
const DEFAULT = {
category: {
@@ -49,6 +51,9 @@ function formReducer(state: any, action: any) {
const SupportNew = () => {
const { ui, app } = useStore()
const router = useRouter()
const projectRef = router.query.ref
const [formState, formDispatch] = useReducer(formReducer, DEFAULT)
const [errors, setErrors] = useState<any>([])
const [loading, setLoading] = useState<boolean>(false)
@@ -72,7 +77,12 @@ const SupportNew = () => {
useEffect(() => {
// set project default
if (sortedProjects.length > 1) {
handleOnChange({ name: 'project', value: sortedProjects[0].ref })
const selectedProject = sortedProjects.find((project: Project) => project.ref === projectRef)
if (!isUndefined(selectedProject)) {
handleOnChange({ name: 'project', value: selectedProject.ref })
} else {
handleOnChange({ name: 'project', value: sortedProjects[0].ref })
}
} else {
// set as 'No specific project'
handleOnChange({ name: 'project', value: projectDefaults[0].ref })
+1 -1
View File
@@ -226,7 +226,7 @@ const Connecting = () => (
const ProjectLinksEmptyState = () => (
<div className="flex flex-col space-y-4">
<Typography.Text>
You haven’t created a Supabase project yet. Get started by creating a new Supabase project,
You haven't created a Supabase project yet. Get started by creating a new Supabase project,
then close this window and retry adding integration.
</Typography.Text>
<Typography.Link href="https://app.supabase.io">
+11 -7
View File
@@ -1,6 +1,6 @@
import { cloneDeep } from 'lodash'
import { values } from 'mobx'
import { Project } from 'types'
import { Organization, Project } from 'types'
import { API_URL, STRIPE_PRODUCT_IDS } from 'lib/constants'
import { IRootStore } from '../RootStore'
@@ -71,19 +71,23 @@ export default class AppStore implements IAppStore {
}
}
onOrgUpdated(org: any) {
if (org && org.id) {
this.organizations.data[org.id] = { ...org }
onOrgUpdated(updatedOrg: Organization) {
if (updatedOrg && updatedOrg.id) {
const originalOrg = this.organizations.data[updatedOrg.id]
this.organizations.data[updatedOrg.id] = {
...originalOrg,
...updatedOrg,
}
}
}
onOrgAdded(org: any) {
onOrgAdded(org: Organization) {
if (org && org.id) {
this.organizations.data[org.id] = { ...org }
this.organizations.data[org.id] = org
}
}
onOrgDeleted(org: any) {
onOrgDeleted(org: Organization) {
if (org && org.id) {
const projects = values(this.projects.data)
// cleanup projects saved queries
+6 -1
View File
@@ -17,7 +17,12 @@ test('templates', async () => {
// userEvent.click(screen.getByText("Some option"))
// expect(mockFn).toBeCalled()
})
test('custom mode', async () => {
render(<LogPanel isCustomQuery />)
await waitFor(() => {
expect(() => screen.getByPlaceholderText(/Search/)).toThrow()
})
})
test('filter input change and submit', async () => {
const mockFn = jest.fn()
render(<LogPanel onSearch={mockFn} />)
+40 -2
View File
@@ -42,15 +42,21 @@ LogPage.mockImplementation((props) => {
const Page = jest.requireActual('pages/project/[ref]/settings/logs/[type]').LogPage
// wrap with SWR to reset the cache each time
return (
<SWRConfig value={{ provider: () => new Map() }}>
<SWRConfig
value={{
provider: () => new Map(),
shouldRetryOnError: false,
}}
>
<Page {...props} />
</SWRConfig>
)
})
import { render, fireEvent, waitFor, screen } from '@testing-library/react'
import { render, fireEvent, waitFor, screen, act } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { getToggleByText } from '../../helpers'
import { wait } from '@testing-library/user-event/dist/utils'
beforeEach(() => {
// reset mocks between tests
@@ -181,6 +187,12 @@ test('where clause will trigger a log refresh', async () => {
return { data: [] }
})
const { container } = render(<LogPage />)
// fill search bar with some value, should be ignored when in custom mode
userEvent.type(screen.getByPlaceholderText(/Search/), 'search_value')
userEvent.click(screen.getByText('Go'))
// clear mock calls, for clean assertions
get.mockClear()
let editor = container.querySelector('.monaco-editor')
expect(editor).toBeFalsy()
// TODO: abstract this out into a toggle selection helper
@@ -198,6 +210,8 @@ test('where clause will trigger a log refresh', async () => {
() => {
expect(get).toHaveBeenCalledWith(expect.stringContaining('where'))
expect(get).toHaveBeenCalledWith(expect.stringContaining('metadata.field'))
// should ignore search bar value
expect(get).not.toHaveBeenCalledWith(expect.stringContaining('search_value'))
},
{ timeout: 1000 }
)
@@ -298,3 +312,27 @@ test('load older btn will fetch older logs', async () => {
})
await waitFor(() => screen.getByText('second event'))
})
test('bug: load older btn does not error out when previous page is empty', async () => {
// bugfix for https://sentry.io/organizations/supabase/issues/2903331460/?project=5459134&referrer=slack
get.mockImplementation((url) => {
if (url.includes('count')) {
return {}
}
return { data: [] }
})
render(<LogPage />)
userEvent.click(screen.getByText('Load older'))
// NOTE: potential race condition, since we are asserting that something DOES NOT EXIST
// wait for 500s to make sure all ui logic is complete
// need to wrap in act because internal react state is changing during this time.
await act(async () => await wait(100))
// clicking load older multiple times should not give error
await waitFor(() => {
expect(screen.queryByText(/Sorry/)).toBeNull()
expect(screen.queryByText(/An error occured/)).toBeNull()
expect(screen.queryByText(/undefined/)).toBeNull()
})
})
+6 -2
View File
@@ -4,9 +4,13 @@ export interface Organization {
name: string
billing_email: string
project_limit: number
stripe_customer_id?: string
total_free_projects?: number
members: any[]
projects: any[]
is_owner?: boolean
stripe_customer_id?: string
stripe_customer_object?: any
total_free_projects?: number
total_paid_projects?: number
}
export interface Project {
+2 -2
View File
@@ -1,5 +1,5 @@
process.env.SUPABASE_URL = 'http://localhost:8000'
process.env.SUPABASE_KEY_ANON =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYyNzIwODU0MCwiZXhwIjoxOTc0MzYzNzQwfQ.zcaQfHd3VA7XgJmdGfmV86OLVJT9s2MTmSy-e69BpUY'
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE'
process.env.SUPABASE_KEY_ADMIN =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaWF0IjoxNjI3MjA4NTQwLCJleHAiOjE5NzQzNjM3NDB9.pkT3PNpO4DtO45Ac5HK_TKCx8sGLgNtV__pr_ZrRSAU'
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q'
+1 -3
View File
@@ -133,9 +133,7 @@ Migrating projects can be achieved using standard PostgreSQL tooling. This is pa
When you create a new project in Supabase we ask for a password. You can use this password to connect directly to your Postgres database.
If you forget your password, you can reset it from the Dashboard SQL editor:
For example:
If you forget your password, you can reset it from the Dashboard under the database settings page, or through the SQL editor as such:
```sql
alter user postgres
+4 -4
View File
@@ -133,7 +133,7 @@ Restart your Next.js development server to read in the new values from `.env.loc
npm run dev
```
## Step 5: Install Auth0 Next.js library
## Step 6: Install Auth0 Next.js library
Install the `@auth0/nextjs-auth0` library.
@@ -211,7 +211,7 @@ You should now be able to view the landing page.
![Landing page](/img/guides/integrations/auth0/YdBKRy6.png)
## Step 6: Sign Auth0 token for Supabase
## Step 7: Sign Auth0 token for Supabase
Currently, neither Supabase or Auth0 allow for a custom signing secret to be set for their JWT. They also use different [signing algorithms](https://auth0.com/docs/configure/applications/signing-algorithms).
@@ -263,7 +263,7 @@ We are signing this JWT using Supabase's signing secret, so Supabase will be abl
Now we just need to send the token along with the request to Supabase.
## Step 7: Requesting data from Supabase
## Step 8: Requesting data from Supabase
Create a new file called `utils/supabase.js` and add the following:
@@ -391,7 +391,7 @@ Either way, when we reload our application, we are still getting the empty state
This is because we enabled Row Level Security, which blocks all requests by default. To enable our user to select their `todos` we need to write a policy.
## Step 8: Write a policy to allow select
## Step 9: Write a policy to allow select
Our policy will need to know who our currently logged in user is to determine whether or not they should have access. Let's create a PostgreSQL function to extract the current user from our new JWT.
+471 -175
View File
@@ -3929,72 +3929,73 @@
}
},
"d3": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz",
"integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/d3/-/d3-7.2.1.tgz",
"integrity": "sha512-E/5sP0aeK6YPXI/+4QlefvBFgmcyR2jYftId0PrYWv4Y/gW3c3thp1XG4rQzF0eUwV9tR1x05X5eWuJ6rQXvew==",
"requires": {
"d3-array": "1",
"d3-axis": "1",
"d3-brush": "1",
"d3-chord": "1",
"d3-collection": "1",
"d3-color": "1",
"d3-contour": "1",
"d3-dispatch": "1",
"d3-drag": "1",
"d3-dsv": "1",
"d3-ease": "1",
"d3-fetch": "1",
"d3-force": "1",
"d3-format": "1",
"d3-geo": "1",
"d3-hierarchy": "1",
"d3-interpolate": "1",
"d3-path": "1",
"d3-polygon": "1",
"d3-quadtree": "1",
"d3-random": "1",
"d3-scale": "2",
"d3-scale-chromatic": "1",
"d3-selection": "1",
"d3-shape": "1",
"d3-time": "1",
"d3-time-format": "2",
"d3-timer": "1",
"d3-transition": "1",
"d3-voronoi": "1",
"d3-zoom": "1"
"d3-array": "3",
"d3-axis": "3",
"d3-brush": "3",
"d3-chord": "3",
"d3-color": "3",
"d3-contour": "3",
"d3-delaunay": "6",
"d3-dispatch": "3",
"d3-drag": "3",
"d3-dsv": "3",
"d3-ease": "3",
"d3-fetch": "3",
"d3-force": "3",
"d3-format": "3",
"d3-geo": "3",
"d3-hierarchy": "3",
"d3-interpolate": "3",
"d3-path": "3",
"d3-polygon": "3",
"d3-quadtree": "3",
"d3-random": "3",
"d3-scale": "4",
"d3-scale-chromatic": "3",
"d3-selection": "3",
"d3-shape": "3",
"d3-time": "3",
"d3-time-format": "4",
"d3-timer": "3",
"d3-transition": "3",
"d3-zoom": "3"
}
},
"d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.1.1.tgz",
"integrity": "sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ==",
"requires": {
"internmap": "1 - 2"
}
},
"d3-axis": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz",
"integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
"integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="
},
"d3-brush": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz",
"integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
"integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
"d3-dispatch": "1 - 3",
"d3-drag": "2 - 3",
"d3-interpolate": "1 - 3",
"d3-selection": "3",
"d3-transition": "3"
}
},
"d3-chord": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz",
"integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
"integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
"requires": {
"d3-array": "1",
"d3-path": "1"
"d3-path": "1 - 3"
}
},
"d3-collection": {
@@ -4003,183 +4004,199 @@
"integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A=="
},
"d3-color": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.0.1.tgz",
"integrity": "sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw=="
},
"d3-contour": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz",
"integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-3.0.1.tgz",
"integrity": "sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ==",
"requires": {
"d3-array": "^1.1.1"
"d3-array": "2 - 3"
}
},
"d3-delaunay": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz",
"integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==",
"requires": {
"delaunator": "5"
}
},
"d3-dispatch": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
"integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="
},
"d3-drag": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz",
"integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
"integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
"requires": {
"d3-dispatch": "1",
"d3-selection": "1"
"d3-dispatch": "1 - 3",
"d3-selection": "3"
}
},
"d3-dsv": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz",
"integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
"integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
"requires": {
"commander": "2",
"iconv-lite": "0.4",
"commander": "7",
"iconv-lite": "0.6",
"rw": "1"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
}
}
},
"d3-ease": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
"integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="
},
"d3-fetch": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz",
"integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
"integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
"requires": {
"d3-dsv": "1"
"d3-dsv": "1 - 3"
}
},
"d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
"integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
"integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
"requires": {
"d3-collection": "1",
"d3-dispatch": "1",
"d3-quadtree": "1",
"d3-timer": "1"
"d3-dispatch": "1 - 3",
"d3-quadtree": "1 - 3",
"d3-timer": "1 - 3"
}
},
"d3-format": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
"integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="
},
"d3-geo": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz",
"integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz",
"integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==",
"requires": {
"d3-array": "1"
"d3-array": "2.5.0 - 3"
}
},
"d3-hierarchy": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz",
"integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.1.tgz",
"integrity": "sha512-LtAIu54UctRmhGKllleflmHalttH3zkfSi4NlKrTAoFKjC+AFBJohsCAdgCBYQwH0F8hIOGY89X1pPqAchlMkA=="
},
"d3-interpolate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
"integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
"requires": {
"d3-color": "1"
"d3-color": "1 - 3"
}
},
"d3-path": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.0.1.tgz",
"integrity": "sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w=="
},
"d3-polygon": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz",
"integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
"integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="
},
"d3-quadtree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
"integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
"integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="
},
"d3-random": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz",
"integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
"integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="
},
"d3-scale": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
"requires": {
"d3-array": "^1.2.0",
"d3-collection": "1",
"d3-format": "1",
"d3-interpolate": "1",
"d3-time": "1",
"d3-time-format": "2"
"d3-array": "2.10.0 - 3",
"d3-format": "1 - 3",
"d3-interpolate": "1.2.0 - 3",
"d3-time": "2.1.1 - 3",
"d3-time-format": "2 - 4"
}
},
"d3-scale-chromatic": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
"integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
"integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==",
"requires": {
"d3-color": "1",
"d3-interpolate": "1"
"d3-color": "1 - 3",
"d3-interpolate": "1 - 3"
}
},
"d3-selection": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz",
"integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="
},
"d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.0.1.tgz",
"integrity": "sha512-HNZNEQoDhuCrDWEc/BMbF/hKtzMZVoe64TvisFLDp2Iyj0UShB/E6/lBsLlJTfBMbYgftHj90cXJ0SEitlE6Xw==",
"requires": {
"d3-path": "1"
"d3-path": "1 - 3"
}
},
"d3-time": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz",
"integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==",
"requires": {
"d3-array": "2 - 3"
}
},
"d3-time-format": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
"integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
"requires": {
"d3-time": "1"
"d3-time": "1 - 3"
}
},
"d3-timer": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="
},
"d3-transition": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz",
"integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
"integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
"requires": {
"d3-color": "1",
"d3-dispatch": "1",
"d3-ease": "1",
"d3-interpolate": "1",
"d3-selection": "^1.1.0",
"d3-timer": "1"
"d3-color": "1 - 3",
"d3-dispatch": "1 - 3",
"d3-ease": "1 - 3",
"d3-interpolate": "1 - 3",
"d3-timer": "1 - 3"
}
},
"d3-voronoi": {
@@ -4188,15 +4205,15 @@
"integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg=="
},
"d3-zoom": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz",
"integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
"integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
"d3-dispatch": "1 - 3",
"d3-drag": "2 - 3",
"d3-interpolate": "1 - 3",
"d3-selection": "2 - 3",
"d3-transition": "2 - 3"
}
},
"dagre": {
@@ -4217,6 +4234,267 @@
"dagre": "^0.8.5",
"graphlib": "^2.1.8",
"lodash": "^4.17.15"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"d3": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz",
"integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==",
"requires": {
"d3-array": "1",
"d3-axis": "1",
"d3-brush": "1",
"d3-chord": "1",
"d3-collection": "1",
"d3-color": "1",
"d3-contour": "1",
"d3-dispatch": "1",
"d3-drag": "1",
"d3-dsv": "1",
"d3-ease": "1",
"d3-fetch": "1",
"d3-force": "1",
"d3-format": "1",
"d3-geo": "1",
"d3-hierarchy": "1",
"d3-interpolate": "1",
"d3-path": "1",
"d3-polygon": "1",
"d3-quadtree": "1",
"d3-random": "1",
"d3-scale": "2",
"d3-scale-chromatic": "1",
"d3-selection": "1",
"d3-shape": "1",
"d3-time": "1",
"d3-time-format": "2",
"d3-timer": "1",
"d3-transition": "1",
"d3-voronoi": "1",
"d3-zoom": "1"
}
},
"d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
},
"d3-axis": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz",
"integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ=="
},
"d3-brush": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz",
"integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==",
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
}
},
"d3-chord": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz",
"integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==",
"requires": {
"d3-array": "1",
"d3-path": "1"
}
},
"d3-color": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
},
"d3-contour": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz",
"integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==",
"requires": {
"d3-array": "^1.1.1"
}
},
"d3-dispatch": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
},
"d3-drag": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz",
"integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==",
"requires": {
"d3-dispatch": "1",
"d3-selection": "1"
}
},
"d3-dsv": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz",
"integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==",
"requires": {
"commander": "2",
"iconv-lite": "0.4",
"rw": "1"
}
},
"d3-ease": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
"integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
},
"d3-fetch": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz",
"integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==",
"requires": {
"d3-dsv": "1"
}
},
"d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
"integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==",
"requires": {
"d3-collection": "1",
"d3-dispatch": "1",
"d3-quadtree": "1",
"d3-timer": "1"
}
},
"d3-format": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
"integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
},
"d3-geo": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz",
"integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==",
"requires": {
"d3-array": "1"
}
},
"d3-hierarchy": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz",
"integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ=="
},
"d3-interpolate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
"integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
"requires": {
"d3-color": "1"
}
},
"d3-path": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
},
"d3-polygon": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz",
"integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
},
"d3-quadtree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
"integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
},
"d3-random": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz",
"integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ=="
},
"d3-scale": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
"requires": {
"d3-array": "^1.2.0",
"d3-collection": "1",
"d3-format": "1",
"d3-interpolate": "1",
"d3-time": "1",
"d3-time-format": "2"
}
},
"d3-scale-chromatic": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
"integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==",
"requires": {
"d3-color": "1",
"d3-interpolate": "1"
}
},
"d3-selection": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz",
"integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
},
"d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
"requires": {
"d3-path": "1"
}
},
"d3-time": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
},
"d3-time-format": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
"integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
"requires": {
"d3-time": "1"
}
},
"d3-timer": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
},
"d3-transition": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz",
"integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==",
"requires": {
"d3-color": "1",
"d3-dispatch": "1",
"d3-ease": "1",
"d3-interpolate": "1",
"d3-selection": "^1.1.0",
"d3-timer": "1"
}
},
"d3-zoom": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz",
"integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==",
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
}
}
}
},
"debug": {
@@ -4394,6 +4672,14 @@
"slash": "^3.0.0"
}
},
"delaunator": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
"integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
"requires": {
"robust-predicates": "^3.0.0"
}
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -4532,9 +4818,9 @@
}
},
"dompurify": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.1.tgz",
"integrity": "sha512-xGWt+NHAQS+4tpgbOAI08yxW0Pr256Gu/FNE2frZVTbgrBUn8M7tz7/ktS/LZ2MHeGqz6topj0/xY+y8R5FBFw=="
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.4.tgz",
"integrity": "sha512-6BVcgOAVFXjI0JTjEvZy901Rghm+7fDQOrNIcxB4+gdhj6Kwp6T9VBhBY/AbagKHJocRkDYGd6wvI+p4/10xtQ=="
},
"domutils": {
"version": "1.5.1",
@@ -6283,6 +6569,11 @@
"side-channel": "^1.0.4"
}
},
"internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="
},
"interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
@@ -7077,15 +7368,15 @@
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="
},
"mermaid": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.12.1.tgz",
"integrity": "sha512-0UCcSF0FLoNcPBsRF4f9OIV32t41fV18//z8o3S+FDz2PbDA1CRGKdQF9IX84VP4Tv9kcgJI/oqJdcBEtB/GPA==",
"version": "8.13.8",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.13.8.tgz",
"integrity": "sha512-Z5v31rvo8P7BPTiGicdJl9BbzyUe9s5sXILK8sM1g7ijkagpfFjPtXZVsq5P1WlN8m/fUp2PPNXVF9SqeTM91w==",
"requires": {
"@braintree/sanitize-url": "^3.1.0",
"d3": "^5.16.0",
"d3": "^7.0.0",
"dagre": "^0.8.5",
"dagre-d3": "^0.6.4",
"dompurify": "2.3.1",
"dompurify": "2.3.4",
"graphlib": "^2.1.8",
"khroma": "^1.4.1",
"moment-mini": "^2.24.0",
@@ -9336,6 +9627,11 @@
"glob": "^7.1.3"
}
},
"robust-predicates": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz",
"integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g=="
},
"rtl-detect": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz",
@@ -10271,9 +10567,9 @@
}
},
"stylis": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.10.tgz",
"integrity": "sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg=="
"version": "4.0.13",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
},
"supports-color": {
"version": "7.2.0",
+1 -1
View File
@@ -18,7 +18,7 @@
"@docusaurus/preset-classic": "^2.0.0-beta.6",
"@kiwicopple/prism-react-renderer": "github:kiwicopple/prism-react-renderer",
"jsrsasign": "^10.4.1",
"mermaid": "^8.6.4",
"mermaid": "^8.13.8",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-inlinesvg": "^2.0.1"
+42
View File
@@ -716,6 +716,48 @@ pages:
console.log(event, session)
})
```
- name: Listen to sign in
js: |
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'SIGNED_IN') console.log('SIGNED_IN', session)
})
```
- name: Listen to sign out
js: |
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'SIGNED_OUT') console.log('SIGNED_OUT', session)
})
```
- name: Listen to token refresh
js: |
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'TOKEN_REFRESHED') console.log('TOKEN_REFRESHED', session)
})
```
- name: Listen to user updates
js: |
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'USER_UPDATED') console.log('USER_UPDATED', session)
})
```
- name: Listen to user deleted
js: |
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'USER_DELETED') console.log('USER_DELETED', session)
})
```
- name: Listen to password recovery events
js: |
```js
supabase.auth.onAuthStateChange((event, session) => {
if (event == 'PASSWORD_RECOVERY') console.log('PASSWORD_RECOVERY', session)
})
```
auth.api.getUser():
title: 'getUser()'
$ref: '@supabase/gotrue-js.GoTrueApi.getUser'
+14 -10
View File
@@ -3,21 +3,23 @@ var axios = require('axios')
var fs = require('fs')
const query = `
query BIO_QUERY($username: String!) {
organization(login: $username) {
query Sponsors {
organization(login: "supabase") {
id
sponsorshipsAsMaintainer(first: 100) {
totalCount
sponsors(first: 100) {
nodes {
createdAt
privacyLevel
tier {
name
... on Organization {
id
createdAt
name : login
}
sponsor {
... on User {
id
createdAt
login
}
}
totalCount
}
}
}
@@ -39,10 +41,11 @@ const fetchAllSponsors = async () => {
},
}
)
return data.data.organization.sponsorshipsAsMaintainer
return data.data.organization.sponsors
}
const formatResults = (graphqlResponse) => {
console.log('graph', graphqlResponse)
return graphqlResponse.nodes
.filter((x) => !!x.sponsor)
.map((x) => ({
@@ -65,6 +68,7 @@ const writeFile = (data) => {
const main = async () => {
const sponsorsResponse = await fetchAllSponsors()
// console.log('sponsorsResponse.totalCount', sponsorsResponse.totalCount)
const formatted = formatResults(sponsorsResponse)
writeFile(formatted)
}
+1 -1
View File
@@ -199,4 +199,4 @@
"tier": "$49 a month",
"sponsor": "CryptoJobsList"
}
]
]
+7 -1
View File
@@ -243,11 +243,17 @@ const Nav = (props: Props) => {
</div>
<div className="hidden lg:flex items-center sm:space-x-3">
<a href="https://github.com/supabase/supabase" target="_blank">
<Button type="default" icon={<IconStar />}>
<Button
className="sbui-btn sbui-btn-text sbui-btn--tiny sbui-btn--text-align-center"
icon={<IconStar />}
>
Star us on GitHub
</Button>
</a>
<a href="https://app.supabase.io/">
<Button type="default">Sign in</Button>
</a>
<a href="https://app.supabase.io/new/project">
<Button>Start your project</Button>
</a>
</div>
+16 -16
View File
@@ -1,33 +1,33 @@
[
{
"type": "Announcement",
"title": "Launch Week II: The SQL",
"description": "We're launching a product every day for one week in July.",
"imgUrl": "images/case-study-monitoro.jpg",
"logoUrl": "images/logos/monitoro.png",
"organization": "Monitoro",
"url": "/blog/2021/07/22/supabase-launch-week-sql",
"title": "Supabase Launch Week III: Holiday Special",
"description": "Santa's little hackers have been hard at work because we've got another five days of launches ready to go.",
"imgUrl": "images/blog/launch-week-three/launch-week-three-og.jpg",
"logoUrl": "images/blog/launch-week-three/launch-week-three-og.jpg",
"organization": "Supabase",
"url": "/blog/2021/11/26/supabase-launch-week-the-trilogy",
"postMeta": {
"name": "Paul Copplestone",
"avatarUrl": "https://avatars0.githubusercontent.com/u/10214025?v=4",
"publishDate": "Mar 16, 2020",
"readLength": 6
"publishDate": "Nov 26, 2021",
"readLength": 2
},
"ctaText": "View case study"
},
{
"type": "Announcement",
"title": "Supabase Storage",
"description": "Supabase launches Storage leveraging Postgres.",
"imgUrl": "images/case-study-monitoro.jpg",
"logoUrl": "images/logos/monitoro.png",
"organization": "Monitoro",
"url": "/blog/2021/03/30/supabase-storage",
"title": "Supabase $30m Series A",
"description": "Supabase just raised $30M, bringing our total funding to $36M. How will we spend this? Read on to find out.",
"imgUrl": "images/blog/series-a/supabase-series-a.png",
"logoUrl": "images/blog/series-a/supabase-series-a.png",
"organization": "Supabase",
"url": "/blog/2021/10/28/supabase-series-a",
"postMeta": {
"name": "Paul Copplestone",
"avatarUrl": "https://avatars0.githubusercontent.com/u/10214025?v=4",
"publishDate": "Mar 16, 2020",
"readLength": 6
"publishDate": "Oct 28, 2021",
"readLength": 28
},
"ctaText": "View case study"
}
+1 -1
View File
@@ -5,7 +5,7 @@
},
{
"question": "Is there a cap on the number of projects for the Free Tier?",
"answer": "Yes, on the Free Tier you can have a maximum of two organizations, each with up to two projects. This means that you can have a maximum of four free projects in your account."
"answer": "Yes, you have can up to 2 free projects in your account across all organizations that you own. You also are able to create as many organizations as you want."
},
{
"question": "When will I be billed?",