mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 02:15:05 +03:00
37 files changed
+757
-164
No files matched your search
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
env:
|
||||
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
|
||||
PROJECT_ID: ${{ secrets.PROJECT_ID }}
|
||||
PROJECT_ID: ${{ secrets.OG_IMAGE_SUPABASE_PROJECT_ID }}
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Generate Embeddings for Search
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/search.yml'
|
||||
- 'supabase/migrations/**'
|
||||
- 'apps/docs/**'
|
||||
- 'spec/**'
|
||||
workflow_dispatch: {}
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
|
||||
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
|
||||
PROJECT_ID: ${{ secrets.SEARCH_SUPABASE_PROJECT_ID }}
|
||||
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SEARCH_SUPABASE_URL }}
|
||||
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SEARCH_SUPABASE_SERVICE_ROLE_KEY }}
|
||||
SUPABASE_DB_PASSWORD: ${{ secrets.SEARCH_SUPABASE_DB_PASSWORD }}
|
||||
SEARCH_GITHUB_APP_ID: ${{ secrets.SEARCH_GITHUB_APP_ID }}
|
||||
SEARCH_GITHUB_APP_INSTALLATION_ID: ${{ secrets.SEARCH_GITHUB_APP_INSTALLATION_ID }}
|
||||
SEARCH_GITHUB_APP_PRIVATE_KEY: ${{ secrets.SEARCH_GITHUB_APP_PRIVATE_KEY }}
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Download dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Link Supabase project
|
||||
run: npx supabase link --project-ref $PROJECT_ID
|
||||
|
||||
- name: Run migrations
|
||||
run: npx supabase db push
|
||||
|
||||
- name: Refresh embeddings
|
||||
working-directory: ./apps/docs
|
||||
run: npm run embeddings
|
||||
@@ -5,6 +5,9 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
||||
# PRIVATE
|
||||
OPENAI_KEY=
|
||||
SUPABASE_SERVICE_ROLE_KEY=
|
||||
SEARCH_GITHUB_APP_ID=
|
||||
SEARCH_GITHUB_APP_INSTALLATION_ID=
|
||||
SEARCH_GITHUB_APP_PRIVATE_KEY=
|
||||
|
||||
# Set IS_PLATFORM to true if you have the api keys and urls
|
||||
NEXT_PUBLIC_IS_PLATFORM=false
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.staging.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
@@ -20,4 +21,4 @@ yarn-error.log*
|
||||
|
||||
**/*/generated/**/*
|
||||
!**/*/generated/.gitkeep
|
||||
!**/*/generated/**/.gitkeep
|
||||
!**/*/generated/**/.gitkeep
|
||||
@@ -577,7 +577,16 @@ export const functions = {
|
||||
name: 'Connecting directly to Postgres',
|
||||
url: '/guides/functions/connect-to-postgres',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Third-Party Tools',
|
||||
url: undefined,
|
||||
items: [
|
||||
{ name: 'Dart Edge on Supabase', url: '/guides/functions/dart-edge' },
|
||||
{ name: 'Browserless.io', url: '/guides/functions/examples/screenshots' },
|
||||
{ name: 'OpenAI API', url: '/guides/functions/examples/openai' },
|
||||
{ name: 'Upstash Redis', url: '/guides/functions/examples/upstash-redis' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
"@mdx-js/loader": "^1.6.22",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"@next/mdx": "^12.0.4",
|
||||
"@octokit/auth-app": "^4.0.9",
|
||||
"@octokit/core": "^4.2.0",
|
||||
"@octokit/plugin-paginate-graphql": "^2.0.1",
|
||||
"@radix-ui/react-accordion": "^1.0.1",
|
||||
"@supabase/auth-helpers-nextjs": "^0.5.6",
|
||||
"@supabase/auth-helpers-react": "^0.3.1",
|
||||
@@ -94,6 +97,7 @@
|
||||
"ui": "*",
|
||||
"unist-builder": "^3.0.1",
|
||||
"unist-util-filter": "^4.0.1",
|
||||
"uuid": "^9.0.0",
|
||||
"valtio": "^1.7.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth-twilio',
|
||||
title: 'Phone Auth with Twilio',
|
||||
@@ -308,33 +309,35 @@ To make use of WhatsApp OTP, please complete the following steps:
|
||||
- Submit a template via the [Twilio Guide For Submitting WhatsApp templates](https://www.twilio.com/docs/whatsapp/tutorial/send-whatsapp-notification-messages-templates#creating-message-templates-and-submitting-them-for-approval)
|
||||
|
||||
<Admonition type="caution">
|
||||
The message template submitted to Twilio must exactly match the SMS Body entered on the Supabase dashboard.
|
||||
The message template submitted to Twilio must exactly match the SMS Body entered on the Supabase
|
||||
dashboard.
|
||||
</Admonition>
|
||||
|
||||
The sign in process with WhatsApp is similar to the sign in process for SMS. Do note the additional `whatsapp` parameter added:
|
||||
|
||||
```js
|
||||
const {data, error } = await supabase.auth.signInWithOtp({
|
||||
phone: '+57336567365',
|
||||
options: {
|
||||
channel:'whatsapp'
|
||||
}
|
||||
})
|
||||
const { data, error } = await supabase.auth.signInWithOtp({
|
||||
phone: '+57336567365',
|
||||
options: {
|
||||
channel: 'whatsapp',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
You can also sign up with `whatsapp` as a channel:
|
||||
|
||||
```js
|
||||
const {data, error }= await supabase.auth.signUp({
|
||||
phone: '+57336567365',
|
||||
password: 'testsupabasenow',
|
||||
options: {
|
||||
channel:'whatsapp',
|
||||
}
|
||||
const { data, error } = await supabase.auth.signUp({
|
||||
phone: '+57336567365',
|
||||
password: 'testsupabasenow',
|
||||
options: {
|
||||
channel: 'whatsapp',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
There is no change in the verification process, you should continue to use the `sms` type for verification
|
||||
|
||||
```js
|
||||
// After receiving a WhatsApp OTP
|
||||
let { data, error } = await supabase.auth.verifyOtp({
|
||||
|
||||
@@ -10,6 +10,15 @@ export const meta = {
|
||||
|
||||
> ⚠️ WARNING: Dart Edge is an experimental project - it's probably not ready for production usage unless you're okay with living on the 'edge'. Open issues on [Dart Edge repo](https://github.com/invertase/dart_edge) if you encounter any issues.
|
||||
|
||||
<div class="video-container">
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/53jhgrDONW4"
|
||||
frameBorder="1"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
## **Pre requirements**
|
||||
|
||||
Make sure you have [the edge CLI](https://docs.dartedge.dev/#getting-started) installed in addition to [the Supabase CLI](https://supabase.com/docs/guides/cli#installation).
|
||||
|
||||
@@ -6,6 +6,52 @@ export const meta = {
|
||||
description: 'Run your Edge Functions locally.',
|
||||
}
|
||||
|
||||
## Setting Up Your Environment
|
||||
|
||||
You can follow the [Deno guide](https://deno.com/manual@v1.32.5/getting_started/setup_your_environment) for setting up your development environment with your favorite editor/IDE.
|
||||
|
||||
When developing with VS Code inside of an existing application, you can utilize [multi-root workspaces](https://code.visualstudio.com/docs/editor/workspaces#_multiroot-workspaces).
|
||||
|
||||
<div className="video-container">
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/lFhU3L8VoSQ"
|
||||
frameBorder="1"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
For example, see this `edge-functions.code-workspace` configuration for a CRA (create react app) client with Supabase Edge Functions. You can find the complete example on [GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions).
|
||||
|
||||
```json
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "project-root",
|
||||
"path": "./"
|
||||
},
|
||||
{
|
||||
"name": "client",
|
||||
"path": "app"
|
||||
},
|
||||
{
|
||||
"name": "supabase-functions",
|
||||
"path": "supabase/functions"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.exclude": {
|
||||
"node_modules/": true,
|
||||
"app/": true,
|
||||
"supabase/functions/": true
|
||||
},
|
||||
"deno.importMap": "./supabase/functions/import_map.json"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Running Edge Functions locally
|
||||
|
||||
You can run your Edge Function locally using [`supabase functions serve`](/docs/reference/cli/usage#supabase-functions-serve):
|
||||
|
||||
```bash
|
||||
@@ -15,7 +61,7 @@ supabase functions serve # start the Functions watcher
|
||||
|
||||
The `functions serve` command has hot-reloading capabilities. It will watch for any changes to your files and restart the Deno server.
|
||||
|
||||
### Invoking Edge Functions locally
|
||||
## Invoking Edge Functions locally
|
||||
|
||||
While serving your local Edge Function, you can invoke it using curl:
|
||||
|
||||
|
||||
@@ -88,6 +88,50 @@ const { data, error } = await supabase.functions.invoke('hello-world', {
|
||||
|
||||
After invoking your Edge Function you should see the response `{ "message":"Hello Functions!" }`.
|
||||
|
||||
## Setting Up Your Environment
|
||||
|
||||
You can follow the [Deno guide](https://deno.com/manual@v1.32.5/getting_started/setup_your_environment) for setting up your development environment with your favorite editor/IDE.
|
||||
|
||||
When developing with VS Code inside of an existing application, you can utilize [multi-root workspaces](https://code.visualstudio.com/docs/editor/workspaces#_multiroot-workspaces).
|
||||
|
||||
<div className="video-container">
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/lFhU3L8VoSQ"
|
||||
frameBorder="1"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
For example, see this `edge-functions.code-workspace` configuration for a CRA (create react app) client with Supabase Edge Functions. You can find the complete example on [GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions).
|
||||
|
||||
```json
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "project-root",
|
||||
"path": "./"
|
||||
},
|
||||
{
|
||||
"name": "client",
|
||||
"path": "app"
|
||||
},
|
||||
{
|
||||
"name": "supabase-functions",
|
||||
"path": "supabase/functions"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.exclude": {
|
||||
"node_modules/": true,
|
||||
"app/": true,
|
||||
"supabase/functions/": true
|
||||
},
|
||||
"deno.importMap": "./supabase/functions/import_map.json"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Database Functions vs Edge Functions
|
||||
|
||||
For data-intensive operations we recommend using [Database Functions](/docs/guides/database/functions), which are executed within your database
|
||||
|
||||
@@ -12,7 +12,7 @@ In some cases, access to new features require upgrading or migrating your Supaba
|
||||
|
||||
## Upgrade your project
|
||||
|
||||
<Admonition type="note">This is only available for projects on the Free plan.</Admonition>
|
||||
<Admonition type="note">This is only available for projects on the Free plan. For projects on the Pro plan, please contact support for assistance with upgrading.</Admonition>
|
||||
|
||||
When you pause and restore a project, the restored database includes the latest features. This method _does_ include downtime, so be aware that your project will be inaccessible for a short period of time.
|
||||
|
||||
|
||||
@@ -66,9 +66,11 @@ Use your browser's developer tools to find the WebSocket initiation request and
|
||||
|
||||
</Admonition>
|
||||
|
||||
## Payload Limits
|
||||
## Postgres Changes Payload Limit
|
||||
|
||||
Realtime has a message byte size limit of 1 megabyte.
|
||||
Realtime Postgres Changes has a change payload size limit of 1 mebibyte (MiB).
|
||||
|
||||
When this limit is reached, the `new` and `old` record payloads only include the fields with a value size of less than or equal to 64 bytes.
|
||||
|
||||
## Presence Limits
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ Michel Pelletier
|
||||
Monica El Khoury
|
||||
Nikita Kotlyarov
|
||||
Oli R
|
||||
Pamela Chia
|
||||
Paul Cioanca
|
||||
Paul Copplestone
|
||||
Pavel Borisov
|
||||
|
||||
@@ -3,6 +3,7 @@ import dotenv from 'dotenv'
|
||||
import 'openai'
|
||||
import { Configuration, OpenAIApi } from 'openai'
|
||||
import { inspect } from 'util'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { fetchSources } from './sources'
|
||||
|
||||
dotenv.config()
|
||||
@@ -12,7 +13,14 @@ async function generateEmbeddings() {
|
||||
const args = process.argv.slice(2)
|
||||
const shouldRefresh = args.includes('--refresh')
|
||||
|
||||
const requiredEnvVars = ['NEXT_PUBLIC_SUPABASE_URL', 'SUPABASE_SERVICE_ROLE_KEY', 'OPENAI_KEY']
|
||||
const requiredEnvVars = [
|
||||
'NEXT_PUBLIC_SUPABASE_URL',
|
||||
'SUPABASE_SERVICE_ROLE_KEY',
|
||||
'OPENAI_KEY',
|
||||
'SEARCH_GITHUB_APP_ID',
|
||||
'SEARCH_GITHUB_APP_INSTALLATION_ID',
|
||||
'SEARCH_GITHUB_APP_PRIVATE_KEY',
|
||||
]
|
||||
|
||||
if (requiredEnvVars.some((name) => !process.env[name])) {
|
||||
throw new Error(
|
||||
@@ -33,6 +41,12 @@ async function generateEmbeddings() {
|
||||
}
|
||||
)
|
||||
|
||||
// Use this version to track which pages to purge
|
||||
// after the refresh
|
||||
const refreshVersion = uuidv4()
|
||||
|
||||
const refreshDate = new Date()
|
||||
|
||||
const embeddingSources = await fetchSources()
|
||||
|
||||
console.log(`Discovered ${embeddingSources.length} pages`)
|
||||
@@ -92,6 +106,24 @@ async function generateEmbeddings() {
|
||||
throw updatePageError
|
||||
}
|
||||
}
|
||||
|
||||
// No content/embedding update required on this page
|
||||
// Update other meta info
|
||||
const { error: updatePageError } = await supabaseClient
|
||||
.from('page')
|
||||
.update({
|
||||
type,
|
||||
source,
|
||||
meta,
|
||||
version: refreshVersion,
|
||||
last_refresh: refreshDate,
|
||||
})
|
||||
.filter('id', 'eq', existingPage.id)
|
||||
|
||||
if (updatePageError) {
|
||||
throw updatePageError
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -137,6 +169,8 @@ async function generateEmbeddings() {
|
||||
source,
|
||||
meta,
|
||||
parent_page_id: parentPage?.id,
|
||||
version: refreshVersion,
|
||||
last_refresh: refreshDate,
|
||||
},
|
||||
{ onConflict: 'path' }
|
||||
)
|
||||
@@ -215,6 +249,18 @@ async function generateEmbeddings() {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Removing old pages and their sections`)
|
||||
|
||||
// Delete pages that have been removed (and their sections via cascade)
|
||||
const { error: deletePageError } = await supabaseClient
|
||||
.from('page')
|
||||
.delete()
|
||||
.filter('version', 'neq', refreshVersion)
|
||||
|
||||
if (deletePageError) {
|
||||
throw deletePageError
|
||||
}
|
||||
|
||||
console.log('Embedding generation complete')
|
||||
}
|
||||
|
||||
@@ -222,4 +268,9 @@ async function main() {
|
||||
await generateEmbeddings()
|
||||
}
|
||||
|
||||
main().catch((err) => console.error(err))
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
|
||||
// Exit with non-zero code
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,119 @@
|
||||
import { createAppAuth } from '@octokit/auth-app'
|
||||
import { Octokit } from '@octokit/core'
|
||||
import { paginateGraphql } from '@octokit/plugin-paginate-graphql'
|
||||
import { createHash } from 'crypto'
|
||||
import { BaseSource } from './base'
|
||||
|
||||
export const ExtendedOctokit = Octokit.plugin(paginateGraphql)
|
||||
export type ExtendedOctokit = InstanceType<typeof ExtendedOctokit>
|
||||
|
||||
export type Discussion = {
|
||||
id: string
|
||||
updatedAt: string
|
||||
url: string
|
||||
title: string
|
||||
body: string
|
||||
databaseId: number
|
||||
}
|
||||
|
||||
export type DiscussionsResponse = {
|
||||
repository: {
|
||||
discussions: {
|
||||
totalCount: number
|
||||
nodes: Discussion[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches GitHub discussions for a repository + category
|
||||
*/
|
||||
export async function fetchDiscussions(owner: string, repo: string, categoryId: string) {
|
||||
const octokit = new ExtendedOctokit({
|
||||
authStrategy: createAppAuth,
|
||||
auth: {
|
||||
appId: process.env.SEARCH_GITHUB_APP_ID,
|
||||
installationId: process.env.SEARCH_GITHUB_APP_INSTALLATION_ID,
|
||||
privateKey: process.env.SEARCH_GITHUB_APP_PRIVATE_KEY,
|
||||
},
|
||||
})
|
||||
|
||||
const {
|
||||
repository: {
|
||||
discussions: { nodes: discussions },
|
||||
},
|
||||
} = await octokit.graphql.paginate<DiscussionsResponse>(
|
||||
`
|
||||
query troubleshootDiscussions($cursor: String, $owner: String!, $repo: String!, $categoryId: ID!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
discussions(first: 100, after: $cursor, categoryId: $categoryId) {
|
||||
totalCount
|
||||
nodes {
|
||||
id
|
||||
updatedAt
|
||||
url
|
||||
title
|
||||
body
|
||||
databaseId
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
endCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
owner,
|
||||
repo,
|
||||
categoryId,
|
||||
}
|
||||
)
|
||||
|
||||
return discussions
|
||||
}
|
||||
|
||||
export class GitHubDiscussionSource extends BaseSource {
|
||||
type = 'github-discussions' as const
|
||||
|
||||
constructor(source: string, public discussion: Discussion) {
|
||||
super(source, discussion.url)
|
||||
}
|
||||
|
||||
async load() {
|
||||
const { id, title, updatedAt, body, databaseId } = this.discussion
|
||||
|
||||
const checksum = createHash('sha256').update(updatedAt).digest('base64')
|
||||
|
||||
const meta = { id, title, updatedAt }
|
||||
|
||||
// Currently the discussion post itself is being considered as the answer
|
||||
// (as opposed to a comment marked as answer)
|
||||
// So we link the slug to the initial discussion post rather than a comment answer
|
||||
const slug = `discussion-${databaseId}`
|
||||
|
||||
// Format the discussion title + body as markdown for better embeddings + LLM response
|
||||
const content = `# ${title}\n${body}`
|
||||
|
||||
// For now, only a single section is created for GH discussions
|
||||
// Consider adding multiple if we want to include comments/answers
|
||||
const sections = [
|
||||
{
|
||||
heading: title,
|
||||
slug,
|
||||
content,
|
||||
},
|
||||
]
|
||||
|
||||
this.checksum = checksum
|
||||
this.meta = meta
|
||||
this.sections = sections
|
||||
|
||||
return {
|
||||
checksum,
|
||||
meta,
|
||||
sections,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GitHubDiscussionSource, fetchDiscussions } from './github-discussion'
|
||||
import { MarkdownSource } from './markdown'
|
||||
import {
|
||||
CliReferenceSource,
|
||||
@@ -13,6 +14,7 @@ export type SearchSource =
|
||||
| OpenApiReferenceSource
|
||||
| ClientLibReferenceSource
|
||||
| CliReferenceSource
|
||||
| GitHubDiscussionSource
|
||||
|
||||
/**
|
||||
* Fetches all the sources we want to index for search
|
||||
@@ -71,6 +73,14 @@ export async function fetchSources() {
|
||||
.filter(({ path }) => !ignoredFiles.includes(path))
|
||||
.map((entry) => new MarkdownSource('guide', entry.path))
|
||||
|
||||
const githubDiscussionSources = (
|
||||
await fetchDiscussions(
|
||||
'supabase',
|
||||
'supabase',
|
||||
'DIC_kwDODMpXOc4CUvEr' // 'Troubleshooting' category
|
||||
)
|
||||
).map((discussion) => new GitHubDiscussionSource('supabase/supabase', discussion))
|
||||
|
||||
const sources: SearchSource[] = [
|
||||
openApiReferenceSource,
|
||||
jsLibReferenceSource,
|
||||
@@ -78,6 +88,7 @@ export async function fetchSources() {
|
||||
pythonLibReferenceSource,
|
||||
cSharpLibReferenceSource,
|
||||
cliReferenceSource,
|
||||
...githubDiscussionSources,
|
||||
...guideSources,
|
||||
]
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ export function processMdxForSearch(content: string): ProcessedMdx {
|
||||
})
|
||||
|
||||
const meta = extractMetaExport(mdxTree)
|
||||
const serializableMeta: Json = JSON.parse(JSON.stringify(meta))
|
||||
|
||||
const serializableMeta: Json = meta && JSON.parse(JSON.stringify(meta))
|
||||
|
||||
// Remove all MDX elements from markdown
|
||||
const mdTree = filter(
|
||||
|
||||
@@ -104,7 +104,7 @@ Soon we're going to need to perform a similarity search over these embeddings. L
|
||||
```sql
|
||||
create or replace function match_documents (
|
||||
query_embedding vector(1536),
|
||||
similarity_threshold float,
|
||||
match_threshold float,
|
||||
match_count int
|
||||
)
|
||||
returns table (
|
||||
@@ -117,12 +117,12 @@ as $$
|
||||
begin
|
||||
return query
|
||||
select
|
||||
id,
|
||||
content,
|
||||
documents.id,
|
||||
documents.content,
|
||||
1 - (documents.embedding <=> query_embedding) as similarity
|
||||
from documents
|
||||
where 1 - (documents.embedding <=> query_embedding) > similarity_threshold
|
||||
order by documents.embedding <=> query_embedding
|
||||
where 1 - (documents.embedding <=> query_embedding) > match_threshold
|
||||
order by similarity desc
|
||||
limit match_count;
|
||||
end;
|
||||
$$;
|
||||
|
||||
@@ -15,10 +15,16 @@ thumb: launch-week-6/pggraphql/og-pg-graphql.png
|
||||
---
|
||||
|
||||
It's been 4 months since the [1.0.0 release of pg_graphql](https://supabase.com/blog/pg-graphql-v1).
|
||||
Since then, we’ve pushed several features to improve the APIs that `pg_graphql` produces.
|
||||
Since then, we’ve pushed several features to improve the APIs that `pg_graphql` produces.
|
||||
|
||||
In this article, we’ll walk through those features and show examples of each.
|
||||
|
||||
<div className="bg-gray-300 rounded-lg px-6 py-2 italic">
|
||||
|
||||
📢 These features are only available on projects with Postgres version `15.1.0.63` or higher. For help with upgrading, please review the [migrating and upgrading projects guide](https://supabase.com/docs/guides/platform/migrating-and-upgrading-projects).
|
||||
|
||||
</div>
|
||||
|
||||
### View Support
|
||||
|
||||
Prior to `v1.1`, `pg_graphql` would only reflect standard tables. Since then, views, materialized views, and foreign tables are now also reflected in the GraphQL schema.
|
||||
@@ -26,7 +32,7 @@ Prior to `v1.1`, `pg_graphql` would only reflect standard tables. Since then, vi
|
||||
For example:
|
||||
|
||||
```sql
|
||||
create view "ProjectOwner" as
|
||||
create view "ProjectOwner" as
|
||||
select
|
||||
acc.id,
|
||||
acc.name
|
||||
@@ -70,7 +76,7 @@ With associated `Edge` and `Connection` types. That enables querying via:
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, simple views automatically support mutation events like inserts and updates. You might use these to migrate underlying tables while maintaining backwards compatibility with previous API versions.
|
||||
Additionally, simple views automatically support mutation events like inserts and updates. You might use these to migrate underlying tables while maintaining backwards compatibility with previous API versions.
|
||||
|
||||
## Filtering
|
||||
|
||||
@@ -109,7 +115,7 @@ to return all `blog`s where the `name` is `null`.
|
||||
|
||||
### **`like`**, **`ilike`**, and **`startsWith`**
|
||||
|
||||
Text filtering options in `pg_graphql` have historically been restricted to equality checks. The hesitation was due to concerns about exposing a default filter that is difficult to index. The combination of [citext](https://www.postgresql.org/docs/current/citext.html) and [PGroonga available on the platform](https://supabase.com/docs/guides/database/extensions/pgroonga) solves those scalability risks and enabled us to expand the `StringFilter` with options for `like` `ilike` and `startsWith`.
|
||||
Text filtering options in `pg_graphql` have historically been restricted to equality checks. The hesitation was due to concerns about exposing a default filter that is difficult to index. The combination of [citext](https://www.postgresql.org/docs/current/citext.html) and [PGroonga available on the platform](https://supabase.com/docs/guides/database/extensions/pgroonga) solves those scalability risks and enabled us to expand the `StringFilter` with options for `like` `ilike` and `startsWith`.
|
||||
|
||||
```graphql
|
||||
input StringFilter {
|
||||
@@ -118,7 +124,7 @@ input StringFilter {
|
||||
startsWith: String
|
||||
like: String
|
||||
ilike: String
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that `startsWith` filters should be preferred where appropriate because they can leverage simple B-Tree indexes to improve performance.
|
||||
@@ -139,7 +145,7 @@ Note that `startsWith` filters should be preferred where appropriate because the
|
||||
|
||||
### GraphQL directives `@skip` and `@include`
|
||||
|
||||
The GraphQL spec has evolved over time. Although the spec is clear, it is common for GraphQL servers to selectively omit some chunks of functionality. For example, some frameworks intentionally do not expose an introspection schema as a form of security through obscurity.
|
||||
The GraphQL spec has evolved over time. Although the spec is clear, it is common for GraphQL servers to selectively omit some chunks of functionality. For example, some frameworks intentionally do not expose an introspection schema as a form of security through obscurity.
|
||||
|
||||
`pg_graphql` aims to be unopinionated and adhere exactly to the spec. The `@skip` and `@include` directives are part of the [GraphQL core specification](https://spec.graphql.org/October2021/#sec--skip) and are now functional.
|
||||
|
||||
@@ -198,6 +204,6 @@ The headline features we aim to launch in coming releases of `pg_graphql` includ
|
||||
|
||||
## More pg_graphql
|
||||
|
||||
- [Introducing pg_graphql: A GraphQL extension for PostgreSQL](https://supabase.com/blog/pg-graphql)
|
||||
- [Introducing pg_graphql: A GraphQL extension for PostgreSQL](https://supabase.com/blog/pg-graphql)
|
||||
- [GraphQL is now available in Supabase](https://supabase.com/blog/graphql-now-available)
|
||||
- [pg_graphql v1.0](https://supabase.com/blog/pg-graphql-v1)
|
||||
@@ -42,7 +42,6 @@
|
||||
"parse-numeric-range": "^1.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-countdown": "^2.3.5",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-ga": "^3.3.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
|
||||
@@ -57,7 +57,7 @@ services:
|
||||
|
||||
auth:
|
||||
container_name: supabase-auth
|
||||
image: supabase/gotrue:v2.47.0
|
||||
image: supabase/gotrue:v2.60.7
|
||||
depends_on:
|
||||
db:
|
||||
# Disable this if you are using an external Postgres database
|
||||
|
||||
Generated
+67
-12
@@ -42,6 +42,9 @@
|
||||
"@mdx-js/loader": "^1.6.22",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"@next/mdx": "^12.0.4",
|
||||
"@octokit/auth-app": "^4.0.9",
|
||||
"@octokit/core": "^4.2.0",
|
||||
"@octokit/plugin-paginate-graphql": "^2.0.1",
|
||||
"@radix-ui/react-accordion": "^1.0.1",
|
||||
"@supabase/auth-helpers-nextjs": "^0.5.6",
|
||||
"@supabase/auth-helpers-react": "^0.3.1",
|
||||
@@ -89,6 +92,7 @@
|
||||
"ui": "*",
|
||||
"unist-builder": "^3.0.1",
|
||||
"unist-util-filter": "^4.0.1",
|
||||
"uuid": "^9.0.0",
|
||||
"valtio": "^1.7.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -593,6 +597,14 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"apps/docs/node_modules/uuid": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"apps/docs/node_modules/valtio": {
|
||||
"version": "1.7.6",
|
||||
"license": "MIT",
|
||||
@@ -683,7 +695,6 @@
|
||||
"parse-numeric-range": "^1.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-countdown": "^2.3.5",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-ga": "^3.3.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
@@ -5821,6 +5832,14 @@
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz",
|
||||
"integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-graphql": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-2.0.1.tgz",
|
||||
"integrity": "sha512-ZlhrWMlkGeK7qkWMKPKb6b7SP6lowN0lsOm+eyDssTBMoEZKSfwK+mrG4YtUhM66YNrJI22L32Vt+CcjteU0Vw==",
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz",
|
||||
@@ -9547,9 +9566,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/gotrue-js": {
|
||||
"version": "2.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.18.1.tgz",
|
||||
"integrity": "sha512-nXTQPbV1t1WRmdAfUeed0uIXiTwNplCGVEnHbbymyx0V7YZShlzgayuB5WZDRZLau5jg616NIRWf6/9VNF3hlg==",
|
||||
"version": "2.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.24.0.tgz",
|
||||
"integrity": "sha512-ZsH4K5cbMTjfMytXaDYVYs9l9igmlZFxiwXn7J2IP/CklWR5qmLCma+dvat5rccPLITVkN6oAZbKxDzW+pEgCg==",
|
||||
"dependencies": {
|
||||
"cross-fetch": "^3.1.5"
|
||||
}
|
||||
@@ -38890,7 +38909,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@supabase/gotrue-js": "^2.16.0",
|
||||
"@supabase/gotrue-js": "2.24.0",
|
||||
"@supabase/ui": "^0.37.0-alpha.50",
|
||||
"react-use": "^17.4.0"
|
||||
},
|
||||
@@ -39005,6 +39024,7 @@
|
||||
"postcss": "^8.4.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-countdown": "^2.3.5",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
@@ -39018,6 +39038,7 @@
|
||||
"@storybook/react": "^6.5.16",
|
||||
"@types/common-tags": "^1.8.1",
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-copy-to-clipboard": "^5.0.4",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"sql-formatter": "^12.2.0",
|
||||
"storybook-dark-mode": "^2.1.1",
|
||||
@@ -39047,6 +39068,15 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"packages/ui/node_modules/@types/react-copy-to-clipboard": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz",
|
||||
"integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"packages/ui/node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"license": "MIT",
|
||||
@@ -43523,6 +43553,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz",
|
||||
"integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA=="
|
||||
},
|
||||
"@octokit/plugin-paginate-graphql": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-2.0.1.tgz",
|
||||
"integrity": "sha512-ZlhrWMlkGeK7qkWMKPKb6b7SP6lowN0lsOm+eyDssTBMoEZKSfwK+mrG4YtUhM66YNrJI22L32Vt+CcjteU0Vw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz",
|
||||
@@ -46230,9 +46266,9 @@
|
||||
}
|
||||
},
|
||||
"@supabase/gotrue-js": {
|
||||
"version": "2.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.18.1.tgz",
|
||||
"integrity": "sha512-nXTQPbV1t1WRmdAfUeed0uIXiTwNplCGVEnHbbymyx0V7YZShlzgayuB5WZDRZLau5jg616NIRWf6/9VNF3hlg==",
|
||||
"version": "2.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.24.0.tgz",
|
||||
"integrity": "sha512-ZsH4K5cbMTjfMytXaDYVYs9l9igmlZFxiwXn7J2IP/CklWR5qmLCma+dvat5rccPLITVkN6oAZbKxDzW+pEgCg==",
|
||||
"requires": {
|
||||
"cross-fetch": "^3.1.5"
|
||||
}
|
||||
@@ -49775,12 +49811,12 @@
|
||||
"version": "file:packages/common",
|
||||
"requires": {
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@supabase/gotrue-js": "^2.16.0",
|
||||
"@supabase/gotrue-js": "2.24.0",
|
||||
"@supabase/ui": "^0.37.0-alpha.50",
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"config": "*",
|
||||
"react-use": "*",
|
||||
"react-use": "^17.4.0",
|
||||
"tsconfig": "*",
|
||||
"typescript": "^4.5.3"
|
||||
},
|
||||
@@ -51481,6 +51517,9 @@
|
||||
"@mdx-js/loader": "^1.6.22",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"@next/mdx": "^12.0.4",
|
||||
"@octokit/auth-app": "^4.0.9",
|
||||
"@octokit/core": "^4.2.0",
|
||||
"@octokit/plugin-paginate-graphql": "^2.0.1",
|
||||
"@radix-ui/react-accordion": "^1.0.1",
|
||||
"@supabase/auth-helpers-nextjs": "^0.5.6",
|
||||
"@supabase/auth-helpers-react": "^0.3.1",
|
||||
@@ -51542,6 +51581,7 @@
|
||||
"ui": "*",
|
||||
"unist-builder": "^3.0.1",
|
||||
"unist-util-filter": "^4.0.1",
|
||||
"uuid": "^9.0.0",
|
||||
"valtio": "^1.7.6"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -51877,6 +51917,11 @@
|
||||
"unist-util-is": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
|
||||
},
|
||||
"valtio": {
|
||||
"version": "1.7.6",
|
||||
"requires": {
|
||||
@@ -66373,7 +66418,7 @@
|
||||
"config": "*",
|
||||
"configcat-js": "^7.0.0",
|
||||
"dayjs": "^1.11.0",
|
||||
"eslint-config-next": "*",
|
||||
"eslint-config-next": "^13.3.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"generate-password": "^1.7.0",
|
||||
"graphql": "^16.6.0",
|
||||
@@ -68050,6 +68095,7 @@
|
||||
"@tailwindcss/typography": "^0.5.0",
|
||||
"@types/common-tags": "^1.8.1",
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-copy-to-clipboard": "^5.0.4",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"clsx": "^1.2.1",
|
||||
@@ -68063,6 +68109,7 @@
|
||||
"postcss": "^8.4.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-countdown": "^2.3.5",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
@@ -68094,6 +68141,15 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"@types/react-copy-to-clipboard": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz",
|
||||
"integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.2.1"
|
||||
},
|
||||
@@ -69822,7 +69878,6 @@
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"react": "^17.0.2",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-countdown": "^2.3.5",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-ga": "^3.3.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@supabase/gotrue-js": "^2.16.0",
|
||||
"@supabase/gotrue-js": "2.24.0",
|
||||
"@supabase/ui": "^0.37.0-alpha.50",
|
||||
"react-use": "^17.4.0"
|
||||
},
|
||||
|
||||
@@ -42,15 +42,17 @@
|
||||
"sse.js": "^0.6.1",
|
||||
"tailwind-merge": "^1.10.0",
|
||||
"tailwindcss": "^3.0.15",
|
||||
"tailwindcss-radix": "^1.6.0"
|
||||
"tailwindcss-radix": "^1.6.0",
|
||||
"react-countdown": "^2.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/react": "^6.5.16",
|
||||
"storybook-dark-mode": "^2.1.1",
|
||||
"@types/common-tags": "^1.8.1",
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-copy-to-clipboard": "^5.0.4",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"sql-formatter": "^12.2.0",
|
||||
"storybook-dark-mode": "^2.1.1",
|
||||
"typescript": "4.3.4"
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,9 @@ import {
|
||||
IconAlertTriangle,
|
||||
IconBook,
|
||||
IconChevronRight,
|
||||
IconGitHub,
|
||||
IconHash,
|
||||
IconMessageSquare,
|
||||
IconSearch,
|
||||
useCommandMenu,
|
||||
} from 'ui'
|
||||
@@ -27,6 +29,7 @@ const questions = [
|
||||
export enum PageType {
|
||||
Markdown = 'markdown',
|
||||
Reference = 'reference',
|
||||
GithubDiscussion = 'github-discussions',
|
||||
}
|
||||
|
||||
export interface PageSection {
|
||||
@@ -163,14 +166,11 @@ const DocsSearch = () => {
|
||||
value={`${page.meta.title}-item-index-${i}`}
|
||||
type="block-link"
|
||||
onSelect={() => {
|
||||
// TODO: replace with Next.js router/Link when cross-project link logic solved
|
||||
window.location.assign(`/docs/${page.path}`)
|
||||
openLink(page.type, formatPageUrl(page))
|
||||
}}
|
||||
>
|
||||
<div className="grow flex gap-3 items-center">
|
||||
<IconContainer>
|
||||
<IconBook strokeWidth={1.5} className="!mr-0 !w-4 !h-4" />
|
||||
</IconContainer>
|
||||
<IconContainer>{getPageIcon(page)}</IconContainer>
|
||||
<div className="flex flex-col gap-0">
|
||||
<CommandLabel>
|
||||
<TextHighlighter text={page.meta.title} query={search} />
|
||||
@@ -190,21 +190,14 @@ const DocsSearch = () => {
|
||||
forceMount
|
||||
className="ml-3 mb-3"
|
||||
onSelect={() => {
|
||||
// TODO: replace with Next.js router/Link when cross-project link logic solved
|
||||
window.location.assign(
|
||||
`/docs/${page.path}${page.type === PageType.Reference ? '/' : '#'}${
|
||||
section.slug
|
||||
}`
|
||||
)
|
||||
openLink(page.type, formatSectionUrl(page, section))
|
||||
}}
|
||||
key={`${page.meta.title}__${section.heading}-item-index-${i}`}
|
||||
value={`${page.meta.title}__${section.heading}-item-index-${i}`}
|
||||
type="block-link"
|
||||
>
|
||||
<div className="grow flex gap-3 items-center">
|
||||
<IconContainer>
|
||||
<IconHash strokeWidth={1.5} className="!mr-0 !w-4 !h-4" />
|
||||
</IconContainer>
|
||||
<IconContainer>{getPageSectionIcon(page)}</IconContainer>
|
||||
<div className="flex flex-col gap-2">
|
||||
<cite>
|
||||
<TextHighlighter
|
||||
@@ -281,3 +274,63 @@ const DocsSearch = () => {
|
||||
}
|
||||
|
||||
export default DocsSearch
|
||||
|
||||
export function formatPageUrl(page: PageResult) {
|
||||
switch (page.type) {
|
||||
case PageType.Markdown:
|
||||
case PageType.Reference:
|
||||
return `/docs/${page.path}`
|
||||
case PageType.GithubDiscussion:
|
||||
return page.path
|
||||
default:
|
||||
throw new Error(`Unknown page type '${page.type}'`)
|
||||
}
|
||||
}
|
||||
|
||||
export function formatSectionUrl(page: PageResult, section: PageSection) {
|
||||
switch (page.type) {
|
||||
case PageType.Markdown:
|
||||
case PageType.GithubDiscussion:
|
||||
return `${formatPageUrl(page)}#${section.slug}`
|
||||
case PageType.Reference:
|
||||
return `${formatPageUrl(page)}/${section.slug}`
|
||||
default:
|
||||
throw new Error(`Unknown page type '${page.type}'`)
|
||||
}
|
||||
}
|
||||
|
||||
export function getPageIcon(page: PageResult) {
|
||||
switch (page.type) {
|
||||
case PageType.Markdown:
|
||||
case PageType.Reference:
|
||||
return <IconBook strokeWidth={1.5} className="!mr-0 !w-4 !h-4" />
|
||||
case PageType.GithubDiscussion:
|
||||
return <IconGitHub strokeWidth={1.5} className="!mr-0 !w-4 !h-4" />
|
||||
default:
|
||||
throw new Error(`Unknown page type '${page.type}'`)
|
||||
}
|
||||
}
|
||||
|
||||
export function getPageSectionIcon(page: PageResult) {
|
||||
switch (page.type) {
|
||||
case PageType.Markdown:
|
||||
case PageType.Reference:
|
||||
return <IconHash strokeWidth={1.5} className="!mr-0 !w-4 !h-4" />
|
||||
case PageType.GithubDiscussion:
|
||||
return <IconMessageSquare strokeWidth={1.5} className="!mr-0 !w-4 !h-4" />
|
||||
default:
|
||||
throw new Error(`Unknown page type '${page.type}'`)
|
||||
}
|
||||
}
|
||||
|
||||
export function openLink(pageType: PageType, link: string) {
|
||||
switch (pageType) {
|
||||
case PageType.Markdown:
|
||||
case PageType.Reference:
|
||||
return window.location.assign(link)
|
||||
case PageType.GithubDiscussion:
|
||||
return window.open(link, '_blank')
|
||||
default:
|
||||
throw new Error(`Unknown page type '${pageType}'`)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,11 @@ const SidePanel = ({
|
||||
onCloseAutoFocus={props.onCloseAutoFocus}
|
||||
onEscapeKeyDown={props.onEscapeKeyDown}
|
||||
onPointerDownOutside={props.onPointerDownOutside}
|
||||
onInteractOutside={props.onInteractOutside}
|
||||
onInteractOutside={(event) => {
|
||||
const isToast = (event.target as Element)?.closest('#toast')
|
||||
if (isToast) event.preventDefault()
|
||||
if (props.onInteractOutside) props.onInteractOutside(event)
|
||||
}}
|
||||
>
|
||||
{header && <header className={__styles.header}>{header}</header>}
|
||||
<div className={__styles.contents}>{children}</div>
|
||||
|
||||
+202
-18
@@ -1,7 +1,7 @@
|
||||
elispec: '001'
|
||||
clispec: '001'
|
||||
info:
|
||||
id: cli
|
||||
version: 1.42.0
|
||||
version: 1.50.13
|
||||
title: Supabase CLI
|
||||
language: sh
|
||||
source: https://github.com/supabase/cli
|
||||
@@ -405,6 +405,25 @@ commands:
|
||||
- id: supabase-test-db
|
||||
title: supabase test db
|
||||
summary: Tests local database with pgTAP
|
||||
description: |2
|
||||
|
||||
Executes pgTAP tests against the local database.
|
||||
|
||||
Requires the local development stack to be started by running `supabase start`.
|
||||
|
||||
Runs `pg_prove` in a container with unit test files volume mounted from `supabase/tests` directory. The test file can be suffixed by either `.sql` or `.pg` extension.
|
||||
|
||||
Since each test is wrapped in its own transaction, it will be individually rolled back regardless of success or failure.
|
||||
examples:
|
||||
- id: basic-usage
|
||||
name: Basic usage
|
||||
code: supabase test db
|
||||
response: |
|
||||
/tmp/supabase/tests/nested/order_test.pg .. ok
|
||||
/tmp/supabase/tests/pet_test.sql .......... ok
|
||||
All tests successful.
|
||||
Files=2, Tests=2, 6 wallclock secs ( 0.03 usr 0.01 sys + 0.05 cusr 0.02 csys = 0.11 CPU)
|
||||
Result: PASS
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase test db
|
||||
@@ -460,7 +479,8 @@ commands:
|
||||
response: |
|
||||
supabase local development setup is running.
|
||||
|
||||
API URL: http://localhost:54321
|
||||
API URL: http://localhost:54321
|
||||
GraphQL URL: http://localhost:54321/graphql/v1
|
||||
DB URL: postgresql://postgres:postgres@localhost:54322/postgres
|
||||
Studio URL: http://localhost:54323
|
||||
Inbucket URL: http://localhost:54324
|
||||
@@ -474,6 +494,7 @@ commands:
|
||||
ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0"
|
||||
API_URL="http://localhost:54321"
|
||||
DB_URL="postgresql://postgres:postgres@localhost:54322/postgres"
|
||||
GRAPHQL_URL="http://localhost:54321/graphql/v1"
|
||||
INBUCKET_URL="http://localhost:54324"
|
||||
JWT_SECRET="super-secret-jwt-token-with-at-least-32-characters-long"
|
||||
SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"
|
||||
@@ -485,6 +506,7 @@ commands:
|
||||
Stopped services: [supabase_inbucket_cli supabase_rest_cli supabase_studio_cli]
|
||||
SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0"
|
||||
DB_URL="postgresql://postgres:postgres@localhost:54322/postgres"
|
||||
GRAPHQL_URL="http://localhost:54321/graphql/v1"
|
||||
JWT_SECRET="super-secret-jwt-token-with-at-least-32-characters-long"
|
||||
SUPABASE_SERVICE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"
|
||||
tags:
|
||||
@@ -494,25 +516,25 @@ commands:
|
||||
subcommands: []
|
||||
flags:
|
||||
- id: output
|
||||
name: -o, --output <[ env | json | pretty | toml | yaml ]>
|
||||
name: -o, --output <[ env | pretty | json | toml | yaml ]>
|
||||
description: Output format of status variables.
|
||||
default_value: pretty
|
||||
accepted_values:
|
||||
- id: env
|
||||
name: env
|
||||
type: '[ env | json | pretty | toml | yaml ]'
|
||||
- id: json
|
||||
name: json
|
||||
type: '[ env | json | pretty | toml | yaml ]'
|
||||
type: '[ env | pretty | json | toml | yaml ]'
|
||||
- id: pretty
|
||||
name: pretty
|
||||
type: '[ env | json | pretty | toml | yaml ]'
|
||||
type: '[ env | pretty | json | toml | yaml ]'
|
||||
- id: json
|
||||
name: json
|
||||
type: '[ env | pretty | json | toml | yaml ]'
|
||||
- id: toml
|
||||
name: toml
|
||||
type: '[ env | json | pretty | toml | yaml ]'
|
||||
type: '[ env | pretty | json | toml | yaml ]'
|
||||
- id: yaml
|
||||
name: yaml
|
||||
type: '[ env | json | pretty | toml | yaml ]'
|
||||
type: '[ env | pretty | json | toml | yaml ]'
|
||||
- id: override-name
|
||||
name: --override-name <strings>
|
||||
description: Override specific variable names.
|
||||
@@ -536,6 +558,7 @@ commands:
|
||||
name: Basic usage
|
||||
code: supabase start
|
||||
response: |
|
||||
Creating custom roles supabase/roles.sql...
|
||||
Applying migration 20220810154536_employee.sql...
|
||||
Seeding data supabase/seed.sql...
|
||||
Started supabase local development setup.
|
||||
@@ -545,13 +568,11 @@ commands:
|
||||
response: |
|
||||
Excluding container: supabase/studio:20221214-4eecc99
|
||||
Excluding container: darthsim/imgproxy:v3.8.0
|
||||
Seeding data supabase/seed.sql...
|
||||
Started supabase local development setup.
|
||||
- id: ignore-health-check
|
||||
name: Ignore service health checks
|
||||
code: supabase start --ignore-health-check
|
||||
response: |
|
||||
Seeding data supabase/seed.sql...
|
||||
service not healthy: [supabase_storage_cli]
|
||||
Started supabase local development setup.
|
||||
tags:
|
||||
@@ -563,7 +584,7 @@ commands:
|
||||
- id: exclude
|
||||
name: -x, --exclude <strings>
|
||||
description: |
|
||||
Names of containers to not start. [gotrue,realtime,storage-api,imgproxy,kong,inbucket,postgrest,pgadmin-schema-diff,migra,postgres-meta,studio,deno-relay]
|
||||
Names of containers to not start. [gotrue,realtime,storage-api,imgproxy,kong,inbucket,postgrest,pgadmin-schema-diff,migra,postgres-meta,studio,edge-runtime,logflare,vector]
|
||||
default_value: '[]'
|
||||
- id: ignore-health-check
|
||||
name: --ignore-health-check
|
||||
@@ -759,6 +780,9 @@ commands:
|
||||
- id: us-west-1
|
||||
name: us-west-1
|
||||
type: string
|
||||
- id: us-west-2
|
||||
name: us-west-2
|
||||
type: string
|
||||
- id: supabase-orgs
|
||||
title: supabase orgs
|
||||
summary: Manage Supabase organizations
|
||||
@@ -1089,19 +1113,19 @@ commands:
|
||||
name: Basic usage
|
||||
code: supabase link --project-ref ********************
|
||||
response: |
|
||||
Enter your database password: ********
|
||||
Enter your database password (or leave blank to skip): ********
|
||||
Finished supabase link.
|
||||
- id: without-password
|
||||
name: Link without database password
|
||||
code: supabase link --project-ref ******************** <<< ""
|
||||
response: |
|
||||
Enter your database password:
|
||||
Enter your database password (or leave blank to skip):
|
||||
Finished supabase link.
|
||||
- id: using-alternate-dns
|
||||
name: Link using DNS-over-HTTPS resolver
|
||||
code: supabase link --project-ref ******************** --dns-resolver https
|
||||
response: |
|
||||
Enter your database password:
|
||||
Enter your database password (or leave blank to skip):
|
||||
Finished supabase link.
|
||||
tags:
|
||||
- local-dev
|
||||
@@ -1429,6 +1453,25 @@ commands:
|
||||
- id: supabase-db-reset
|
||||
title: supabase db reset
|
||||
summary: Resets the local database to current migrations
|
||||
description: |2
|
||||
|
||||
Resets the local database to a clean state.
|
||||
|
||||
Requires the local development stack to be started by running `supabase start`.
|
||||
|
||||
Recreates the local Postgres container and applies all local migrations found in `supabase/migrations` directory. If test data is defined in `supabase/seed.sql`, it will be seeded after the migrations are run. Any other data or schema changes made during local development will be discarded.
|
||||
|
||||
Note that since Postgres roles are cluster level entities, those changes will persist between resets. In order to reset custom roles, you need to restart the local development stack.
|
||||
examples:
|
||||
- id: basic-usage
|
||||
name: Basic usage
|
||||
code: supabase db reset
|
||||
response: |
|
||||
Resetting database...
|
||||
Initializing schema...
|
||||
Applying migration 20220810154537_create_employees_table.sql...
|
||||
Seeding data supabase/seed.sql...
|
||||
Finished supabase db reset on branch main.
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase db reset
|
||||
@@ -1469,6 +1512,37 @@ commands:
|
||||
- id: supabase-db-push
|
||||
title: supabase db push
|
||||
summary: Push new migrations to the remote database
|
||||
description: |2
|
||||
|
||||
Pushes all local migrations to a remote database.
|
||||
|
||||
Requires your local project to be linked to a remote database by running `supabase link`. For self-hosted databases, you can pass in the connection parameters using `--db-url` flag.
|
||||
|
||||
The first time this command is run, a migration history table will be created under `supabase_migrations.schema_migrations`. After successfully applying a migration, a new row will be inserted into the migration history table with timestamp as its unique id. Subsequent pushes will skip migrations that have already been applied.
|
||||
|
||||
If you need to mutate the migration history table, such as deleting existing entries or inserting new entries without actually running the migration, use the `migration repair` command.
|
||||
|
||||
Use the `--dry-run` flag to view the list of changes before applying.
|
||||
examples:
|
||||
- id: basic-usage
|
||||
name: Basic usage
|
||||
code: supabase db push
|
||||
response: |
|
||||
Linked project is up to date.
|
||||
- id: self-hosted
|
||||
name: Self hosted
|
||||
code: supabase db push --db-url "postgres://user:pass@localhost:5432/postgres"
|
||||
response: |
|
||||
Pushing migration 20230410135622_create_employees_table.sql...
|
||||
Finished supabase db push.
|
||||
- id: dry-run
|
||||
name: Dry run
|
||||
code: supabase db push --dry-run
|
||||
response: |
|
||||
DRY RUN: migrations will *not* be pushed to the database.
|
||||
Would push migration 20230410135622_create_employees_table.sql...
|
||||
Would push migration 20230425064254_my_table.sql...
|
||||
Finished supabase db push.
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase db push [flags]
|
||||
@@ -1490,6 +1564,40 @@ commands:
|
||||
- id: supabase-db-lint
|
||||
title: supabase db lint
|
||||
summary: Checks local database for typing error
|
||||
description: |2
|
||||
|
||||
Lints local database for schema errors.
|
||||
|
||||
Requires the local development stack to be running when linting against the local database. To lint against a remote or self-hosted database, specify the `--linked` or `--db-url` flag respectively.
|
||||
|
||||
Runs `plpgsql_check` extension in the local Postgres container to check for errors in all schemas. The default lint level is `warning` and can be raised to error via the `--level` flag.
|
||||
|
||||
To lint against specific schemas only, pass in the `--schema` flag.
|
||||
examples:
|
||||
- id: basic-usage
|
||||
name: Basic usage
|
||||
code: supabase db lint
|
||||
response: |
|
||||
Linting schema: public
|
||||
|
||||
No schema errors found
|
||||
- id: schema-warnings
|
||||
name: Warnings for a specific schema
|
||||
code: supabase db lint --level warning --schema storage
|
||||
response: |
|
||||
Linting schema: storage
|
||||
[
|
||||
{
|
||||
"function": "storage.search",
|
||||
"issues": [
|
||||
{
|
||||
"level": "warning",
|
||||
"message": "unused variable \"_bucketid\"",
|
||||
"sqlState": "00000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase db lint [flags]
|
||||
@@ -1517,6 +1625,34 @@ commands:
|
||||
- id: supabase-db-dump
|
||||
title: supabase db dump
|
||||
summary: Dumps data or schemas from the remote database
|
||||
description: |2
|
||||
|
||||
Dumps contents from a remote database.
|
||||
|
||||
Requires your local project to be linked to a remote database by running `supabase link`. For self-hosted databases, you can pass in the connection parameters using `--db-url` flag.
|
||||
|
||||
Runs `pg_dump` in a container with additional flags to exclude Supabase managed schemas. The ignored schemas include auth, stroage, and those created by extensions.
|
||||
|
||||
The default dump does not contain any data or custom roles. To dump those contents explicitly, specify either the `--data-only` and `--role-only` flag.
|
||||
examples:
|
||||
- id: basic-usage
|
||||
name: Basic usage
|
||||
code: supabase db dump -f supabase/schema.sql
|
||||
response: |
|
||||
Dumping schemas from remote database...
|
||||
Dumped schema to supabase/schema.sql.
|
||||
- id: role-only
|
||||
name: Role only
|
||||
code: supabase db dump -f supabase/roles.sql --role-only
|
||||
response: |
|
||||
Dumping roles from remote database...
|
||||
Dumped schema to supabase/roles.sql.
|
||||
- id: data-only
|
||||
name: Data only
|
||||
code: supabase db dump -f supabase/seed.sql --data-only
|
||||
response: |
|
||||
Dumping data from remote database...
|
||||
Dumped schema to supabase/seed.sql.
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase db dump [flags]
|
||||
@@ -1545,6 +1681,54 @@ commands:
|
||||
- id: supabase-db-diff
|
||||
title: supabase db diff
|
||||
summary: Diffs the local database for schema changes
|
||||
description: |2
|
||||
|
||||
Diffs schema changes made to the local or remote database.
|
||||
|
||||
Requires the local development stack to be running when diffing against the local database. To diff against a remote or self-hosted database, specify the `--linked` or `--db-url` flag respectively.
|
||||
|
||||
Runs [djrobstep/migra](https://github.com/djrobstep/migra) in a container to compare schema differences between the target database and a shadow database. The shadow database is created by applying migrations in local `supabase/migrations` directory in a separate container. Output is written to stdout by default. For convenience, you can also save the schema diff as a new migration file by passing in `-f` flag.
|
||||
|
||||
By default, all schemas in the target database are diffed. Use the `--schema public,extensions` flag to restrict diffing to a subset of schemas.
|
||||
|
||||
While the diff command is able to capture most schema changes, there are cases where it is known to fail. Currently, this could happen if you schema contains:
|
||||
|
||||
- Changes to publication
|
||||
- Changes to storage buckets
|
||||
- Views with `security_invoker` attributes
|
||||
examples:
|
||||
- id: basic-usage
|
||||
name: Basic usage
|
||||
code: supabase db diff -f my_table
|
||||
response: |
|
||||
Connecting to local database...
|
||||
Creating shadow database...
|
||||
Applying migration 20230425064254_remote_commit.sql...
|
||||
Diffing schemas: auth,extensions,public,storage
|
||||
Finished supabase db diff on branch main.
|
||||
|
||||
No schema changes found
|
||||
- id: linked-project
|
||||
name: Against linked project
|
||||
code: supabase db diff -f my_table --linked
|
||||
response: |
|
||||
Connecting to local database...
|
||||
Creating shadow database...
|
||||
Diffing schemas: auth,extensions,public,storage
|
||||
Finished supabase db diff on branch main.
|
||||
|
||||
WARNING: The diff tool is not foolproof, so you may need to manually rearrange and modify the generated migration.
|
||||
Run supabase db reset to verify that the new migration does not generate errors.
|
||||
- id: specific-schema
|
||||
name: For a specific schema
|
||||
code: supabase db diff -f my_table --schema auth
|
||||
response: |
|
||||
Connecting to local database...
|
||||
Creating shadow database...
|
||||
Diffing schemas: auth
|
||||
Finished supabase db diff on branch main.
|
||||
|
||||
No schema changes found
|
||||
tags: []
|
||||
links: []
|
||||
usage: supabase db diff [flags]
|
||||
@@ -1602,7 +1786,7 @@ commands:
|
||||
|
||||
To load completions in your current shell session:
|
||||
|
||||
source <(supabase completion zsh); compdef _supabase supabase
|
||||
source <(supabase completion zsh)
|
||||
|
||||
To load completions for every new session, execute once:
|
||||
|
||||
|
||||
@@ -183,12 +183,6 @@ const PolicyEditorModal: FC<Props> = ({
|
||||
/>,
|
||||
]}
|
||||
onCancel={onSelectCancel}
|
||||
onInteractOutside={(event) => {
|
||||
const isToast = (event.target as Element)?.closest('#toast')
|
||||
if (isToast) {
|
||||
event.preventDefault()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="">
|
||||
{view === POLICY_MODAL_VIEWS.SELECTION ? (
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { FC } from 'react'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { Badge, IconClipboard, IconExternalLink, IconGlobe } from 'ui'
|
||||
import Table from 'components/to-be-cleaned/Table'
|
||||
|
||||
import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock'
|
||||
import router, { useRouter } from 'next/router'
|
||||
// import logDropdown from './logDropdown'
|
||||
|
||||
interface Props {
|
||||
log: any
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
const FunctionLogsItem: FC<Props> = ({ log, onClick }) => {
|
||||
const islogConfirmed = log.email_confirmed_at || log.phone_confirmed_at
|
||||
|
||||
const router = useRouter()
|
||||
const { ref } = router.query
|
||||
|
||||
return (
|
||||
<Table.tr key={log.id} onClick={onClick}>
|
||||
<Table.td className="whitespace-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="rounded bg-scale-500 px-2">{log.function_status}</div>
|
||||
</div>
|
||||
</Table.td>
|
||||
<Table.td className="">
|
||||
<span className="text-xs text-scale-1100">{log.method}</span>
|
||||
</Table.td>
|
||||
<Table.td className="">
|
||||
<span className="font-mono text-xs text-scale-1100">{log.url}</span>
|
||||
</Table.td>
|
||||
<Table.td className="">
|
||||
<span className="text-scale-1100">
|
||||
{dayjs(log.created_at).format('DD MMM, YYYY HH:mm')}
|
||||
</span>
|
||||
</Table.td>
|
||||
</Table.tr>
|
||||
)
|
||||
}
|
||||
|
||||
export default observer(FunctionLogsItem)
|
||||
@@ -75,14 +75,6 @@ const Results = ({ id, rows }: { id: string; rows: readonly any[] }) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (rows.length <= 0) {
|
||||
return (
|
||||
<div className="bg-table-header-light dark:bg-table-header-dark">
|
||||
<p className="m-0 border-0 px-6 py-4 font-mono text-sm">Success. No rows returned</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DataGrid
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Button, IconChevronRight, IconMaximize2, IconPlay } from 'ui'
|
||||
import Table from 'components/to-be-cleaned/Table'
|
||||
import { useRouter } from 'next/router'
|
||||
import SqlSnippetCode from './Logs.SqlSnippetCode'
|
||||
import { timestampLocalFormatter, TimestampLocalFormatter } from './LogsFormatters'
|
||||
|
||||
interface Props {
|
||||
item: any
|
||||
@@ -33,12 +34,12 @@ const SavedQueriesItem: FC<Props> = ({ item }: Props) => {
|
||||
</Table.td>
|
||||
<Table.td className="">
|
||||
<span className="text-scale-1100">
|
||||
{dayjs(item.inserted_at).format('DD MMM, YYYY HH:mm')}
|
||||
{timestampLocalFormatter(item.inserted_at)}
|
||||
</span>
|
||||
</Table.td>
|
||||
<Table.td className="">
|
||||
<span className="text-scale-1100">
|
||||
{dayjs(item.updated_at).format('DD MMM, YYYY HH:mm')}
|
||||
{timestampLocalFormatter(item.updated_at)}
|
||||
</span>
|
||||
</Table.td>
|
||||
<Table.td className=" text-right">
|
||||
|
||||
@@ -235,9 +235,16 @@ export const TimestampLocalFormatter = ({
|
||||
className?: string
|
||||
value: string | number
|
||||
}) => {
|
||||
return <span className={`text-xs ${className}`}>{timestampLocalFormatter(value)}</span>
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string to local timestamp display
|
||||
* Accepts unix microsecond or iso timestamp
|
||||
*/
|
||||
export const timestampLocalFormatter = (value: string | number) => {
|
||||
const timestamp = isUnixMicro(value) ? unixMicroToIsoTimestamp(value) : value
|
||||
const formattedTimestamp = dayjs(timestamp).format('DD MMM, HH:mm:ss')
|
||||
return <span className={`text-xs ${className}`}>{formattedTimestamp}</span>
|
||||
return dayjs(timestamp).format('DD MMM HH:mm:ss')
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
-4
@@ -198,10 +198,6 @@ const ColumnEditor = ({
|
||||
applyFunction={(resolve: () => void) => onSaveChanges(resolve)}
|
||||
/>
|
||||
}
|
||||
onInteractOutside={(event) => {
|
||||
const isToast = (event.target as Element)?.closest('#toast')
|
||||
if (isToast) event.preventDefault()
|
||||
}}
|
||||
>
|
||||
<FormSection header={<FormSectionLabel className="lg:!col-span-4">General</FormSectionLabel>}>
|
||||
<FormSectionContent loading={false} className="lg:!col-span-8">
|
||||
|
||||
@@ -143,10 +143,6 @@ const RowEditor = ({
|
||||
isEditingJson || isSelectingForeignKey ? ' mr-32' : ''
|
||||
}`}
|
||||
onCancel={closePanel}
|
||||
onInteractOutside={(event) => {
|
||||
const isToast = (event.target as Element)?.closest('#toast')
|
||||
if (isToast) event.preventDefault()
|
||||
}}
|
||||
>
|
||||
<form onSubmit={(e) => onSaveChanges(e)} className="h-full">
|
||||
<div className="flex h-full flex-col">
|
||||
|
||||
-4
@@ -192,10 +192,6 @@ const SpreadsheetImport: FC<Props> = ({
|
||||
applyFunction={onConfirm}
|
||||
/>
|
||||
}
|
||||
onInteractOutside={(event) => {
|
||||
const isToast = (event.target as Element)?.closest('#toast')
|
||||
if (isToast) event.preventDefault()
|
||||
}}
|
||||
>
|
||||
<SidePanel.Content>
|
||||
<div className="pt-6">
|
||||
|
||||
-6
@@ -183,12 +183,6 @@ const TableEditor: FC<Props> = ({
|
||||
applyFunction={(resolve: () => void) => onSaveChanges(resolve)}
|
||||
/>
|
||||
}
|
||||
onInteractOutside={(event) => {
|
||||
const isToast = (event.target as Element)?.closest('#toast')
|
||||
if (isToast) {
|
||||
event.preventDefault()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<>
|
||||
<SidePanel.Content>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
alter table "public"."page"
|
||||
add "version" uuid,
|
||||
add "last_refresh" timestamptz;
|
||||
Reference in new issue
Block a user