diff --git a/.prettierignore b/.prettierignore index 9ab0849d504..db287264935 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,4 +3,5 @@ node_modules package-lock.json docker* -apps/**/out \ No newline at end of file +apps/**/out +**/**.mdx \ No newline at end of file diff --git a/apps/docs/.env.example b/apps/docs/.env.example new file mode 100644 index 00000000000..074fa5ced44 --- /dev/null +++ b/apps/docs/.env.example @@ -0,0 +1,8 @@ +# PUBLIC +NEXT_PUBLIC_NEW_DOCS=true +NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321 +NEXT_PUBLIC_SUPABASE_ANON_KEY= + +# PRIVATE +OPENAI_KEY= +SUPABASE_SERVICE_ROLE_KEY= diff --git a/apps/docs/components/Clippy/Clippy.tsx b/apps/docs/components/Clippy/Clippy.tsx new file mode 100644 index 00000000000..8b32b2c042f --- /dev/null +++ b/apps/docs/components/Clippy/Clippy.tsx @@ -0,0 +1,35 @@ +import { useTheme } from 'common/Providers' +import Image from 'next/image' +import { FC } from 'react' +import { createPortal } from 'react-dom' +import clippyImageDark from '../../public/img/clippy-dark.png' +import clippyImage from '../../public/img/clippy.png' +import ClippyBubble from './ClippyBubble' +import ClippyModal from './ClippyModal' +import { useClippy } from './ClippyProvider' +import { useFlag } from '~/hooks/useFlag' +const Clippy: FC = () => { + const { isDarkMode } = useTheme() + const { isOpen, open, close } = useClippy() + const enableClippy = useFlag('enableClippy') + + return ( + <> + {!isOpen && ( +
+
Sorry, I don't know how to help with that.
+Searching for results
+Sorry, looks like Clippy is having a hard time!
+Please try again in a bit.
+ + tag
// if it's fewer than 70 characters, add a white-space: pre so it doesn't wrap
const shortCodeBlockClasses =
- typeof children === 'string' && children.length < 70 ? 'short-inline-codeblock' : ''
+ typeof codeValue === 'string' && codeValue.length < 70 ? 'short-inline-codeblock' : ''
let lang = language ? language : className ? className.replace('language-', '') : 'js'
// force jsx to be js highlighted
@@ -118,7 +126,7 @@ const CodeBlock: FC = ({
paddingBottom: '4px',
}}
>
- {(value || children)?.trimEnd()}
+ {codeValue}
{!hideCopy && (value || children) && className ? (
= ({
`${!title ? 'top-2' : 'top-[3.25rem]'}`,
].join(' ')}
>
- {/* //
+ {/* //
@ts-ignore */}
-
-
+
+
+
+
+
-
-
- ```csharp
- var url = Environment.GetEnvironmentVariable("SUPABASE_URL");
- var key = Environment.GetEnvironmentVariable("SUPABASE_KEY");
-
- var options = new Supabase.SupabaseOptions
- {
- AutoConnectRealtime = true
- };
-
- var supabase = new Supabase.Client(url, key, options);
- await supabase.InitializeAsync();
- ```
-
-
-
-
-
- ```csharp
- public static MauiApp CreateMauiApp()
- {
- // ...
- var builder = MauiApp.CreateBuilder();
-
- var url = Environment.GetEnvironmentVariable("SUPABASE_URL");
- var key = Environment.GetEnvironmentVariable("SUPABASE_KEY");
- var options = new SupabaseOptions
- {
- AutoRefreshToken = true,
- AutoConnectRealtime = true,
- SessionHandler = new SupabaseSessionHandler()
- };
-
- // Note the creation as a singleton.
- builder.Services.AddSingleton(provider => new Supabase.Client(url, key, options));
- }
- ```
-
-
-
-
- ```csharp
- // Given the following Model representing the Supabase Database (Message.cs)
- [Table("messages")]
- public class Message : BaseModel
- {
- [PrimaryKey("id")]
- public int Id { get; set; }
-
- [Column("username")]
- public string UserName { get; set; }
-
- [Column("channel_id")]
- public int ChannelId { get; set; }
-
- public override bool Equals(object obj)
- {
- return obj is Message message &&
- Id == message.Id;
- }
-
- public override int GetHashCode()
- {
- return HashCode.Combine(Id);
- }
- }
-
- void Initialize()
- {
- // Get All Messages
- var response = await client.Table().Get();
- List models = response.Models;
-
- // Insert
- var newMessage = new Message { UserName = "acupofjose", ChannelId = 1 };
- await client.Table().Insert();
-
- // Update
- var model = response.Models.First();
- model.UserName = "elrhomariyounes";
- await model.Update();
-
- // Delete
- await response.Models.Last().Delete();
-
- // etc.
- }
- ```
-
-
-
-
-
-
diff --git a/apps/docs/hooks/useFlag.ts b/apps/docs/hooks/useFlag.ts
new file mode 100644
index 00000000000..3e990f6b3a8
--- /dev/null
+++ b/apps/docs/hooks/useFlag.ts
@@ -0,0 +1,7 @@
+import { useContext } from 'react'
+import FlagContext from 'components/Flag/FlagContext'
+
+export function useFlag(name: string) {
+ const store: any = useContext(FlagContext)
+ return store[name]
+}
diff --git a/apps/docs/layouts/SiteLayout.tsx b/apps/docs/layouts/SiteLayout.tsx
index 6c7a05943ab..d1f37b40d1b 100644
--- a/apps/docs/layouts/SiteLayout.tsx
+++ b/apps/docs/layouts/SiteLayout.tsx
@@ -7,6 +7,7 @@ import TopNavBarRef from '~/components/Navigation/NavigationMenu/TopNavBarRef'
import FooterHelpCallout from '~/components/FooterHelpCallout'
import { memo, useEffect } from 'react'
+import Clippy from '~/components/Clippy/Clippy'
import Footer from '~/components/Navigation/Footer'
import { menuState, useMenuLevelId, useMenuMobileOpen } from '~/hooks/useMenuState'
@@ -338,6 +339,9 @@ const SiteLayout = ({ children }) => {
+
+
+
)
diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs
index bf98d6d34fd..003bb8c1340 100644
--- a/apps/docs/next.config.mjs
+++ b/apps/docs/next.config.mjs
@@ -84,6 +84,6 @@ const nextConfig = {
// next.config.js
export default () => {
// const plugins = [withMDX]/
- const plugins = [withTM(['ui', 'common']), withMDX, withYaml]
+ const plugins = [withTM(['ui', 'common', '@supabase/auth-helpers-nextjs']), withMDX, withYaml]
return plugins.reduce((acc, next) => next(acc), nextConfig)
}
diff --git a/apps/docs/package.json b/apps/docs/package.json
index f5168dc5a4e..a8c42541d9e 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -8,6 +8,7 @@
"start": "next start",
"lint": "next lint",
"build:sitemap": "node ./internals/generate-sitemap.mjs",
+ "build:embeddings": "tsx scripts/generate-embeddings.ts",
"postbuild": "ts-node ./scripts/build-search.ts && node ./internals/generate-sitemap.mjs",
"generate:all": "npm-run-all --parallel gen:api gen:cli gen:gotrue gen:storage gen:supabase-dart:v0 gen:supabase-dart:v1 gen:supabase-csharp:v0 gen:supabase-js:v1 gen:supabase-js:v2 gen:realtime",
"gen:api": "npm-run-all gen:api:usage",
@@ -42,6 +43,9 @@
"@mdx-js/react": "^1.6.22",
"@next/mdx": "^12.0.4",
"@radix-ui/react-accordion": "^1.0.1",
+ "@supabase/auth-helpers-nextjs": "^0.5.4",
+ "@supabase/auth-helpers-react": "^0.3.1",
+ "@supabase/supabase-js": "^2.4.1",
"algoliasearch": "^4.14.2",
"babel": "^6.23.0",
"clsx": "^1.2.1",
@@ -52,7 +56,12 @@
"jsrsasign": "^10.5.26",
"lodash": "^4.17.21",
"markdown-toc": "^1.2.0",
+ "mdast": "^3.0.0",
+ "mdast-util-from-markdown": "^1.2.0",
+ "mdast-util-mdx": "^2.0.0",
+ "mdast-util-to-markdown": "^1.5.0",
"mdx-mermaid": "2.0.0-rc3",
+ "micromark-extension-mdxjs": "^1.0.0",
"next": "12.3.2",
"next-compose-plugins": "^2.2.1",
"next-mdx-remote": "^4.1.0",
@@ -60,6 +69,7 @@
"next-plugin-yaml": "^1.0.1",
"next-seo": "^5.14.1",
"next-transpile-modules": "^9.0.0",
+ "openai": "^3.1.0",
"react": "17.0.2",
"react-copy-to-clipboard": "^5.0.2",
"react-dom": "17.0.2",
@@ -72,7 +82,10 @@
"remark-gfm": "^3.0.1",
"remark-slug": "^7.0.1",
"shiki": "^0.11.1",
+ "sse.js": "^0.6.1",
"ui": "*",
+ "unist-builder": "^3.0.1",
+ "unist-util-filter": "^4.0.1",
"valtio": "^1.7.6"
},
"devDependencies": {
@@ -91,6 +104,7 @@
"sass": "^1.55.0",
"ts-node": "^10.9.1",
"tsconfig": "*",
+ "tsx": "^3.12.2",
"typescript": "^4.5.3"
}
}
diff --git a/apps/docs/pages/_app.tsx b/apps/docs/pages/_app.tsx
index 0736cff9c2b..b72ffab2086 100644
--- a/apps/docs/pages/_app.tsx
+++ b/apps/docs/pages/_app.tsx
@@ -1,21 +1,26 @@
+import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
+import { SessionContextProvider } from '@supabase/auth-helpers-react'
+import { ThemeProvider } from 'common/Providers'
import { DefaultSeo } from 'next-seo'
import { useRouter } from 'next/router'
-import { useEffect } from 'react'
+import { useEffect, useState } from 'react'
import { AppPropsWithLayout } from 'types'
+import ClippyProvider from '~/components/Clippy/ClippyProvider'
import { SearchProvider } from '~/components/DocSearch'
import Favicons from '~/components/Favicons'
-import { ThemeProvider } from 'common/Providers'
import SiteLayout from '~/layouts/SiteLayout'
+import { post } from '~/lib/fetchWrappers'
+import FlagProvider from 'components/Flag/FlagProvider'
import '../styles/algolia-search.scss'
import '../styles/ch.scss'
import '../styles/docsearch.scss'
import '../styles/main.scss?v=1.0.0'
import '../styles/new-docs.scss'
import '../styles/prism-okaidia.scss'
-import { post } from '~/lib/fetchWrappers'
function MyApp({ Component, pageProps }: AppPropsWithLayout) {
const router = useRouter()
+ const [supabase] = useState(() => createBrowserSupabaseClient())
function telemetry(route: string) {
return post(`https://api.supabase.io/platform/telemetry/page`, {
@@ -58,36 +63,42 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
return (
<>
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
)
}
diff --git a/apps/docs/pages/guides/cli/local-development.mdx b/apps/docs/pages/guides/cli/local-development.mdx
index 5431bfdc3a9..1c8f21a9b05 100644
--- a/apps/docs/pages/guides/cli/local-development.mdx
+++ b/apps/docs/pages/guides/cli/local-development.mdx
@@ -152,10 +152,11 @@ Database changes are managed through "migrations." Database migrations are a com
For this guide, create a table called `employees`. In Supabase Studio, navigate to the **SQL Editor** page and run the following SQL command:
```sql
-create table employees (
- id integer primary key generated always as identity,
- name text
-);
+create table
+ employees (
+ id integer primary key generated always as identity,
+ name text
+ );
```
@@ -177,8 +178,9 @@ This creates a new migration named `supabase/migrations/_create_emplo
Use the seed script in `supabase/seed.sql` (created with [`supabase init`](/docs/reference/cli/usage#supabase-init)) to add sample data to the table.
```sql
--- in supabase/seed.sql
-insert into public.employees (name)
+ -- in supabase/seed.sql
+insert into
+ public.employees (name)
values
('Erlich Bachman'),
('Richard Hendricks'),
@@ -198,9 +200,9 @@ You should now see the contents of `employees` in Studio.
Use the [`reset`](/docs/reference/cli/usage#supabase-db-reset) command to revert any changes to the local database.
```sql
--- run on local database to make a change
-alter table employees
- add department text default 'Hooli';
+ -- run on local database to make a change
+alter table
+ employees add department text default 'Hooli';
```
Run the following command to reset the local database:
@@ -258,10 +260,6 @@ The local development environment is not as feature-complete as the Supabase Pla
- Logs are not supported through the interface (however you can access them through the Docker containers).
- You cannot update your project settings in the Dashboard—this must be done using the CLI.
-```
-
-```
-
export const Page = ({ children }) =>
export default Page
diff --git a/apps/docs/pages/guides/database/extensions/pgvector.mdx b/apps/docs/pages/guides/database/extensions/pgvector.mdx
new file mode 100644
index 00000000000..42118b9197f
--- /dev/null
+++ b/apps/docs/pages/guides/database/extensions/pgvector.mdx
@@ -0,0 +1,101 @@
+import Layout from '~/layouts/DefaultGuideLayout'
+
+export const meta = {
+ id: 'pgvector',
+ title: 'pgvector: Embeddings and vector similarity',
+ description:
+ 'pgvector: a PostgreSQL extension for storing embeddings and performing vector similarity search.',
+}
+
+[pgvector](https://github.com/pgvector/pgvector/) is a PostgreSQL extension for vector similarity search. It can also be used for storing [embeddings](https://en.wikipedia.org/wiki/Word_embedding).
+
+## Concepts
+
+### Vector similarity
+
+Vector similarity refers to a measure of the similarity between two related items. For example, if you have a list of products, you can use vector similarity to find similar products. To do this, you need to convert each product into a "vector" of numbers, using a mathematical model. You can use a similar model for text, images, and other types of data. Once all of these vectors are stored in the database, you can use vector similarity to find similar items.
+
+### Embeddings
+
+This is particularly useful if you're building on top of OpenAI's [GPT-3](https://openai.com/blog/gpt-3-apps/). You can create and store [embeddings](https://platform.openai.com/docs/guides/embeddings) which match the GPT model you're using.
+
+## Usage
+
+### Enable the extension
+
+
+
+
+1. Go to the [Database](https://app.supabase.com/project/_/database/tables) page in the Dashboard.
+2. Click on **Extensions** in the sidebar.
+3. Search for "vector" and enable the extension.
+
+
+
+
+```sql
+ -- Example: enable the "vector" extension.
+create extension vector
+with
+ schema extensions;
+
+-- Example: disable the "vector" extension
+drop
+ extension if exists vector;
+```
+
+Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension".
+To disable an extension, call `drop extension`.
+
+
+
+
+## Usage
+
+### Create a table to store vectors
+
+```sql
+create table
+ posts (
+ id serial primary key,
+ title text not null,
+ body text not null,
+ embedding vector (1536)
+ );
+```
+
+### Storing a vector / embedding
+
+In this example we'll generate a vector using the OpenAI API client, then store it in the database using the Supabase client.
+
+```js
+const title = 'First post!'
+const body = 'Hello world!'
+
+// Generate a vector using OpenAI
+const embeddingResponse = await openai.createEmbedding({
+ model: 'text-embedding-ada-002',
+ input: body,
+})
+const [responseData] = embeddingResponse.data.data.
+
+// Store the vector in Postgres
+const { data, error } = await supabase.from('posts').insert({
+ title,
+ body,
+ embedding: responseData.embedding,
+})
+```
+
+## Resources
+
+- Source code: [github.com/pgvector/pgvector](https://github.com/pgvector/pgvector/)
+
+export const Page = ({ children }) =>
+
+export default Page
diff --git a/apps/docs/pages/guides/getting-started/tutorials/with-angular.mdx b/apps/docs/pages/guides/getting-started/tutorials/with-angular.mdx
index b76748ad8aa..ae2870332c2 100644
--- a/apps/docs/pages/guides/getting-started/tutorials/with-angular.mdx
+++ b/apps/docs/pages/guides/getting-started/tutorials/with-angular.mdx
@@ -62,7 +62,6 @@ import {
User,
} from '@supabase/supabase-js'
import { environment } from 'src/environments/environment'
-import { Database } from 'src/schema'
export interface Profile {
id?: string
@@ -136,7 +135,7 @@ Let's set up an Angular component to manage logins and sign ups. We'll use Magic
Create an **AuthComponent** with `ng g c auth` Angular CLI command.
```ts title=src/app/auth/auth.component.ts
-import { Component, OnInit } from '@angular/core'
+import { Component } from '@angular/core'
import { FormBuilder } from '@angular/forms'
import { SupabaseService } from '../supabase.service'
@@ -145,7 +144,7 @@ import { SupabaseService } from '../supabase.service'
templateUrl: './auth.component.html',
styleUrls: ['./auth.component.css'],
})
-export class AuthComponent implements OnInit {
+export class AuthComponent {
loading = false
signInForm = this.formBuilder.group({
@@ -157,8 +156,6 @@ export class AuthComponent implements OnInit {
private readonly formBuilder: FormBuilder
) {}
- ngOnInit(): void {}
-
async onSubmit(): Promise {
try {
this.loading = true
@@ -406,7 +403,7 @@ Let's create an avatar for the user so that they can upload a profile photo.
Create an **AvatarComponent** with `ng g c avatar` Angular CLI command.
```ts title=src/app/avatar/avatar.component.ts
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
+import { Component, EventEmitter, Input, Output } from '@angular/core'
import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser'
import { SupabaseService } from '../supabase.service'
@@ -415,7 +412,7 @@ import { SupabaseService } from '../supabase.service'
templateUrl: './avatar.component.html',
styleUrls: ['./avatar.component.css'],
})
-export class AvatarComponent implements OnInit {
+export class AvatarComponent {
_avatarUrl: SafeResourceUrl | undefined
uploading = false
@@ -430,8 +427,6 @@ export class AvatarComponent implements OnInit {
constructor(private readonly supabase: SupabaseService, private readonly dom: DomSanitizer) {}
- ngOnInit(): void {}
-
async downloadImage(path: string) {
try {
const { data } = await this.supabase.downLoadImage(path)
diff --git a/apps/docs/pages/guides/realtime/presence.mdx b/apps/docs/pages/guides/realtime/presence.mdx
index 3ae8d565260..e938e74ca3d 100644
--- a/apps/docs/pages/guides/realtime/presence.mdx
+++ b/apps/docs/pages/guides/realtime/presence.mdx
@@ -130,7 +130,7 @@ channel.subscribe(async (status) => {
})
if (presenceTrackStatus === 'ok') {
- const presenceUntrackStatus = await channe.untrack()
+ const presenceUntrackStatus = await channel.untrack()
console.log(presenceUntrackStatus)
}
}
diff --git a/apps/docs/public/img/clippy-dark.png b/apps/docs/public/img/clippy-dark.png
new file mode 100644
index 00000000000..be142ffbe5e
Binary files /dev/null and b/apps/docs/public/img/clippy-dark.png differ
diff --git a/apps/docs/public/img/clippy.png b/apps/docs/public/img/clippy.png
new file mode 100644
index 00000000000..5acb1b6e1d3
Binary files /dev/null and b/apps/docs/public/img/clippy.png differ
diff --git a/apps/docs/scripts/generate-embeddings.ts b/apps/docs/scripts/generate-embeddings.ts
new file mode 100644
index 00000000000..41b5a25ecbd
--- /dev/null
+++ b/apps/docs/scripts/generate-embeddings.ts
@@ -0,0 +1,335 @@
+import { createClient } from '@supabase/supabase-js'
+import { createHash } from 'crypto'
+import dotenv from 'dotenv'
+import { ObjectExpression } from 'estree'
+import { readdir, readFile, stat } from 'fs/promises'
+import { Content, Root } from 'mdast'
+import { fromMarkdown } from 'mdast-util-from-markdown'
+import { mdxFromMarkdown, MdxjsEsm } from 'mdast-util-mdx'
+import { toMarkdown } from 'mdast-util-to-markdown'
+import { mdxjs } from 'micromark-extension-mdxjs'
+import 'openai'
+import { Configuration, OpenAIApi } from 'openai'
+import { join } from 'path'
+import { u } from 'unist-builder'
+import { filter } from 'unist-util-filter'
+import { inspect } from 'util'
+
+dotenv.config()
+
+const ignoredFiles = ['pages/404.mdx']
+
+/**
+ * Extracts ES literals from an `estree` `ObjectExpression`
+ * into a plain JavaScript object.
+ */
+function getObjectFromExpression(node: ObjectExpression) {
+ return node.properties.reduce<
+ Record
+ >((object, property) => {
+ if (property.type !== 'Property') {
+ return object
+ }
+
+ const key = (property.key.type === 'Identifier' && property.key.name) || undefined
+ const value = (property.value.type === 'Literal' && property.value.value) || undefined
+
+ if (!key) {
+ return object
+ }
+
+ return {
+ ...object,
+ [key]: value,
+ }
+ }, {})
+}
+
+/**
+ * Extracts the `meta` ESM export from the MDX file.
+ *
+ * This info is akin to frontmatter.
+ */
+function extractMetaExport(mdxTree: Root) {
+ const metaExportNode = mdxTree.children.find((node): node is MdxjsEsm => {
+ return (
+ node.type === 'mdxjsEsm' &&
+ node.data?.estree?.body[0]?.type === 'ExportNamedDeclaration' &&
+ node.data.estree.body[0].declaration?.type === 'VariableDeclaration' &&
+ node.data.estree.body[0].declaration.declarations[0]?.id.type === 'Identifier' &&
+ node.data.estree.body[0].declaration.declarations[0].id.name === 'meta'
+ )
+ })
+
+ if (!metaExportNode) {
+ return undefined
+ }
+
+ const objectExpression =
+ (metaExportNode.data?.estree?.body[0]?.type === 'ExportNamedDeclaration' &&
+ metaExportNode.data.estree.body[0].declaration?.type === 'VariableDeclaration' &&
+ metaExportNode.data.estree.body[0].declaration.declarations[0]?.id.type === 'Identifier' &&
+ metaExportNode.data.estree.body[0].declaration.declarations[0].id.name === 'meta' &&
+ metaExportNode.data.estree.body[0].declaration.declarations[0].init?.type ===
+ 'ObjectExpression' &&
+ metaExportNode.data.estree.body[0].declaration.declarations[0].init) ||
+ undefined
+
+ if (!objectExpression) {
+ return undefined
+ }
+
+ return getObjectFromExpression(objectExpression)
+}
+
+/**
+ * Splits a `mdast` tree into multiple trees based on
+ * a predicate function. Will include the splitting node
+ * at the beginning of each tree.
+ *
+ * Useful to split a markdown file into smaller sections.
+ */
+function splitTreeBy(tree: Root, predicate: (node: Content) => boolean) {
+ return tree.children.reduce((trees, node) => {
+ const [lastTree] = trees.slice(-1)
+
+ if (!lastTree || predicate(node)) {
+ const tree: Root = u('root', [node])
+ return trees.concat(tree)
+ }
+
+ lastTree.children.push(node)
+ return trees
+ }, [])
+}
+
+type Meta = ReturnType
+
+type ProcessedMdx = {
+ checksum: string
+ meta: Meta
+ sections: string[]
+}
+
+/**
+ * Processes MDX content for search indexing.
+ * It extracts metadata, strips it of all JSX,
+ * and splits it into sub-sections based on criteria.
+ */
+function processMdxForSearch(content: string): ProcessedMdx {
+ const checksum = createHash('sha256').update(content).digest('base64')
+
+ const mdxTree = fromMarkdown(content, {
+ extensions: [mdxjs()],
+ mdastExtensions: [mdxFromMarkdown()],
+ })
+
+ const meta = extractMetaExport(mdxTree)
+
+ // Remove all MDX elements from markdown
+ const mdTree = filter(
+ mdxTree,
+ (node) =>
+ ![
+ 'mdxjsEsm',
+ 'mdxJsxFlowElement',
+ 'mdxJsxTextElement',
+ 'mdxFlowExpression',
+ 'mdxTextExpression',
+ ].includes(node.type)
+ )
+
+ if (!mdTree) {
+ return {
+ checksum,
+ meta,
+ sections: [],
+ }
+ }
+
+ const sectionTrees = splitTreeBy(mdTree, (node) => node.type === 'heading')
+
+ const sections = sectionTrees.map((tree) => toMarkdown(tree))
+
+ return {
+ checksum,
+ meta,
+ sections,
+ }
+}
+
+async function walk(dir: string): Promise {
+ const immediateFiles = await readdir(dir)
+
+ const recursiveFiles = await Promise.all(
+ immediateFiles.map(async (file) => {
+ const filePath = join(dir, file)
+ const stats = await stat(filePath)
+ if (stats.isDirectory()) {
+ return walk(filePath)
+ } else if (stats.isFile()) {
+ return [filePath]
+ } else {
+ return []
+ }
+ })
+ )
+
+ const flattenedFiles = recursiveFiles.reduce(
+ (all, folderContents) => all.concat(folderContents),
+ []
+ )
+
+ return flattenedFiles
+}
+
+async function generateEmbeddings() {
+ if (
+ !process.env.NEXT_PUBLIC_SUPABASE_URL ||
+ !process.env.SUPABASE_SERVICE_ROLE_KEY ||
+ !process.env.OPENAI_KEY
+ ) {
+ return console.log(
+ 'Environment variables NEXT_PUBLIC_SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, and OPENAI_KEY are required: skipping embeddings generation'
+ )
+ }
+
+ const supabaseClient = createClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL,
+ process.env.SUPABASE_SERVICE_ROLE_KEY
+ )
+
+ const markdownFiles = (await walk('pages'))
+ .filter((fileName) => /\.mdx?$/.test(fileName))
+ .filter((fileName) => !ignoredFiles.includes(fileName))
+
+ console.log(`Discovered ${markdownFiles.length} pages`)
+ console.log('Checking which pages are new or have changed')
+
+ for (const markdownFile of markdownFiles) {
+ const path = markdownFile.replace(/^pages/, '').replace(/\.mdx?$/, '')
+ try {
+ const contents = await readFile(markdownFile, 'utf8')
+
+ const { checksum, meta, sections } = processMdxForSearch(contents)
+
+ // Check for existing page in DB and compare checksums
+ const { error: fetchPageError, data: existingPage } = await supabaseClient
+ .from('page')
+ .select()
+ .filter('path', 'eq', path)
+ .limit(1)
+ .maybeSingle()
+
+ if (fetchPageError) {
+ throw fetchPageError
+ }
+
+ // We use checksum to determine if this page & its sections need to be regenerated
+ if (existingPage?.checksum === checksum) {
+ continue
+ }
+
+ console.log({ checksum, path, meta })
+
+ if (existingPage) {
+ console.log(
+ `Docs have changed for '${path}', removing old page sections and their embeddings`
+ )
+
+ const { error: deletePageSectionError } = await supabaseClient
+ .from('page_section')
+ .delete()
+ .filter('page_id', 'eq', existingPage.id)
+
+ if (deletePageSectionError) {
+ throw deletePageSectionError
+ }
+ }
+
+ // Create/update page record. Intentionally clear checksum until we
+ // have successfully generated all page sections.
+ const { error: upsertPageError, data: page } = await supabaseClient
+ .from('page')
+ .upsert({ checksum: null, path, meta }, { onConflict: 'path' })
+ .select()
+ .limit(1)
+ .single()
+
+ if (upsertPageError) {
+ throw upsertPageError
+ }
+
+ console.log(`Adding ${sections.length} page sections (with embeddings) for '${path}'`)
+ for (const section of sections) {
+ // OpenAI recommends replacing newlines with spaces for best results (specific to embeddings)
+ const input = section.replace(/\n/g, ' ')
+
+ try {
+ const configuration = new Configuration({ apiKey: process.env.OPENAI_KEY })
+ const openai = new OpenAIApi(configuration)
+
+ const embeddingResponse = await openai.createEmbedding({
+ model: 'text-embedding-ada-002',
+ input,
+ })
+
+ if (embeddingResponse.status !== 200) {
+ throw new Error(inspect(embeddingResponse.data, false, 2))
+ }
+
+ const [responseData] = embeddingResponse.data.data
+
+ const { error: insertPageSectionError, data: pageSection } = await supabaseClient
+ .from('page_section')
+ .insert({
+ page_id: page.id,
+ content: section,
+ token_count: embeddingResponse.data.usage.total_tokens,
+ embedding: responseData.embedding,
+ })
+ .select()
+ .limit(1)
+ .single()
+
+ if (insertPageSectionError) {
+ throw insertPageSectionError
+ }
+ } catch (err) {
+ // TODO: decide how to better handle failed embeddings
+ console.error(
+ `Failed to generate embeddings for '${path}' page section starting with '${input.slice(
+ 0,
+ 40
+ )}...'`
+ )
+
+ throw err
+ }
+ }
+
+ // Set page checksum so that we know this page was stored successfully
+ const { error: updatePageError } = await supabaseClient
+ .from('page')
+ .update({ checksum })
+ .filter('id', 'eq', page.id)
+
+ if (updatePageError) {
+ throw updatePageError
+ }
+ } catch (err) {
+ console.error(
+ `Page '${path}' or one/multiple of its page sections failed to store properly. Page has been marked with null checksum to indicate that it needs to be re-generated.`
+ )
+ console.error(err)
+ }
+ }
+
+ console.log('Embedding generation complete')
+}
+
+async function main() {
+ await generateEmbeddings()
+}
+
+main().catch((err) => console.error(err))
diff --git a/apps/docs/styles/algolia-search.scss b/apps/docs/styles/algolia-search.scss
index 0e2b90589f6..56ac843d5d2 100644
--- a/apps/docs/styles/algolia-search.scss
+++ b/apps/docs/styles/algolia-search.scss
@@ -953,6 +953,7 @@ body {
// search bar
input[type='search'].DocSearch-Input {
background-color: var(--colors-scale1);
+ box-shadow: none;
}
.dark .DocSearch-Input {
diff --git a/apps/docs/types/sse.d.ts b/apps/docs/types/sse.d.ts
new file mode 100644
index 00000000000..dbf97ac0836
--- /dev/null
+++ b/apps/docs/types/sse.d.ts
@@ -0,0 +1,12 @@
+declare module 'sse.js' {
+ export type SSEOptions = EventSourceInit & {
+ headers?: Record
+ payload?: string
+ method?: string
+ }
+
+ export class SSE extends EventSource {
+ constructor(url: string | URL, sseOptions?: SSEOptions)
+ stream(): void
+ }
+}
diff --git a/apps/www/_blog/2023-02-03-openai-embeddings-postgres-vector.mdx b/apps/www/_blog/2023-02-03-openai-embeddings-postgres-vector.mdx
new file mode 100644
index 00000000000..caf2c2bd758
--- /dev/null
+++ b/apps/www/_blog/2023-02-03-openai-embeddings-postgres-vector.mdx
@@ -0,0 +1,377 @@
+---
+title: Storing OpenAI embeddings in Postgres with pgvector
+description: An example of how to build an AI-powered search engine using OpenAI's embeddings and PostgreSQL.
+author: gregnr
+image: embeddings/og_pgvector.png
+thumb: embeddings/og_pgvector.png
+tags:
+ - postgres
+ - ai
+date: '2023-01-06'
+toc_depth: 3
+---
+
+A new PostgreSQL extension is now available in Supabase: [`pgvector`](https://github.com/pgvector/pgvector), an open-source vector similarity search.
+
+The exponential progress of AI functionality over the past year has inspired many new real world applications. One specific challenge has been the ability to store and query _embeddings_ at scale.
+In this post we'll explain what embeddings are, why we might want to use them, and how we can store and query them in PostgreSQL using `pgvector`.
+
+## What are embeddings?
+
+Embeddings capture the “relatedness” of text, images, video, or other types of information. This relatedness is most commonly used for:
+
+- **Search:** how similar is a search term to a body of text?
+- **Recommendations:** how similar are two products?
+- **Classifications:** how do we categorize a body of text?
+- **Clustering:** how do we identify trends?
+
+Let's explore an example of text embeddings. Say we have three phrases:
+
+1. “The cat chases the mouse”
+2. “The kitten hunts rodents”
+3. “I like ham sandwiches”
+
+Your job is to group phrases with similar meaning. If you are a human, this should be obvious. Phrases 1 and 2 are almost identical, while phrase 3 has a completely different meaning.
+
+Although phrases 1 and 2 are similar, they share no common vocabulary (besides “the”). Yet their meanings are nearly identical. How can we teach a computer that these are the same?
+
+## Human language
+
+Humans use words and symbols to communicate language. But words in isolation are mostly meaningless - we need to draw from shared knowledge & experience in order to make sense of them. The phrase “You should Google it” only makes sense if you know that Google is a search engine and that people have been using it as a verb.
+
+In the same way, we need to train a neural network model to understand human language. An effective model should be trained on millions of different examples to understand what each word, phrase, sentence, or paragraph could mean in different contexts.
+
+So how does this relate to embeddings?
+
+## How do embeddings work?
+
+Embeddings compress discrete information (words & symbols) into distributed continuous-valued data (vectors). If we took our phrases from before and plot them on a chart, it might look something like this:
+
+
+
+Phrases 1 and 2 would be plotted close to each other, since their meanings are similar. We would expect phrase 3 to live somewhere far away since it isn't related. If we had a fourth phrase, “Sally ate Swiss cheese”, this might exist somewhere between phrase 3 (cheese can go on sandwiches) and phrase 1 (mice like Swiss cheese).
+
+In this example we only have 2 dimensions: the X and Y axis. In reality, we would need many more dimensions to effectively capture the complexities of human language.
+
+## OpenAI embeddings
+
+OpenAI offers an [API](https://platform.openai.com/docs/guides/embeddings) to generate embeddings for a string of text using its language model. You feed it any text information (blog articles, documentation, your company's knowledge base), and it will output a vector of floating point numbers that represents the “meaning” of that text.
+
+Compared to our 2-dimensional example above, their latest embedding model `text-embedding-ada-002` will output 1536 dimensions.
+
+Why is this useful? Once we have generated embeddings on multiple texts, it is trivial to calculate how similar they are using vector math operations like cosine distance. A perfect use case for this is search. Your process might look something like this:
+
+1. Pre-process your knowledge base and generate embeddings for each page
+2. Store your embeddings to be referenced later (more on this)
+3. Build a search page that prompts your user for input
+4. Take user's input, generate a one-time embedding, then perform a similarity search against your pre-processed embeddings.
+5. Return the most similar pages to the user
+
+## Embeddings in practice
+
+At a small scale, you could store your embeddings in a CSV file, load them into Python, and use a library like `numPy` to calculated similarity between them using something like cosine distance or dot product. OpenAI has a cookbook [example](https://github.com/openai/openai-cookbook/blob/main/examples/Semantic_text_search_using_embeddings.ipynb) that does just that. Unfortunately this likely won't scale well:
+
+- What if I need to store and search over a large number of documents and embeddings (more than can fit in memory)?
+- What if I want to create/update/delete embeddings dynamically?
+- What if I'm not using Python?
+
+### Using PostgreSQL
+
+Enter [`pgvector`](https://github.com/pgvector/pgvector), an extension for PostgreSQL that allows you to both store and query vector embeddings within your database. Let's try it out.
+
+First we'll enable the **Vector** extension. In Supabase, this can be done from the web portal through `Database` → `Extensions`. You can also do this in SQL by running:
+
+```sql
+create extension vector;
+```
+
+Next let's create a table to store our documents and their embeddings:
+
+```sql
+create table documents (
+ id bigserial primary key,
+ content text,
+ embedding vector (1536)
+);
+```
+
+`pgvector` introduces a new data type called `vector`. In the code above, we create a column named `embedding` with the `vector` data type. The size of the vector defines how many dimensions the vector holds. OpenAI's `text-embedding-ada-002` model outputs 1536 dimensions, so we will use that for our vector size.
+
+We also create a `text` column named `content` to store the original document text that produced this embedding. Depending on your use case, you might just store a reference (URL or foreign key) to a document here instead.
+
+Soon we're going to need to perform a similarity search over these embeddings. Let's create a function to do that:
+
+```sql
+create or replace function match_documents (
+ query_embedding vector(1536),
+ similarity_threshold float,
+ match_count int
+)
+returns table (
+ id bigint,
+ content text,
+ similarity float
+)
+language plpgsql
+as $$
+begin
+ return query
+ select
+ id,
+ content,
+ (documents.embedding <=> query_embedding) as similarity
+ from documents
+ where (documents.embedding <=> query_embedding) > similarity_threshold
+ order by documents.embedding <=> query_embedding
+ limit match_count;
+end;
+$$;
+```
+
+`pgvector` introduces 3 new operators that can be used to calculate similarity:
+
+| Operator | Description |
+| -------- | ---------------------- |
+| `<->` | Euclidean distance |
+| `<#>` | negative inner product |
+| `<=>` | cosine distance |
+
+OpenAI recommends cosine similarity on their embeddings, so we will use that here.
+
+Now we can call `match_documents()`, pass in our embedding, similarity threshold, and match count, and we'll get a list of all documents that match. And since this is all managed by Postgres, our application code becomes very simple.
+
+### Indexing
+
+Once your table starts to grow with embeddings, you will likely want to add an index to speed up queries. Vector indexes are particularly important when you're ordering results because vectors are not grouped by similarity, so finding the closest by sequential scan is a resource-intensive operation.
+
+Each distance operator requires a different type of index. We expect to order by cosine distance, so we need `vector_cosine_ops` index. A good starting number of lists is 4 \* sqrt(table_rows):
+
+```sql
+create index on documents
+using ivfflat (embedding vector_cosine_ops)
+with (lists = 100);
+```
+
+You can read more about indexing on `pgvector`'s GitHub page [here](https://github.com/pgvector/pgvector#indexing).
+
+### Generating embeddings
+
+Let's use JavaScript to generate embeddings and store them in Postgres:
+
+```tsx
+import { createClient } from '@supabase/supabase-js'
+import { Configuration, OpenAIApi } from 'openai'
+import { supabaseClient } from './lib/supabase'
+
+async function generateEmbeddings() {
+ const configuration = new Configuration({ apiKey: '' })
+ const openAi = new OpenAIApi(configuration)
+
+ const documents = await getDocuments() // Your custom function to load docs
+
+ // Assuming each document is a string
+ for (const document of documents) {
+ // OpenAI recommends replacing newlines with spaces for best results
+ const input = document.replace(/\n/g, ' ')
+
+ const embeddingResponse = await openai.createEmbedding({
+ model: 'text-embedding-ada-002',
+ input,
+ })
+
+ const [{ embedding }] = embeddingResponse.data.data
+
+ // In production we should handle possible errors
+ await supabaseClient.from('documents').insert({
+ content: document,
+ embedding,
+ })
+ }
+}
+```
+
+### Building a simple search function
+
+Finally, let's create an [Edge Function](https://supabase.com/docs/guides/functions) to perform our similarity search:
+
+```tsx
+import { serve } from 'https://deno.land/std@0.170.0/http/server.ts'
+import 'https://deno.land/x/xhr@0.2.1/mod.ts'
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.5.0'
+import { Configuration, OpenAIApi } from 'https://esm.sh/openai@3.1.0'
+import { supabaseClient } from './lib/supabase'
+
+export const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
+}
+
+serve(async (req) => {
+ // Handle CORS
+ if (req.method === 'OPTIONS') {
+ return new Response('ok', { headers: corsHeaders })
+ }
+
+ // Search query is passed in request payload
+ const { query } = await req.json()
+
+ // OpenAI recommends replacing newlines with spaces for best results
+ const input = query.replace(/\n/g, ' ')
+
+ const configuration = new Configuration({ apiKey: '' })
+ const openai = new OpenAIApi(configuration)
+
+ // Generate a one-time embedding for the query itself
+ const embeddingResponse = await openai.createEmbedding({
+ model: 'text-embedding-ada-002',
+ input,
+ })
+
+ const [{ embedding }] = embeddingResponse.data.data
+
+ // In production we should handle possible errors
+ const { data: documents } = await supabaseClient.rpc('match_documents', {
+ query_embedding: embedding,
+ match_threshold: 0.78, // Choose an appropriate threshold for your data
+ match_count: 10, // Choose the number of matches
+ })
+
+ return new Response(JSON.stringify(documents), {
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+ })
+})
+```
+
+### Building a smarter search function
+
+ChatGPT doesn't just return existing documents. It's able to assimilate a variety of information into a single, cohesive answer. To do this, we need to provide GPT with some relevant documents, and a prompt that it can use to formulate this answer.
+
+One of the biggest challenges of OpenAI's `text-davinci-003` [completion model](https://beta.openai.com/docs/guides/completion) is the 4000 token limit. You must fit both your prompt and the resulting completion within the 4000 tokens. This makes it challenging if you wanted to prompt GPT-3 to answer questions about your own custom knowledge base that would never fit in a single prompt.
+
+Embeddings can help solve this by splitting your prompts into a two-phased process:
+
+1. Query your embedding database for the most relevant documents related to the question
+2. Inject these documents as context for GPT-3 to reference in its answer
+
+Here's another Edge Function that expands upon the simple example above:
+
+```tsx
+import { serve } from 'https://deno.land/std@0.170.0/http/server.ts'
+import 'https://deno.land/x/xhr@0.2.1/mod.ts'
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.5.0'
+import GPT3Tokenizer from 'https://esm.sh/gpt3-tokenizer@1.1.5'
+import { Configuration, OpenAIApi } from 'https://esm.sh/openai@3.1.0'
+import { stripIndent } from 'https://esm.sh/common-tags@1.8.2'
+import { supabaseClient } from './lib/supabase'
+
+export const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
+}
+
+serve(async (req) => {
+ // Handle CORS
+ if (req.method === 'OPTIONS') {
+ return new Response('ok', { headers: corsHeaders })
+ }
+
+ // Search query is passed in request payload
+ const { query } = await req.json()
+
+ // OpenAI recommends replacing newlines with spaces for best results
+ const input = query.replace(/\n/g, ' ')
+
+ const configuration = new Configuration({ apiKey: '' })
+ const openai = new OpenAIApi(configuration)
+
+ // Generate a one-time embedding for the query itself
+ const embeddingResponse = await openai.createEmbedding({
+ model: 'text-embedding-ada-002',
+ input,
+ })
+
+ const [{ embedding }] = embeddingResponse.data.data
+
+ // Fetching whole documents for this simple example.
+ //
+ // Ideally for context injection, documents are chunked into
+ // smaller sections at earlier pre-processing/embedding step.
+ const { data: documents } = await supabaseClient.rpc('match_documents', {
+ query_embedding: embedding,
+ match_threshold: 0.78, // Choose an appropriate threshold for your data
+ match_count: 10, // Choose the number of matches
+ })
+
+ const tokenizer = new GPT3Tokenizer({ type: 'gpt3' })
+ let tokenCount = 0
+ let contextText = ''
+
+ // Concat matched documents
+ for (let i = 0; i < documents.length; i++) {
+ const document = documents[i]
+ const content = document.content
+ const encoded = tokenizer.encode(content)
+ tokenCount += encoded.text.length
+
+ // Limit context to max 1500 tokens (configurable)
+ if (tokenCount > 1500) {
+ break
+ }
+
+ contextText += `${content.trim()}\n---\n`
+ }
+
+ const prompt = stripIndent`${oneLine`
+ You are a very enthusiastic Supabase representative who loves
+ to help people! Given the following sections from the Supabase
+ documentation, answer the question using only that information,
+ outputted in markdown format. If you are unsure and the answer
+ is not explicitly written in the documentation, say
+ "Sorry, I don't know how to help with that."`}
+
+ Context sections:
+ ${contextText}
+
+ Question: """
+ ${query}
+ """
+
+ Answer as markdown (including related code snippets if available):
+ `
+
+ // In production we should handle possible errors
+ const completionResponse = await openai.createCompletion({
+ model: 'text-davinci-003',
+ prompt,
+ max_tokens: 512, // Choose the max allowed tokens in completion
+ temperature: 0, // Set to 0 for deterministic results
+ })
+
+ const {
+ id,
+ choices: [{ text }],
+ } = completionResponse.data
+
+ return new Response(JSON.stringify({ id, text }), {
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+ })
+})
+```
+
+### Streaming results
+
+OpenAI API responses take longer to depending on the length of the “answer”. ChatGPT has a nice UX for this by streaming the response to the user immediately. You can see a similar effect for the Supabase docs:
+
+
+
+The OpenAI API supports [completion streaming](https://platform.openai.com/docs/api-reference/completions/create#completions/create-stream) with Server Side Events. Supabase Edge Functions are run Deno, which also supports [Server Side Events](https://deno.com/blog/deploy-streams#server-sent-events). Check out [this commit](https://github.com/supabase/supabase/pull/12056/commits/bd83e9ba2f7263440888228e3b29007604d94841) to see how we modified the Function above to build a streaming interface.
+
+## Wrap up
+
+Storing embeddings in Postgres opens a world of possibilities. You can combine your search function with telemetry functions, add an user-provided feedback (thumbs up/down), and make your search feel more integrated with your products.
+
+Tomorrow we'll be releasing our own version of this interface in the Supabase docs, to provide Supabase-specific answers.
+
+The pgvector extension is available on all new Supabase projects today. If you want to try it out, launch a new Postgres database today: [database.new](https://database.new)
diff --git a/apps/www/lib/authors.json b/apps/www/lib/authors.json
index 1b2c394d052..584c633d00a 100644
--- a/apps/www/lib/authors.json
+++ b/apps/www/lib/authors.json
@@ -264,5 +264,12 @@
"position": "Engineering",
"author_url": "https://github.com/hf",
"author_image_url": "https://github.com/hf.png"
+ },
+ {
+ "author_id": "gregnr",
+ "author": "Greg Richardson",
+ "position": "Open Source Contributor",
+ "author_url": "https://github.com/gregnr",
+ "author_image_url": "https://github.com/gregnr.png"
}
]
diff --git a/apps/www/public/images/blog/embeddings/embeddings.mp4 b/apps/www/public/images/blog/embeddings/embeddings.mp4
new file mode 100644
index 00000000000..43611770d3a
Binary files /dev/null and b/apps/www/public/images/blog/embeddings/embeddings.mp4 differ
diff --git a/apps/www/public/images/blog/embeddings/og_pgvector.png b/apps/www/public/images/blog/embeddings/og_pgvector.png
new file mode 100644
index 00000000000..b3506d9ac82
Binary files /dev/null and b/apps/www/public/images/blog/embeddings/og_pgvector.png differ
diff --git a/apps/www/public/images/blog/embeddings/vector-similarity.png b/apps/www/public/images/blog/embeddings/vector-similarity.png
new file mode 100644
index 00000000000..b2282e76f1e
Binary files /dev/null and b/apps/www/public/images/blog/embeddings/vector-similarity.png differ
diff --git a/apps/www/public/rss.xml b/apps/www/public/rss.xml
index 2e9e12c7b1b..3debdf27d81 100644
--- a/apps/www/public/rss.xml
+++ b/apps/www/public/rss.xml
@@ -5,1078 +5,1085 @@
https://supabase.com
Latest news from Supabase
en
- Wed, 04 Jan 2023 03:03:30 +0000
+ Thu, 05 Jan 2023 23:11:00 +0000
-
+
https://supabase.com/blog/openai-embeddings-postgres-vector
+ Storing OpenAI embeddings in Postgres with pgvector
+ https://supabase.com/blog/openai-embeddings-postgres-vector
+ An example of how to build an AI-powered search engine using OpenAI's embeddings and PostgreSQL.
+ Thu, 05 Jan 2023 23:11:00 +0000
+
+-
https://supabase.com/blog/supabase-beta-december-2022
Supabase Beta December 2022
https://supabase.com/blog/supabase-beta-december-2022
This month the Beta Update is a Launch Week 6 Special, where we review the cascade of announcements.
- Wed, 04 Jan 2023 03:03:30 +0000
+ Wed, 04 Jan 2023 23:11:00 +0000
-
https://supabase.com/blog/launch-week-6-hackathon-winners
Launch Week 6 Hackathon Winners
https://supabase.com/blog/launch-week-6-hackathon-winners
Announcing the winners of the Launch Week 6 Hackathon!
- Mon, 02 Jan 2023 03:03:30 +0000
+ Mon, 02 Jan 2023 23:11:00 +0000
-
https://supabase.com/blog/vault-now-in-beta
Supabase Vault is now in Beta
https://supabase.com/blog/vault-now-in-beta
A Postgres extension to store encrypted secrets and encrypt data.
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/postgrest-11-prerelease
PostgREST 11 pre-release
https://supabase.com/blog/postgrest-11-prerelease
Describes new features of PostgREST 11 pre-release
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/postgres-point-in-time-recovery
Point in Time Recovery is now available for Pro projects
https://supabase.com/blog/postgres-point-in-time-recovery
We're making PITR available for more projects, with a new Dashboard UI that makes it simple to use.
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/pg-graphql-v1
pg_graphql v1.0
https://supabase.com/blog/pg-graphql-v1
Announcing the v1.0 release of pg_graphql
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/new-in-postgres-15
What's new in Postgres 15?
https://supabase.com/blog/new-in-postgres-15
Describes the release of Postgres 15, new features and reasons to use it
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/launch-week-6-wrap-up
Launch Week 6: Wrap Up
https://supabase.com/blog/launch-week-6-wrap-up
That's a wrap on Supabase Launch Week Day 6. Here's everything we shipped in one long blog post.
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/launch-week-6-community-day
Community Day
https://supabase.com/blog/launch-week-6-community-day
Wrapping up Launch Week 6 with contributors, partners, and friends.
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/custom-domain-names
Custom Domain Names
https://supabase.com/blog/custom-domain-names
Change your Supabase project's domain name to your own domain.
- Thu, 15 Dec 2022 03:03:30 +0000
+ Thu, 15 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/postgres-foreign-data-wrappers-rust
Supabase Wrappers, a Postgres FDW framework written in Rust
https://supabase.com/blog/postgres-foreign-data-wrappers-rust
A framework for building Postgres Foreign Data Wrappers which connects to Stripe, Firebase, Clickhouse, and more.
- Wed, 14 Dec 2022 03:03:30 +0000
+ Wed, 14 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/mfa-auth-via-rls
Multi-factor Authentication via Row Level Security Enforcement
https://supabase.com/blog/mfa-auth-via-rls
MFA Auth with enforcement via RLS
- Tue, 13 Dec 2022 03:03:30 +0000
+ Tue, 13 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/storage-image-resizing-smart-cdn
Supabase Storage v2: Image resizing and Smart CDN
https://supabase.com/blog/storage-image-resizing-smart-cdn
We're introducing new features for Supabase Storage: Image resizing and a Smart CDN.
- Mon, 12 Dec 2022 03:03:30 +0000
+ Mon, 12 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/new-supabase-docs-built-with-nextjs
New Supabase Docs, built with Next.js
https://supabase.com/blog/new-supabase-docs-built-with-nextjs
We've redesigned our Docs and migrated to Next.js
- Sun, 11 Dec 2022 03:03:30 +0000
+ Sun, 11 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/postgres-crdt
pg_crdt - an experimental CRDT extension for Postgres
https://supabase.com/blog/postgres-crdt
Embedding Yjs and Automerge into Postgres for collaborative applications.
- Fri, 09 Dec 2022 03:03:30 +0000
+ Fri, 09 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/who-we-hire
Who We Hire at Supabase
https://supabase.com/blog/who-we-hire
Traits we look for to maintain a culture of shipping fast and often
- Thu, 08 Dec 2022 03:03:30 +0000
+ Thu, 08 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/launch-week-6-hackathon
Launch Week 6 Hackathon
https://supabase.com/blog/launch-week-6-hackathon
Build an Open Source Project, Win $1500 and the Supabase Darkmode Keyboard
- Thu, 08 Dec 2022 03:03:30 +0000
+ Thu, 08 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-november-2022
Supabase Beta November 2022
https://supabase.com/blog/supabase-beta-november-2022
We are preparing everything for Launch Week 6, but we still had time to ship some goodies this month!
- Tue, 06 Dec 2022 03:03:30 +0000
+ Tue, 06 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/the-supabase-content-storm
The Supabase Content Storm
https://supabase.com/blog/the-supabase-content-storm
We worked with +30 content creators to drop a mountain of content simultaneously.
- Mon, 05 Dec 2022 03:03:30 +0000
+ Mon, 05 Dec 2022 23:11:00 +0000
-
https://supabase.com/blog/transparent-column-encryption-with-postgres
Transparent Column Encryption with Postgres
https://supabase.com/blog/transparent-column-encryption-with-postgres
Using pgsodium's Transparent Column Encryption to encrypt data and provide your users with row-level encryption.
- Wed, 30 Nov 2022 03:03:30 +0000
+ Wed, 30 Nov 2022 23:11:00 +0000
-
https://supabase.com/blog/sql-or-nosql-both-with-postgresql
SQL or NoSQL? Why not use both (with PostgreSQL)?
https://supabase.com/blog/sql-or-nosql-both-with-postgresql
How to turn Postgres into an easy-to-use NoSQL database that retains all the power of SQL
- Wed, 23 Nov 2022 03:03:30 +0000
+ Wed, 23 Nov 2022 23:11:00 +0000
-
https://supabase.com/blog/flutter-authentication-and-authorization-with-rls
Flutter Authentication and Authorization with RLS
https://supabase.com/blog/flutter-authentication-and-authorization-with-rls
Learn how you can secure your Flutter app using Supabase Row Level Security.
- Mon, 21 Nov 2022 03:03:30 +0000
+ Mon, 21 Nov 2022 23:11:00 +0000
-
https://supabase.com/blog/fetching-and-caching-supabase-data-in-next-js-server-components
Fetching and caching Supabase data in Next.js 13 Server Components
https://supabase.com/blog/fetching-and-caching-supabase-data-in-next-js-server-components
Next.js 13 introduces new data fetching and caching methods to enable React Server Components and Suspense.
- Wed, 16 Nov 2022 03:03:30 +0000
+ Wed, 16 Nov 2022 23:11:00 +0000
-
https://supabase.com/blog/authentication-in-ionic-angular
Authentication in Ionic Angular with Supabase
https://supabase.com/blog/authentication-in-ionic-angular
Learn how to build an Ionic Angular app with authentication, Row Level Security, and Magic Link auth.
- Mon, 07 Nov 2022 03:03:30 +0000
+ Mon, 07 Nov 2022 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-update-october-2022
Supabase Beta October 2022
https://supabase.com/blog/supabase-beta-update-october-2022
New SDKs, quickstarts, Functions tricks, and more. But, more importantly, Launch Week 6️ has a date!
- Tue, 01 Nov 2022 02:02:30 +0000
+ Tue, 01 Nov 2022 23:11:00 +0000
-
https://supabase.com/blog/postgresql-commitfest
What is PostgreSQL commitfest and how to contribute
https://supabase.com/blog/postgresql-commitfest
A time-tested method for contributing to the core Postgres code
- Wed, 26 Oct 2022 02:02:30 +0000
+ Wed, 26 Oct 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-flutter-sdk-v1-released
supabase-flutter v1 Released
https://supabase.com/blog/supabase-flutter-sdk-v1-released
We've released supabase-flutter v1. More intuitive way of accessing Supabase from your Flutter application.
- Thu, 20 Oct 2022 02:02:30 +0000
+ Thu, 20 Oct 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-js-v2-released
supabase-js v2 Released
https://supabase.com/blog/supabase-js-v2-released
We've released supabase-js v2. Updated examples, quickstarts, and an improved experience.
- Wed, 19 Oct 2022 02:02:30 +0000
+ Wed, 19 Oct 2022 22:10:00 +0000
-
https://supabase.com/blog/postgres-full-text-search-vs-the-rest
Postgres Full Text Search vs the rest
https://supabase.com/blog/postgres-full-text-search-vs-the-rest
Comparing one of the most popular Postgres features against alternatives
- Thu, 13 Oct 2022 02:02:30 +0000
+ Thu, 13 Oct 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-update-september-2022
Supabase Beta September 2022
https://supabase.com/blog/supabase-beta-update-september-2022
We were too focused on clearing out the backlog so we didn't ship anything new last month... or did we?!
- Tue, 04 Oct 2022 02:02:30 +0000
+ Tue, 04 Oct 2022 22:10:00 +0000
-
https://supabase.com/blog/postgres-wasm
Postgres WASM by Snaplet and Supabase
https://supabase.com/blog/postgres-wasm
We're open sourcing postgres-wasm, a PostgresQL server that runs inside a browser, with our friends at Snaplet.
- Sun, 02 Oct 2022 02:02:30 +0000
+ Sun, 02 Oct 2022 22:10:00 +0000
-
https://supabase.com/blog/choosing-a-postgres-primary-key
Choosing a Postgres Primary Key
https://supabase.com/blog/choosing-a-postgres-primary-key
Turns out the question of which identifier to use as a Primary Key is complicated -- we're going to dive into some of the complexity and inherent trade-offs, and figure things out
- Wed, 07 Sep 2022 02:02:30 +0000
+ Wed, 07 Sep 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-update-august-2022
Supabase Beta August 2022
https://supabase.com/blog/supabase-beta-update-august-2022
Launch Week Special. See everything we shipped, plus winners of the Hackathon and the extended Community Highlights
- Tue, 06 Sep 2022 02:02:30 +0000
+ Tue, 06 Sep 2022 22:10:00 +0000
-
https://supabase.com/blog/launch-week-5-hackathon-winners
Launch Week 5 Hackathon Winners
https://supabase.com/blog/launch-week-5-hackathon-winners
Announcing the winners of the Launch Week 5 Hackathon!
- Wed, 24 Aug 2022 02:02:30 +0000
+ Wed, 24 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/building-a-realtime-trello-board-with-supabase-and-angular
Building a Realtime Trello Board with Supabase and Angular
https://supabase.com/blog/building-a-realtime-trello-board-with-supabase-and-angular
Go beyond the hello world example with this real world project.
- Tue, 23 Aug 2022 02:02:30 +0000
+ Tue, 23 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-vault
Supabase Vault
https://supabase.com/blog/supabase-vault
Today we're announcing Vault, a Postgres extension for managing secrets and encryption inside your database.
- Thu, 18 Aug 2022 02:02:30 +0000
+ Thu, 18 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/postgrest-v10
PostgREST v10: EXPLAIN and Improved Relationship Detection
https://supabase.com/blog/postgrest-v10
Today, PostgREST 10 was released. Let's take a look at some of the new features that go hand in hand with supabase-js v2.
- Thu, 18 Aug 2022 02:02:30 +0000
+ Thu, 18 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/pg-jsonschema-a-postgres-extension-for-json-validation
pg_jsonschema: JSON Schema support for Postgres
https://supabase.com/blog/pg-jsonschema-a-postgres-extension-for-json-validation
Today we're releasing pg_jsonschema, a Postgres extension for JSON validation.
- Thu, 18 Aug 2022 02:02:30 +0000
+ Thu, 18 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/launch-week-5-one-more-thing
One more thing
https://supabase.com/blog/launch-week-5-one-more-thing
Let's be honest, it's never just one more thing.
- Thu, 18 Aug 2022 02:02:30 +0000
+ Thu, 18 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/launch-week-5-community-day
Community Day
https://supabase.com/blog/launch-week-5-community-day
Wrapping up Launch Week 5 with contributors, partners, and friends.
- Thu, 18 Aug 2022 02:02:30 +0000
+ Thu, 18 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-realtime-multiplayer-general-availability
Realtime: Multiplayer Edition
https://supabase.com/blog/supabase-realtime-multiplayer-general-availability
Announcing the general availability of Realtime's Broadcast and Presence.
- Wed, 17 Aug 2022 02:02:30 +0000
+ Wed, 17 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-soc2
Supabase is SOC2 compliant
https://supabase.com/blog/supabase-soc2
Supabase is now SOC2 compliant. Learn how we got here and what it means for our customers.
- Tue, 16 Aug 2022 02:02:30 +0000
+ Tue, 16 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-js-v2
supabase-js v2
https://supabase.com/blog/supabase-js-v2
A look at supabase-js v2, which brings type support and focuses on quality-of-life improvements for developers.
- Mon, 15 Aug 2022 02:02:30 +0000
+ Mon, 15 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-cli-v1-and-admin-api-beta
Supabase CLI v1 and Management API Beta
https://supabase.com/blog/supabase-cli-v1-and-admin-api-beta
We are moving Supabase CLI v1 out of beta, and releasing Management API beta.
- Sun, 14 Aug 2022 02:02:30 +0000
+ Sun, 14 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-series-b
Supabase Series B
https://supabase.com/blog/supabase-series-b
Supabase raised $80M in May, bringing our total funding to $116M.
- Thu, 11 Aug 2022 02:02:30 +0000
+ Thu, 11 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/launch-week-5-hackathon
Launch Week 5 Hackathon
https://supabase.com/blog/launch-week-5-hackathon
Build to win $1500 - Friday 12th to Monday 21st August 2022
- Tue, 09 Aug 2022 02:02:30 +0000
+ Tue, 09 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/slack-consolidate-slackbot-to-consolidate-messages
Slack Consolidate: a slackbot built with Python and Supabase
https://supabase.com/blog/slack-consolidate-slackbot-to-consolidate-messages
A slackbot to consolidate messages from different channels using Supabase, Slack SDK and Python
- Mon, 08 Aug 2022 02:02:30 +0000
+ Mon, 08 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-update-july-2022
Supabase Beta July 2022
https://supabase.com/blog/supabase-beta-update-july-2022
Launch Week Golden Tickets, Flutter SDK 1.0 Developer Preview and more...
- Tue, 02 Aug 2022 02:02:30 +0000
+ Tue, 02 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-flutter-sdk-1-developer-preview
Supabase Flutter SDK 1.0 Developer Preview
https://supabase.com/blog/supabase-flutter-sdk-1-developer-preview
Supabase Flutter SDK is getting a major update and we need your help making it better.
- Mon, 01 Aug 2022 02:02:30 +0000
+ Mon, 01 Aug 2022 22:10:00 +0000
-
https://supabase.com/blog/seen-by-in-postgresql
Implementing "seen by" functionality with Postgres
https://supabase.com/blog/seen-by-in-postgresql
Different approaches for tracking visitor counts with PostgreSQL.
- Sun, 17 Jul 2022 02:02:30 +0000
+ Sun, 17 Jul 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-auth-helpers-with-sveltekit-support
Revamped Auth Helpers for Supabase (with SvelteKit support)
https://supabase.com/blog/supabase-auth-helpers-with-sveltekit-support
Supabase Auth Helpers now have improved developer experience, Sveltekit support, and more.
- Tue, 12 Jul 2022 02:02:30 +0000
+ Tue, 12 Jul 2022 22:10:00 +0000
-
https://supabase.com/blog/beta-update-june-2022
Supabase Beta June 2022
https://supabase.com/blog/beta-update-june-2022
Auth Helpers, Unlimited Free Projects, CLI and more...
- Tue, 05 Jul 2022 02:02:30 +0000
+ Tue, 05 Jul 2022 22:10:00 +0000
-
https://supabase.com/blog/flutter-tutorial-building-a-chat-app
Flutter Tutorial: building a Flutter chat app
https://supabase.com/blog/flutter-tutorial-building-a-chat-app
Learn how to build a Flutter chat app with open source and scalable backend (inc. auth, realtime, database, and more).
- Wed, 29 Jun 2022 02:02:30 +0000
+ Wed, 29 Jun 2022 22:10:00 +0000
-
https://supabase.com/blog/visualizing-supabase-data-using-metabase
Visualizing Supabase Data using Metabase
https://supabase.com/blog/visualizing-supabase-data-using-metabase
How to create different kinds of charts out of data stored in Supabase using Metabase.
- Tue, 28 Jun 2022 02:02:30 +0000
+ Tue, 28 Jun 2022 22:10:00 +0000
-
https://supabase.com/blog/partial-postgresql-data-dumps-with-rls
Partial data dumps using Postgres Row Level Security
https://supabase.com/blog/partial-postgresql-data-dumps-with-rls
Using RLS to create seed files for local PostgreSQL testing.
- Mon, 27 Jun 2022 02:02:30 +0000
+ Mon, 27 Jun 2022 22:10:00 +0000
-
https://supabase.com/blog/loading-data-supabase-python
Python data loading with Supabase
https://supabase.com/blog/loading-data-supabase-python
An example of how to load data into Supabase using supabase-py
- Thu, 16 Jun 2022 02:02:30 +0000
+ Thu, 16 Jun 2022 22:10:00 +0000
-
https://supabase.com/blog/beta-update-may-2022
Supabase Beta May 2022
https://supabase.com/blog/beta-update-may-2022
Product and community updates including wildcard auth redirects, edge functions with webhooks, and Prometheus endpoints for everybody.
- Tue, 31 May 2022 02:02:30 +0000
+ Tue, 31 May 2022 22:10:00 +0000
-
https://supabase.com/blog/how-supabase-accelerates-development-of-all-pull-together
How Mike Lyndon is using Supabase to accelerate development of AllPullTogether
https://supabase.com/blog/how-supabase-accelerates-development-of-all-pull-together
Mike Lyndon is learning web development as he builds AllPullTogether, and Supabase is helping him accelerate what he can accomplish.
- Wed, 25 May 2022 02:02:30 +0000
+ Wed, 25 May 2022 22:10:00 +0000
-
https://supabase.com/blog/partner-gallery-works-with-supabase
Works With Supabase - announcing our Partner Gallery
https://supabase.com/blog/partner-gallery-works-with-supabase
Introducing our Partner Gallery - open source and made with Supabase.
- Tue, 19 Apr 2022 02:02:30 +0000
+ Tue, 19 Apr 2022 22:10:00 +0000
-
https://supabase.com/blog/bring-the-func-hackathon-winners
Bring the Func Hackathon Winners 2022
https://supabase.com/blog/bring-the-func-hackathon-winners
Celebrating many amazing OSS Hackathon projects using GraphQL and Edge Functions.
- Sun, 17 Apr 2022 02:02:30 +0000
+ Sun, 17 Apr 2022 22:10:00 +0000
-
https://supabase.com/blog/beta-update-march-2022
Supabase Beta March 2022
https://supabase.com/blog/beta-update-march-2022
Functions, GraphQL, and much more.
- Thu, 14 Apr 2022 02:02:30 +0000
+ Thu, 14 Apr 2022 22:10:00 +0000
-
https://supabase.com/blog/supabrew
Supabrew - Never Code Thirsty
https://supabase.com/blog/supabrew
A light and refreshing non-alcoholic beer for devs.
- Fri, 01 Apr 2022 02:02:30 +0000
+ Thu, 31 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-realtime-with-multiplayer-features
Supabase Realtime, with Multiplayer Features
https://supabase.com/blog/supabase-realtime-with-multiplayer-features
Today we're announced Realtime, with multiplayer features. Realtime enables broadcast, presence, and listening to database changes delivered over WebSockets.
- Fri, 01 Apr 2022 02:02:30 +0000
+ Thu, 31 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/hackathon-bring-the-func
Hackathon: Bring the Func(🕺)
https://supabase.com/blog/hackathon-bring-the-func
Build open-source projects with our latest features, win limited edition swag and plant a tree!
- Fri, 01 Apr 2022 02:02:30 +0000
+ Thu, 31 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-edge-functions
Edge Functions are now available in Supabase
https://supabase.com/blog/supabase-edge-functions
Today we're launching Edge Functions. Edge Functions let you execute Typescript code close to your users, no matter where they're located.
- Wed, 30 Mar 2022 02:02:30 +0000
+ Wed, 30 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-enterprise
Introducing Supabase Enterprise
https://supabase.com/blog/supabase-enterprise
Today we are releasing Supabase Enterprise, a suite of features to scale your project.
- Tue, 29 Mar 2022 02:02:30 +0000
+ Tue, 29 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/graphql-now-available
GraphQL is now available in Supabase
https://supabase.com/blog/graphql-now-available
GraphQL support is now in general availability on the Supabase platform via our open source PostgreSQL extension, pg_graphql (beta).
- Mon, 28 Mar 2022 02:02:30 +0000
+ Mon, 28 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/community-day-lw4
Community Day
https://supabase.com/blog/community-day-lw4
Kicking off Launch Week 4 with contributors, partners, and friends.
- Sun, 27 Mar 2022 02:02:30 +0000
+ Sun, 27 Mar 2022 22:10:00 +0000
-
https://supabase.com/blog/supabase-launch-week-four
Supabase Launch Week 4
https://supabase.com/blog/supabase-launch-week-four
Launch Week 4: One new feature every day for an entire week. Starting Monday 28th March.
- Thu, 24 Mar 2022 02:02:30 +0000
+ Thu, 24 Mar 2022 23:11:00 +0000
-
https://supabase.com/blog/should-i-open-source-my-company
Should I Open Source my Company?
https://supabase.com/blog/should-i-open-source-my-company
The unexpected upsides of building in public
- Thu, 24 Mar 2022 02:02:30 +0000
+ Thu, 24 Mar 2022 23:11:00 +0000
-
https://supabase.com/blog/audit
Postgres Auditing in 150 lines of SQL
https://supabase.com/blog/audit
PostgreSQL has a robust set of features which we can leverage to create a generic auditing solution in 150 lines of SQL.
- Mon, 07 Mar 2022 03:03:30 +0000
+ Mon, 07 Mar 2022 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-january-2022
Supabase Beta January 2022
https://supabase.com/blog/supabase-beta-january-2022
New auth providers, SMS providers, and new videos.
- Mon, 21 Feb 2022 03:03:30 +0000
+ Mon, 21 Feb 2022 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-december-2021
Supabase Beta December 2021
https://supabase.com/blog/supabase-beta-december-2021
New crypto extension, Postgres videos, and a bunch of cool integrations.
- Wed, 19 Jan 2022 03:03:30 +0000
+ Wed, 19 Jan 2022 23:11:00 +0000
-
https://supabase.com/blog/product-hunt-golden-kitty-awards-2021
Golden Kitty Awards Ceremony Watch Party with Supabase
https://supabase.com/blog/product-hunt-golden-kitty-awards-2021
Hang out with us while watching the Product Hunt Golden Kitty Awards Ceremony
- Wed, 19 Jan 2022 03:03:30 +0000
+ Wed, 19 Jan 2022 23:11:00 +0000
-
https://supabase.com/blog/holiday-hackdays-winners-2021
Holiday Hackdays Winners 2021
https://supabase.com/blog/holiday-hackdays-winners-2021
Celebrating many amazing projects submitted to our Holiday Hackdays Hackathon.
- Thu, 16 Dec 2021 03:03:30 +0000
+ Thu, 16 Dec 2021 23:11:00 +0000
-
https://supabase.com/blog/beta-november-2021-launch-week-recap
Supabase Beta November 2021: Launch Week Recap
https://supabase.com/blog/beta-november-2021-launch-week-recap
We wrapped up November with Supabase's third Launch Week. Here's all the awesome stuff that got shipped ...
- Tue, 14 Dec 2021 03:03:30 +0000
+ Tue, 14 Dec 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-holiday-hackdays-hackathon
Kicking off the Holiday Hackdays
https://supabase.com/blog/supabase-holiday-hackdays-hackathon
Build cool stuff and celebrate open-source software with us during the Holiday Hackdays!
- Thu, 02 Dec 2021 03:03:30 +0000
+ Thu, 02 Dec 2021 23:11:00 +0000
-
https://supabase.com/blog/pg-graphql
pg_graphql: A GraphQL extension for PostgreSQL
https://supabase.com/blog/pg-graphql
GraphQL support is in development for PostgreSQL + Supabase.
- Thu, 02 Dec 2021 03:03:30 +0000
+ Thu, 02 Dec 2021 23:11:00 +0000
-
https://supabase.com/blog/launch-week-three-friday-five-more-things
Five more things
https://supabase.com/blog/launch-week-three-friday-five-more-things
It's never just one more thing!
- Thu, 02 Dec 2021 03:03:30 +0000
+ Thu, 02 Dec 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-acquires-logflare
Supabase acquires Logflare
https://supabase.com/blog/supabase-acquires-logflare
Today, we're ecstatic to announce that Logflare is joining Supabase.
- Wed, 01 Dec 2021 03:03:30 +0000
+ Wed, 01 Dec 2021 23:11:00 +0000
-
https://supabase.com/blog/realtime-row-level-security-in-postgresql
Realtime Postgres RLS now available on Supabase
https://supabase.com/blog/realtime-row-level-security-in-postgresql
Realtime database changes are now broadcast to authenticated users, respecting the same PostgreSQL policies that you use for Row Level Security.
- Tue, 30 Nov 2021 03:03:30 +0000
+ Tue, 30 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-studio
Supabase Studio
https://supabase.com/blog/supabase-studio
The same Dashboard that you're using on our Platform is now available for local development and Self-Hosting.
- Mon, 29 Nov 2021 03:03:30 +0000
+ Mon, 29 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/community-day-lw3
Community Day
https://supabase.com/blog/community-day-lw3
Kicking off launch week by highlighting the communities around Supabase.
- Sun, 28 Nov 2021 03:03:30 +0000
+ Sun, 28 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/whats-new-in-postgres-14
New in PostgreSQL 14: What every developer should know
https://supabase.com/blog/whats-new-in-postgres-14
A quick look at some new features and functionality in PostgreSQL 14.
- Sat, 27 Nov 2021 03:03:30 +0000
+ Sat, 27 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/postgrest-9
PostgREST 9
https://supabase.com/blog/postgrest-9
New features and updates in PostgREST version 9.
- Fri, 26 Nov 2021 03:03:30 +0000
+ Fri, 26 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-launch-week-the-trilogy
Supabase Launch Week III: Holiday Special
https://supabase.com/blog/supabase-launch-week-the-trilogy
Tis the season to be shipping.
- Thu, 25 Nov 2021 03:03:30 +0000
+ Thu, 25 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-how-we-launch
How we launch at Supabase
https://supabase.com/blog/supabase-how-we-launch
The history and methodology of Supabase Launch Week.
- Thu, 25 Nov 2021 03:03:30 +0000
+ Thu, 25 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-october-2021
Supabase Beta October 2021
https://supabase.com/blog/supabase-beta-october-2021
Three new Auth providers, multi-schema support, and we're gearing up for another Launch Week.
- Sat, 06 Nov 2021 02:02:30 +0000
+ Sat, 06 Nov 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-series-a
Supabase $30m Series A
https://supabase.com/blog/supabase-series-a
Supabase just raised $30M, bringing our total funding to $36M.
- Wed, 27 Oct 2021 02:02:30 +0000
+ Wed, 27 Oct 2021 22:10:00 +0000
-
https://supabase.com/blog/replenysh-time-to-value-in-less-than-24-hours
Replenysh uses Supabase to implement OTP in less than 24-hours
https://supabase.com/blog/replenysh-time-to-value-in-less-than-24-hours
Learn how Replenysh uses Supabase to power the circular economy, redefining how brands interact with their customers and products.
- Mon, 18 Oct 2021 02:02:30 +0000
+ Mon, 18 Oct 2021 22:10:00 +0000
-
https://supabase.com/blog/hacktoberfest-hackathon-winners-2021
Hacktoberfest Hackathon Winners 2021
https://supabase.com/blog/hacktoberfest-hackathon-winners-2021
Celebrating many amazing projects submitted to our Hacktoberfest Hackathon.
- Wed, 13 Oct 2021 02:02:30 +0000
+ Wed, 13 Oct 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-sept-2021
Supabase Beta Sept 2021
https://supabase.com/blog/supabase-beta-sept-2021
Hackathon, Aborting request, UI updates, and now Hiring.
- Sun, 03 Oct 2021 02:02:30 +0000
+ Sun, 03 Oct 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-hacktoberfest-hackathon-2021
Supabase Hacktoberfest Hackathon 2021
https://supabase.com/blog/supabase-hacktoberfest-hackathon-2021
We're running another Supabase Hackathon during Hacktoberfest!
- Mon, 27 Sep 2021 02:02:30 +0000
+ Mon, 27 Sep 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-august-2021
Supabase Beta August 2021
https://supabase.com/blog/supabase-beta-august-2021
Fundraising, Realtime Security, custom SMS templates, and deployments in South Korea.
- Thu, 09 Sep 2021 02:02:30 +0000
+ Thu, 09 Sep 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-july-2021
Supabase Beta July 2021
https://supabase.com/blog/supabase-beta-july-2021
Discord Logins, Vercel Integration, Full text search, and OAuth guides.
- Wed, 11 Aug 2021 02:02:30 +0000
+ Wed, 11 Aug 2021 22:10:00 +0000
-
https://supabase.com/blog/hackathon-winners
Open Source Hackathon Winners
https://supabase.com/blog/hackathon-winners
Let the medal ceremony begin for the best projects submitted during the Supabase Hackathon.
- Sun, 08 Aug 2021 02:02:30 +0000
+ Sun, 08 Aug 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-swag-store
Supabase Swag Store
https://supabase.com/blog/supabase-swag-store
Today we are officially launching the Supabase Swag Store.
- Thu, 29 Jul 2021 02:02:30 +0000
+ Thu, 29 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-functions-updates
Updates for Supabase Functions
https://supabase.com/blog/supabase-functions-updates
The question on everyone's mind - are we launching Supabase Functions? Well, it's complicated.
- Thu, 29 Jul 2021 02:02:30 +0000
+ Thu, 29 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/1-the-supabase-hackathon
The Supabase Hackathon
https://supabase.com/blog/1-the-supabase-hackathon
A whole week of Hacking for Fun and Prizes.
- Thu, 29 Jul 2021 02:02:30 +0000
+ Thu, 29 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-reports-and-metrics
Supabase Reports and Metrics
https://supabase.com/blog/supabase-reports-and-metrics
We're exposing a full set of metrics in your projects, so that you can build better (and faster) products for your users.
- Wed, 28 Jul 2021 02:02:30 +0000
+ Wed, 28 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-auth-passwordless-sms-login
Supabase Auth v2: Phone Auth now available
https://supabase.com/blog/supabase-auth-passwordless-sms-login
Phone Auth is available today on all new and existing Supabase projects.
- Tue, 27 Jul 2021 02:02:30 +0000
+ Tue, 27 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/mobbin-supabase-200000-users
Mobbin uses Supabase to authenticate 200,000 users
https://supabase.com/blog/mobbin-supabase-200000-users
Learn how Mobbin migrated 200,000 users from Firebase for a better authentication experience.
- Tue, 27 Jul 2021 02:02:30 +0000
+ Tue, 27 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/storage-beta
Supabase Storage now in Beta
https://supabase.com/blog/storage-beta
Supabase Storage moves into Beta.
- Mon, 26 Jul 2021 02:02:30 +0000
+ Mon, 26 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/spot-flutter-with-postgres
Spot: a video sharing app built with Flutter
https://supabase.com/blog/spot-flutter-with-postgres
Spot is a geolocation-based video-sharing app with some social networking features.
- Mon, 26 Jul 2021 02:02:30 +0000
+ Mon, 26 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-postgres-13
Supabase is now on Postgres 13.3
https://supabase.com/blog/supabase-postgres-13
From today, new Supabase projects will be on a version of Supabase Postgres that runs on Postgres 13.3.
- Sun, 25 Jul 2021 02:02:30 +0000
+ Sun, 25 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-community-day
Supabase Community Day
https://supabase.com/blog/supabase-community-day
Community Day
- Sun, 25 Jul 2021 02:02:30 +0000
+ Sun, 25 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/epsilon3-self-hosting
Epsilon3 Self-Host Supabase To Revolutionize Space Operations
https://supabase.com/blog/epsilon3-self-hosting
Learn how the team at Epsilon3 use Supabase to help teams execute secure and reliable operations in an industry that project spend runs into the billions.
- Sun, 25 Jul 2021 02:02:30 +0000
+ Sun, 25 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-launch-week-sql
Supabase Launch Week II: The SQL
https://supabase.com/blog/supabase-launch-week-sql
Five days of Supabase. Again.
- Wed, 21 Jul 2021 02:02:30 +0000
+ Wed, 21 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/roles-postgres-hooks
Protecting reserved roles with PostgreSQL Hooks
https://supabase.com/blog/roles-postgres-hooks
Using Postgres Hooks to protect functionality in your Postgres database.
- Thu, 01 Jul 2021 02:02:30 +0000
+ Thu, 01 Jul 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-june-2021
Supabase Beta June 2021
https://supabase.com/blog/supabase-beta-june-2021
Discord Logins, Vercel Integration, Full text search, and OAuth guides.
- Tue, 01 Jun 2021 02:02:30 +0000
+ Tue, 01 Jun 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-may-2021
Supabase Beta May 2021
https://supabase.com/blog/supabase-beta-may-2021
Apple & Twitter Logins, Supabase Grid, Go & Swift Libraries.
- Tue, 01 Jun 2021 02:02:30 +0000
+ Tue, 01 Jun 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-april-2021
Supabase Beta April 2021
https://supabase.com/blog/supabase-beta-april-2021
Supabase "gardening" - stability, security, and community support.
- Tue, 04 May 2021 02:02:30 +0000
+ Tue, 04 May 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-beta-march-2021
Supabase Beta March 2021
https://supabase.com/blog/supabase-beta-march-2021
Launch week, Storage, Supabase CLI, Connection Pooling, Supabase UI, and Pricing.
- Mon, 05 Apr 2021 02:02:30 +0000
+ Mon, 05 Apr 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-workflows
Workflows are coming to Supabase
https://supabase.com/blog/supabase-workflows
Functions are great, but you know what's better?
- Thu, 01 Apr 2021 02:02:30 +0000
+ Thu, 01 Apr 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-pgbouncer
PgBouncer is now available in Supabase
https://supabase.com/blog/supabase-pgbouncer
Better support for Serverless and Postgres.
- Thu, 01 Apr 2021 02:02:30 +0000
+ Thu, 01 Apr 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-dot-com
Supabase Dot Com
https://supabase.com/blog/supabase-dot-com
The Supabase Domain name is changing.
- Thu, 01 Apr 2021 02:02:30 +0000
+ Thu, 01 Apr 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-nft-marketplace
Supabase Launches NFT Marketplace
https://supabase.com/blog/supabase-nft-marketplace
A fully encrypted NFT platform to protect and transact your digital assets
- Thu, 01 Apr 2021 02:02:30 +0000
+ Wed, 31 Mar 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-cli
Supabase CLI
https://supabase.com/blog/supabase-cli
Local development, database migrations, and self-hosting.
- Wed, 31 Mar 2021 02:02:30 +0000
+ Tue, 30 Mar 2021 22:10:00 +0000
-
https://supabase.com/blog/supabase-storage
Storage is now available in Supabase
https://supabase.com/blog/supabase-storage
Launching Supabase Storage and how you can use it in your apps
- Tue, 30 Mar 2021 02:02:30 +0000
+ Mon, 29 Mar 2021 22:10:00 +0000
-
https://supabase.com/blog/pricing
Supabase Beta Pricing
https://supabase.com/blog/pricing
Supabase launches Beta pricing structure
- Mon, 29 Mar 2021 02:02:30 +0000
+ Sun, 28 Mar 2021 22:10:00 +0000
-
https://supabase.com/blog/launch-week
Launch week
https://supabase.com/blog/launch-week
Five days of Supabase.
- Wed, 24 Mar 2021 02:02:30 +0000
+ Wed, 24 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/angels-of-supabase
Angels of Supabase
https://supabase.com/blog/angels-of-supabase
Meet the investors of Supabase.
- Wed, 24 Mar 2021 02:02:30 +0000
+ Wed, 24 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/In-The-Loop
Developers stay up to date with intheloop.dev
https://supabase.com/blog/In-The-Loop
Learn why Kevin is building intheloop.dev with Supabase
- Mon, 22 Mar 2021 02:02:30 +0000
+ Sun, 21 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/using-supabase-replit
Using Supabase in Replit
https://supabase.com/blog/using-supabase-replit
Free hosted relational database from within your node.js repl
- Thu, 11 Mar 2021 03:03:30 +0000
+ Wed, 10 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/toad-a-link-shortener-with-simple-apis-for-low-coders
Toad, a link shortener with simple APIs for low-coders
https://supabase.com/blog/toad-a-link-shortener-with-simple-apis-for-low-coders
An easy-to-use link shortening tool with simple APIs
- Mon, 08 Mar 2021 03:03:30 +0000
+ Sun, 07 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/postgres-as-a-cron-server
Postgres as a CRON Server
https://supabase.com/blog/postgres-as-a-cron-server
Running repetitive tasks with your Postgres database.
- Fri, 05 Mar 2021 03:03:30 +0000
+ Thu, 04 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-february-2021
Supabase Beta February 2021
https://supabase.com/blog/supabase-beta-february-2021
One year of building.
- Tue, 02 Mar 2021 03:03:30 +0000
+ Mon, 01 Mar 2021 23:11:00 +0000
-
https://supabase.com/blog/cracking-postgres-interview
Cracking PostgreSQL Interview Questions
https://supabase.com/blog/cracking-postgres-interview
Understand the top PostgreSQL Interview Questions
- Sat, 27 Feb 2021 03:03:30 +0000
+ Fri, 26 Feb 2021 23:11:00 +0000
-
https://supabase.com/blog/case-study-roboflow
Roboflow.com choose Supabase to power Paint.wtf leaderboard
https://supabase.com/blog/case-study-roboflow
Learn how Roboflow.com used Supabase to build their Paint.wtf leaderboard
- Tue, 09 Feb 2021 03:03:30 +0000
+ Mon, 08 Feb 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-january-2021
Supabase Beta January 2021
https://supabase.com/blog/supabase-beta-january-2021
Eleven months of building.
- Tue, 02 Feb 2021 03:03:30 +0000
+ Mon, 01 Feb 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-beta-december-2020
Supabase Beta December 2020
https://supabase.com/blog/supabase-beta-december-2020
Ten months of building.
- Sat, 02 Jan 2021 03:03:30 +0000
+ Fri, 01 Jan 2021 23:11:00 +0000
-
https://supabase.com/blog/supabase-dashboard-performance
Making the Supabase Dashboard Supa-fast
https://supabase.com/blog/supabase-dashboard-performance
Improving the performance of the Supabase dashboard
- Sun, 13 Dec 2020 03:03:30 +0000
+ Sat, 12 Dec 2020 23:11:00 +0000
-
https://supabase.com/blog/supabase-striveschool
Supabase Partners With Strive School To Help Teach Open Source
https://supabase.com/blog/supabase-striveschool
Supabase Partners With Strive School To Help Teach Open Source To The Next Generation Of Developers
- Wed, 02 Dec 2020 03:03:30 +0000
+ Tue, 01 Dec 2020 23:11:00 +0000
-
https://supabase.com/blog/case-study-xendit
Xendit Built a Counter-Fraud Watchlist for the Fintech Industry
https://supabase.com/blog/case-study-xendit
See how Xendit use Supabase to build a full-text search engine.
- Wed, 02 Dec 2020 03:03:30 +0000
+ Tue, 01 Dec 2020 23:11:00 +0000
-
https://supabase.com/blog/case-study-tayfa
TAYFA Built a No-Code Website Builder in Seven Days
https://supabase.com/blog/case-study-tayfa
See how Tayfa went from idea to paying customer in less than 30 days.
- Wed, 02 Dec 2020 03:03:30 +0000
+ Tue, 01 Dec 2020 23:11:00 +0000
-
https://supabase.com/blog/case-study-monitoro
Monitoro Built a Web Crawler Handling Millions of API Requests
https://supabase.com/blog/case-study-monitoro
See how Monitoro built an automated scraping platform using Supabase.
- Wed, 02 Dec 2020 03:03:30 +0000
+ Tue, 01 Dec 2020 23:11:00 +0000
-
https://supabase.com/blog/supabase-alpha-november-2020
Supabase Alpha November 2020
https://supabase.com/blog/supabase-alpha-november-2020
Nine months of building.
- Tue, 01 Dec 2020 03:03:30 +0000
+ Mon, 30 Nov 2020 23:11:00 +0000
-
https://supabase.com/blog/postgresql-views
Postgres Views
https://supabase.com/blog/postgresql-views
Creating and using a view in PostgreSQL.
- Wed, 18 Nov 2020 03:03:30 +0000
+ Tue, 17 Nov 2020 23:11:00 +0000
-
https://supabase.com/blog/supabase-alpha-october-2020
Supabase Alpha October 2020
https://supabase.com/blog/supabase-alpha-october-2020
Eight months of building.
- Mon, 02 Nov 2020 03:03:30 +0000
+ Sun, 01 Nov 2020 23:11:00 +0000
-
https://supabase.com/blog/improved-dx
Supabase.js 1.0
https://supabase.com/blog/improved-dx
We're releasing a new version of our Supabase client with some awesome new improvements.
- Fri, 30 Oct 2020 02:02:30 +0000
+ Thu, 29 Oct 2020 23:11:00 +0000
-
https://supabase.com/blog/supabase-alpha-september-2020
Supabase Alpha September 2020
https://supabase.com/blog/supabase-alpha-september-2020
Seven months of building.
- Sat, 03 Oct 2020 02:02:30 +0000
+ Fri, 02 Oct 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-hacktoberfest-2020
Supabase Hacktoberfest 2020
https://supabase.com/blog/supabase-hacktoberfest-2020
Join us for a celebration of open source software and learn how to contribute to Supabase.
- Fri, 11 Sep 2020 02:02:30 +0000
+ Thu, 10 Sep 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-alpha-august-2020
Supabase Alpha August 2020
https://supabase.com/blog/supabase-alpha-august-2020
Six months of building
- Thu, 03 Sep 2020 02:02:30 +0000
+ Wed, 02 Sep 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-auth
Supabase Auth
https://supabase.com/blog/supabase-auth
Authenticate and authorize your users with Supabase Auth
- Wed, 05 Aug 2020 02:02:30 +0000
+ Tue, 04 Aug 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-alpha-july-2020
Supabase Alpha July 2020
https://supabase.com/blog/supabase-alpha-july-2020
Five months of building
- Sun, 02 Aug 2020 02:02:30 +0000
+ Sat, 01 Aug 2020 22:10:00 +0000
-
https://supabase.com/blog/continuous-postgresql-backup-walg
Continuous PostgreSQL Backups using WAL-G
https://supabase.com/blog/continuous-postgresql-backup-walg
Have you ever wanted to restore your database's state to a particular moment in time? This post explains how, using WAL-G.
- Sun, 02 Aug 2020 02:02:30 +0000
+ Sat, 01 Aug 2020 22:10:00 +0000
-
https://supabase.com/blog/alpha-launch-postmortem
Alpha Launch Postmortem
https://supabase.com/blog/alpha-launch-postmortem
Everything that went wrong with Supabase's launch
- Fri, 10 Jul 2020 02:02:30 +0000
+ Thu, 09 Jul 2020 22:10:00 +0000
-
https://supabase.com/blog/postgresql-templates
What are PostgreSQL Templates?
https://supabase.com/blog/postgresql-templates
What are PostgreSQL templates and what are they used for?
- Thu, 09 Jul 2020 02:02:30 +0000
+ Wed, 08 Jul 2020 22:10:00 +0000
-
https://supabase.com/blog/postgresql-physical-logical-backups
Physical vs Logical Backups in PostgreSQL
https://supabase.com/blog/postgresql-physical-logical-backups
What are physical and logical backups in Postgres?
- Tue, 07 Jul 2020 02:02:30 +0000
+ Mon, 06 Jul 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-alpha-june-2020
Supabase Alpha June 2020
https://supabase.com/blog/supabase-alpha-june-2020
Four months of building
- Wed, 01 Jul 2020 02:02:30 +0000
+ Tue, 30 Jun 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-steve-chavez
Steve Chavez has joined Supabase
https://supabase.com/blog/supabase-steve-chavez
Steve joins Supabase to help build Auth.
- Mon, 15 Jun 2020 02:02:30 +0000
+ Sun, 14 Jun 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-alpha-may-2020
Supabase Alpha May 2020
https://supabase.com/blog/supabase-alpha-may-2020
Three months of building
- Mon, 01 Jun 2020 02:02:30 +0000
+ Sun, 31 May 2020 22:10:00 +0000
-
https://supabase.com/blog/supabase-alpha-april-2020
Supabase Alpha April 2020
https://supabase.com/blog/supabase-alpha-april-2020
Two months of building
- Mon, 01 Jun 2020 02:02:30 +0000
+ Sun, 31 May 2020 22:10:00 +0000
diff --git a/package-lock.json b/package-lock.json
index 29773e5561f..5bb23e0dd7c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -47,6 +47,9 @@
"@mdx-js/react": "^1.6.22",
"@next/mdx": "^12.0.4",
"@radix-ui/react-accordion": "^1.0.1",
+ "@supabase/auth-helpers-nextjs": "^0.5.4",
+ "@supabase/auth-helpers-react": "^0.3.1",
+ "@supabase/supabase-js": "^2.4.1",
"algoliasearch": "^4.14.2",
"babel": "^6.23.0",
"clsx": "^1.2.1",
@@ -57,7 +60,12 @@
"jsrsasign": "^10.5.26",
"lodash": "^4.17.21",
"markdown-toc": "^1.2.0",
+ "mdast": "^3.0.0",
+ "mdast-util-from-markdown": "^1.2.0",
+ "mdast-util-mdx": "^2.0.0",
+ "mdast-util-to-markdown": "^1.5.0",
"mdx-mermaid": "2.0.0-rc3",
+ "micromark-extension-mdxjs": "^1.0.0",
"next": "12.3.2",
"next-compose-plugins": "^2.2.1",
"next-mdx-remote": "^4.1.0",
@@ -65,6 +73,7 @@
"next-plugin-yaml": "^1.0.1",
"next-seo": "^5.14.1",
"next-transpile-modules": "^9.0.0",
+ "openai": "^3.1.0",
"react": "17.0.2",
"react-copy-to-clipboard": "^5.0.2",
"react-dom": "17.0.2",
@@ -77,7 +86,10 @@
"remark-gfm": "^3.0.1",
"remark-slug": "^7.0.1",
"shiki": "^0.11.1",
+ "sse.js": "^0.6.1",
"ui": "*",
+ "unist-builder": "^3.0.1",
+ "unist-util-filter": "^4.0.1",
"valtio": "^1.7.6"
},
"devDependencies": {
@@ -96,6 +108,7 @@
"sass": "^1.55.0",
"ts-node": "^10.9.1",
"tsconfig": "*",
+ "tsx": "^3.12.2",
"typescript": "^4.5.3"
}
},
@@ -202,20 +215,10 @@
"url": "https://opencollective.com/unified"
}
},
- "apps/docs/node_modules/@mdx-js/mdx/node_modules/remark-mdx": {
- "version": "1.6.22",
- "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz",
- "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==",
- "dependencies": {
- "@babel/core": "7.12.9",
- "@babel/helper-plugin-utils": "7.10.4",
- "@babel/plugin-proposal-object-rest-spread": "7.12.1",
- "@babel/plugin-syntax-jsx": "7.12.1",
- "@mdx-js/util": "1.6.22",
- "is-alphabetical": "1.0.4",
- "remark-parse": "8.0.3",
- "unified": "9.2.0"
- },
+ "apps/docs/node_modules/@mdx-js/mdx/node_modules/unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
@@ -541,6 +544,15 @@
"url": "https://opencollective.com/unified"
}
},
+ "apps/docs/node_modules/mdast-util-to-hast/node_modules/unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"apps/docs/node_modules/mdx-mermaid": {
"version": "2.0.0-rc3",
"resolved": "https://registry.npmjs.org/mdx-mermaid/-/mdx-mermaid-2.0.0-rc3.tgz",
@@ -657,6 +669,25 @@
"resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz",
"integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ=="
},
+ "apps/docs/node_modules/remark-mdx": {
+ "version": "1.6.22",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz",
+ "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==",
+ "dependencies": {
+ "@babel/core": "7.12.9",
+ "@babel/helper-plugin-utils": "7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "7.12.1",
+ "@babel/plugin-syntax-jsx": "7.12.1",
+ "@mdx-js/util": "1.6.22",
+ "is-alphabetical": "1.0.4",
+ "remark-parse": "8.0.3",
+ "unified": "9.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"apps/docs/node_modules/remark-parse": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
@@ -727,15 +758,6 @@
"url": "https://opencollective.com/unified"
}
},
- "apps/docs/node_modules/unist-builder": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
- "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"apps/docs/node_modules/unist-util-generated": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz",
@@ -3362,6 +3384,68 @@
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.2.tgz",
"integrity": "sha512-QCckjiC7xXHIUaIL3ektBtjJ0w7tTA3iqKcAE/Hjn1lZ5omp7i3Y4e09rAr9ZybqirL7AbxCLLq0Ra5DDPKeug=="
},
+ "node_modules/@esbuild-kit/cjs-loader": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.1.tgz",
+ "integrity": "sha512-lhc/XLith28QdW0HpHZvZKkorWgmCNT7sVelMHDj3HFdTfdqkwEKvT+aXVQtNAmCC39VJhunDkWhONWB7335mg==",
+ "dev": true,
+ "dependencies": {
+ "@esbuild-kit/core-utils": "^3.0.0",
+ "get-tsconfig": "^4.2.0"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.0.0.tgz",
+ "integrity": "sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "~0.15.10",
+ "source-map-support": "^0.5.21"
+ }
+ },
+ "node_modules/@esbuild-kit/esm-loader": {
+ "version": "2.5.4",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.4.tgz",
+ "integrity": "sha512-afmtLf6uqxD5IgwCzomtqCYIgz/sjHzCWZFvfS5+FzeYxOURPUo4QcHtqJxbxWOMOogKriZanN/1bJQE/ZL93A==",
+ "dev": true,
+ "dependencies": {
+ "@esbuild-kit/core-utils": "^3.0.0",
+ "get-tsconfig": "^4.2.0"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+ "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+ "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@eslint/eslintrc": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@@ -4535,9 +4619,9 @@
}
},
"node_modules/@mdx-js/loader": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-2.1.5.tgz",
- "integrity": "sha512-oXjfTa/iAcMmW8DdQ+hQFodPCLqw5VKT2yoZkLwrZfPVVpUgKrI+5/ZePYq328xxtAUStZmR3ed0PWJrwd5Pkg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-2.2.1.tgz",
+ "integrity": "sha512-J4E8A5H+xtk4otZiEZ5AXl61Tj04Avm5MqLQazITdI3+puVXVnTTuZUKM1oNHTtfDIfOl0uMt+o/Ij+x6Fvf+g==",
"dependencies": {
"@mdx-js/mdx": "^2.0.0",
"source-map": "^0.7.0"
@@ -4551,9 +4635,9 @@
}
},
"node_modules/@mdx-js/mdx": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.1.5.tgz",
- "integrity": "sha512-zEG0lt+Bl/r5U6e0TOS7qDbsXICtemfAPquxWFsMbdzrvlWaqMGemLl+sjVpqlyaaiCiGVQBSGdCk0t1qXjkQg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.2.1.tgz",
+ "integrity": "sha512-hZ3ex7exYLJn6FfReq8yTvA6TE53uW9UHJQM9IlSauOuS55J9y8RtA7W+dzp6Yrzr00/U1sd7q+Wf61q6SfiTQ==",
"dependencies": {
"@types/estree-jsx": "^1.0.0",
"@types/mdx": "^2.0.0",
@@ -4813,9 +4897,9 @@
}
},
"node_modules/@mdx-js/react": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.1.5.tgz",
- "integrity": "sha512-3Az1I6SAWA9R38rYjz5rXBrGKeZhq96CSSyQtqY+maPj8stBsoUH5pNcmIixuGkufYsh8F5+ka2CVPo2fycWZw==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.2.1.tgz",
+ "integrity": "sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==",
"dependencies": {
"@types/mdx": "^2.0.0",
"@types/react": ">=16"
@@ -9844,6 +9928,33 @@
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.44.1.tgz",
"integrity": "sha512-DKj3U6tS+sCNsSXsoZbOl5gDrAVD3cAZ9QCiVSykLC3iJo085kkmw/3BAACRH54Bq2bN34yySuH6G1SLh2xHXA=="
},
+ "node_modules/@supabase/auth-helpers-nextjs": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-nextjs/-/auth-helpers-nextjs-0.5.4.tgz",
+ "integrity": "sha512-Xm3BMDOYPbNyuh8UXDRgBDc3JkeM5S2PfuC1jFJ73CCay4YiH1YxTz06Cvtp+vLH432qdjnqH+49ehVvUehPnQ==",
+ "dependencies": {
+ "@supabase/auth-helpers-shared": "0.2.4"
+ },
+ "peerDependencies": {
+ "@supabase/supabase-js": "^2.0.4"
+ }
+ },
+ "node_modules/@supabase/auth-helpers-react": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-react/-/auth-helpers-react-0.3.1.tgz",
+ "integrity": "sha512-g3SFv08Dz9FapNif/ZY1b7qKGlMJDyTLSayHBz3kb3FuYxg7aLWgQtydDhm5AGbc0XtvpIBuhGTIOVevwpdosA==",
+ "peerDependencies": {
+ "@supabase/supabase-js": "^2.0.4"
+ }
+ },
+ "node_modules/@supabase/auth-helpers-shared": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-shared/-/auth-helpers-shared-0.2.4.tgz",
+ "integrity": "sha512-c+hi3N6DhjPTzjXGOokre4gmMZOqt0f1ORrwZwi2s07pk3cbkmn77DwwVtlYMNi3oZNYRQqAfxJu83UzpJrrmg==",
+ "peerDependencies": {
+ "@supabase/supabase-js": "^2.0.4"
+ }
+ },
"node_modules/@supabase/auth-ui-react": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@supabase/auth-ui-react/-/auth-ui-react-0.1.8.tgz",
@@ -9871,9 +9982,9 @@
}
},
"node_modules/@supabase/gotrue-js": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.3.1.tgz",
- "integrity": "sha512-txYVDrKAFXxT4nyVGnW3M9Oid4u3Xe/Na+wTEzwU+IBuPUEz72ZBHNKo6HBKlZNpnlGtgCSciYhH8qFkZYGV3g==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.10.0.tgz",
+ "integrity": "sha512-3k9zg+TN4rJFVbAWoX1KnOpKthb21HxYu87mBG8ccCXSl3fxnFBJNs898+pksj4fw5E6aM/dVtHHHAfV3MwVRQ==",
"dependencies": {
"cross-fetch": "^3.1.5"
}
@@ -9898,9 +10009,9 @@
}
},
"node_modules/@supabase/postgrest-js": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.1.0.tgz",
- "integrity": "sha512-qkY8TqIu5sJuae8gjeDPjEqPrefzcTraW9PNSVJQHq4TEv98ZmwaXGwBGz0bVL63bqrGA5hqREbQHkANUTXrvA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.3.0.tgz",
+ "integrity": "sha512-XVX0XaWTyT06mtj67gKb0OasP9hUNIYpypgdKnIqBSib5fXD3aRb6U5rt9y9gG1UMi7pCCgv2qulKRIQlHbb9w==",
"dependencies": {
"cross-fetch": "^3.1.5"
}
@@ -9926,9 +10037,9 @@
}
},
"node_modules/@supabase/realtime-js": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.1.0.tgz",
- "integrity": "sha512-iplLCofTeYjnx9FIOsIwHLhMp0+7UVyiA4/sCeq40VdOgN9eTIhjEno9Tgh4dJARi4aaXoKfRX1DTxgZaOpPAw==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.3.1.tgz",
+ "integrity": "sha512-AX4pzZozVPvHAWfPcKl0UWj19pqwogD9TnCEHq1x/6oQjVoqA3n6H+1Ea2of9MheSroajHguaQMen3xLEoWrug==",
"dependencies": {
"@types/phoenix": "^1.5.4",
"websocket": "^1.0.34"
@@ -9940,23 +10051,23 @@
"integrity": "sha512-xC4nnUfRUUbQsEH+62bxwf10G7lt4mS0mIq3rM/Yw3MJ0SUToSxIuRTd115GfvFjx5HPbFLJFNVSn8p8njvLaQ=="
},
"node_modules/@supabase/storage-js": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.0.0.tgz",
- "integrity": "sha512-7kXThdRt/xqnOOvZZxBqNkeX1CFNUWc0hYBJtNN/Uvt8ok9hD14foYmroWrHn046wEYFqUrB9U35JYsfTrvltA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.3.0.tgz",
+ "integrity": "sha512-YGWVCEYYYF3+UiyL8O4xC78N9n9paLbT0hHl8dmYAtd3DqyWtu5Eph9JTu0PWm+/29Zhns5TbhUZW4xpWjJfPQ==",
"dependencies": {
"cross-fetch": "^3.1.5"
}
},
"node_modules/@supabase/supabase-js": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.1.1.tgz",
- "integrity": "sha512-6uBz31zrYfXkb5f2lzSHtncLWDQG5LvuH/OrmIAJqnjvliyd1pXMCGn/03xTfnflbjMolbOva+XMrydkyIMDfQ==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.4.1.tgz",
+ "integrity": "sha512-nFePO2yKVip3VI+OyfUOxhv0IyMmZDeieFJS39y84evPOM9zuZomEmkhwnmEWrLFI7hSr+o2QvY4P+q3c2MbGQ==",
"dependencies": {
"@supabase/functions-js": "^2.0.0",
- "@supabase/gotrue-js": "^2.3.1",
- "@supabase/postgrest-js": "^1.1.0",
- "@supabase/realtime-js": "^2.1.0",
- "@supabase/storage-js": "^2.0.0",
+ "@supabase/gotrue-js": "^2.7.2",
+ "@supabase/postgrest-js": "^1.1.1",
+ "@supabase/realtime-js": "^2.3.1",
+ "@supabase/storage-js": "^2.1.0",
"cross-fetch": "^3.1.5"
}
},
@@ -11994,8 +12105,7 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
@@ -13872,7 +13982,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -15937,7 +16046,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
"engines": {
"node": ">=0.4.0"
}
@@ -16683,6 +16791,363 @@
"ext": "^1.1.2"
}
},
+ "node_modules/esbuild": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+ "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.15.18",
+ "@esbuild/linux-loong64": "0.15.18",
+ "esbuild-android-64": "0.15.18",
+ "esbuild-android-arm64": "0.15.18",
+ "esbuild-darwin-64": "0.15.18",
+ "esbuild-darwin-arm64": "0.15.18",
+ "esbuild-freebsd-64": "0.15.18",
+ "esbuild-freebsd-arm64": "0.15.18",
+ "esbuild-linux-32": "0.15.18",
+ "esbuild-linux-64": "0.15.18",
+ "esbuild-linux-arm": "0.15.18",
+ "esbuild-linux-arm64": "0.15.18",
+ "esbuild-linux-mips64le": "0.15.18",
+ "esbuild-linux-ppc64le": "0.15.18",
+ "esbuild-linux-riscv64": "0.15.18",
+ "esbuild-linux-s390x": "0.15.18",
+ "esbuild-netbsd-64": "0.15.18",
+ "esbuild-openbsd-64": "0.15.18",
+ "esbuild-sunos-64": "0.15.18",
+ "esbuild-windows-32": "0.15.18",
+ "esbuild-windows-64": "0.15.18",
+ "esbuild-windows-arm64": "0.15.18"
+ }
+ },
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+ "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+ "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+ "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+ "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+ "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+ "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+ "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+ "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+ "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+ "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+ "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+ "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+ "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+ "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+ "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+ "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+ "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+ "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+ "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+ "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -18867,6 +19332,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-tsconfig": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.3.0.tgz",
+ "integrity": "sha512-YCcF28IqSay3fqpIu5y3Krg/utCBHBeoflkZyHj/QcqI2nrLPC3ZegS9CmIo+hJb8K7aiGsuUl7PwWVjNG2HQQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
"node_modules/get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@@ -23836,6 +24310,12 @@
"safe-buffer": "^5.1.2"
}
},
+ "node_modules/mdast": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mdast/-/mdast-3.0.0.tgz",
+ "integrity": "sha512-xySmf8g4fPKMeC07jXGz971EkLbWAJ83s4US2Tj9lEdnZ142UP5grN73H1Xd3HzrdbU5o9GYYP/y8F9ZSwLE9g==",
+ "deprecated": "`mdast` was renamed to `remark`"
+ },
"node_modules/mdast-squeeze-paragraphs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz",
@@ -24207,6 +24687,28 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/mdast-util-phrasing": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz",
+ "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-phrasing/node_modules/unist-util-is": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.0.tgz",
+ "integrity": "sha512-Glt17jWwZeyqrFqOK0pF1Ded5U3yzJnFr8CG1GMjCWTp9zDo2p+cmD6pWbZU8AgM5WU3IzRv6+rBwhzsGh6hBQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/mdast-util-to-hast": {
"version": "12.2.4",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.2.4.tgz",
@@ -24290,13 +24792,14 @@
}
},
"node_modules/mdast-util-to-markdown": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz",
- "integrity": "sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz",
+ "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==",
"dependencies": {
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^3.0.0",
"mdast-util-to-string": "^3.0.0",
"micromark-util-decode-string": "^1.0.0",
"unist-util-visit": "^4.0.0",
@@ -25406,7 +25909,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -25415,7 +25917,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@@ -25923,12 +26424,12 @@
}
},
"node_modules/next-mdx-remote": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.2.0.tgz",
- "integrity": "sha512-X5RhD7f7b78pH2abbuusObSGgII5l54OdusS/2iXljN7WN1cel6ToLlZeCZcyxx9cR4wmBGQYGongIttDYNmAA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.3.0.tgz",
+ "integrity": "sha512-fbxkY03pM2Wx5bDNTVKpYD5Hx3QVZGH+6xDtVIxlxXz4HTifP1yI2DrkDvxXbTz0SYGIbluRMIW81IOOa8pigA==",
"dependencies": {
- "@mdx-js/mdx": "^2.0.0",
- "@mdx-js/react": "^2.0.0",
+ "@mdx-js/mdx": "^2.2.1",
+ "@mdx-js/react": "^2.2.1",
"vfile": "^5.3.0",
"vfile-matter": "^3.0.1"
},
@@ -27246,6 +27747,36 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/openai": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-3.1.0.tgz",
+ "integrity": "sha512-v5kKFH5o+8ld+t0arudj833Mgm3GcgBnbyN9946bj6u7bvel4Yg6YFz2A4HLIYDzmMjIo0s6vSG9x73kOwvdCg==",
+ "dependencies": {
+ "axios": "^0.26.0",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/openai/node_modules/axios": {
+ "version": "0.26.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
+ "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
+ "dependencies": {
+ "follow-redirects": "^1.14.8"
+ }
+ },
+ "node_modules/openai/node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/openapi-types": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.0.2.tgz",
@@ -33952,6 +34483,11 @@
"node": ">= 0.6"
}
},
+ "node_modules/sse.js": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/sse.js/-/sse.js-0.6.1.tgz",
+ "integrity": "sha512-peXG6GnWqF5hnubhMw0WfB6rqQy7z7LaMBT067vqgQwC3gKz8JGFzexBSV80FqZ9JoUDwo3Xt5nxkrGrgbPrtA=="
+ },
"node_modules/ssr-window": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz",
@@ -35470,6 +36006,23 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
+ "node_modules/tsx": {
+ "version": "3.12.2",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.2.tgz",
+ "integrity": "sha512-ykAEkoBg30RXxeOMVeZwar+JH632dZn9EUJVyJwhfag62k6UO/dIyJEV58YuLF6e5BTdV/qmbQrpkWqjq9cUnQ==",
+ "dev": true,
+ "dependencies": {
+ "@esbuild-kit/cjs-loader": "^2.4.1",
+ "@esbuild-kit/core-utils": "^3.0.0",
+ "@esbuild-kit/esm-loader": "^2.5.4"
+ },
+ "bin": {
+ "tsx": "dist/cli.js"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
"node_modules/tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
@@ -35909,9 +36462,9 @@
}
},
"node_modules/unist-builder": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz",
- "integrity": "sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.1.tgz",
+ "integrity": "sha512-gnpOw7DIpCA0vpr6NqdPvTWnlPTApCTRzr+38E6hCWx3rz/cjo83SsKIlS1Z+L5ttScQ2AwutNnb8+tAvpb6qQ==",
"dependencies": {
"@types/unist": "^2.0.0"
},
@@ -35920,6 +36473,38 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/unist-util-filter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-filter/-/unist-util-filter-4.0.1.tgz",
+ "integrity": "sha512-RynicUM/vbOSTSiUK+BnaK9XMfmQUh6gyi7L6taNgc7FIf84GukXVV3ucGzEN/PhUUkdP5hb1MmXc+3cvPUm5Q==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0",
+ "unist-util-visit-parents": "^5.0.0"
+ }
+ },
+ "node_modules/unist-util-filter/node_modules/unist-util-is": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.0.tgz",
+ "integrity": "sha512-Glt17jWwZeyqrFqOK0pF1Ded5U3yzJnFr8CG1GMjCWTp9zDo2p+cmD6pWbZU8AgM5WU3IzRv6+rBwhzsGh6hBQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-filter/node_modules/unist-util-visit-parents": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
+ "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/unist-util-generated": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz",
@@ -40620,6 +41205,50 @@
}
}
},
+ "@esbuild-kit/cjs-loader": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.1.tgz",
+ "integrity": "sha512-lhc/XLith28QdW0HpHZvZKkorWgmCNT7sVelMHDj3HFdTfdqkwEKvT+aXVQtNAmCC39VJhunDkWhONWB7335mg==",
+ "dev": true,
+ "requires": {
+ "@esbuild-kit/core-utils": "^3.0.0",
+ "get-tsconfig": "^4.2.0"
+ }
+ },
+ "@esbuild-kit/core-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.0.0.tgz",
+ "integrity": "sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==",
+ "dev": true,
+ "requires": {
+ "esbuild": "~0.15.10",
+ "source-map-support": "^0.5.21"
+ }
+ },
+ "@esbuild-kit/esm-loader": {
+ "version": "2.5.4",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.4.tgz",
+ "integrity": "sha512-afmtLf6uqxD5IgwCzomtqCYIgz/sjHzCWZFvfS5+FzeYxOURPUo4QcHtqJxbxWOMOogKriZanN/1bJQE/ZL93A==",
+ "dev": true,
+ "requires": {
+ "@esbuild-kit/core-utils": "^3.0.0",
+ "get-tsconfig": "^4.2.0"
+ }
+ },
+ "@esbuild/android-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+ "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+ "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+ "dev": true,
+ "optional": true
+ },
"@eslint/eslintrc": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@@ -41580,18 +42209,18 @@
}
},
"@mdx-js/loader": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-2.1.5.tgz",
- "integrity": "sha512-oXjfTa/iAcMmW8DdQ+hQFodPCLqw5VKT2yoZkLwrZfPVVpUgKrI+5/ZePYq328xxtAUStZmR3ed0PWJrwd5Pkg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-2.2.1.tgz",
+ "integrity": "sha512-J4E8A5H+xtk4otZiEZ5AXl61Tj04Avm5MqLQazITdI3+puVXVnTTuZUKM1oNHTtfDIfOl0uMt+o/Ij+x6Fvf+g==",
"requires": {
"@mdx-js/mdx": "^2.0.0",
"source-map": "^0.7.0"
}
},
"@mdx-js/mdx": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.1.5.tgz",
- "integrity": "sha512-zEG0lt+Bl/r5U6e0TOS7qDbsXICtemfAPquxWFsMbdzrvlWaqMGemLl+sjVpqlyaaiCiGVQBSGdCk0t1qXjkQg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.2.1.tgz",
+ "integrity": "sha512-hZ3ex7exYLJn6FfReq8yTvA6TE53uW9UHJQM9IlSauOuS55J9y8RtA7W+dzp6Yrzr00/U1sd7q+Wf61q6SfiTQ==",
"requires": {
"@types/estree-jsx": "^1.0.0",
"@types/mdx": "^2.0.0",
@@ -41762,9 +42391,9 @@
}
},
"@mdx-js/react": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.1.5.tgz",
- "integrity": "sha512-3Az1I6SAWA9R38rYjz5rXBrGKeZhq96CSSyQtqY+maPj8stBsoUH5pNcmIixuGkufYsh8F5+ka2CVPo2fycWZw==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.2.1.tgz",
+ "integrity": "sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==",
"requires": {
"@types/mdx": "^2.0.0",
"@types/react": ">=16"
@@ -45504,6 +46133,26 @@
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.44.1.tgz",
"integrity": "sha512-DKj3U6tS+sCNsSXsoZbOl5gDrAVD3cAZ9QCiVSykLC3iJo085kkmw/3BAACRH54Bq2bN34yySuH6G1SLh2xHXA=="
},
+ "@supabase/auth-helpers-nextjs": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-nextjs/-/auth-helpers-nextjs-0.5.4.tgz",
+ "integrity": "sha512-Xm3BMDOYPbNyuh8UXDRgBDc3JkeM5S2PfuC1jFJ73CCay4YiH1YxTz06Cvtp+vLH432qdjnqH+49ehVvUehPnQ==",
+ "requires": {
+ "@supabase/auth-helpers-shared": "0.2.4"
+ }
+ },
+ "@supabase/auth-helpers-react": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-react/-/auth-helpers-react-0.3.1.tgz",
+ "integrity": "sha512-g3SFv08Dz9FapNif/ZY1b7qKGlMJDyTLSayHBz3kb3FuYxg7aLWgQtydDhm5AGbc0XtvpIBuhGTIOVevwpdosA==",
+ "requires": {}
+ },
+ "@supabase/auth-helpers-shared": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-shared/-/auth-helpers-shared-0.2.4.tgz",
+ "integrity": "sha512-c+hi3N6DhjPTzjXGOokre4gmMZOqt0f1ORrwZwi2s07pk3cbkmn77DwwVtlYMNi3oZNYRQqAfxJu83UzpJrrmg==",
+ "requires": {}
+ },
"@supabase/auth-ui-react": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@supabase/auth-ui-react/-/auth-ui-react-0.1.8.tgz",
@@ -45525,9 +46174,9 @@
}
},
"@supabase/gotrue-js": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.3.1.tgz",
- "integrity": "sha512-txYVDrKAFXxT4nyVGnW3M9Oid4u3Xe/Na+wTEzwU+IBuPUEz72ZBHNKo6HBKlZNpnlGtgCSciYhH8qFkZYGV3g==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.10.0.tgz",
+ "integrity": "sha512-3k9zg+TN4rJFVbAWoX1KnOpKthb21HxYu87mBG8ccCXSl3fxnFBJNs898+pksj4fw5E6aM/dVtHHHAfV3MwVRQ==",
"requires": {
"cross-fetch": "^3.1.5"
}
@@ -45541,16 +46190,16 @@
"@sinclair/typebox": "^0.25.1",
"pg": "^8.7.1",
"pg-format": "^1.0.4",
- "pgsql-parser": "13.4.0",
+ "pgsql-parser": "^13.3.0",
"postgres-array": "^3.0.1",
"prettier": "^2.6.0",
"prettier-plugin-sql": "^0.12.1"
}
},
"@supabase/postgrest-js": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.1.0.tgz",
- "integrity": "sha512-qkY8TqIu5sJuae8gjeDPjEqPrefzcTraW9PNSVJQHq4TEv98ZmwaXGwBGz0bVL63bqrGA5hqREbQHkANUTXrvA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.3.0.tgz",
+ "integrity": "sha512-XVX0XaWTyT06mtj67gKb0OasP9hUNIYpypgdKnIqBSib5fXD3aRb6U5rt9y9gG1UMi7pCCgv2qulKRIQlHbb9w==",
"requires": {
"cross-fetch": "^3.1.5"
}
@@ -45571,9 +46220,9 @@
}
},
"@supabase/realtime-js": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.1.0.tgz",
- "integrity": "sha512-iplLCofTeYjnx9FIOsIwHLhMp0+7UVyiA4/sCeq40VdOgN9eTIhjEno9Tgh4dJARi4aaXoKfRX1DTxgZaOpPAw==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.3.1.tgz",
+ "integrity": "sha512-AX4pzZozVPvHAWfPcKl0UWj19pqwogD9TnCEHq1x/6oQjVoqA3n6H+1Ea2of9MheSroajHguaQMen3xLEoWrug==",
"requires": {
"@types/phoenix": "^1.5.4",
"websocket": "^1.0.34"
@@ -45585,23 +46234,23 @@
"integrity": "sha512-xC4nnUfRUUbQsEH+62bxwf10G7lt4mS0mIq3rM/Yw3MJ0SUToSxIuRTd115GfvFjx5HPbFLJFNVSn8p8njvLaQ=="
},
"@supabase/storage-js": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.0.0.tgz",
- "integrity": "sha512-7kXThdRt/xqnOOvZZxBqNkeX1CFNUWc0hYBJtNN/Uvt8ok9hD14foYmroWrHn046wEYFqUrB9U35JYsfTrvltA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.3.0.tgz",
+ "integrity": "sha512-YGWVCEYYYF3+UiyL8O4xC78N9n9paLbT0hHl8dmYAtd3DqyWtu5Eph9JTu0PWm+/29Zhns5TbhUZW4xpWjJfPQ==",
"requires": {
"cross-fetch": "^3.1.5"
}
},
"@supabase/supabase-js": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.1.1.tgz",
- "integrity": "sha512-6uBz31zrYfXkb5f2lzSHtncLWDQG5LvuH/OrmIAJqnjvliyd1pXMCGn/03xTfnflbjMolbOva+XMrydkyIMDfQ==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.4.1.tgz",
+ "integrity": "sha512-nFePO2yKVip3VI+OyfUOxhv0IyMmZDeieFJS39y84evPOM9zuZomEmkhwnmEWrLFI7hSr+o2QvY4P+q3c2MbGQ==",
"requires": {
"@supabase/functions-js": "^2.0.0",
- "@supabase/gotrue-js": "^2.3.1",
- "@supabase/postgrest-js": "^1.1.0",
- "@supabase/realtime-js": "^2.1.0",
- "@supabase/storage-js": "^2.0.0",
+ "@supabase/gotrue-js": "^2.7.2",
+ "@supabase/postgrest-js": "^1.1.1",
+ "@supabase/realtime-js": "^2.3.1",
+ "@supabase/storage-js": "^2.1.0",
"cross-fetch": "^3.1.5"
}
},
@@ -47300,8 +47949,7 @@
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"at-least-node": {
"version": "1.0.0",
@@ -48729,7 +49377,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"requires": {
"delayed-stream": "~1.0.0"
}
@@ -50439,8 +51086,7 @@
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"delegate": {
"version": "3.2.0",
@@ -50615,6 +51261,9 @@
"@mdx-js/react": "^1.6.22",
"@next/mdx": "^12.0.4",
"@radix-ui/react-accordion": "^1.0.1",
+ "@supabase/auth-helpers-nextjs": "^0.5.4",
+ "@supabase/auth-helpers-react": "^0.3.1",
+ "@supabase/supabase-js": "^2.4.1",
"@types/node": "^17.0.12",
"@types/react": "17.0.39",
"algoliasearch": "^4.14.2",
@@ -50631,7 +51280,12 @@
"jsrsasign": "^10.5.26",
"lodash": "^4.17.21",
"markdown-toc": "^1.2.0",
+ "mdast": "^3.0.0",
+ "mdast-util-from-markdown": "^1.2.0",
+ "mdast-util-mdx": "^2.0.0",
+ "mdast-util-to-markdown": "^1.5.0",
"mdx-mermaid": "2.0.0-rc3",
+ "micromark-extension-mdxjs": "^1.0.0",
"minimist": "^1.2.6",
"next": "12.3.2",
"next-compose-plugins": "^2.2.1",
@@ -50641,6 +51295,7 @@
"next-seo": "^5.14.1",
"next-transpile-modules": "9.0.0",
"npm-run-all": "^4.1.5",
+ "openai": "^3.1.0",
"openapi-types": "^12.0.2",
"prettier": "^2.2.1",
"react": "17.0.2",
@@ -50656,10 +51311,14 @@
"remark-slug": "^7.0.1",
"sass": "^1.55.0",
"shiki": "^0.11.1",
+ "sse.js": "^0.6.1",
"ts-node": "^10.9.1",
"tsconfig": "*",
+ "tsx": "^3.12.2",
"typescript": "^4.5.3",
"ui": "*",
+ "unist-builder": "^3.0.1",
+ "unist-util-filter": "^4.0.1",
"valtio": "^1.7.6"
},
"dependencies": {
@@ -50745,20 +51404,10 @@
"unist-util-visit": "2.0.3"
},
"dependencies": {
- "remark-mdx": {
- "version": "1.6.22",
- "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz",
- "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==",
- "requires": {
- "@babel/core": "7.12.9",
- "@babel/helper-plugin-utils": "7.10.4",
- "@babel/plugin-proposal-object-rest-spread": "7.12.1",
- "@babel/plugin-syntax-jsx": "7.12.1",
- "@mdx-js/util": "1.6.22",
- "is-alphabetical": "1.0.4",
- "remark-parse": "8.0.3",
- "unified": "9.2.0"
- }
+ "unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw=="
}
}
},
@@ -50932,6 +51581,13 @@
"unist-util-generated": "^1.0.0",
"unist-util-position": "^3.0.0",
"unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw=="
+ }
}
},
"mdx-mermaid": {
@@ -50989,6 +51645,21 @@
"resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz",
"integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ=="
},
+ "remark-mdx": {
+ "version": "1.6.22",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz",
+ "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==",
+ "requires": {
+ "@babel/core": "7.12.9",
+ "@babel/helper-plugin-utils": "7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "7.12.1",
+ "@babel/plugin-syntax-jsx": "7.12.1",
+ "@mdx-js/util": "1.6.22",
+ "is-alphabetical": "1.0.4",
+ "remark-parse": "8.0.3",
+ "unified": "9.2.0"
+ }
+ },
"remark-parse": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
@@ -51045,11 +51716,6 @@
"vfile": "^4.0.0"
}
},
- "unist-builder": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
- "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw=="
- },
"unist-util-generated": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz",
@@ -51556,6 +52222,176 @@
"ext": "^1.1.2"
}
},
+ "esbuild": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+ "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.15.18",
+ "@esbuild/linux-loong64": "0.15.18",
+ "esbuild-android-64": "0.15.18",
+ "esbuild-android-arm64": "0.15.18",
+ "esbuild-darwin-64": "0.15.18",
+ "esbuild-darwin-arm64": "0.15.18",
+ "esbuild-freebsd-64": "0.15.18",
+ "esbuild-freebsd-arm64": "0.15.18",
+ "esbuild-linux-32": "0.15.18",
+ "esbuild-linux-64": "0.15.18",
+ "esbuild-linux-arm": "0.15.18",
+ "esbuild-linux-arm64": "0.15.18",
+ "esbuild-linux-mips64le": "0.15.18",
+ "esbuild-linux-ppc64le": "0.15.18",
+ "esbuild-linux-riscv64": "0.15.18",
+ "esbuild-linux-s390x": "0.15.18",
+ "esbuild-netbsd-64": "0.15.18",
+ "esbuild-openbsd-64": "0.15.18",
+ "esbuild-sunos-64": "0.15.18",
+ "esbuild-windows-32": "0.15.18",
+ "esbuild-windows-64": "0.15.18",
+ "esbuild-windows-arm64": "0.15.18"
+ }
+ },
+ "esbuild-android-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+ "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-android-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+ "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+ "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+ "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+ "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+ "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+ "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+ "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+ "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+ "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-mips64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+ "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-ppc64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+ "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-riscv64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+ "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-s390x": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+ "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-netbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+ "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-openbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+ "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-sunos-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+ "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+ "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+ "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+ "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+ "dev": true,
+ "optional": true
+ },
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -53228,6 +54064,12 @@
"get-intrinsic": "^1.1.1"
}
},
+ "get-tsconfig": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.3.0.tgz",
+ "integrity": "sha512-YCcF28IqSay3fqpIu5y3Krg/utCBHBeoflkZyHj/QcqI2nrLPC3ZegS9CmIo+hJb8K7aiGsuUl7PwWVjNG2HQQ==",
+ "dev": true
+ },
"get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@@ -57087,6 +57929,11 @@
"safe-buffer": "^5.1.2"
}
},
+ "mdast": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mdast/-/mdast-3.0.0.tgz",
+ "integrity": "sha512-xySmf8g4fPKMeC07jXGz971EkLbWAJ83s4US2Tj9lEdnZ142UP5grN73H1Xd3HzrdbU5o9GYYP/y8F9ZSwLE9g=="
+ },
"mdast-squeeze-paragraphs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz",
@@ -57350,6 +58197,22 @@
"mdast-util-to-markdown": "^1.0.0"
}
},
+ "mdast-util-phrasing": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz",
+ "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==",
+ "requires": {
+ "@types/mdast": "^3.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.0.tgz",
+ "integrity": "sha512-Glt17jWwZeyqrFqOK0pF1Ded5U3yzJnFr8CG1GMjCWTp9zDo2p+cmD6pWbZU8AgM5WU3IzRv6+rBwhzsGh6hBQ=="
+ }
+ }
+ },
"mdast-util-to-hast": {
"version": "12.2.4",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.2.4.tgz",
@@ -57411,13 +58274,14 @@
}
},
"mdast-util-to-markdown": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz",
- "integrity": "sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz",
+ "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==",
"requires": {
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^3.0.0",
"mdast-util-to-string": "^3.0.0",
"micromark-util-decode-string": "^1.0.0",
"unist-util-visit": "^4.0.0",
@@ -58152,14 +59016,12 @@
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
"requires": {
"mime-db": "1.52.0"
}
@@ -58805,12 +59667,12 @@
}
},
"next-mdx-remote": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.2.0.tgz",
- "integrity": "sha512-X5RhD7f7b78pH2abbuusObSGgII5l54OdusS/2iXljN7WN1cel6ToLlZeCZcyxx9cR4wmBGQYGongIttDYNmAA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.3.0.tgz",
+ "integrity": "sha512-fbxkY03pM2Wx5bDNTVKpYD5Hx3QVZGH+6xDtVIxlxXz4HTifP1yI2DrkDvxXbTz0SYGIbluRMIW81IOOa8pigA==",
"requires": {
- "@mdx-js/mdx": "^2.0.0",
- "@mdx-js/react": "^2.0.0",
+ "@mdx-js/mdx": "^2.2.1",
+ "@mdx-js/react": "^2.2.1",
"vfile": "^5.3.0",
"vfile-matter": "^3.0.1"
}
@@ -59541,6 +60403,35 @@
"is-wsl": "^2.2.0"
}
},
+ "openai": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-3.1.0.tgz",
+ "integrity": "sha512-v5kKFH5o+8ld+t0arudj833Mgm3GcgBnbyN9946bj6u7bvel4Yg6YFz2A4HLIYDzmMjIo0s6vSG9x73kOwvdCg==",
+ "requires": {
+ "axios": "^0.26.0",
+ "form-data": "^4.0.0"
+ },
+ "dependencies": {
+ "axios": {
+ "version": "0.26.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
+ "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
+ "requires": {
+ "follow-redirects": "^1.14.8"
+ }
+ },
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ }
+ }
+ },
"openapi-types": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.0.2.tgz",
@@ -64503,6 +65394,11 @@
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="
},
+ "sse.js": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/sse.js/-/sse.js-0.6.1.tgz",
+ "integrity": "sha512-peXG6GnWqF5hnubhMw0WfB6rqQy7z7LaMBT067vqgQwC3gKz8JGFzexBSV80FqZ9JoUDwo3Xt5nxkrGrgbPrtA=="
+ },
"ssr-window": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz",
@@ -66102,6 +66998,18 @@
}
}
},
+ "tsx": {
+ "version": "3.12.2",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.2.tgz",
+ "integrity": "sha512-ykAEkoBg30RXxeOMVeZwar+JH632dZn9EUJVyJwhfag62k6UO/dIyJEV58YuLF6e5BTdV/qmbQrpkWqjq9cUnQ==",
+ "dev": true,
+ "requires": {
+ "@esbuild-kit/cjs-loader": "^2.4.1",
+ "@esbuild-kit/core-utils": "^3.0.0",
+ "@esbuild-kit/esm-loader": "^2.5.4",
+ "fsevents": "~2.3.2"
+ }
+ },
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
@@ -66649,13 +67557,39 @@
}
},
"unist-builder": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz",
- "integrity": "sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.1.tgz",
+ "integrity": "sha512-gnpOw7DIpCA0vpr6NqdPvTWnlPTApCTRzr+38E6hCWx3rz/cjo83SsKIlS1Z+L5ttScQ2AwutNnb8+tAvpb6qQ==",
"requires": {
"@types/unist": "^2.0.0"
}
},
+ "unist-util-filter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-filter/-/unist-util-filter-4.0.1.tgz",
+ "integrity": "sha512-RynicUM/vbOSTSiUK+BnaK9XMfmQUh6gyi7L6taNgc7FIf84GukXVV3ucGzEN/PhUUkdP5hb1MmXc+3cvPUm5Q==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0",
+ "unist-util-visit-parents": "^5.0.0"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.0.tgz",
+ "integrity": "sha512-Glt17jWwZeyqrFqOK0pF1Ded5U3yzJnFr8CG1GMjCWTp9zDo2p+cmD6pWbZU8AgM5WU3IzRv6+rBwhzsGh6hBQ=="
+ },
+ "unist-util-visit-parents": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
+ "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0"
+ }
+ }
+ }
+ },
"unist-util-generated": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz",
diff --git a/spec/common-client-libs-sections.json b/spec/common-client-libs-sections.json
index c48f87c6b99..b77ac83e9f2 100644
--- a/spec/common-client-libs-sections.json
+++ b/spec/common-client-libs-sections.json
@@ -10,14 +10,17 @@
"id": "installing",
"slug": "installing",
"type": "markdown",
- "excludes": ["reference_javascript_v1", "reference_dart_v0", "reference_python_v2"]
+ "excludes": [
+ "reference_javascript_v1",
+ "reference_dart_v0",
+ "reference_python_v2"
+ ]
},
{
"title": "Initializing",
"id": "initializing",
"slug": "initializing",
- "type": "markdown",
- "libs": ["csharp"]
+ "type": "function"
},
{
"title": "Typescript Support",
@@ -355,6 +358,14 @@
"product": "database",
"parent": "modifiers",
"type": "function"
+ },
+ {
+ "id": "returns",
+ "title": "Override type of successful response",
+ "slug": "db-returns",
+ "product": "database",
+ "parent": "modifiers",
+ "type": "function"
}
]
}
@@ -367,7 +378,6 @@
"id": "auth-api",
"title": "Overview",
"slug": "auth-api",
-
"type": "function"
},
{
@@ -570,7 +580,6 @@
"id": "admin-api",
"title": "Auth Admin",
"slug": "admin-api",
-
"type": "function",
"items": [
{
@@ -704,7 +713,6 @@
"product": "realtime",
"type": "function"
},
-
{
"id": "remove-channel",
"title": "Unsubscribe from a channel",
@@ -847,7 +855,10 @@
},
{
"title": "Misc",
- "excludes": ["reference_dart_v1", "reference_dart_v0"],
+ "excludes": [
+ "reference_dart_v1",
+ "reference_dart_v0"
+ ],
"items": [
{
"title": "Release Notes",
@@ -858,4 +869,4 @@
}
]
}
-]
+]
\ No newline at end of file
diff --git a/spec/supabase_csharp_v0.yml b/spec/supabase_csharp_v0.yml
index 9f2c963685b..a83d003bd2a 100644
--- a/spec/supabase_csharp_v0.yml
+++ b/spec/supabase_csharp_v0.yml
@@ -16,6 +16,104 @@ info:
version: '0.8.0'
functions:
+ - id: initializing
+ title: Initializing
+ description: |
+ Initializing a new client is pretty straightforward. Find your project url and public key from the
+ admin panel and pass it into your client initialization function.
+
+ `supabase-csharp` is heavily dependent on Models deriving from `BaseModel`. To interact with the API, one must have the associated model (see example) specified.
+
+ Leverage `Table`, `PrimaryKey`, and `Column` attributes to specify names of classes/properties that are different from their C# Versions.
+
+ examples:
+ - id: csharp-init-standard
+ name: Standard
+ code: |
+ ```c#
+ var url = Environment.GetEnvironmentVariable("SUPABASE_URL");
+ var key = Environment.GetEnvironmentVariable("SUPABASE_KEY");
+
+ var options = new Supabase.SupabaseOptions
+ {
+ AutoConnectRealtime = true
+ };
+
+ var supabase = new Supabase.Client(url, key, options);
+ await supabase.InitializeAsync();
+ ```
+ - id: csharp-init-maui
+ name: Dependency Injection (Maui-like)
+ code: |
+ ```c#
+ public static MauiApp CreateMauiApp()
+ {
+ // ...
+ var builder = MauiApp.CreateBuilder();
+
+ var url = Environment.GetEnvironmentVariable("SUPABASE_URL");
+ var key = Environment.GetEnvironmentVariable("SUPABASE_KEY");
+ var options = new SupabaseOptions
+ {
+ AutoRefreshToken = true,
+ AutoConnectRealtime = true,
+ SessionHandler = new SupabaseSessionHandler()
+ };
+
+ // Note the creation as a singleton.
+ builder.Services.AddSingleton(provider => new Supabase.Client(url, key, options));
+ }
+ ```
+ - id: csharp-init-showing-models
+ name: With Models Example
+ code: |
+ ```c#
+ // Given the following Model representing the Supabase Database (Message.cs)
+ [Table("messages")]
+ public class Message : BaseModel
+ {
+ [PrimaryKey("id")]
+ public int Id { get; set; }
+
+ [Column("username")]
+ public string UserName { get; set; }
+
+ [Column("channel_id")]
+ public int ChannelId { get; set; }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Message message &&
+ Id == message.Id;
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Id);
+ }
+ }
+
+ void Initialize()
+ {
+ // Get All Messages
+ var response = await client.Table().Get();
+ List models = response.Models;
+
+ // Insert
+ var newMessage = new Message { UserName = "acupofjose", ChannelId = 1 };
+ await client.Table().Insert();
+
+ // Update
+ var model = response.Models.First();
+ model.UserName = "elrhomariyounes";
+ await model.Update();
+
+ // Delete
+ await response.Models.Last().Delete();
+
+ // etc.
+ }
+ ```
- id: sign-up
title: 'SignUp()'
description: |
diff --git a/spec/supabase_js_v2.yml b/spec/supabase_js_v2.yml
index 4283df18eca..f2e625f0edc 100644
--- a/spec/supabase_js_v2.yml
+++ b/spec/supabase_js_v2.yml
@@ -66,9 +66,9 @@ functions:
db: { schema: 'other_schema' }
})
```
-
+ description: |
By default the API server points to the `public` schema. You can enable other database schemas within the Dashboard.
- Go to `Settings > API > Schema` and add the schema which you want to expose to the API.
+ Go to [Settings > API > Exposed schemas](https://app.supabase.com/project/_/settings/api) and add the schema which you want to expose to the API.
Note: each client connection can only access a single schema, so the code above can access the `other_schema` schema but cannot access the `public` schema.
- id: custom-fetch-implementation
@@ -81,7 +81,7 @@ functions:
global: { fetch: fetch.bind(globalThis) }
})
```
-
+ description: |
`supabase-js` uses the [`cross-fetch`](https://www.npmjs.com/package/cross-fetch) library to make HTTP requests,
but an alternative `fetch` implementation can be provided as an option.
This is most useful in environments where `cross-fetch` is not compatible (for instance Cloudflare Workers).
@@ -101,7 +101,7 @@ functions:
},
});
```
-
+ description: |
For React Native we recommend using `AsyncStorage` as the storage implementation for Supabase Auth.
- id: auth-api
title: 'Overview'
@@ -3895,6 +3895,25 @@ functions:
By default, the data is returned in JSON format, but can also be returned as Comma Separated Values.
hideCodeBlock: true
isSpotlight: true
+ - id: returns
+ $ref: '@supabase/postgrest-js.PostgrestTransformBuilder.returns'
+ title: returns()
+ examples:
+ - id: override-type-of-successful-response
+ name: Override type of successful response
+ code: |
+ ```ts
+ const { data } = await supabase
+ .from('countries')
+ .select()
+ .returns()
+ ```
+ response: |
+ ```
+ let x: typeof data // MyType | null
+ ```
+ hideCodeBlock: true
+ isSpotlight: true
# NOTE: Not available on currently deployed PostgREST
# db.geojson():
@@ -4421,7 +4440,8 @@ functions:
.from('avatars')
.update('public/avatar1.png', avatarFile, {
cacheControl: '3600',
- upsert: false
+ // Overwrite file if it exists
+ upsert: true
})
```
- id: update-file-using-arraybuffer-from-base64-file-data
diff --git a/studio/stores/pgmeta/MetaStore.ts b/studio/stores/pgmeta/MetaStore.ts
index 3dcaaeae83e..3d0a73e40d0 100644
--- a/studio/stores/pgmeta/MetaStore.ts
+++ b/studio/stores/pgmeta/MetaStore.ts
@@ -498,21 +498,20 @@ export default class MetaStore implements IMetaStore {
}
) {
const { duplicateTable, isRLSEnabled, isRealtimeEnabled, isDuplicateRows } = metadata
- const sourceTableName = duplicateTable.name
+ const { name: sourceTableName, schema: sourceTableSchema } = duplicateTable
const duplicatedTableName = payload.name
// The following query will copy the structure of the table along with indexes, constraints and
// triggers. However, foreign key constraints are not duplicated over - has to be done separately
const table = await this.rootStore.meta.query(
- `CREATE TABLE "${duplicatedTableName}" (LIKE "${sourceTableName}" INCLUDING ALL);`
+ `CREATE TABLE "${sourceTableSchema}"."${duplicatedTableName}" (LIKE "${sourceTableSchema}"."${sourceTableName}" INCLUDING ALL);`
)
if (table.error) throw table.error
// Duplicate foreign key constraints over
const relationships = duplicateTable.relationships
if (relationships.length > 0) {
- // @ts-ignore, but might need to investigate, sounds bad:
- // Type instantiation is excessively deep and possibly infinite
+ // @ts-ignore
relationships.map(async (relationship: PostgresRelationship) => {
const relation = await this.rootStore.meta.addForeignKey({
...relationship,
@@ -525,7 +524,7 @@ export default class MetaStore implements IMetaStore {
// Duplicate rows if needed
if (isDuplicateRows) {
const rows = await this.rootStore.meta.query(
- `INSERT INTO "${duplicatedTableName}" SELECT * FROM ${sourceTableName};`
+ `INSERT INTO "${sourceTableSchema}"."${duplicatedTableName}" SELECT * FROM "${sourceTableSchema}"."${sourceTableName}";`
)
if (rows.error) throw rows.error
@@ -535,7 +534,7 @@ export default class MetaStore implements IMetaStore {
const identityColumns = columns.filter((column) => column.identity_generation !== null)
identityColumns.map(async (column) => {
const identity = await this.rootStore.meta.query(
- `SELECT setval('${duplicatedTableName}_${column.name}_seq', (SELECT MAX("${column.name}") FROM "${sourceTableName}"));`
+ `SELECT setval('"${sourceTableSchema}"."${duplicatedTableName}_${column.name}_seq"', (SELECT MAX("${column.name}") FROM "${sourceTableSchema}"."${sourceTableName}"));`
)
if (identity.error) throw identity.error
})
@@ -543,7 +542,7 @@ export default class MetaStore implements IMetaStore {
await this.tables.load()
const tables = this.tables.list()
- const duplicatedTable = find(tables, { name: duplicatedTableName })
+ const duplicatedTable = find(tables, { schema: sourceTableSchema, name: duplicatedTableName })
if (isRLSEnabled) {
const updateTable: any = await this.tables.update(duplicatedTable!.id, {
diff --git a/supabase/config.toml b/supabase/config.toml
new file mode 100644
index 00000000000..7b1702d2d8e
--- /dev/null
+++ b/supabase/config.toml
@@ -0,0 +1,72 @@
+# A string used to distinguish different Supabase projects on the same host. Defaults to the working
+# directory name when running `supabase init`.
+project_id = "supabase"
+
+[api]
+# Port to use for the API URL.
+port = 54321
+# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
+# endpoints. public and storage are always included.
+schemas = ["public", "storage", "graphql_public"]
+# Extra schemas to add to the search_path of every request. public is always included.
+extra_search_path = ["public", "extensions"]
+# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
+# for accidental or malicious requests.
+max_rows = 1000
+
+[db]
+# Port to use for the local database URL.
+port = 54322
+# The database major version to use. This has to be the same as your remote database's. Run `SHOW
+# server_version;` on the remote database to check.
+major_version = 15
+
+[studio]
+# Port to use for Supabase Studio.
+port = 54323
+
+# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
+# are monitored, and you can view the emails that would have been sent from the web interface.
+[inbucket]
+# Port to use for the email testing server web interface.
+port = 54324
+smtp_port = 54325
+pop3_port = 54326
+
+[storage]
+# The maximum file size allowed (e.g. "5MB", "500KB").
+file_size_limit = "50MiB"
+
+[auth]
+# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
+# in emails.
+site_url = "http://localhost:3000"
+# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
+additional_redirect_urls = ["https://localhost:3000"]
+# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 seconds (one
+# week).
+jwt_expiry = 3600
+# Allow/disallow new user signups to your project.
+enable_signup = true
+
+[auth.email]
+# Allow/disallow new user signups via email to your project.
+enable_signup = true
+# If enabled, a user will be required to confirm any email change on both the old, and new email
+# addresses. If disabled, only the new email is required to confirm.
+double_confirm_changes = true
+# If enabled, users need to confirm their email address before signing in.
+enable_confirmations = false
+
+# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
+# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`,
+# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
+[auth.external.apple]
+enabled = false
+client_id = ""
+secret = ""
+# Overrides the default auth redirectUrl.
+redirect_uri = ""
+# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
+# or any other third-party OIDC providers.
+url = ""
diff --git a/supabase/functions/clippy-search/errors.ts b/supabase/functions/clippy-search/errors.ts
new file mode 100644
index 00000000000..0c8772c500a
--- /dev/null
+++ b/supabase/functions/clippy-search/errors.ts
@@ -0,0 +1,7 @@
+export class ApplicationError extends Error {
+ constructor(message: string, public data: Record = {}) {
+ super(message)
+ }
+}
+
+export class UserError extends ApplicationError {}
diff --git a/supabase/functions/clippy-search/index.ts b/supabase/functions/clippy-search/index.ts
new file mode 100644
index 00000000000..5b4a33d464e
--- /dev/null
+++ b/supabase/functions/clippy-search/index.ts
@@ -0,0 +1,187 @@
+import { serve } from 'https://deno.land/std@0.170.0/http/server.ts'
+import 'https://deno.land/x/xhr@0.2.1/mod.ts'
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.5.0'
+import { oneLine, stripIndent } from 'https://esm.sh/common-tags@1.8.2'
+import GPT3Tokenizer from 'https://esm.sh/gpt3-tokenizer@1.1.5'
+import { Configuration, CreateCompletionRequest, OpenAIApi } from 'https://esm.sh/openai@3.1.0'
+import { ApplicationError, UserError } from './errors.ts'
+
+const openAiKey = Deno.env.get('OPENAI_KEY')
+const supabaseUrl = Deno.env.get('SUPABASE_URL')
+const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
+
+export const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
+}
+
+serve(async (req) => {
+ try {
+ // Handle CORS
+ if (req.method === 'OPTIONS') {
+ return new Response('ok', { headers: corsHeaders })
+ }
+
+ if (!openAiKey) {
+ throw new ApplicationError('Missing environment variable OPENAI_KEY')
+ }
+
+ if (!supabaseUrl) {
+ throw new ApplicationError('Missing environment variable SUPABASE_URL')
+ }
+
+ if (!supabaseServiceKey) {
+ throw new ApplicationError('Missing environment variable SUPABASE_SERVICE_ROLE_KEY')
+ }
+
+ const requestData = await req.json()
+
+ if (!requestData) {
+ throw new UserError('Missing request data')
+ }
+
+ const { query } = requestData
+
+ if (!query) {
+ throw new UserError('Missing query in request data')
+ }
+
+ const sanitizedQuery = query.trim()
+
+ const supabaseClient = createClient(supabaseUrl, supabaseServiceKey)
+
+ const configuration = new Configuration({ apiKey: openAiKey })
+ const openai = new OpenAIApi(configuration)
+
+ // Moderate the content to comply with OpenAI T&C
+ const moderationResponse = await openai.createModeration({ input: sanitizedQuery })
+
+ const [results] = moderationResponse.data.results
+
+ if (results.flagged) {
+ throw new UserError('Flagged content', {
+ flagged: true,
+ categories: results.categories,
+ })
+ }
+
+ const embeddingResponse = await openai.createEmbedding({
+ model: 'text-embedding-ada-002',
+ input: sanitizedQuery.replaceAll('\n', ' '),
+ })
+
+ if (embeddingResponse.status !== 200) {
+ throw new ApplicationError('Failed to create embedding for question', embeddingResponse)
+ }
+
+ const [{ embedding }] = embeddingResponse.data.data
+
+ const { error: matchError, data: pageSections } = await supabaseClient.rpc(
+ 'match_page_sections',
+ {
+ embedding,
+ match_threshold: 0.78,
+ match_count: 10,
+ min_content_length: 50,
+ }
+ )
+
+ if (matchError) {
+ throw new ApplicationError('Failed to match page sections', matchError)
+ }
+
+ const tokenizer = new GPT3Tokenizer({ type: 'gpt3' })
+ let tokenCount = 0
+ let contextText = ''
+
+ for (let i = 0; i < pageSections.length; i++) {
+ const pageSection = pageSections[i]
+ const content = pageSection.content
+ const encoded = tokenizer.encode(content)
+ tokenCount += encoded.text.length
+
+ if (tokenCount >= 1500) {
+ break
+ }
+
+ contextText += `${content.trim()}\n---\n`
+ }
+
+ const prompt = stripIndent`
+ ${oneLine`
+ You are a very enthusiastic Supabase representative who loves
+ to help people! Given the following sections from the Supabase
+ documentation, answer the question using only that information,
+ outputted in markdown format. If you are unsure and the answer
+ is not explicitly written in the documentation, say
+ "Sorry, I don't know how to help with that."
+ `}
+
+ Context sections:
+ ${contextText}
+
+ Question: """
+ ${sanitizedQuery}
+ """
+
+ Answer as markdown (including related code snippets if available):
+ `
+
+ const completionOptions: CreateCompletionRequest = {
+ model: 'text-davinci-003',
+ prompt,
+ max_tokens: 512,
+ temperature: 0,
+ stream: true,
+ }
+
+ const response = await fetch('https://api.openai.com/v1/completions', {
+ headers: {
+ Authorization: `Bearer ${openAiKey}`,
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
+ body: JSON.stringify(completionOptions),
+ })
+
+ if (!response.ok) {
+ const error = await response.json()
+ throw new ApplicationError('Failed to generate completion', error)
+ }
+
+ // Proxy the streamed SSE response from OpenAI
+ return new Response(response.body, {
+ headers: {
+ ...corsHeaders,
+ 'Content-Type': 'text/event-stream',
+ },
+ })
+ } catch (err: unknown) {
+ if (err instanceof UserError) {
+ return new Response(
+ JSON.stringify({
+ error: err.message,
+ data: err.data,
+ }),
+ {
+ status: 400,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+ }
+ )
+ }
+
+ // Print out unexpected errors to help with debugging
+ console.error(err)
+
+ // TODO: include more response info in debug environments
+ return new Response(
+ JSON.stringify({
+ error: 'There was an error processing your request',
+ }),
+ {
+ status: 500,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+ }
+ )
+ }
+})
diff --git a/supabase/migrations/20230126220613_doc_embeddings.sql b/supabase/migrations/20230126220613_doc_embeddings.sql
new file mode 100644
index 00000000000..6a77dc0b443
--- /dev/null
+++ b/supabase/migrations/20230126220613_doc_embeddings.sql
@@ -0,0 +1,16 @@
+create extension if not exists vector with schema public;
+
+create table "public"."page" (
+ id bigserial primary key,
+ path text not null unique,
+ checksum text,
+ meta jsonb
+);
+
+create table "public"."page_section" (
+ id bigserial primary key,
+ page_id bigint not null references public.page on delete cascade,
+ content text,
+ token_count int,
+ embedding vector(1536)
+);
diff --git a/supabase/migrations/20230128004504_embedding_similarity_search.sql b/supabase/migrations/20230128004504_embedding_similarity_search.sql
new file mode 100644
index 00000000000..7999cd07581
--- /dev/null
+++ b/supabase/migrations/20230128004504_embedding_similarity_search.sql
@@ -0,0 +1,31 @@
+create or replace function match_page_sections(embedding vector(1536), match_threshold float, match_count int, min_content_length int)
+returns table (path text, content text, similarity float)
+language plpgsql
+as $$
+#variable_conflict use_variable
+begin
+ return query
+ select
+ page.path,
+ page_section.content,
+ (page_section.embedding <#> embedding) * -1 as similarity
+ from page_section
+ join page
+ on page_section.page_id = page.id
+
+ -- We only care about sections that have a useful amount of content
+ where length(page_section.content) >= min_content_length
+
+ -- The dot product is negative because of a Postgres limitation, so we negate it
+ and (page_section.embedding <#> embedding) * -1 > match_threshold
+
+ -- OpenAI embeddings are normalized to length 1, so
+ -- cosine similarity and dot product will produce the same results.
+ -- Using dot product which can be computed slightly faster.
+ --
+ -- For the different syntaxes, see https://github.com/pgvector/pgvector
+ order by page_section.embedding <#> embedding
+
+ limit match_count;
+end;
+$$;
diff --git a/supabase/seed.sql b/supabase/seed.sql
new file mode 100644
index 00000000000..e69de29bb2d