From 7c127c8f6435a6e571bc8a261eaeadbb8b057c2d Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Fri, 23 Dec 2022 16:52:20 -0600 Subject: [PATCH 01/30] Begin C# Documentation based off Flutter v1 docs --- apps/docs/components/CodeBlock/CodeBlock.tsx | 4 +- .../Navigation/NavigationMenu/HomeMenu.tsx | 6 + .../NavigationMenu.constants.ts | 35 + .../NavigationMenu/NavigationMenu.tsx | 17 + apps/docs/data/nav/supabase-csharp/v0.ts | 134 + apps/docs/data/nonGeneratedReferencePages.ts | 4 +- apps/docs/docs/ref/csharp/initialization.mdx | 67 + apps/docs/docs/ref/csharp/installing.mdx | 33 + apps/docs/docs/ref/csharp/introduction.mdx | 20 + apps/docs/docs/ref/csharp/release-notes.mdx | 6 + .../docs/docs/ref/csharp/v0/release-notes.mdx | 6 + apps/docs/layouts/SiteLayout.tsx | 4 + apps/docs/middleware.ts | 2 +- apps/docs/package.json | 8 +- .../docs/pages/reference/csharp/[...slug].tsx | 21 + .../reference/csharp/crawlers/[...slug].tsx | 43 + .../pages/reference/csharp/v0/[...slug].tsx | 21 + .../csharp/v0/crawlers/[...slug].tsx | 42 + apps/docs/public/img/icons/csharp.png | Bin 0 -> 6935 bytes .../public/img/icons/menu/c-sharp-icon.svg | 9 + .../img/icons/menu/reference-csharp.svg | 9 + package-lock.json | 17 + spec/common-client-libs-sections.json | 130 +- spec/supabase_csharp_v0.yml | 2388 +++++++++++++++++ 24 files changed, 2956 insertions(+), 70 deletions(-) create mode 100644 apps/docs/data/nav/supabase-csharp/v0.ts create mode 100644 apps/docs/docs/ref/csharp/initialization.mdx create mode 100644 apps/docs/docs/ref/csharp/installing.mdx create mode 100644 apps/docs/docs/ref/csharp/introduction.mdx create mode 100644 apps/docs/docs/ref/csharp/release-notes.mdx create mode 100644 apps/docs/docs/ref/csharp/v0/release-notes.mdx create mode 100644 apps/docs/pages/reference/csharp/[...slug].tsx create mode 100644 apps/docs/pages/reference/csharp/crawlers/[...slug].tsx create mode 100644 apps/docs/pages/reference/csharp/v0/[...slug].tsx create mode 100644 apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx create mode 100644 apps/docs/public/img/icons/csharp.png create mode 100644 apps/docs/public/img/icons/menu/c-sharp-icon.svg create mode 100644 apps/docs/public/img/icons/menu/reference-csharp.svg create mode 100644 spec/supabase_csharp_v0.yml diff --git a/apps/docs/components/CodeBlock/CodeBlock.tsx b/apps/docs/components/CodeBlock/CodeBlock.tsx index f4e962bb2aa..c29120c7bfb 100644 --- a/apps/docs/components/CodeBlock/CodeBlock.tsx +++ b/apps/docs/components/CodeBlock/CodeBlock.tsx @@ -6,6 +6,7 @@ import { Button, IconCheck, IconCopy } from 'ui' import js from 'react-syntax-highlighter/dist/cjs/languages/hljs/javascript' import ts from 'react-syntax-highlighter/dist/cjs/languages/hljs/typescript' +import csharp from 'react-syntax-highlighter/dist/cjs/languages/hljs/csharp' import py from 'react-syntax-highlighter/dist/cjs/languages/hljs/python' import sql from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql' import bash from 'react-syntax-highlighter/dist/cjs/languages/hljs/bash' @@ -17,7 +18,7 @@ import { useTheme } from 'common/Providers' interface Props { title?: string - language: 'js' | 'jsx' | 'sql' | 'py' | 'bash' | 'ts' | 'dart' | 'json' + language: 'js' | 'jsx' | 'sql' | 'py' | 'bash' | 'ts' | 'dart' | 'json' | 'csharp' linesToHighlight?: number[] hideCopy?: boolean hideLineNumbers?: boolean @@ -62,6 +63,7 @@ const CodeBlock: FC = ({ SyntaxHighlighter.registerLanguage('sql', sql) SyntaxHighlighter.registerLanguage('bash', bash) SyntaxHighlighter.registerLanguage('dart', dart) + SyntaxHighlighter.registerLanguage('csharp', csharp) SyntaxHighlighter.registerLanguage('json', json) const large = false diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx index 9a1f712f859..dcbafaa330b 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx @@ -94,6 +94,12 @@ const home = [ href: '/reference/dart/introduction', level: 'reference_dart', }, + { + label: 'C#', + icon: '/img/icons/menu/reference-csharp', + href: '/reference/csharp/introduction', + level: 'reference_csharp', + }, { label: 'Tools Reference', }, diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index d9837f2ea65..ff7a0b3aa65 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -22,6 +22,12 @@ export const REFERENCES: References = { versions: ['v1', 'v0'], icon: '/docs/img/libraries/flutter-icon.svg', }, + csharp: { + name: 'C#', + library: 'supabase-csharp', + versions: ['v0'], + icon: '/docs/img/libraries/c-sharp-icon.svg', + }, cli: { name: 'CLI', library: undefined, @@ -697,6 +703,20 @@ export const reference = { items: [], icon: '/img/icons/menu/reference-dart', }, + { + name: 'supabase-csharp', + url: '/reference/csharp/start', + level: 'reference_csharp', + items: [], + icon: '/img/icons/menu/reference-csharp', + }, + { + name: 'supbase-python', + url: '/reference/python/start', + level: 'reference_python', + items: [], + icon: 'docs/img/icons/javascript.svg', + }, // { // name: 'supabase-python', // url: '/reference/python/start', @@ -746,6 +766,7 @@ export const reference_dart_v0 = { url: '/guides/reference/dart', parent: '/reference', } + export const reference_dart_v1 = { icon: 'reference-dart', title: 'dart', @@ -753,6 +774,13 @@ export const reference_dart_v1 = { parent: '/reference', } +export const reference_csharp_v0 = { + icon: 'reference-csharp', + title: 'c#', + url: 'guides/reference/csharp', + parent: '/reference', +} + export const reference_cli = { icon: 'reference-cli', title: 'Supabase CLI', @@ -846,6 +874,13 @@ export const references = [ icon: '/docs/img/icons/dart-icon.svg', url: '/reference/dart/start', }, + { + label: 'supabase-csharp', + versions: ['v0'], + description: 'something about the reference', + icon: '/docs/img/icons/c-sharp-icon.svg', + url: '/reference/csharp/start', + }, ], }, { diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx index cfb4d87b143..29bfc21edfe 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx @@ -11,6 +11,8 @@ import spec_js_v1 from '~/../../spec/supabase_js_v1.yml' assert { type: 'yml' } import spec_dart_v1 from '~/../../spec/supabase_dart_v1.yml' assert { type: 'yml' } // @ts-expect-error import spec_dart_v0 from '~/../../spec/supabase_dart_v0.yml' assert { type: 'yml' } +// @ts-expect-error +import spec_csharp_v0 from '~/../../spec/supabase_csharp_v0.yml' assert { type: 'yml' } // import { gen_v3 } from '~/lib/refGenerator/helpers' import apiCommonSections from '~/../../spec/common-api-sections.json' import cliCommonSections from '~/../../spec/common-cli-sections.json' @@ -47,6 +49,7 @@ export type RefIdOptions = | 'reference_javascript_v2' | 'reference_dart_v0' | 'reference_dart_v1' + | 'reference_csharp_v0' | 'reference_cli' | 'reference_api' | 'reference_self_hosting_auth' @@ -56,6 +59,7 @@ export type RefIdOptions = export type RefKeyOptions = | 'javascript' | 'dart' + | 'csharp' | 'cli' | 'api' | 'self-hosting-auth' @@ -126,6 +130,10 @@ const NavigationMenu = () => { case url.includes(`/docs/reference/dart`) && url: menuState.setMenuLevelId('reference_dart_v1') break + // C# v0 (latest) + case url.includes(`/docs/reference/csharp`) && url: + menuState.setMenuLevelId('reference_csharp_v0') + break case url.includes(`/docs/reference/cli`) && url: menuState.setMenuLevelId('reference_cli') break @@ -175,6 +183,7 @@ const NavigationMenu = () => { const isReference_Javascript_V2 = 'reference_javascript_v2' === level const isReference_Dart_V0 = 'reference_dart_v0' === level const isReference_Dart_V1 = 'reference_dart_v1' === level + const isReference_Csharp_V0 = 'reference_csharp_v0' === level const isReference_Cli = 'reference_cli' === level const isReference_Api = 'reference_api' === level const isReference_Self_Hosting_Auth = 'reference_self_hosting_auth' === level @@ -229,6 +238,14 @@ const NavigationMenu = () => { lib="dart" spec={spec_dart_v1} /> + {/* // Tools */} + + +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. + + + + + + + + + ```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)); + } + ``` + + + + + + diff --git a/apps/docs/docs/ref/csharp/installing.mdx b/apps/docs/docs/ref/csharp/installing.mdx new file mode 100644 index 00000000000..e274af8e280 --- /dev/null +++ b/apps/docs/docs/ref/csharp/installing.mdx @@ -0,0 +1,33 @@ +--- +id: installing +title: 'Installing & Initialization' +slug: installing +custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supabase.yml +--- + +### Install from NuGet + + + + + You can install Supabase package from [nuget.org](https://www.nuget.org/packages/supabase-csharp/) + + + + + + + + + ```sh Terminal + dotnet add package supabase-csharp + ``` + + + + + + diff --git a/apps/docs/docs/ref/csharp/introduction.mdx b/apps/docs/docs/ref/csharp/introduction.mdx new file mode 100644 index 00000000000..6c699314937 --- /dev/null +++ b/apps/docs/docs/ref/csharp/introduction.mdx @@ -0,0 +1,20 @@ +--- +id: introduction +title: Introduction +hideTitle: true +--- + +
+ +
+

C# Client Library

+

supabase-csharp

+
+
+ +
+ This reference documents every object and method available in Supabase's C# + library, [supabase-csharp](https://www.nuget.org/packages/supabase-csharp). You can + use supabase-csharp to interact with your Postgres database, listen to database changes, invoke + Deno Edge Functions, build login and user management functionality, and manage large files. +
diff --git a/apps/docs/docs/ref/csharp/release-notes.mdx b/apps/docs/docs/ref/csharp/release-notes.mdx new file mode 100644 index 00000000000..b5e0e218918 --- /dev/null +++ b/apps/docs/docs/ref/csharp/release-notes.mdx @@ -0,0 +1,6 @@ +--- +id: release-notes +title: Release Notes +--- + +## dart this is the release notes file. diff --git a/apps/docs/docs/ref/csharp/v0/release-notes.mdx b/apps/docs/docs/ref/csharp/v0/release-notes.mdx new file mode 100644 index 00000000000..2ecb0ef3990 --- /dev/null +++ b/apps/docs/docs/ref/csharp/v0/release-notes.mdx @@ -0,0 +1,6 @@ +--- +id: release-notes +title: Release Notes +--- + +## dart v0 this is the release notes file. diff --git a/apps/docs/layouts/SiteLayout.tsx b/apps/docs/layouts/SiteLayout.tsx index eb017378efd..3bf76800ee4 100644 --- a/apps/docs/layouts/SiteLayout.tsx +++ b/apps/docs/layouts/SiteLayout.tsx @@ -71,6 +71,10 @@ const levelsData = { icon: '/docs/img/icons/menu/reference-dart', name: 'Dart Reference v0.0', }, + reference_csharp_v0: { + icon: '/docs/img/icons/menu/reference-csharp', + name: 'C# Reference v0.0', + }, reference_cli: { icon: '/docs/img/icons/menu/reference-cli', name: 'CLI Reference', diff --git a/apps/docs/middleware.ts b/apps/docs/middleware.ts index d13ce4a442f..254486ccf06 100644 --- a/apps/docs/middleware.ts +++ b/apps/docs/middleware.ts @@ -3,7 +3,7 @@ import type { NextRequest } from 'next/server' import isbot from 'isbot' export function middleware(request: NextRequest) { - const specs = ['javascript', 'dart'] + const specs = ['javascript', 'dart', 'csharp'] let version = '' if (request.url.includes('/v1/')) { diff --git a/apps/docs/package.json b/apps/docs/package.json index 2abc71adb53..009c9759c91 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -9,7 +9,7 @@ "lint": "next lint", "build:sitemap": "node ./internals/generate-sitemap.mjs", "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-js:v1 gen:supabase-js:v2 gen:realtime", + "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", "gen:api:usage": "ts-node ./generator/index.ts gen --type api --url https://api.supabase.com --input ../../spec/transforms/api_v0_openapi_deparsed.json --output ./docs/reference/api/generated/usage.mdx", "gen:cli": "npm-run-all gen:cli:commands gen:cli:config", @@ -25,6 +25,8 @@ "gen:supabase-dart:v0:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_dart_v0.yml --output ./docs/reference/dart/v0/generated", "gen:supabase-dart:v1": "npm-run-all gen:supabase-dart:v1:ref", "gen:supabase-dart:v1:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_dart_v1.yml --output ./docs/reference/dart/generated", + "gen:supabase-csharp:v0": "npm-run-all gen:supabase-dart:v1:ref", + "gen:supabase-csharp:v0:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_csharp_v1.yml --output ./docs/reference/csharp/generated", "gen:supabase-js:v1": "npm-run-all gen:supabase-js:v1:ref", "gen:supabase-js:v1:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_js_v1.yml --output ./docs/reference/javascript/v1/generated", "gen:supabase-js:v2": "npm-run-all gen:supabase-js:v2:ref", @@ -42,6 +44,7 @@ "@radix-ui/react-accordion": "^1.0.1", "algoliasearch": "^4.14.2", "babel": "^6.23.0", + "clsx": "^1.2.1", "common": "*", "config": "*", "gray-matter": "^4.0.3", @@ -63,6 +66,7 @@ "react-intersection-observer": "^9.4.0", "react-markdown": "^8.0.3", "react-syntax-highlighter": "^15.3.1", + "rehype-slug": "^5.1.0", "remark": "^14.0.2", "remark-admonitions": "^1.2.1", "remark-gfm": "^3.0.1", @@ -72,10 +76,10 @@ "valtio": "^1.7.6" }, "devDependencies": { - "dotenv": "^16.0.3", "@types/node": "^17.0.12", "@types/react": "17.0.39", "config": "*", + "dotenv": "^16.0.3", "ejs": "^3.1.8", "eslint": "8.9.0", "globby": "^12.0.2", diff --git a/apps/docs/pages/reference/csharp/[...slug].tsx b/apps/docs/pages/reference/csharp/[...slug].tsx new file mode 100644 index 00000000000..04e731b5aeb --- /dev/null +++ b/apps/docs/pages/reference/csharp/[...slug].tsx @@ -0,0 +1,21 @@ +import clientLibsCommonSections from '~/../../spec/common-client-libs-sections.json' +// @ts-expect-error +import spec from '~/../../spec/supabase_csharp_v0.yml' assert { type: 'yml' } +import RefSectionHandler from '~/components/reference/RefSectionHandler' +import { flattenSections } from '~/lib/helpers' +import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths' +import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps' + +const sections = flattenSections(clientLibsCommonSections) + +export default function JSReference(props) { + return +} + +export async function getStaticProps({ params }: { params: { slug: string[] } }) { + return handleRefStaticProps(sections, params, '/csharp', '/csharp') +} + +export function getStaticPaths() { + return handleRefGetStaticPaths() +} diff --git a/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx b/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx new file mode 100644 index 00000000000..c12f3cabbf2 --- /dev/null +++ b/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx @@ -0,0 +1,43 @@ +import clientLibsCommonSections from '~/../../spec/common-client-libs-sections.json' +import typeSpec from '~/../../spec/enrichments/tsdoc_v2/combined.json' +// @ts-expect-error +import spec from '~/../../spec/supabase_dart_v1.yml' assert { type: 'yml' } +import RefSectionHandler from '~/components/reference/RefSectionHandler' +import { flattenSections } from '~/lib/helpers' +import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths' +import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps' +import { useRouter } from 'next/router' +import RefSEO from '~/components/reference/RefSEO' + +const sections = flattenSections(clientLibsCommonSections) + +export default function JSReference(props) { + const router = useRouter() + const slug = router.query.slug[0] + const filteredSection = sections.filter((section) => section.id === slug) + + const pageTitle = filteredSection[0]?.title + ? `${filteredSection[0]?.title} | Supabase` + : 'Supabase' + + return ( + <> + + + + + ) +} + +export async function getStaticProps({ params }: { params: { slug: string[] } }) { + return handleRefStaticProps(sections, params, '/dart', '/dart') +} + +export function getStaticPaths() { + return handleRefGetStaticPaths() +} diff --git a/apps/docs/pages/reference/csharp/v0/[...slug].tsx b/apps/docs/pages/reference/csharp/v0/[...slug].tsx new file mode 100644 index 00000000000..a76c3f386be --- /dev/null +++ b/apps/docs/pages/reference/csharp/v0/[...slug].tsx @@ -0,0 +1,21 @@ +import clientLibsCommonSections from '~/../../spec/common-client-libs-sections.json' +// @ts-expect-error +import spec from '~/../../spec/supabase_csharp_v0.yml' assert { type: 'yml' } +import RefSectionHandler from '~/components/reference/RefSectionHandler' +import { flattenSections } from '~/lib/helpers' +import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths' +import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps' + +const sections = flattenSections(clientLibsCommonSections) + +export default function JSReference(props) { + return +} + +export async function getStaticProps({ params }: { params: { slug: string[] } }) { + return handleRefStaticProps(sections, params, '/csharp/v0', '/csharp/v0') +} + +export function getStaticPaths() { + return handleRefGetStaticPaths() +} diff --git a/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx b/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx new file mode 100644 index 00000000000..4c78342f556 --- /dev/null +++ b/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx @@ -0,0 +1,42 @@ +import clientLibsCommonSections from '~/../../spec/common-client-libs-sections.json' +import typeSpec from '~/../../spec/enrichments/tsdoc_v2/combined.json' +// @ts-expect-error +import spec from '~/../../spec/supabase_csharp_v0.yml' assert { type: 'yml' } +import RefSectionHandler from '~/components/reference/RefSectionHandler' +import { flattenSections } from '~/lib/helpers' +import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths' +import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps' +import { useRouter } from 'next/router' +import RefSEO from '~/components/reference/RefSEO' + +const sections = flattenSections(clientLibsCommonSections) + +export default function JSReference(props) { + const router = useRouter() + const slug = router.query.slug[0] + const filteredSection = sections.filter((section) => section.id === slug) + + const pageTitle = filteredSection[0]?.title + ? `${filteredSection[0]?.title} | Supabase` + : 'Supabase' + return ( + <> + + + + + ) +} + +export async function getStaticProps({ params }: { params: { slug: string[] } }) { + return handleRefStaticProps(sections, params, '/csharp/v0', '/csharp/v0') +} + +export function getStaticPaths() { + return handleRefGetStaticPaths() +} diff --git a/apps/docs/public/img/icons/csharp.png b/apps/docs/public/img/icons/csharp.png new file mode 100644 index 0000000000000000000000000000000000000000..37f9fd725faa644a840459ea4a92567978984a10 GIT binary patch literal 6935 zcmaiZdpy(a|NqReA#6@lQ}f;&ZZz8*+8l>riX4(C9mY1~w3%~sQ^F){q83r^&ZR<$ zQZZwcbh_^lpORyr>UKz!QhncaA3mS&=kxvj{#E`W_>IRIO%y@}pjS9U}sBQ2i2DQ#mwSXxvVl?6CCD%+>n zf&yaL2~2ECOmr;YHpKy0mTL<>FHKtj*kzK0C|F(740|2LJ$Z>>t7tA~}CckLCZde9#dVONa%DK(zQ*a&}7O z|3SWl{0BKVA}%409}&m>YXSeJ;xG6=7(w^_ca{_;_rDQ)d;h=5V`Bbo8TMkH7+_XeiNA5YzN?nw!dOwyNr3qu|UXj*^s{>Pghsp_&82vG>Gy2 zJzTJ!Zmu>Ys*TNBGU109FmSdYZzLy`&P)KQ$V4zdN#wO;QUJ-y*3!n7L|jX>u_Y3h zB`;Hh^}u2#F#mt_OIeMz2RXdGZ5fgLgt++B<*6U3zKPBI@%H02I&wM3vDoEE+cLwJ z{O$m7fox{N(I{?lcP9zwiRIKk(_F_o{5|QvDj(>3^ zN3cO@|M%J~{;% zbzJj{Rh|v^lJZfj?&>TmM3-Lor>`%oGqUk|m})FnRD0IxU}hngy>%HTpbeYdcOo|(?;!DJDJ};^i}nZ?umcu>^}0| z!R#IXGyJ6Y!i80RPMI62FRw1DH1tO(msfJHfjb6*%LwK}AS#+mLk@DR0u6y^rF+ty z15zq}|HnWY;8B(_+rvM)ko;p;0&TmlDlk)IM z3nF;mCrx4Yh`9>pFty+c9d)N3KkZg(GAY0}f9!py1QBjtftwa@DV*M4TK!rL^^Nt@ z&`vXjCE-5@!TPdiN@@EjbripJAAGR*Rd}!@rGQZfR0XmYqmGiMct|v zk%+K#sAr(!k;B;}^(;Kjb%Sa3(IX6zfN7}Ucgf8}(36QeX7bFin9iXfJhgfaM0A!3 z!UNrlE2f8G5pL*SBN3gcA>OF5An+xZyb3dAj%sGHboR@%syp?7t_a1#lXT%lm`JF) zstt}yM&N%zTiry_(~#@a$RP;^`2~RJ!>)4?8_{~+*vJR8$A^jJ62_B!=W2u>UODTO zf~%ChkCEWgwOKKDL$=V1E~-~mJ(~vvBkiex%p0{0d99EKTr(8SHMO)Oa32hcuQxR+AbQH&{ zsW}bN4Rwy0#E!%>_aW&)CB7ZQp)jBzlhH8*z_9r(W?2;v6^=5rvV7?AtE&PP;P+Hs zr#74Fb)Jw2{E;u$E)b#9-V0lxq3}mL=IpwjysRKXKWw5Fv+t6au-8|1 zWAA5ds)iGHTxXPh=42yxT{abZefNd~H2Z#>c)s-@KuZtCiQhY`;ApG$z&l zI`s7;u6OdKdtQ8S z;soc>wPdwl=#Szj%D?8CD-Aw6=Os6@rVZ$&|hfJS>t#ft8Pk6w*)7OVDhP*O~V zW_SEVLF1yu$`p6awv`q71qpM5jUO!ZV%;@6(kgHT@negWuNLSCccj#svI+g_U26QB zH8#=$Y<^Vyoks)W`mt%J2<|_}rwk`FYntuK z_b#qku{v2`@C)TihNME-q#Yfz8ZdY}@<{I@ghLv;Bj4m{(V20E> zwe9`lq^i9Ij(beG-#9#HKHFe=L;(1umY3cdq{bgJ5gn>O^h@Q$z;~yb-6<3obXVtK zeA&*iA)=D1SiG}m`i^}rCFqQwW_;+DJ+4?Zb`e`)U(?Vr#*Oi#atUEcqF(@Zi-!Zjt`hgA_uG zzw4@`Nd4iU3U*GzyI)sIYl$0FGx};iOKVN;t7P=oK9|;FH>ia5UB4-u)+H zt<~6|%mdFN73DUi@y=NR>2)T+Y6r?C9Q~Upso{lw^JE)LI;q$o@aERS7 zoLHQ^FJ417WR7Y{8Acx^x_BqqIr3ERy{E+_+1v0`JD;?ye3uq7yhMyH*dn^BW4ES+ z0`)Q~p2-Wt>cFsyJXIGoGo~jqNQ#6cNlB0^=&TsN4*mT{aHA^i{|bBA`YV+QSnBJuB zz#WqqCH|0%~Da1lW@?`ln~n0QmM^ZT){lt$U{5!#NdhwNulmTgnwD_f;J zjof?ooMwmF#Wk~=OKxn=dJ1bDIQyFb$EG%a-n!7VePPee13Sk~;B$M?7r#EwZQ7b! zMOC|cuN9eSlD4`Y^9EfvlG8s93vLLgh;F1$tIe%2m&-TPkY@QsO{B_d($ zVx47iDFxb6xIA_Y<-UYm|KY7Ak8NL&nidO}ASVMQlZn^4<2}vwq|X-A`PRElgVZO- zZv?)=Fe`kPO|p1@PwfQZhu7gw$uKhVhx>Y(`Jy7qiy>F))g0li$q<3_57%{U+d$J< zZUmjaldH2-rN|(W?(TG;P<6sL)NtIvcv)0)*A#yH$Zu8}VhR-Ysyzua+-U_;pIcsJ ztz6sz$ge=5*I3PF4ly}>mfQO@hkZ+ifeIV>(b89HG4|iAzwoZwBp0p-e!Zs~m`du5 zCLXi%kW3GU##CLtd&|>ZQi)RQL#!U_E!|@_5cIu+lW|_m@#? z!al?v)xXT0U?}g1=9b>r+T;QjmfVp)3TxnkesG6lcl1W#e5>lrAv=#Jf`ra^uWM1` zHGyC~7B<`dE^96G7>&|is3je_vDvOZJwyDmukOL!)Zwnp5aRMyi#^^t~})ZS)P za^e2qGpXHat2m#+$1m#eFx{=F{Y_4?!PVgnyESA8j1}qV*Rbxl*5hXDcoi*7&4c=% z#MIjlqsI&jODHMBwJP6<kGEuZ1KDBv8JW=8?Vv6CBvzE2=m*-1t_ng zv-R+X)7wdVW;Y)@n=j>&a|0ZMlRGZ8A5N^ipegIZ1U0ey)>!K7%%N^QL{S`?zJQZB ziqAF!-Rj>pWLQkZTWbBD@i6_KQS?&!@7laii3ff>?wj6?fWANE|M_l z4z`Q_JXMM3C2?`yJ5N#Pc}YW^cg(NT<#~1Nb9S7!S+ktQUY!?xJKOGnyQgO`CGTP7 zxM86n*go(6-f^SCu3%awSj8tu7F%aEWl(cK%3KqrAp^|u-QntQHDoU4M%`iGcOzw? z<|YNGCm&+5(%Gx%yI?qBAv^cU^7eQ`&D^C+TyTg`{z zis}PZJ?DyY%UXXi6rR!!*Ib)!TXJW0U`}xvOk`K#aSdOXjT2RjnOC2V3x9M{{+{oX zgN*lwW^@dy$YzqUs^ z&2G<`5Zg>uG7iCx>CsHP6`vF0n4oHfL$DlrG~650k_K(Ls_QHf972zZ`z^k^6*WZF z!BW5q=~3h~?IBp%1(?er;cV3&c}`@aqLl-~9OjodnlfM2zjZQWR$jVKdqQwx zt}@xq%3M{57*9<)mY4SX`(k;CKk|6cx9&;Q8?wE%&4@Uc@alxhzxI3AP)Oq|rzhycW`TmO`$^l+z?7 z#JZT_&O$~VnK{~pomR?XSyy+07anVcr)>R3_4l_LxOf^?cdk>+Zi9*5(S^ULDxZbp zgAq9J=7fOsBqQB>$ixt%V!CmD2%8(>Vj^(Sh-}q(e3(HlAue6PP_tN8ey6PE-E^T{ zCK85vPX1-OXa`+bsjAxsH%vwV;9X7*ig6j`?oN*OG7wc56cliVj;_Zq(6z+vL!{%h z_nJ(WQJaT}OOuT=UU@%*0$#HC;aAFgGN4UrOg!M~836(ZIrbEoaQD?=XM#t1h5LJy7{HR#IiIknT$rRl}ziu9>D|u~&@_sw-`7 zI;fTYsYld;5X=9R&#ho*9jwdt*Lr2YL4KXvp;IQ3#4@Fod0Gs=>@Vg>D=SNo{r4cF h*DSh;0`l{xHOjhYgo#D8s-^!~o^BiImtA)4`yajWjm-c6 literal 0 HcmV?d00001 diff --git a/apps/docs/public/img/icons/menu/c-sharp-icon.svg b/apps/docs/public/img/icons/menu/c-sharp-icon.svg new file mode 100644 index 00000000000..40d0375079d --- /dev/null +++ b/apps/docs/public/img/icons/menu/c-sharp-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/docs/public/img/icons/menu/reference-csharp.svg b/apps/docs/public/img/icons/menu/reference-csharp.svg new file mode 100644 index 00000000000..40d0375079d --- /dev/null +++ b/apps/docs/public/img/icons/menu/reference-csharp.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index a623b4950f1..04c9896005c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "@radix-ui/react-accordion": "^1.0.1", "algoliasearch": "^4.14.2", "babel": "^6.23.0", + "clsx": "^1.2.1", "common": "*", "config": "*", "gray-matter": "^4.0.3", @@ -70,6 +71,7 @@ "react-intersection-observer": "^9.4.0", "react-markdown": "^8.0.3", "react-syntax-highlighter": "^15.3.1", + "rehype-slug": "^5.1.0", "remark": "^14.0.2", "remark-admonitions": "^1.2.1", "remark-gfm": "^3.0.1", @@ -417,6 +419,14 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "apps/docs/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "apps/docs/node_modules/eslint": { "version": "8.9.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz", @@ -49505,6 +49515,7 @@ "@types/react": "17.0.39", "algoliasearch": "^4.14.2", "babel": "^6.23.0", + "clsx": "*", "common": "*", "config": "*", "dotenv": "^16.0.3", @@ -49534,6 +49545,7 @@ "react-intersection-observer": "^9.4.0", "react-markdown": "^8.0.3", "react-syntax-highlighter": "^15.3.1", + "rehype-slug": "^5.1.0", "remark": "^14.0.2", "remark-admonitions": "^1.2.1", "remark-gfm": "^3.0.1", @@ -49735,6 +49747,11 @@ "uri-js": "^4.2.2" } }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, "eslint": { "version": "8.9.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz", diff --git a/spec/common-client-libs-sections.json b/spec/common-client-libs-sections.json index d80a1e8b3fb..9478de69da0 100644 --- a/spec/common-client-libs-sections.json +++ b/spec/common-client-libs-sections.json @@ -4,14 +4,14 @@ "id": "introduction", "slug": "introduction", "type": "markdown", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "title": "Installing", "id": "installing", "slug": "installing", "type": "markdown", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "title": "Initializing", @@ -28,7 +28,7 @@ }, { "title": "Database", - "libs": ["js", "js_v1", "dart", "dart_v0"], + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"], "items": [ { "id": "select", @@ -36,7 +36,7 @@ "slug": "select", "product": "database", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "insert", @@ -44,7 +44,7 @@ "slug": "insert", "product": "database", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "update", @@ -52,7 +52,7 @@ "slug": "update", "product": "database", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "upsert", @@ -60,7 +60,7 @@ "slug": "upsert", "product": "database", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "delete", @@ -68,7 +68,7 @@ "slug": "delete", "product": "database", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "rpc", @@ -76,7 +76,7 @@ "slug": "rpc", "product": "database", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "using-filters", @@ -85,7 +85,7 @@ "slug": "using-filters", "product": "database", "type": "function", - "libs": ["js", "dart", "dart_v0"], + "libs": ["js", "dart", "dart_v0", "csharp"], "items": [ { "id": "eq", @@ -94,7 +94,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "neq", @@ -103,7 +103,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "gt", @@ -112,7 +112,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "gte", @@ -121,7 +121,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "lt", @@ -130,7 +130,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "lte", @@ -139,7 +139,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "like", @@ -148,7 +148,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "ilike", @@ -157,7 +157,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "is", @@ -166,7 +166,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "in", @@ -175,7 +175,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "contains", @@ -184,7 +184,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "contained-by", @@ -193,7 +193,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "range-gt", @@ -202,7 +202,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "range-gte", @@ -211,7 +211,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "range-lt", @@ -220,7 +220,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "range-lte", @@ -229,7 +229,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "range-adjacent", @@ -238,7 +238,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "overlaps", @@ -247,7 +247,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "text-search", @@ -256,7 +256,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "match", @@ -265,7 +265,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "not", @@ -274,7 +274,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "or", @@ -283,7 +283,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "filter", @@ -292,7 +292,7 @@ "product": "database", "parent": "filters", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] } ] }, @@ -304,7 +304,7 @@ "product": "database", "parent": "modifiers", "type": "function", - "libs": ["js", "dart", "dart_v0"], + "libs": ["js", "dart", "dart_v0", "csharp"], "items": [ { "id": "db-modifiers-select", @@ -322,7 +322,7 @@ "product": "database", "parent": "modifiers", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "limit", @@ -331,7 +331,7 @@ "product": "database", "parent": "modifiers", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "range", @@ -340,7 +340,7 @@ "product": "database", "parent": "modifiers", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "abort-signal", @@ -358,7 +358,7 @@ "product": "database", "parent": "modifiers", "type": "function", - "libs": ["js", "dart", "dart_v0"] + "libs": ["js", "dart", "dart_v0", "csharp"] }, { "id": "maybe-single", @@ -384,7 +384,7 @@ }, { "title": "Auth", - "libs": ["js", "js_v1", "dart", "dart_v0"], + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"], "items": [ { "id": "auth-api", @@ -399,7 +399,7 @@ "slug": "auth-signup", "product": "auth", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "sign-in", @@ -407,7 +407,7 @@ "slug": "auth-signin", "product": "auth", "type": "function", - "libs": ["js_v1", "dart_v0"] + "libs": ["js_v1", "dart_v0", "csharp"] }, { "id": "sign-in-with-provider", @@ -415,7 +415,7 @@ "slug": "auth-signinwithprovider", "product": "auth", "type": "function", - "libs": ["dart_v0"] + "libs": ["dart_v0", "csharp"] }, { "id": "sign-in-with-password", @@ -559,7 +559,7 @@ "slug": "auth-onauthstatechange", "product": "auth", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "reset-password-for-email", @@ -567,7 +567,7 @@ "slug": "auth-resetpasswordforemail", "product": "auth", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "mfa-enroll", @@ -718,7 +718,7 @@ }, { "title": "Functions", - "libs": ["js", "js_v1", "dart", "dart_v0"], + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"], "items": [ { "id": "invoke", @@ -726,13 +726,13 @@ "slug": "auth-admin-invoke", "product": "functions", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] } ] }, { "title": "Realtime", - "libs": ["js", "js_v1", "dart", "dart_v0"], + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"], "items": [ { "id": "stream", @@ -740,7 +740,7 @@ "slug": "stream", "product": "realtime", "type": "function", - "libs": ["dart", "dart_v0"] + "libs": ["dart", "dart_v0", "csharp"] }, { "id": "subscribe", @@ -748,7 +748,7 @@ "slug": "subscribe", "product": "realtime", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "remove-subscription", @@ -756,7 +756,7 @@ "slug": "removesubscription", "product": "realtime", "type": "function", - "libs": ["dart_v0", "js_v1"] + "libs": ["dart_v0", "csharp", "js_v1"] }, { "id": "remove-all-subscriptions", @@ -803,7 +803,7 @@ }, { "title": "Storage", - "libs": ["js", "js_v1", "dart", "dart_v0"], + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"], "items": [ { "id": "create-bucket", @@ -811,7 +811,7 @@ "slug": "storage-createbucket", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "get-bucket", @@ -819,7 +819,7 @@ "slug": "storage-getbucket", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "list-buckets", @@ -827,7 +827,7 @@ "slug": "storage-listbuckets", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "update-bucket", @@ -835,7 +835,7 @@ "slug": "storage-updatebucket", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "delete-bucket", @@ -843,7 +843,7 @@ "slug": "storage-deletebucket", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "empty-bucket", @@ -851,7 +851,7 @@ "slug": "storage-emptybucket", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-upload", @@ -859,7 +859,7 @@ "slug": "storage-from-upload", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-download", @@ -867,7 +867,7 @@ "slug": "storage-from-download", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-list", @@ -875,7 +875,7 @@ "slug": "storage-from-list", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-update", @@ -883,7 +883,7 @@ "slug": "storage-from-update", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-move", @@ -891,7 +891,7 @@ "slug": "storage-from-move", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-copy", @@ -907,7 +907,7 @@ "slug": "storage-from-remove", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-create-signed-url", @@ -915,7 +915,7 @@ "slug": "storage-from-createsignedurl", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] }, { "id": "from-create-signed-urls", @@ -931,7 +931,7 @@ "slug": "storage-from-getpublicurl", "product": "storage", "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0"] + "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] } ] }, diff --git a/spec/supabase_csharp_v0.yml b/spec/supabase_csharp_v0.yml new file mode 100644 index 00000000000..f9e6c805d80 --- /dev/null +++ b/spec/supabase_csharp_v0.yml @@ -0,0 +1,2388 @@ +openref: 0.1 + +info: + id: reference/csharp + title: Getting started + description: | + + Supabase C#. + + definition: ../../spec/enrichments/tsdoc_v2/combined.json + slugPrefix: '/' + specUrl: https://github.com/supabase/supabase/edit/master/spec/supabase_csharp_v0.yml + libraries: + - name: 'C#' + id: 'csharp' + version: '0.0.1' + +functions: + - id: sign-up + title: 'SignUp()' + description: | + Creates a new user. + notes: | + - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://app.supabase.com/project/_/auth/providers). + - **Confirm email** determines if users need to confirm their email address after signing up. + - If **Confirm email** is enabled, a `user` is returned but `session` is null. + - If **Confirm email** is disabled, both a `user` and a `session` are returned. + - When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://app.supabase.com/project/_/auth/url-configuration). + - If SignUp() is called for an existing confirmed user: + - If **Confirm email** is enabled in [your project](https://app.supabase.com/project/_/auth/providers), an obfuscated/fake user object is returned. + - If **Confirm email** is disabled, the error message, `User already registered` is returned. + examples: + - id: sign-up + name: Sign up. + isSpotlight: true + code: | + ```c# + var session = await supabase.Auth.SignUp(email, password); + ``` + - id: sign-in-with-password + title: 'SignIn(email, password)' + description: | + Log in an existing user using email or phone number with password. + notes: | + - Requires either an email and password or a phone number and password. + examples: + - id: sign-in-with-email-and-password + name: Sign in with email and password + isSpotlight: true + code: | + ```c# + var session = await supabase.Auth.SignIn(email, password); + ``` + - id: sign-in-with-phone-and-password + name: Sign in with phone and password + code: | + ```c# + var session = await supabase.Auth.SignIn(SignInType.Phone, phoneNumber, password); + ``` + - id: sign-in-with-otp + title: 'SendMagicLink() and SignIn(SignInType, Phone)' + notes: | + - Requires either an email or phone number. + - This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number. + - If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP. + - If you're using phone, you can configure whether you want the user to receive a OTP. + - The magic link's destination URL is determined by the [`SITE_URL`](https://supabase.com/docs/reference/auth/config#site_url). You can modify the `SITE_URL` or add additional redirect urls in [your project](https://app.supabase.com/project/_/auth/settings). + examples: + - id: sign-in-with-email + name: Send Magic Link. + isSpotlight: true + description: | + The user will be sent an email which contains either a magiclink or a OTP or both. By default, a given user can only request a OTP once every 60 seconds. + You can pass `emailRedirectTo` with dynamic link to bring the users back to your app after they click on the magic link. + code: | + ```c# + var options = new SignInOptions { RedirectTo = "http://myredirect.example" }; + var didSendMagicLink = await supabase.Auth.SendMagicLink("joseph@supabase.io", options); + ``` + - id: sign-in-with-sms-otp + name: Sign in with SMS OTP. + description: The user will be sent a SMS which contains a OTP. By default, a given user can only request a OTP once every 60 seconds. + code: | + ```c# + await supabase.Auth.SignIn(SignInType.Phone, "+13334445555"); + + // Paired with `VerifyOTP` to get a session + var session = await supabase.Auth.VerifyOTP("+13334445555", TOKEN, MobileOtpType.SMS); + ``` + - id: sign-in-with-oauth + title: 'SignIn(Provider)' + description: | + Signs the user in using third party OAuth providers. + notes: | + - This method is used for signing in using a third-party provider. + - Supabase supports many different [third-party providers](https://supabase.com/docs/guides/auth#providers). + examples: + - id: sign-in-using-a-third-party-provider + name: Sign in using a third-party provider + isSpotlight: true + code: | + ```c# + var signInUrl = supabase.Auth.SignIn(Provider.Github); + ``` + - id: sign-in-with-scopes + name: With scopes + description: | + If you need additional data from an OAuth provider, you can include a space-separated list of scopes in your request to get back an OAuth provider token. + You may also need to specify the scopes in the provider's OAuth app settings, depending on the provider. + code: | + ```c# + var signInUrl = supabase.Auth.SignIn(Provider.Github, 'repo gist notifications'); + + // after user comes back from signin flow + var session = supabase.Auth.GetSessionFromUrl(REDIRECTED_URI); + ``` + - id: sign-out + title: 'SignOut()' + description: | + Signs out the current user, if there is a logged in user. + notes: | + - In order to use the `SignOut()` method, the user needs to be signed in first. + examples: + - id: sign-out + name: Sign out + isSpotlight: true + code: | + ```c# + await supabase.Auth.SignOut(); + ``` + - id: verify-otp + title: 'VerifyOtp()' + notes: | + - The `VerifyOtp` method takes in different verification types. If a phone number is used, the type can either be `sms` or `phone_change`. If an email address is used, the type can be one of the following: `signup`, `magiclink`, `recovery`, `invite` or `email_change`. + - The verification type used should be determined based on the corresponding auth method called before `VerifyOtp` to sign up / sign-in a user. + examples: + - id: verify-sms-one-time-password(otp) + name: Verify Sms One-Time Password (OTP) + isSpotlight: true + code: | + ```c# + var session = await supabase.Auth.VerifyOTP("+13334445555", TOKEN, MobileOtpType.SMS); + ``` + - id: get-session + title: 'CurrentSession' + description: | + Returns the session data, if there is an active session. + examples: + - id: get-the-session-data + name: Get the session data + isSpotlight: true + code: | + ```c# + var session = supabase.Auth.CurrentSession; + ``` + - id: get-user + title: 'CurrentUser' + description: | + Returns the user data, if there is a logged in user. + examples: + - name: Get the logged in user + isSpotlight: true + code: | + ```c# + var user = supabase.Auth.CurrentUser; + ``` + - id: update-user + title: 'UpdateUser()' + description: | + Updates user data, if there is a logged in user. + notes: | + - In order to use the `updateUser()` method, the user needs to be signed in first. + - By Default, email updates sends a confirmation link to both the user's current and new email. + To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/settings). + examples: + - id: update-the-email-for-an-authenticated-user + name: Update the email for an authenticated user + description: Sends a "Confirm Email Change" email to the new email address. + isSpotlight: true + code: | + ```c# + var attrs = new UserAttributes { Email = "new-email@example.com" }; + var response = await supabase.Auth.Update(attrs); + ``` + - id: update-the-password-for-an-authenticated-user + name: Update the password for an authenticated user + isSpotlight: false + code: | + ```c# + var attrs = new UserAttributes { Password = "***********" }; + var response = await supabase.Auth.Update(attrs); + ``` + - id: update-the-users-metadata + name: Update the user's metadata + isSpotlight: true + code: | + ```c# + var attrs = new UserAttributes + { + Data = new Dictionary { {"example", "data" } } + }; + var response = await supabase.Auth.Update(attrs); + ``` + - id: on-auth-state-change + title: 'StateChanged' + description: | + Receive a notification every time an auth event happens. + notes: | + - Types of auth events: `AuthState.SignedIn`, `AuthState.SignedOut`, `AuthState.UserUpdated`, `AuthState.PasswordRecovery`, `AuthState.TokenRefreshed` + examples: + - id: listen-to-auth-changes + name: Listen to auth changes + isSpotlight: true + code: | + ```c# + supabase.Auth.StateChanged += (sender, ev) => + { + switch (ev.State) + { + case AuthState.SignedIn: + break; + case AuthState.SignedOut: + break; + case AuthState.UserUpdated: + break; + case AuthState.PasswordRecovery: + break; + case AuthState.TokenRefreshed: + break; + } + }; + ``` + - id: auth-reset-password-for-email + title: 'ResetPasswordForEmail()' + description: | + Sends a reset request to an email address. + notes: | + Sends a password reset request to an email address. When the user clicks the reset link in the email they are redirected back to your application. Prompt the user for a new password and call Auth.UpdateUser(): + + examples: + - id: reset-password + name: Reset password for Flutter + isSpotlight: true + code: | + ```c# + await supabase.Auth.ResetPasswordForEmail("joseph@supabase.io"); + ``` + - id: invoke + title: 'invoke()' + description: | + Invokes a Supabase Function. See the [guide](/docs/guides/functions) for details on writing Functions. + notes: | + - Requires an Authorization header. + - Invoke params generally match the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) spec. + examples: + - id: basic-invocation + name: Basic invocation. + isSpotlight: true + code: | + ```c# + var options = new InvokeFunctionOptions + { + Headers = new Dictionary {{ "Authorization", "Bearer 1234" }}, + Body = new Dictionary { { "foo", "bar" } } + }; + + await supabase.Functions.Invoke("hello", options: options); + ``` + - id: modeled-invocation + name: Modeled invocation + code: | + ``` c# + class HelloResponse + { + [JsonProperty("name")] + public string Name { get; set; } + } + + await supabase.Functions.Invoke("hello"); + ``` + - id: select + description: | + Performs vertical filtering with SELECT. + title: 'Fetch data: Select()' + notes: | + - **Column Names must match names in database, not names specified on model properties.** + - By default, Supabase projects will return a maximum of 1,000 rows. This setting can be changed in Project API Settings. It's recommended that you keep it low to limit the payload size of accidental or malicious requests. You can use `range()` queries to paginate through your data. + - `From()` can be combined with [Modifiers](/docs/reference/csharp/using-modifiers) + - `From()` can be combined with [Filters](/docs/reference/csharp/using-filters) + - If using the Supabase hosted platform `apikey` is technically a reserved keyword, since the API gateway will pluck it out for authentication. [It should be avoided as a column name](https://github.com/supabase/supabase/issues/5465). + examples: + - id: getting-your-data + name: Getting your data + isSpotlight: true + code: | + ```c# + var result = await supabase.From().Get(); + var cities = result.Models + ``` + - id: selecting-specific-columns + name: Selecting specific columns + description: You can select specific fields from your tables. + code: | + ```c# + var result = await supabase + .From() + .Select("name, createdAt") + .Get(); + ``` + - id: query-foreign-tables + name: Query foreign tables + description: If your database has relationships, you can query related tables too. + code: | + ```c# + var data = await supabase + .From() + .Select("id, supplier:supplier_id(name), purchaser:purchaser_id(name)") + .Get(); + ``` + - id: filtering-with-inner-joins + name: Filtering with inner joins + description: | + If you want to filter a table based on a child table's values you can use the `!inner()` function. For example, if you wanted + to select all rows in a `message` table which belong to a user with the `username` "Jane": + code: | + ```c# + var result = await supabase + .From() + .Select("*, users!inner(*)") + .Filter("user.username", Operator.Equals, "Jane") + .Get(); + ``` + - id: querying-with-count-option + name: Querying with count option + description: | + You can get the number of rows by using the count option. + Allowed values for count option are [exact](https://postgrest.org/en/stable/api.html#exact-count), [planned](https://postgrest.org/en/stable/api.html#planned-count) and [estimated](https://postgrest.org/en/stable/api.html#estimated-count). + code: | + ```c# + var count = await supabase + .From() + .Select("name") + .Count(CountType.Exact); + ``` + - id: querying-json-data + name: Querying JSON data + description: | + If you have data inside of a JSONB column, you can apply select + and query filters to the data values. Postgres offers a + [number of operators](https://www.postgresql.org/docs/current/functions-json.html) + for querying JSON data. Also see + [PostgREST docs](http://postgrest.org/en/v7.0.0/api.html#json-columns) for more details. + code: | + ```c# + var result = await supabase + .From() + .Select("id, name, address->street") + .Filter("address->postcode", Operator.Equals, 90210) + .Get(); + ``` + + - id: insert + description: | + Performs an INSERT into the table. + title: 'Create data: Insert()' + examples: + - id: create-a-record + name: Create a record + isSpotlight: true + code: | + ```c# + [Table("cities")] + class City : BaseModel + { + [PrimaryKey("id", false)] + public int Id { get; set; } + + [Column("name")] + public string Name { get; set; } + + [Column("country_id")] + public int CountryId { get; set; } + } + + var model = new City + { + Name = "The Shire", + CountryId = 554 + }; + + await supabase.From().Insert(model); + ``` + - id: bulk-create + name: Bulk create + code: | + ```c# + [Table("cities")] + class City : BaseModel + { + [PrimaryKey("id", false)] + public int Id { get; set; } + + [Column("name")] + public string Name { get; set; } + + [Column("country_id")] + public int CountryId { get; set; } + } + + var models = new List + { + new City { Name = "The Shire", CountryId = 554 }, + new City { Name = "Rohan", CountryId = 553 }, + }; + + await supabase.From().Insert(models); + ``` + - id: fetch-inserted-data + name: Fetch inserted record + code: | + ```dart + var result = await supabase + .From() + .Insert(models, new QueryOptions { Returning = ReturnType.Representation }); + ``` + + - id: update + description: | + Performs an UPDATE on the table. + title: 'Modify data: Update()' + notes: | + - `Update()` is typically called using a model as an argument or from a hydrated model. + examples: + - id: updating-your-data + name: Update your data + isSpotlight: true + code: | + ```c# + var model = await supabase + .From() + .Filter("name", Operator.Equals, "Auckland") + .Single(); + + model.Name = "Middle Earth"; + + await model.Update(); + ``` + + - id: upsert + description: | + Performs an UPSERT into the table. + title: 'Upsert data: Upsert()' + notes: | + - Primary keys should be included in the data payload in order for an update to work correctly. + - Primary keys must be natural, not surrogate. There are however, [workarounds](https://github.com/PostgREST/postgrest/issues/1118) for surrogate primary keys. + examples: + - id: upsert-your-data + name: Upsert your data + isSpotlight: true + code: | + ```c# + var model = new City + { + Id = 554, + Name = "Middle Earth" + }; + + await supabase.From().Upsert(model); + ``` + - id: upserting-into-tables-with-constraints + name: Upserting into tables with constraints + description: | + Running the following will cause supabase to upsert data into the `users` table. + If the username 'supabot' already exists, the `onConflict` argument tells supabase to overwrite that row + based on the column passed into `onConflict`. + isSpotlight: true + code: | + ```c# + var model = new City + { + Id = 554, + Name = "Middle Earth" + }; + + await supabase + .From() + .Upsert(model, new QueryOptions { OnConflict = "name" }); + ``` + - id: return-the-exact-number-of-rows + name: Return the exact number of rows + description: | + Allowed values for count option are `exact`, `planned` and `estimated`. + code: | + ```c# + var model = new City + { + Id = 554, + Name = "Middle Earth" + }; + + await supabase + .From() + .Upsert(model, new QueryOptions { Count = QueryOptions.CountType.Exact }); + ``` + + - id: delete + description: | + Performs a DELETE on the table. + title: 'Delete data: Delete()' + notes: | + - `delete()` should always be combined with [Filters](/docs/reference/csharp/using-filters) to target the item(s) you wish to delete. + examples: + - id: delete-records + name: Delete records + isSpotlight: true + code: | + ```c# + await supabase + .From() + .Filter("id", Operator.Equals, 342) + .Delete(); + ``` + + - id: rpc + title: 'Stored Procedures: rpc()' + description: | + You can call stored procedures as a "Remote Procedure Call". + + That's a fancy way of saying that you can put some logic into your database then call it from anywhere. + It's especially useful when the logic rarely changes - like password resets and updates. + examples: + - id: call-a-stored-procedure + name: Call a stored procedure + isSpotlight: true + description: This is an example invoking a stored procedure. + code: | + ```dart + final data = await supabase + .rpc('hello_world'); + ``` + - id: with-parameters + name: With Parameters + code: | + ```dart + final data = await supabase + .rpc('echo_city', params: { 'name': 'The Shire' }); + ``` + + - id: subscribe + description: | + Subscribe to realtime changes in your database. + title: 'on().subscribe()' + notes: | + - Realtime is disabled by default for new Projects for better database performance and security. You can turn it on by [managing replication](/docs/guides/api#managing-realtime). + - If you want to receive the "previous" data for updates and deletes, you will need to set `REPLICA IDENTITY` to `FULL`, like this: `ALTER TABLE your_table REPLICA IDENTITY FULL;` + examples: + - id: listen-to-all-database-changes + name: Listen to all database changes + isSpotlight: true + code: | + ```dart + supabase.channel('*').on( + RealtimeListenTypes.postgresChanges, + ChannelFilter(event: '*', schema: '*'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }, + ).subscribe(); + ``` + - id: listening-to-a-specific-table + name: Listening to a specific table + code: | + ```dart + supabase.channel('public:countries').on( + RealtimeListenTypes.postgresChanges, + ChannelFilter(event: '*', schema: 'public', table: 'countries'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }, + ).subscribe(); + ``` + - id: listening-to-inserts + name: Listening to inserts + code: | + ```dart + supabase.channel('public:countries').on( + RealtimeListenTypes.postgresChanges, + ChannelFilter(event: 'INSERT', schema: 'public', table: 'countries'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }, + ).subscribe(); + ``` + - id: listening-to-updates + name: Listening to updates + description: | + By default, Supabase will send only the updated record. If you want to receive the previous values as well you can + enable full replication for the table you are listening too: + + ```sql + alter table "your_table" replica identity full; + ``` + code: | + ```dart + supabase.channel('public:countries').on( + RealtimeListenTypes.postgresChanges, + ChannelFilter(event: 'UPDATE', schema: 'public', table: 'countries'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }, + ).subscribe(); + ``` + - id: listening-to-deletes + name: Listening to deletes + description: | + By default, Supabase does not send deleted records. If you want to receive the deleted record you can + enable full replication for the table you are listening too: + + ```sql + alter table "your_table" replica identity full; + ``` + code: | + ```dart + supabase.channel('public:countries').on( + RealtimeListenTypes.postgresChanges, + ChannelFilter(event: 'DELETE', schema: 'public', table: 'countries'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }, + ).subscribe(); + ``` + - id: listening-to-multiple-events + name: Listening to multiple events + description: You can chain listeners if you want to listen to multiple events for each table. + code: | + ```dart + supabase.channel('public:countries').on(RealtimeListenTypes.postgresChanges, + ChannelFilter(event: 'INSERT', schema: 'public', table: 'countries'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }).on(RealtimeListenTypes.postgresChanges, + ChannelFilter(event: 'DELETE', schema: 'public', table: 'countries'), + (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }).subscribe(); + ``` + - id: listening-to-row-level-changes + name: Listening to row level changes + description: You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match. + code: | + ```dart + supabase.channel('public:countries:id=eq.200').on( + RealtimeListenTypes.postgresChanges, + ChannelFilter( + event: 'UPDATE', + schema: 'public', + table: 'countries', + filter: 'id=eq.200', + ), (payload, [ref]) { + print('Change received: ${payload.toString()}'); + }).subscribe(); + ``` + + - id: remove-channel + description: | + Unsubscribes and removes Realtime channel from Realtime client. + title: 'removeChannel()' + notes: | + - Removing a channel is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed. + examples: + - id: removes-a-channel + name: Remove a channel + isSpotlight: true + code: | + ```dart + final status = await supabase.removeChannel(channel); + ``` + + - id: remove-all-channels + description: | + Unsubscribes and removes all Realtime channels from Realtime client. + title: 'removeAllChannels()' + notes: | + - Removing channels is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed. + examples: + - id: remove-all-channels + name: Remove all channels + isSpotlight: true + code: | + ```dart + final statuses = await supabase.removeAllChannels(); + ``` + + - id: get-channels + description: | + Returns all Realtime channels. + title: 'getChannels()' + examples: + - id: get-all-channels + name: Get all channels + isSpotlight: true + code: | + ```dart + final channels = supabase.getChannels(); + ``` + + - id: stream + description: | + Notifies of data at the queried table. + title: 'stream()' + notes: | + - `stream()` will emit the initial data as well as any further change on the database as `Stream` of `List>` by combining Postgrest and Realtime. + - Takes a list of primary key columns as its argument. + examples: + - id: listening-to-a-specific-table + name: Listening to a specific table + isSpotlight: true + code: | + ```dart + supabase.from('countries') + .stream(primaryKey: ['id']) + .listen((List> data) { + // Do something awesome with the data + }); + ``` + - id: listening-to-a-specific-rows-within-a-table + name: Listening to a specific rows within a table + description: | + You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match. + This syntax is the as how you can filter data in Realtime + code: | + ```dart + supabase.from('countries') + .stream(primaryKey: ['id']) + .eq('id', '120') + .listen((List> data) { + // Do something awesome with the data + }); + ``` + - id: with-order + name: With `order()` + code: | + ```dart + supabase.from('countries') + .stream(primaryKey: ['id']) + .order('name', ascending: true) + .listen((List> data) { + // Do something awesome with the data + }); + ``` + - id: with-limit + name: With `limit()` + code: | + ```dart + supabase.from('countries') + .stream(primaryKey: ['id']) + .order('name', ascending: true) + .limit(10) + .listen((List> data) { + // Do something awesome with the data + }); + ``` + - id: using-stream-with-stream-builder + name: Using `stream()` with `StreamBuilder` + description: | + When using `stream()` with a `StreamBuilder` within your Flutter application, make sure to store your stream in a variable to prevent refetching upon rebuilding. + code: | + ```dart + final supabase = Supabase.instance.client; + + class MyWidget extends StatefulWidget { + const MyWidget({Key? key}) : super(key: key); + + @override + State createState() => _MyWidgetState(); + } + + class _MyWidgetState extends State { + // Persist the stream in a local variable to prevent refetching upon rebuilds + final _stream = supabase.from('countries').stream(primaryKey: ['id']); + + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: _stream, + builder: (context, snapshot) { + // Return your widget with the data from the snapshot + }, + ); + } + } + ``` + + - id: list-buckets + description: | + Retrieves the details of all Storage buckets within an existing product. + title: 'listBuckets()' + $ref: '@supabase/storage-js.packages/StorageBucketApi.default.listBuckets' + notes: | + - Policy permissions required: + - `buckets` permissions: `select` + - `objects` permissions: none + examples: + - id: list-buckets + name: List buckets + isSpotlight: true + code: | + ```dart + final List buckets = await supabase + .storage + .listBuckets(); + ``` + + - id: get-bucket + description: | + Retrieves the details of an existing Storage bucket. + title: 'getBucket()' + $ref: '@supabase/storage-js.packages/StorageBucketApi.default.getBucket' + notes: | + - Policy permissions required: + - `buckets` permissions: `select` + - `objects` permissions: none + examples: + - id: get-bucket + name: Get bucket + isSpotlight: true + code: | + ```dart + final Bucket bucket = await supabase + .storage + .getBucket('avatars'); + ``` + + - id: create-bucket + description: | + Creates a new Storage bucket + title: 'createBucket()' + notes: | + - Policy permissions required: + - `buckets` permissions: `insert` + - `objects` permissions: none + examples: + - id: create-bucket + name: Create bucket + isSpotlight: true + code: | + ```dart + final String bucketId = await supabase + .storage + .createBucket('avatars'); + ``` + + - id: empty-bucket + description: | + Removes all objects inside a single bucket. + title: 'emptyBucket()' + notes: | + - Policy permissions required: + - `buckets` permissions: `select` + - `objects` permissions: `select` and `delete` + examples: + - id: empty-bucket + name: Empty bucket + isSpotlight: true + code: | + ```dart + final String result = await supabase + .storage + .emptyBucket('avatars'); + ``` + - id: update-bucket + description: | + Updates a new Storage bucket + title: 'updateBucket()' + notes: | + - Policy permissions required: + - `buckets` permissions: `update` + - `objects` permissions: none + examples: + - id: update-bucket + name: Update bucket + isSpotlight: true + code: | + ```dart + final res = await supabase + .storage + .updateBucket('avatars', const BucketOptions(public: false)); + ``` + + - id: delete-bucket + description: | + Deletes an existing bucket. A bucket can't be deleted with existing objects inside it. You must first `empty()` the bucket. + title: 'deleteBucket()' + notes: | + - Policy permissions required: + - `buckets` permissions: `select` and `delete` + - `objects` permissions: none + examples: + - id: delete-bucket + name: Delete bucket + isSpotlight: true + code: | + ```dart + final String result = await supabase + .storage + .deleteBucket('avatars'); + ``` + + - id: from-upload + description: | + Uploads a file to an existing bucket. + title: 'from.upload()' + $ref: '@supabase/storage-js.packages/StorageFileApi.default.upload' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `insert` + examples: + - id: upload-file + name: Upload file + isSpotlight: true + code: | + ```dart + final avatarFile = File('path/to/file'); + final String path = await supabase.storage.from('avatars').upload( + 'public/avatar1.png', + avatarFile, + fileOptions: const FileOptions(cacheControl: '3600', upsert: false), + ); + ``` + + - id: from-update + description: | + Replaces an existing file at the specified path with a new one. + title: 'from.update()' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `update` and `select` + examples: + - id: update-file + name: Update file + isSpotlight: true + code: | + ```dart + final avatarFile = File('path/to/local/file'); + final String path = await supabase.storage.from('avatars').update( + 'public/avatar1.png', + avatarFile, + fileOptions: const FileOptions(cacheControl: '3600', upsert: false), + ); + ``` + + - id: from-move + description: | + Moves an existing file, optionally renaming it at the same time. + title: 'from.move()' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `update` and `select` + examples: + - id: move-file + name: Move file + isSpotlight: true + code: | + ```dart + final String result = await supabase + .storage + .from('avatars') + .move('public/avatar1.png', 'private/avatar2.png'); + ``` + + - id: from-create-signed-url + description: | + Create signed url to download file without requiring permissions. This URL can be valid for a set number of seconds. + title: 'from.createSignedUrl()' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `select` + examples: + - id: create-signed-url + name: Create Signed URL + isSpotlight: true + code: | + ```dart + final String signedUrl = await supabase + .storage + .from('avatars') + .createSignedUrl('avatar1.png', 60); + ``` + - id: create-signed-url-with-transform + name: With transform + code: | + ```dart + final String signedUrl = await supabase + .storage + .from('avatars') + .createSignedUrl( + 'avatar1.png', + 60, + transform: TransformOptions( + width: 200, + height: 200, + ), + ); + ``` + + - id: from-get-public-url + description: | + Retrieve URLs for assets in public buckets + title: 'from.getPublicUrl()' + notes: | + - The bucket needs to be set to public, either via [updateBucket()](/docs/reference/javascript/storage-updatebucket) or by going to Storage on [app.supabase.com](https://app.supabase.com), clicking the overflow menu on a bucket and choosing "Make public" + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: none + examples: + - id: returns-the-url-for-an-asset-in-a-public-bucket + name: Returns the URL for an asset in a public bucket + isSpotlight: true + code: | + ```dart + final String publicUrl = supabase + .storage + .from('public-bucket') + .getPublicUrl('avatar1.png'); + ``` + - id: returns-the-url-for-an-asset-in-a-public-bucket-with-transform + name: With transform + isSpotlight: true + code: | + ```dart + final String publicUrl = await supabase + .storage + .from('public-bucket') + .getPublicUrl( + 'avatar1.png', + transform: TransformOptions( + width: 200, + height: 200, + ), + ); + ``` + + - id: from-download + description: | + Downloads a file. + title: 'from.download()' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `select` + examples: + - id: download-file + name: Download file + isSpotlight: true + code: | + ```dart + final Uint8List file = await supabase + .storage + .from('avatars') + .download('avatar1.png'); + ``` + - id: download-file-with-transform + name: With transform + isSpotlight: true + code: | + ```dart + final Uint8List file = await supabase + .storage + .from('avatars') + .download( + 'avatar1.png', + transform: TransformOptions( + width: 200, + height: 200, + ), + ); + ``` + + - id: from-remove + description: | + Deletes files within the same bucket + title: 'from.remove()' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `delete` and `select` + examples: + - id: delete-file + name: Delete file + isSpotlight: true + code: | + ```dart + final List objects = await supabase + .storage + .from('avatars') + .remove(['avatar1.png']); + ``` + + - id: from-list + description: | + Lists all the files within a bucket. + title: 'from.list()' + notes: | + - Policy permissions required: + - `buckets` permissions: none + - `objects` permissions: `select` + examples: + - id: list-files-in-a-bucket + name: List files in a bucket + isSpotlight: true + code: | + ```dart + final List objects = await supabase + .storage + .from('avatars') + .list(); + ``` + - id: using-modifiers + title: Using Modifiers + description: | + Filters work on the row level—they allow you to return rows that + only match certain conditions without changing the shape of the rows. + Modifiers are everything that don't fit that definition—allowing you to + change the format of the response (e.g., returning a CSV string). + + Modifiers must be specified after filters. Some modifiers only apply for + queries that return rows (e.g., `select()` or `rpc()` on a function that + returns a table response). + + - id: limit + title: limit() + description: | + Limits the result with the specified count. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .limit(1); + ``` + - id: with-embedded-resources + name: With embedded resources + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, cities(name)') + .eq('name', 'United States') + .limit(1, foreignTable: 'cities' ); + ``` + + - id: order + title: order() + description: | + Orders the result with the specified column. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .order('id', ascending: false ); + ``` + - id: with-embedded-resources + name: With embedded resources + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, cities(name)') + .eq('name', 'United States') + .order('name', foreignTable: 'cities'); + ``` + + - id: range + title: range() + description: | + Limits the result to rows within the specified range, inclusive. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .range(0,3); + ``` + + - id: single + title: single() + description: | + Retrieves only one row from the result. Result must be one row (e.g. using limit), otherwise this will result in an error. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .single(); + ``` + + - id: using-filters + title: Using Filters + description: | + Filters allow you to only return rows that match certain conditions. + + Filters can be used on `select()`, `update()`, and `delete()` queries. + + If a Database function returns a table response, you can also apply filters. + examples: + - id: applying-filters + name: Applying Filters + description: | + Filters must be applied after any of `select()`, `update()`, `upsert()`, + `delete()`, and `rpc()` and before + [modifiers](/docs/reference/dart/using-modifiers). + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .eq('name', 'The Shire'); // Correct + + final data = await supabase + .from('cities') + .eq('name', 'The Shire') // Incorrect + .select('name, country_id'); + ``` + - id: chaining-filters + name: Chaining Filters + description: | + Filters must be applied after any of `select()`, `update()`, `upsert()`, + `delete()`, and `rpc()` and before + [modifiers](/docs/reference/dart/using-modifiers). + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .eq('name', 'The Shire'); // Correct + + final data = await supabase + .from('cities') + .eq('name', 'The Shire') // Incorrect + .select('name, country_id'); + ``` + - id: conditional-chaining + name: Conditional Chaining + description: | + Filters can be built up one step at a time and then executed. For example: + code: | + ```dart + final data = await supabase + .from('users') + .select() + .eq('address->postcode', 90210); + ``` + - id: filter-by-value-within-json-column + name: Filter by values within a JSON column + description: | + Filters can be built up one step at a time and then executed. For example: + data: + sql: | + ```sql + create table + users ( + id int8 primary key, + name text, + address jsonb + ); + + insert into + users (id, name, address) + values + (1, 'Michael', '{ "postcode": 90210 }'), + (2, 'Jane', null); + ``` + response: | + ```json + { + "data": [ + { + "id": 1, + "name": "Michael", + "address": { + "postcode": 90210 + } + } + ], + "status": 200, + "statusText": "OK" + } + ``` + code: | + ```dart + final data = await supabase + .from('users') + .select() + .eq('address->postcode', 90210); + ``` + - id: filter-foreign-tables + name: Filter Foreign Tables + code: | + ```dart + final data = await supabase + .from('countries') + .select(''' + name, + cities!inner ( + name + ) + ''') + .eq('cities.name', 'Bali'); + ``` + data: + sql: | + ```sql + create table + countries (id int8 primary key, name text); + create table + cities ( + id int8 primary key, + country_id int8 not null references countries, + name text + ); + + insert into + countries (id, name) + values + (1, 'Germany'), + (2, 'Indonesia'); + insert into + cities (id, country_id, name) + values + (1, 2, 'Bali'), + (2, 1, 'Munich'); + ``` + response: | + ```json + { + "data": [ + { + "name": "Indonesia", + "cities": [ + { + "name": "Bali" + } + ] + } + ], + "status": 200, + "statusText": "OK" + } + ``` + - id: or + title: or() + description: | + Finds all rows satisfying at least one of the filters. + notes: | + - `.or()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values. + + ```dart + .or('id.in.(6,7),arraycol.cs.{"a","b"}') // Use Postgres list () and 'in' for in_ filter. Array {} and 'cs' for contains. + .or('id.in.(${mylist.join(',')}),arraycol.cs.{${mylistArray.join(',')}}') // You can insert a Dart list for list or array column. + .or('id.in.(${mylist.join(',')}),rangecol.cs.(${mylistRange.join(',')}]') // You can insert a Dart list for list or range column. + ``` + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .or('id.eq.20,id.eq.30'); + ``` + - id: use-or-with-and + name: Use `or` with `and` + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .or('id.gt.20,and(name.eq.New Zealand,name.eq.France)'); + ``` + + - id: not + title: not() + description: | + Finds all rows which doesn't satisfy the filter. + notes: | + - `.not()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values. + + ```dart + .not('name','eq','Paris') + .not('arraycol','cs','{"a","b"}') // Use Postgres array {} for array column and 'cs' for contains. + .not('rangecol','cs','(1,2]') // Use Postgres range syntax for range column. + .not('id','in','(6,7)') // Use Postgres list () and 'in' for in_ filter. + .not('id','in','(${mylist.join(',')})') // You can insert a Dart list array. + ``` + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .not('name', 'eq', 'Paris'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .not('name', 'eq', 'Paris'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .not('name', 'eq', 'Paris'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities) + .not('name', 'eq', 'Paris'); + ``` + + - id: match + title: match() + description: | + Finds all rows whose columns match the specified `query` object. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .match({'name': 'Beijing', 'country_id': 156}); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .match({'name': 'Beijing', 'country_id': 156}); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .match({'name': 'Beijing', 'country_id': 156}); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .match({'name': 'Beijing', 'country_id': 156}); + ``` + + - id: eq + title: eq() + description: | + Finds all rows whose value on the stated `column` exactly matches the specified `value`. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .eq('name', 'The shire'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .eq('name', 'San Francisco'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .eq('name', 'Mordor'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .eq('name', 'San Francisco'); + ``` + + - id: neq + title: neq() + description: | + Finds all rows whose value on the stated `column` doesn't match the specified `value`. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .neq('name', 'The shire'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .neq('name', 'San Francisco'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .neq('name', 'Mordor'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .neq('name', 'Lagos'); + ``` + + - id: gt + title: gt() + description: | + Finds all rows whose value on the stated `column` is greater than the specified `value`. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .gt('country_id', 250); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .gt('country_id', 250); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .gt('country_id', 250); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .gt('country_id', 250); + ``` + + - id: gte + title: gte() + description: | + Finds all rows whose value on the stated `column` is greater than or equal to the specified `value`. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .gte('country_id', 250); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .gte('country_id', 250); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .gte('country_id', 250); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .gte('country_id', 250); + ``` + + - id: lt + title: lt() + description: | + Finds all rows whose value on the stated `column` is less than the specified `value`. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .lt('country_id', 250); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .lt('country_id', 250); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .lt('country_id', 250); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .lt('country_id', 250); + ``` + + - id: lte + title: lte() + description: | + Finds all rows whose value on the stated `column` is less than or equal to the specified `value`. + $ref: '@supabase/postgrest-js.PostgrestFilterBuilder.lte' + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .lte('country_id', 250); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .lte('country_id', 250); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .lte('country_id', 250); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .lte('country_id', 250); + ``` + + - id: like + title: like() + description: | + Finds all rows whose value in the stated `column` matches the supplied `pattern` (case sensitive). + $ref: '@supabase/postgrest-js.PostgrestFilterBuilder.lte' + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .like('name', '%la%'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .like('name', '%la%'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .like('name', '%la%'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .like('name', '%la%'); + ``` + + - id: ilike + title: ilike() + description: | + Finds all rows whose value in the stated `column` matches the supplied `pattern` (case insensitive). + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .ilike('name', '%la%'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .ilike('name', '%la%'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .ilike('name', '%la%'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .ilike('name', '%la%'); + ``` + + - id: is + title: is_() + description: | + A check for exact equality (null, true, false), finds all rows whose value on the stated `column` exactly match the specified `value`. + + `is_` and `in_` filter methods are suffixed with `_` to avoid collisions with reserved keywords. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .is_('name', null); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .is_('name', null); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .is_('name', null); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .is_('name', null); + ``` + + - id: in + title: in_() + description: | + Finds all rows whose value on the stated `column` is found on the specified `values`. + + `is_` and `in_` filter methods are suffixed with `_` to avoid collisions with reserved keywords. + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .in_('name', ['Rio de Janeiro', 'San Francisco']); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .in_('name', ['Rio de Janeiro', 'San Francisco']); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .in_('name', ['Rio de Janeiro', 'San Francisco']); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .in_('name', ['Rio de Janeiro', 'San Francisco']); + ``` + + - id: contains + title: contains() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, main_exports') + .contains('main_exports', ['oil']); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .contains('main_exports', ['oil']); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .contains('main_exports', ['oil']); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .contains('main_exports', ['oil']); + ``` + + - id: contained-by + title: containedBy() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, main_exports') + .containedBy('main_exports', ['cars', 'food', 'machine']); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .containedBy('main_exports', ['orks', 'surveillance', 'evil']); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .containedBy('main_exports', ['cars', 'food', 'machine']); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .containedBy('main_exports', ['cars', 'food', 'machine']); + ``` + + - id: range-lt + title: rangeLt() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, population_range_millions') + .rangeLt('population_range_millions', '[150, 250]'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .rangeLt('population_range_millions', '[150, 250]'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .rangeLt('population_range_millions', '[150, 250]'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .rangeLt('population_range_millions', '[150, 250]'); + ``` + + - id: range-gt + title: rangeGt() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, population_range_millions') + .rangeGt('population_range_millions', '[150, 250]'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .rangeGt('population_range_millions', '[150, 250]'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .rangeGt('population_range_millions', '[150, 250]'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .rangeGt('population_range_millions', '[150, 250]'); + ``` + + - id: range-gte + title: rangeGte() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, population_range_millions') + .rangeGte('population_range_millions', '[150, 250]'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .rangeGte('population_range_millions', '[150, 250]'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .rangeGte('population_range_millions', '[150, 250]'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .rangeGte('population_range_millions', '[150, 250]'); + ``` + + - id: range-lte + title: rangeLte() + $ref: '@supabase/postgrest-js.PostgrestFilterBuilder.rangeLte' + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, population_range_millions') + .rangeLte('population_range_millions', '[150, 250]'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .rangeLte('population_range_millions', '[150, 250]'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .rangeLte('population_range_millions', '[150, 250]'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .rangeLte('population_range_millions', [150, 250]); + ``` + + - id: range-adjacent + title: rangeAdjacent() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, population_range_millions') + .rangeAdjacent('population_range_millions', '[70, 185]'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .rangeAdjacent('population_range_millions', '[70, 185]'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .rangeAdjacent('population_range_millions', '[70, 185]'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .rangeAdjacent('population_range_millions', '[70, 185]'); + ``` + + - id: overlaps + title: overlaps() + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('countries') + .select('name, id, main_exports') + .overlaps('main_exports', ['computers', 'minerals']); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('countries') + .update({ 'name': 'Mordor' }) + .overlaps('main_exports', ['computers', 'minerals']); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('countries') + .delete() + .overlaps('main_exports', ['computers', 'minerals']); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_countries') + .overlaps('main_exports', ['computers', 'minerals']); + ``` + + - id: text-search + title: textSearch() + description: | + Finds all rows whose tsvector value on the stated `column` matches to_tsquery(query). + examples: + - id: text-search + name: Text search + code: | + ```dart + final data = await supabase + .from('quotes') + .select('catchphrase') + .textSearch('catchphrase', "'fat' & 'cat'", + config: 'english' + ); + ``` + - id: basic-normalization + name: Basic normalization + description: Uses PostgreSQL's `plainto_tsquery` function. + code: | + ```dart + final data = await supabase + .from('quotes') + .select('catchphrase') + .textSearch('catchphrase', "'fat' & 'cat'", + type: TextSearchType.plain, + config: 'english' + ); + ``` + - id: full-normalization + name: Full normalization + description: Uses PostgreSQL's `phraseto_tsquery` function. + code: | + ```dart + final data = await supabase + .from('quotes') + .select('catchphrase') + .textSearch('catchphrase', "'fat' & 'cat'", + type: TextSearchType.phrase, + config: 'english' + ); + ``` + - id: web-search + name: Websearch + description: | + Uses PostgreSQL's `websearch_to_tsquery` function. + This function will never raise syntax errors, which makes it possible to use raw user-supplied input for search, and can be used + with advanced operators. + + - `unquoted text`: text not inside quote marks will be converted to terms separated by & operators, as if processed by plainto_tsquery. + - `"quoted text"`: text inside quote marks will be converted to terms separated by <-> operators, as if processed by phraseto_tsquery. + - `OR`: the word “or” will be converted to the | operator. + - `-`: a dash will be converted to the ! operator. + + code: | + ```dart + final data = await supabase + .from('quotes') + .select('catchphrase') + .textSearch('catchphrase', "'fat or cat'", + type: TextSearchType.websearch, + config: 'english' + ); + ``` + + - id: filter + title: filter() + description: | + Finds all rows whose `column` satisfies the filter. + notes: | + - `.filter()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values, so it should only be used as an escape hatch in case other filters don't work. + ```dart + .filter('arraycol','cs','{"a","b"}') // Use Postgres array {} and 'cs' for contains. + .filter('rangecol','cs','(1,2]') // Use Postgres range syntax for range column. + .filter('id','in','(6,7)') // Use Postgres list () and 'in' for in_ filter. + .filter('id','cs','{${mylist.join(',')}}') // You can insert a Dart array list. + ``` + examples: + - id: with-select + name: With `select()` + isSpotlight: true + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, country_id') + .filter('name', 'in', '("Paris","Tokyo")'); + ``` + - id: with-update + name: With `update()` + code: | + ```dart + final data = await supabase + .from('cities') + .update({ 'name': 'Mordor' }) + .filter('name', 'in', '("Paris","Tokyo")'); + ``` + - id: with-delete + name: With `delete()` + code: | + ```dart + final data = await supabase + .from('cities') + .delete() + .filter('name', 'in', '("Paris","Tokyo")'); + ``` + - id: with-rpc + name: With `rpc()` + code: | + ```dart + // Only valid if the Stored Procedure returns a table type. + final data = await supabase + .rpc('echo_all_cities') + .filter('name', 'in', '("Paris","Tokyo")'); + ``` + - id: filter-embedded-resources + name: Filter embedded resources + code: | + ```dart + final data = await supabase + .from('cities') + .select('name, countries ( name )') + .filter('countries.name', 'in', '("France","Japan")'); + ``` From 05b7028103a72e0b1a9bf51079be78073056f4a9 Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Fri, 23 Dec 2022 18:18:30 -0600 Subject: [PATCH 02/30] Finish docs with available functionality in c# client --- .../{initialization.mdx => initializing.mdx} | 6 +- spec/common-client-libs-sections.json | 12 +- spec/supabase_csharp_v0.yml | 1732 +++++------------ 3 files changed, 515 insertions(+), 1235 deletions(-) rename apps/docs/docs/ref/csharp/{initialization.mdx => initializing.mdx} (96%) diff --git a/apps/docs/docs/ref/csharp/initialization.mdx b/apps/docs/docs/ref/csharp/initializing.mdx similarity index 96% rename from apps/docs/docs/ref/csharp/initialization.mdx rename to apps/docs/docs/ref/csharp/initializing.mdx index 6f253ddf687..ca29a5605a3 100644 --- a/apps/docs/docs/ref/csharp/initialization.mdx +++ b/apps/docs/docs/ref/csharp/initializing.mdx @@ -1,7 +1,7 @@ --- -id: initialization -title: 'Initialization' -slug: initialization +id: initializing +title: 'Initializing' +slug: initializing custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supabase.yml --- diff --git a/spec/common-client-libs-sections.json b/spec/common-client-libs-sections.json index 9478de69da0..60b6e7716d3 100644 --- a/spec/common-client-libs-sections.json +++ b/spec/common-client-libs-sections.json @@ -17,7 +17,8 @@ "title": "Initializing", "id": "initializing", "slug": "initializing", - "type": "function" + "type": "markdown", + "libs": ["csharp"] }, { "title": "Typescript Support", @@ -342,6 +343,15 @@ "type": "function", "libs": ["js", "dart", "dart_v0", "csharp"] }, + { + "id": "offset", + "title": "Offset the Query", + "slug": "offset", + "product":"database", + "parent":"modifiers", + "type": "function", + "libs": ["csharp"] + }, { "id": "abort-signal", "title": "Set an abort signal", diff --git a/spec/supabase_csharp_v0.yml b/spec/supabase_csharp_v0.yml index f9e6c805d80..6a881cef0b9 100644 --- a/spec/supabase_csharp_v0.yml +++ b/spec/supabase_csharp_v0.yml @@ -418,7 +418,7 @@ functions: - id: fetch-inserted-data name: Fetch inserted record code: | - ```dart + ```c# var result = await supabase .From() .Insert(models, new QueryOptions { Returning = ReturnType.Representation }); @@ -508,7 +508,7 @@ functions: Performs a DELETE on the table. title: 'Delete data: Delete()' notes: | - - `delete()` should always be combined with [Filters](/docs/reference/csharp/using-filters) to target the item(s) you wish to delete. + - `Delete()` should always be combined with [Filters](/docs/reference/csharp/using-filters) to target the item(s) you wish to delete. examples: - id: delete-records name: Delete records @@ -522,7 +522,7 @@ functions: ``` - id: rpc - title: 'Stored Procedures: rpc()' + title: 'Stored Procedures: Rpc()' description: | You can call stored procedures as a "Remote Procedure Call". @@ -534,62 +534,55 @@ functions: isSpotlight: true description: This is an example invoking a stored procedure. code: | - ```dart - final data = await supabase - .rpc('hello_world'); + ```c# + await supabase.Rpc("hello_world", null); ``` - id: with-parameters name: With Parameters code: | - ```dart - final data = await supabase - .rpc('echo_city', params: { 'name': 'The Shire' }); + ```c# + await supabase.Rpc("hello_world", new Dictionary { { "foo", "bar"} }); ``` - id: subscribe description: | Subscribe to realtime changes in your database. - title: 'on().subscribe()' + title: 'From().On()' notes: | - Realtime is disabled by default for new Projects for better database performance and security. You can turn it on by [managing replication](/docs/guides/api#managing-realtime). - If you want to receive the "previous" data for updates and deletes, you will need to set `REPLICA IDENTITY` to `FULL`, like this: `ALTER TABLE your_table REPLICA IDENTITY FULL;` examples: - - id: listen-to-all-database-changes - name: Listen to all database changes - isSpotlight: true - code: | - ```dart - supabase.channel('*').on( - RealtimeListenTypes.postgresChanges, - ChannelFilter(event: '*', schema: '*'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }, - ).subscribe(); - ``` - id: listening-to-a-specific-table name: Listening to a specific table + isSpotlight: true code: | - ```dart - supabase.channel('public:countries').on( - RealtimeListenTypes.postgresChanges, - ChannelFilter(event: '*', schema: 'public', table: 'countries'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }, - ).subscribe(); + ```c# + await supabase.From().On(ChannelEventType.All, (sender, args) => + { + Debug.WriteLine(args.Response.Payload); + }); + ``` + - id: listen-to-all-database-changes + name: Listen to all database changes + code: | + ```c# + var channel = supabase.Realtime.Channel("realtime", "public", "*"); + + channel.OnMessage += (sender, args) => + { + Debug.WriteLine(args.Response.Payload); + }; + + await channel.Subscribe(); ``` - id: listening-to-inserts name: Listening to inserts code: | - ```dart - supabase.channel('public:countries').on( - RealtimeListenTypes.postgresChanges, - ChannelFilter(event: 'INSERT', schema: 'public', table: 'countries'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }, - ).subscribe(); + ```c# + await supabase.From().On(ChannelEventType.Insert, (sender, args) => + { + Debug.WriteLine(args.Response.Payload); + }); ``` - id: listening-to-updates name: Listening to updates @@ -601,14 +594,11 @@ functions: alter table "your_table" replica identity full; ``` code: | - ```dart - supabase.channel('public:countries').on( - RealtimeListenTypes.postgresChanges, - ChannelFilter(event: 'UPDATE', schema: 'public', table: 'countries'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }, - ).subscribe(); + ```c# + await supabase.From().On(ChannelEventType.Update, (sender, args) => + { + Debug.WriteLine(args.Response.Payload); + }); ``` - id: listening-to-deletes name: Listening to deletes @@ -620,51 +610,31 @@ functions: alter table "your_table" replica identity full; ``` code: | - ```dart - supabase.channel('public:countries').on( - RealtimeListenTypes.postgresChanges, - ChannelFilter(event: 'DELETE', schema: 'public', table: 'countries'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }, - ).subscribe(); - ``` - - id: listening-to-multiple-events - name: Listening to multiple events - description: You can chain listeners if you want to listen to multiple events for each table. - code: | - ```dart - supabase.channel('public:countries').on(RealtimeListenTypes.postgresChanges, - ChannelFilter(event: 'INSERT', schema: 'public', table: 'countries'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }).on(RealtimeListenTypes.postgresChanges, - ChannelFilter(event: 'DELETE', schema: 'public', table: 'countries'), - (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }).subscribe(); + ```c# + await supabase.From().On(ChannelEventType.Delete, (sender, args) => + { + Debug.WriteLine(args.Response.Payload); + }); ``` - id: listening-to-row-level-changes name: Listening to row level changes description: You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match. code: | - ```dart - supabase.channel('public:countries:id=eq.200').on( - RealtimeListenTypes.postgresChanges, - ChannelFilter( - event: 'UPDATE', - schema: 'public', - table: 'countries', - filter: 'id=eq.200', - ), (payload, [ref]) { - print('Change received: ${payload.toString()}'); - }).subscribe(); + ```c# + var channel = supabase.Realtime.Channel("realtime", "public", "countries", "id", "id=eq.200"); + + channel.OnMessage += (sender, args) => + { + Debug.WriteLine(args.Response.Payload); + }; + + await channel.Subscribe(); ``` - id: remove-channel description: | Unsubscribes and removes Realtime channel from Realtime client. - title: 'removeChannel()' + title: 'Unsubscribe()' notes: | - Removing a channel is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed. examples: @@ -672,130 +642,120 @@ functions: name: Remove a channel isSpotlight: true code: | - ```dart - final status = await supabase.removeChannel(channel); - ``` + ```c# + var channel = await supabase.From().On(ChannelEventType.All, (sender, args) => { }); + channel.Unsubscribe(); - - id: remove-all-channels - description: | - Unsubscribes and removes all Realtime channels from Realtime client. - title: 'removeAllChannels()' - notes: | - - Removing channels is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed. - examples: - - id: remove-all-channels - name: Remove all channels - isSpotlight: true - code: | - ```dart - final statuses = await supabase.removeAllChannels(); + // OR + + var channel = supabase.Realtime.Channel("realtime", "public", "*"); + channel.Unsubscribe() ``` - id: get-channels description: | Returns all Realtime channels. - title: 'getChannels()' + title: 'Subscriptions' examples: - id: get-all-channels name: Get all channels isSpotlight: true code: | - ```dart - final channels = supabase.getChannels(); + ```c# + var channels = supabase.Realtime.Subscriptions; ``` - - id: stream - description: | - Notifies of data at the queried table. - title: 'stream()' - notes: | - - `stream()` will emit the initial data as well as any further change on the database as `Stream` of `List>` by combining Postgrest and Realtime. - - Takes a list of primary key columns as its argument. - examples: - - id: listening-to-a-specific-table - name: Listening to a specific table - isSpotlight: true - code: | - ```dart - supabase.from('countries') - .stream(primaryKey: ['id']) - .listen((List> data) { - // Do something awesome with the data - }); - ``` - - id: listening-to-a-specific-rows-within-a-table - name: Listening to a specific rows within a table - description: | - You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match. - This syntax is the as how you can filter data in Realtime - code: | - ```dart - supabase.from('countries') - .stream(primaryKey: ['id']) - .eq('id', '120') - .listen((List> data) { - // Do something awesome with the data - }); - ``` - - id: with-order - name: With `order()` - code: | - ```dart - supabase.from('countries') - .stream(primaryKey: ['id']) - .order('name', ascending: true) - .listen((List> data) { - // Do something awesome with the data - }); - ``` - - id: with-limit - name: With `limit()` - code: | - ```dart - supabase.from('countries') - .stream(primaryKey: ['id']) - .order('name', ascending: true) - .limit(10) - .listen((List> data) { - // Do something awesome with the data - }); - ``` - - id: using-stream-with-stream-builder - name: Using `stream()` with `StreamBuilder` - description: | - When using `stream()` with a `StreamBuilder` within your Flutter application, make sure to store your stream in a variable to prevent refetching upon rebuilding. - code: | - ```dart - final supabase = Supabase.instance.client; + # - id: stream + # description: | + # Notifies of data at the queried table. + # title: 'stream()' + # notes: | + # - `stream()` will emit the initial data as well as any further change on the database as `Stream` of `List>` by combining Postgrest and Realtime. + # - Takes a list of primary key columns as its argument. + # examples: + # - id: listening-to-a-specific-table + # name: Listening to a specific table + # isSpotlight: true + # code: | + # ```dart + # supabase.from('countries') + # .stream(primaryKey: ['id']) + # .listen((List> data) { + # // Do something awesome with the data + # }); + # ``` + # - id: listening-to-a-specific-rows-within-a-table + # name: Listening to a specific rows within a table + # description: | + # You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match. + # This syntax is the as how you can filter data in Realtime + # code: | + # ```dart + # supabase.from('countries') + # .stream(primaryKey: ['id']) + # .eq('id', '120') + # .listen((List> data) { + # // Do something awesome with the data + # }); + # ``` + # - id: with-order + # name: With `order()` + # code: | + # ```dart + # supabase.from('countries') + # .stream(primaryKey: ['id']) + # .order('name', ascending: true) + # .listen((List> data) { + # // Do something awesome with the data + # }); + # ``` + # - id: with-limit + # name: With `limit()` + # code: | + # ```dart + # supabase.from('countries') + # .stream(primaryKey: ['id']) + # .order('name', ascending: true) + # .limit(10) + # .listen((List> data) { + # // Do something awesome with the data + # }); + # ``` + # - id: using-stream-with-stream-builder + # name: Using `stream()` with `StreamBuilder` + # description: | + # When using `stream()` with a `StreamBuilder` within your Flutter application, make sure to store your stream in a variable to prevent refetching upon rebuilding. + # code: | + # ```dart + # final supabase = Supabase.instance.client; - class MyWidget extends StatefulWidget { - const MyWidget({Key? key}) : super(key: key); + # class MyWidget extends StatefulWidget { + # const MyWidget({Key? key}) : super(key: key); - @override - State createState() => _MyWidgetState(); - } + # @override + # State createState() => _MyWidgetState(); + # } - class _MyWidgetState extends State { - // Persist the stream in a local variable to prevent refetching upon rebuilds - final _stream = supabase.from('countries').stream(primaryKey: ['id']); + # class _MyWidgetState extends State { + # // Persist the stream in a local variable to prevent refetching upon rebuilds + # final _stream = supabase.from('countries').stream(primaryKey: ['id']); - @override - Widget build(BuildContext context) { - return StreamBuilder( - stream: _stream, - builder: (context, snapshot) { - // Return your widget with the data from the snapshot - }, - ); - } - } - ``` + # @override + # Widget build(BuildContext context) { + # return StreamBuilder( + # stream: _stream, + # builder: (context, snapshot) { + # // Return your widget with the data from the snapshot + # }, + # ); + # } + # } + # ``` - id: list-buckets description: | Retrieves the details of all Storage buckets within an existing product. - title: 'listBuckets()' - $ref: '@supabase/storage-js.packages/StorageBucketApi.default.listBuckets' + title: 'ListBuckets()' notes: | - Policy permissions required: - `buckets` permissions: `select` @@ -805,17 +765,14 @@ functions: name: List buckets isSpotlight: true code: | - ```dart - final List buckets = await supabase - .storage - .listBuckets(); + ```c# + var buckets = await supabase.Storage.ListBuckets(); ``` - id: get-bucket description: | Retrieves the details of an existing Storage bucket. - title: 'getBucket()' - $ref: '@supabase/storage-js.packages/StorageBucketApi.default.getBucket' + title: 'GetBucket()' notes: | - Policy permissions required: - `buckets` permissions: `select` @@ -825,16 +782,14 @@ functions: name: Get bucket isSpotlight: true code: | - ```dart - final Bucket bucket = await supabase - .storage - .getBucket('avatars'); + ```c# + var bucket = await supabase.Storage.GetBucket("avatars"); ``` - id: create-bucket description: | Creates a new Storage bucket - title: 'createBucket()' + title: 'CreateBucket()' notes: | - Policy permissions required: - `buckets` permissions: `insert` @@ -844,16 +799,14 @@ functions: name: Create bucket isSpotlight: true code: | - ```dart - final String bucketId = await supabase - .storage - .createBucket('avatars'); + ```c# + var bucket = await supabase.Storage.CreateBucket("avatars"); ``` - id: empty-bucket description: | Removes all objects inside a single bucket. - title: 'emptyBucket()' + title: 'EmptyBucket()' notes: | - Policy permissions required: - `buckets` permissions: `select` @@ -863,15 +816,13 @@ functions: name: Empty bucket isSpotlight: true code: | - ```dart - final String result = await supabase - .storage - .emptyBucket('avatars'); + ```c# + var bucket = await supabase.Storage.EmptyBucket("avatars"); ``` - id: update-bucket description: | Updates a new Storage bucket - title: 'updateBucket()' + title: 'UpdateBucket()' notes: | - Policy permissions required: - `buckets` permissions: `update` @@ -881,16 +832,14 @@ functions: name: Update bucket isSpotlight: true code: | - ```dart - final res = await supabase - .storage - .updateBucket('avatars', const BucketOptions(public: false)); + ```c# + var bucket = await supabase.Storage.UpdateBucket("avatars", new BucketUpsertOptions { Public = false }); ``` - id: delete-bucket description: | Deletes an existing bucket. A bucket can't be deleted with existing objects inside it. You must first `empty()` the bucket. - title: 'deleteBucket()' + title: 'DeleteBucket()' notes: | - Policy permissions required: - `buckets` permissions: `select` and `delete` @@ -901,16 +850,13 @@ functions: isSpotlight: true code: | ```dart - final String result = await supabase - .storage - .deleteBucket('avatars'); + var result = await supabase.Storage.DeleteBucket("avatars"); ``` - id: from-upload description: | Uploads a file to an existing bucket. - title: 'from.upload()' - $ref: '@supabase/storage-js.packages/StorageFileApi.default.upload' + title: 'From().Upload()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -920,19 +866,28 @@ functions: name: Upload file isSpotlight: true code: | - ```dart - final avatarFile = File('path/to/file'); - final String path = await supabase.storage.from('avatars').upload( - 'public/avatar1.png', - avatarFile, - fileOptions: const FileOptions(cacheControl: '3600', upsert: false), - ); + ```c# + var imagePath = Path.Combine("Assets", "fancy-avatar.png"); + + await supabase.Storage + .From("avatars") + .Upload(imagePath, "fancy-avatar.png", new FileOptions { CacheControl = "3600", Upsert = false }); + ``` + - id: upload-file-with-progress + name: Upload file with Progress + code: | + ```c# + var imagePath = Path.Combine("Assets", "fancy-avatar.png"); + + await supabase.Storage + .From("avatars") + .Upload(imagePath, "fancy-avatar.png", onProgress: (sender, progress) => Debug.WriteLine($"{progress}%")); ``` - id: from-update description: | Replaces an existing file at the specified path with a new one. - title: 'from.update()' + title: 'From().update()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -942,19 +897,15 @@ functions: name: Update file isSpotlight: true code: | - ```dart - final avatarFile = File('path/to/local/file'); - final String path = await supabase.storage.from('avatars').update( - 'public/avatar1.png', - avatarFile, - fileOptions: const FileOptions(cacheControl: '3600', upsert: false), - ); + ```c# + var imagePath = Path.Combine("Assets", "fancy-avatar.png"); + await supabase.Storage.From("avatars").Update(imagePath, "fancy-avatar.png"); ``` - id: from-move description: | Moves an existing file, optionally renaming it at the same time. - title: 'from.move()' + title: 'From().Move()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -964,17 +915,15 @@ functions: name: Move file isSpotlight: true code: | - ```dart - final String result = await supabase - .storage - .from('avatars') - .move('public/avatar1.png', 'private/avatar2.png'); + ```c# + await supabase.Storage.From("avatars") + .Move("public/fancy-avatar.png", "private/fancy-avatar.png"); ``` - id: from-create-signed-url description: | Create signed url to download file without requiring permissions. This URL can be valid for a set number of seconds. - title: 'from.createSignedUrl()' + title: 'From().CreateSignedUrl()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -984,27 +933,8 @@ functions: name: Create Signed URL isSpotlight: true code: | - ```dart - final String signedUrl = await supabase - .storage - .from('avatars') - .createSignedUrl('avatar1.png', 60); - ``` - - id: create-signed-url-with-transform - name: With transform - code: | - ```dart - final String signedUrl = await supabase - .storage - .from('avatars') - .createSignedUrl( - 'avatar1.png', - 60, - transform: TransformOptions( - width: 200, - height: 200, - ), - ); + ```c# + var url = await supabase.Storage.From("avatars").CreateSignedUrl("public/fancy-avatar.png", 60); ``` - id: from-get-public-url @@ -1012,7 +942,7 @@ functions: Retrieve URLs for assets in public buckets title: 'from.getPublicUrl()' notes: | - - The bucket needs to be set to public, either via [updateBucket()](/docs/reference/javascript/storage-updatebucket) or by going to Storage on [app.supabase.com](https://app.supabase.com), clicking the overflow menu on a bucket and choosing "Make public" + - The bucket needs to be set to public, either via [UpdateBucket()](/docs/reference/csharp/storage-updatebucket) or by going to Storage on [app.supabase.com](https://app.supabase.com), clicking the overflow menu on a bucket and choosing "Make public" - Policy permissions required: - `buckets` permissions: none - `objects` permissions: none @@ -1021,33 +951,14 @@ functions: name: Returns the URL for an asset in a public bucket isSpotlight: true code: | - ```dart - final String publicUrl = supabase - .storage - .from('public-bucket') - .getPublicUrl('avatar1.png'); - ``` - - id: returns-the-url-for-an-asset-in-a-public-bucket-with-transform - name: With transform - isSpotlight: true - code: | - ```dart - final String publicUrl = await supabase - .storage - .from('public-bucket') - .getPublicUrl( - 'avatar1.png', - transform: TransformOptions( - width: 200, - height: 200, - ), - ); + ```c# + var publicUrl = supabase.Storage.From("avatars").GetPublicUrl("public/fancy-avatar.png"); ``` - id: from-download description: | Downloads a file. - title: 'from.download()' + title: 'From().Download()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -1057,33 +968,22 @@ functions: name: Download file isSpotlight: true code: | - ```dart - final Uint8List file = await supabase - .storage - .from('avatars') - .download('avatar1.png'); + ```c# + var bytes = await supabase.Storage.From("avatars").Download("public/fancy-avatar.png"); ``` - - id: download-file-with-transform - name: With transform - isSpotlight: true + - id: download-file-with-progress + name: Download file with Progress code: | - ```dart - final Uint8List file = await supabase - .storage - .from('avatars') - .download( - 'avatar1.png', - transform: TransformOptions( - width: 200, - height: 200, - ), - ); + ```c# + var bytes = await supabase.Storage + .From("avatars") + .Download("public/fancy-avatar.png", (sender, progress) => Debug.WriteLine($"{progress}%")); ``` - id: from-remove description: | Deletes files within the same bucket - title: 'from.remove()' + title: 'From().Remove()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -1093,17 +993,14 @@ functions: name: Delete file isSpotlight: true code: | - ```dart - final List objects = await supabase - .storage - .from('avatars') - .remove(['avatar1.png']); + ```c# + await supabase.Storage.From("avatars").Remove(new List { "public/fancy-avatar.png" }); ``` - id: from-list description: | Lists all the files within a bucket. - title: 'from.list()' + title: 'From().list()' notes: | - Policy permissions required: - `buckets` permissions: none @@ -1113,11 +1010,8 @@ functions: name: List files in a bucket isSpotlight: true code: | - ```dart - final List objects = await supabase - .storage - .from('avatars') - .list(); + ```c# + var objects = await supabase.Storage.From("avatars").List(); ``` - id: using-modifiers title: Using Modifiers @@ -1125,94 +1019,105 @@ functions: Filters work on the row level—they allow you to return rows that only match certain conditions without changing the shape of the rows. Modifiers are everything that don't fit that definition—allowing you to - change the format of the response (e.g., returning a CSV string). - - Modifiers must be specified after filters. Some modifiers only apply for - queries that return rows (e.g., `select()` or `rpc()` on a function that - returns a table response). + change the format of the response (e.g., setting a limit or offset). - id: limit - title: limit() + title: Limit() description: | Limits the result with the specified count. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .limit(1); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Limit(10) + .Get(); ``` - id: with-embedded-resources name: With embedded resources code: | - ```dart - final data = await supabase - .from('countries') - .select('name, cities(name)') - .eq('name', 'United States') - .limit(1, foreignTable: 'cities' ); + ```c# + var result = await supabase.From() + .Select("name, cities(name)") + .Filter("name", Operator.Equals, "United States") + .Limit(10, "cities") + .Get(); ``` - id: order - title: order() + title: Order() description: | Orders the result with the specified column. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .order('id', ascending: false ); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Order("id", Ordering.Descending) + .Get(); ``` - id: with-embedded-resources name: With embedded resources code: | - ```dart - final data = await supabase - .from('countries') - .select('name, cities(name)') - .eq('name', 'United States') - .order('name', foreignTable: 'cities'); + ```c# + var result = await supabase.From() + .Select("name, cities(name)") + .Filter("name", Operator.Equals, "United States") + .Order("cities", "name", Ordering.Descending) + .Get(); ``` - id: range - title: range() + title: Range() description: | Limits the result to rows within the specified range, inclusive. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .range(0,3); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Range(0, 3) + .Get(); + ``` + + - id: offset + title: Offset() + description: | + Specifies the offset of the queried rows to be returned (useful in pagination) + examples: + - id: with-select + name: With `Select()` + isSpotlight: true + code: | + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Offset(25) + .Get(); ``` - id: single - title: single() + title: Single() description: | Retrieves only one row from the result. Result must be one row (e.g. using limit), otherwise this will result in an error. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .single(); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Single(); ``` - id: using-filters @@ -1220,61 +1125,25 @@ functions: description: | Filters allow you to only return rows that match certain conditions. - Filters can be used on `select()`, `update()`, and `delete()` queries. + Filters can be used on `Select()`, `update()`, and `Delete()` queries. If a Database function returns a table response, you can also apply filters. examples: - id: applying-filters name: Applying Filters description: | - Filters must be applied after any of `select()`, `update()`, `upsert()`, - `delete()`, and `rpc()` and before - [modifiers](/docs/reference/dart/using-modifiers). + Filters must be applied after any of `Select()`, `update()`, `upsert()`, + `Delete()`, and `rpc()` and before + [modifiers](/docs/reference/csharp/using-modifiers). code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .eq('name', 'The Shire'); // Correct - - final data = await supabase - .from('cities') - .eq('name', 'The Shire') // Incorrect - .select('name, country_id'); - ``` - - id: chaining-filters - name: Chaining Filters - description: | - Filters must be applied after any of `select()`, `update()`, `upsert()`, - `delete()`, and `rpc()` and before - [modifiers](/docs/reference/dart/using-modifiers). - code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .eq('name', 'The Shire'); // Correct - - final data = await supabase - .from('cities') - .eq('name', 'The Shire') // Incorrect - .select('name, country_id'); - ``` - - id: conditional-chaining - name: Conditional Chaining - description: | - Filters can be built up one step at a time and then executed. For example: - code: | - ```dart - final data = await supabase - .from('users') - .select() - .eq('address->postcode', 90210); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("name", Operator.Equals, "The Shire") + .Single(); ``` - id: filter-by-value-within-json-column name: Filter by values within a JSON column - description: | - Filters can be built up one step at a time and then executed. For example: data: sql: | ```sql @@ -1308,25 +1177,20 @@ functions: } ``` code: | - ```dart - final data = await supabase - .from('users') - .select() - .eq('address->postcode', 90210); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("address->postcode", Operator.Equals, 90210) + .Get(); ``` - id: filter-foreign-tables name: Filter Foreign Tables code: | - ```dart - final data = await supabase - .from('countries') - .select(''' - name, - cities!inner ( - name - ) - ''') - .eq('cities.name', 'Bali'); + ```c# + var results = await supabase.From() + .Select("name, cities!inner(name)") + .Filter("cities.name", Operator.Equals, "Bali") + .Get(); ``` data: sql: | @@ -1369,940 +1233,409 @@ functions: } ``` - id: or - title: or() + title: Or() description: | Finds all rows satisfying at least one of the filters. - notes: | - - `.or()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values. - - ```dart - .or('id.in.(6,7),arraycol.cs.{"a","b"}') // Use Postgres list () and 'in' for in_ filter. Array {} and 'cs' for contains. - .or('id.in.(${mylist.join(',')}),arraycol.cs.{${mylistArray.join(',')}}') // You can insert a Dart list for list or array column. - .or('id.in.(${mylist.join(',')}),rangecol.cs.(${mylistRange.join(',')}]') // You can insert a Dart list for list or range column. - ``` examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .or('id.eq.20,id.eq.30'); + ```c# + var filters = new List + { + new QueryFilter("id", Operator.Equals, 20), + new QueryFilter("id", Operator.Equals, 30) + }; + + var result = await supabase.From() + .Or(filters) + .Get(); ``` - id: use-or-with-and name: Use `or` with `and` code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .or('id.gt.20,and(name.eq.New Zealand,name.eq.France)'); + ```c# + var filters = new List + { + new QueryFilter("id", Operator.Equals, 20), + new QueryFilter("id", Operator.Equals, 30), + new QueryFilter(Operator.And, new List + { + new QueryFilter("name", Operator.Equals, "New Zealand"), + new QueryFilter("name", Operator.Equals, "France") + }) + }; + + var result = await supabase.From() + .Or(filters) + .Get(); ``` - id: not - title: not() + title: Not() description: | Finds all rows which doesn't satisfy the filter. - notes: | - - `.not()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values. - - ```dart - .not('name','eq','Paris') - .not('arraycol','cs','{"a","b"}') // Use Postgres array {} for array column and 'cs' for contains. - .not('rangecol','cs','(1,2]') // Use Postgres range syntax for range column. - .not('id','in','(6,7)') // Use Postgres list () and 'in' for in_ filter. - .not('id','in','(${mylist.join(',')})') // You can insert a Dart list array. - ``` examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .not('name', 'eq', 'Paris'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .not('name', 'eq', 'Paris'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .not('name', 'eq', 'Paris'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities) - .not('name', 'eq', 'Paris'); + ```c# + var result = await supabase.From() + .Select("id, name") + .Not("name", Operator.Equals, "Paris") + .Get(); ``` - id: match - title: match() + title: Match() description: | - Finds all rows whose columns match the specified `query` object. + - Finds a model given a class (useful when hydrating models and correlating with database) + - Finds all rows whose columns match the specified `Dictionary` object. examples: - - id: with-select - name: With `select()` + - id: with-model + name: With Model isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .match({'name': 'Beijing', 'country_id': 156}); + ```c# + var city = new City + { + Id = 224, + Name = "Atlanta" + }; + + var model = supabase.From().Match(city).Single(); ``` - - id: with-update - name: With `update()` + - id: with-dictionary + name: With Dictionary code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .match({'name': 'Beijing', 'country_id': 156}); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .match({'name': 'Beijing', 'country_id': 156}); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .match({'name': 'Beijing', 'country_id': 156}); + ```c# + var opts = new Dictionary + { + {"name","Beijing"}, + {"country_id", "156"} + }; + + var model = supabase.From().Match(opts).Single(); ``` - id: eq - title: eq() + title: Operator.Equals description: | Finds all rows whose value on the stated `column` exactly matches the specified `value`. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .eq('name', 'The shire'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .eq('name', 'San Francisco'); + ```c# + var result = await supabase.From() + .Filter("name", Operator.Equals, "Bali") + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | ```dart - final data = await supabase - .from('cities') - .delete() - .eq('name', 'Mordor'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .eq('name', 'San Francisco'); + await supabase.From() + .Filter("name", Operator.Equals, "Bali") + .Delete(); ``` - id: neq - title: neq() + title: Operator.NotEqual description: | Finds all rows whose value on the stated `column` doesn't match the specified `value`. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .neq('name', 'The shire'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .neq('name', 'San Francisco'); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("name", Operator.NotEqual, "Bali") + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .neq('name', 'Mordor'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .neq('name', 'Lagos'); + ```c# + await supabase.From() + .Filter("name", Operator.NotEqual, "Bali") + .Delete(); ``` - id: gt - title: gt() + title: Operator.GreaterThan description: | Finds all rows whose value on the stated `column` is greater than the specified `value`. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .gt('country_id', 250); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .gt('country_id', 250); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("country_id", Operator.GreaterThan, 250) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .gt('country_id', 250); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .gt('country_id', 250); + ```c# + await supabase.From() + .Filter("country_id", Operator.GreaterThan, 250) + .Delete(); ``` - id: gte - title: gte() + title: Operator.GreaterThanOrEqual description: | Finds all rows whose value on the stated `column` is greater than or equal to the specified `value`. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .gte('country_id', 250); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .gte('country_id', 250); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("country_id", Operator.GreaterThanOrEqual, 250) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .gte('country_id', 250); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .gte('country_id', 250); + ```c# + await supabase.From() + .Filter("country_id", Operator.GreaterThanOrEqual, 250) + .Delete(); ``` - id: lt - title: lt() + title: Operator.LessThan description: | Finds all rows whose value on the stated `column` is less than the specified `value`. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .lt('country_id', 250); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .lt('country_id', 250); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("country_id", Operator.LessThan, 250) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .lt('country_id', 250); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .lt('country_id', 250); + ```c# + await supabase.From() + .Filter("country_id", Operator.LessThan, 250) + .Delete(); ``` - id: lte - title: lte() + title: Operator.LessThanOrEqual description: | Finds all rows whose value on the stated `column` is less than or equal to the specified `value`. $ref: '@supabase/postgrest-js.PostgrestFilterBuilder.lte' examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .lte('country_id', 250); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .lte('country_id', 250); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("country_id", Operator.LessThanOrEqual, 250) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .lte('country_id', 250); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .lte('country_id', 250); + ```c# + await supabase.From() + .Filter("country_id", Operator.LessThanOrEqual, 250) + .Delete(); ``` - id: like - title: like() + title: Operator.Like description: | Finds all rows whose value in the stated `column` matches the supplied `pattern` (case sensitive). - $ref: '@supabase/postgrest-js.PostgrestFilterBuilder.lte' examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .like('name', '%la%'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .like('name', '%la%'); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("name", Operator.Like, "%la%") + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .like('name', '%la%'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .like('name', '%la%'); + ```c# + await supabase.From() + .Filter("name", Operator.Like, "%la%") + .Delete(); ``` - id: ilike - title: ilike() + title: Operator.ILike description: | Finds all rows whose value in the stated `column` matches the supplied `pattern` (case insensitive). examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .ilike('name', '%la%'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .ilike('name', '%la%'); + ```c# + await supabase.From() + .Filter("name", Operator.ILike, "%la%") + .Delete(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .ilike('name', '%la%'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .ilike('name', '%la%'); + ```c# + await supabase.From() + .Filter("name", Operator.ILike, "%la%") + .Delete(); ``` - id: is - title: is_() + title: Operator.Is description: | A check for exact equality (null, true, false), finds all rows whose value on the stated `column` exactly match the specified `value`. - - `is_` and `in_` filter methods are suffixed with `_` to avoid collisions with reserved keywords. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .is_('name', null); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .is_('name', null); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("name", Operator.Is, null) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .is_('name', null); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .is_('name', null); + ```c# + await supabase.From() + .Filter("name", Operator.Is, null) + .Delete(); ``` - id: in - title: in_() + title: Operator.In description: | Finds all rows whose value on the stated `column` is found on the specified `values`. - - `is_` and `in_` filter methods are suffixed with `_` to avoid collisions with reserved keywords. examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .in_('name', ['Rio de Janeiro', 'San Francisco']); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .in_('name', ['Rio de Janeiro', 'San Francisco']); + ```c# + var result = await supabase.From() + .Select("name, country_id") + .Filter("name", Operator.In, new List { "Rio de Janiero", "San Francisco" }) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .in_('name', ['Rio de Janeiro', 'San Francisco']); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .in_('name', ['Rio de Janeiro', 'San Francisco']); + ```c# + await supabase.From() + .Filter("name", Operator.In, new List { "Rio de Janiero", "San Francisco" }) + .Delete(); ``` - id: contains - title: contains() + title: Operator.Contains examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, main_exports') - .contains('main_exports', ['oil']); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .contains('main_exports', ['oil']); + ```c# + var result = await supabase.From() + .Select("name, country_id, main_exports") + .Filter("main_exports", Operator.Contains, new List { "oil", "fish" }) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .contains('main_exports', ['oil']); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .contains('main_exports', ['oil']); + ```c# + await supabase.From() + .Filter("main_exports", Operator.Contains, new List { "oil", "fish" }) + .Delete(); ``` - id: contained-by - title: containedBy() + title: Operator.ContainedIn examples: - id: with-select - name: With `select()` + name: With `Select()` isSpotlight: true code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, main_exports') - .containedBy('main_exports', ['cars', 'food', 'machine']); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .containedBy('main_exports', ['orks', 'surveillance', 'evil']); + ```c# + var result = await supabase.From() + .Select("name, country_id, main_exports") + .Filter("main_exports", Operator.ContainedIn, new List { "oil", "fish" }) + .Get(); ``` - id: with-delete - name: With `delete()` + name: With `Delete()` code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .containedBy('main_exports', ['cars', 'food', 'machine']); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .containedBy('main_exports', ['cars', 'food', 'machine']); - ``` - - - id: range-lt - title: rangeLt() - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, population_range_millions') - .rangeLt('population_range_millions', '[150, 250]'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .rangeLt('population_range_millions', '[150, 250]'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .rangeLt('population_range_millions', '[150, 250]'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .rangeLt('population_range_millions', '[150, 250]'); - ``` - - - id: range-gt - title: rangeGt() - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, population_range_millions') - .rangeGt('population_range_millions', '[150, 250]'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .rangeGt('population_range_millions', '[150, 250]'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .rangeGt('population_range_millions', '[150, 250]'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .rangeGt('population_range_millions', '[150, 250]'); - ``` - - - id: range-gte - title: rangeGte() - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, population_range_millions') - .rangeGte('population_range_millions', '[150, 250]'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .rangeGte('population_range_millions', '[150, 250]'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .rangeGte('population_range_millions', '[150, 250]'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .rangeGte('population_range_millions', '[150, 250]'); - ``` - - - id: range-lte - title: rangeLte() - $ref: '@supabase/postgrest-js.PostgrestFilterBuilder.rangeLte' - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, population_range_millions') - .rangeLte('population_range_millions', '[150, 250]'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .rangeLte('population_range_millions', '[150, 250]'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .rangeLte('population_range_millions', '[150, 250]'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .rangeLte('population_range_millions', [150, 250]); - ``` - - - id: range-adjacent - title: rangeAdjacent() - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, population_range_millions') - .rangeAdjacent('population_range_millions', '[70, 185]'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .rangeAdjacent('population_range_millions', '[70, 185]'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .rangeAdjacent('population_range_millions', '[70, 185]'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .rangeAdjacent('population_range_millions', '[70, 185]'); - ``` - - - id: overlaps - title: overlaps() - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('countries') - .select('name, id, main_exports') - .overlaps('main_exports', ['computers', 'minerals']); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('countries') - .update({ 'name': 'Mordor' }) - .overlaps('main_exports', ['computers', 'minerals']); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('countries') - .delete() - .overlaps('main_exports', ['computers', 'minerals']); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_countries') - .overlaps('main_exports', ['computers', 'minerals']); + ```c# + await supabase.From() + .Filter("main_exports", Operator.ContainedIn, new List { "oil", "fish" }) + .Delete(); ``` - id: text-search - title: textSearch() + title: Operator.[FTS,PLFTS,PHFTS,WFTS] (Full Text Search) description: | Finds all rows whose tsvector value on the stated `column` matches to_tsquery(query). examples: - id: text-search name: Text search code: | - ```dart - final data = await supabase - .from('quotes') - .select('catchphrase') - .textSearch('catchphrase', "'fat' & 'cat'", - config: 'english' - ); + ```c# + var result = await supabase.From() + .Select("catchphrase") + .Filter("catchphrase", Operator.FTS, new FullTextSearchConfig("'fat' & 'cat", "english")) + .Get(); ``` - id: basic-normalization name: Basic normalization description: Uses PostgreSQL's `plainto_tsquery` function. code: | - ```dart - final data = await supabase - .from('quotes') - .select('catchphrase') - .textSearch('catchphrase', "'fat' & 'cat'", - type: TextSearchType.plain, - config: 'english' - ); + ```c# + var result = await supabase.From() + .Select("catchphrase") + .Filter("catchphrase", Operator.PLFTS, new FullTextSearchConfig("'fat' & 'cat", "english")) + .Get(); ``` - id: full-normalization name: Full normalization description: Uses PostgreSQL's `phraseto_tsquery` function. code: | - ```dart - final data = await supabase - .from('quotes') - .select('catchphrase') - .textSearch('catchphrase', "'fat' & 'cat'", - type: TextSearchType.phrase, - config: 'english' - ); + ```c# + var result = await supabase.From() + .Select("catchphrase") + .Filter("catchphrase", Operator.PHFTS, new FullTextSearchConfig("'fat' & 'cat", "english")) + .Get(); ``` - id: web-search name: Websearch @@ -2317,72 +1650,9 @@ functions: - `-`: a dash will be converted to the ! operator. code: | - ```dart - final data = await supabase - .from('quotes') - .select('catchphrase') - .textSearch('catchphrase', "'fat or cat'", - type: TextSearchType.websearch, - config: 'english' - ); - ``` - - - id: filter - title: filter() - description: | - Finds all rows whose `column` satisfies the filter. - notes: | - - `.filter()` expects you to use the raw [PostgREST syntax](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows) for the filter names and values, so it should only be used as an escape hatch in case other filters don't work. - ```dart - .filter('arraycol','cs','{"a","b"}') // Use Postgres array {} and 'cs' for contains. - .filter('rangecol','cs','(1,2]') // Use Postgres range syntax for range column. - .filter('id','in','(6,7)') // Use Postgres list () and 'in' for in_ filter. - .filter('id','cs','{${mylist.join(',')}}') // You can insert a Dart array list. - ``` - examples: - - id: with-select - name: With `select()` - isSpotlight: true - code: | - ```dart - final data = await supabase - .from('cities') - .select('name, country_id') - .filter('name', 'in', '("Paris","Tokyo")'); - ``` - - id: with-update - name: With `update()` - code: | - ```dart - final data = await supabase - .from('cities') - .update({ 'name': 'Mordor' }) - .filter('name', 'in', '("Paris","Tokyo")'); - ``` - - id: with-delete - name: With `delete()` - code: | - ```dart - final data = await supabase - .from('cities') - .delete() - .filter('name', 'in', '("Paris","Tokyo")'); - ``` - - id: with-rpc - name: With `rpc()` - code: | - ```dart - // Only valid if the Stored Procedure returns a table type. - final data = await supabase - .rpc('echo_all_cities') - .filter('name', 'in', '("Paris","Tokyo")'); - ``` - - id: filter-embedded-resources - name: Filter embedded resources - code: | - ```dart - final data = await supabase - .from('cities') - .select('name, countries ( name )') - .filter('countries.name', 'in', '("France","Japan")'); + ```c# + var result = await supabase.From() + .Select("catchphrase") + .Filter("catchphrase", Operator.WFTS, new FullTextSearchConfig("'fat' & 'cat", "english")) + .Get(); ``` From 7113c3e6d5ac7a4bc4c750c69b6a982b6e983d94 Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Mon, 16 Jan 2023 11:22:24 -0600 Subject: [PATCH 03/30] Update code blocks to support c# and update some of the Postgrest DB examples --- .../reference/RefFunctionSection.tsx | 2 ++ spec/supabase_csharp_v0.yml | 23 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/apps/docs/components/reference/RefFunctionSection.tsx b/apps/docs/components/reference/RefFunctionSection.tsx index 59e0c0a6abd..296e19ef9c7 100644 --- a/apps/docs/components/reference/RefFunctionSection.tsx +++ b/apps/docs/components/reference/RefFunctionSection.tsx @@ -122,6 +122,8 @@ const RefFunctionSection: React.FC = (props) => { ? 'ts' : example?.code?.startsWith('```dart') ? 'dart' + : example?.code?.startsWith('```c#') + ? 'c#' : 'js' // ` // import { createClient } from '@supabase/supabase-js' diff --git a/spec/supabase_csharp_v0.yml b/spec/supabase_csharp_v0.yml index 6a881cef0b9..7ae300882d5 100644 --- a/spec/supabase_csharp_v0.yml +++ b/spec/supabase_csharp_v0.yml @@ -304,7 +304,7 @@ functions: ```c# var result = await supabase .From() - .Select("name, createdAt") + .Select(x => new object[] {x.Name, x.CreatedAt}) .Get(); ``` - id: query-foreign-tables @@ -339,7 +339,7 @@ functions: ```c# var count = await supabase .From() - .Select("name") + .Select(x => new object[] { x.Name }) .Count(CountType.Exact); ``` - id: querying-json-data @@ -431,14 +431,24 @@ functions: notes: | - `Update()` is typically called using a model as an argument or from a hydrated model. examples: - - id: updating-your-data + - id: updating-your-data-with-filter name: Update your data isSpotlight: true + code: | + ```c# + var update = await supabase + .From() + .Where(x => x.Name == "Auckland") + .Set(x => new KeyValuePair(x.Name, "Middle Earth")) + .Update(); + ``` + - id: updating-your-data + name: Update your data code: | ```c# var model = await supabase .From() - .Filter("name", Operator.Equals, "Auckland") + .Where(x => x.Name == "Auckland") .Single(); model.Name = "Middle Earth"; @@ -484,7 +494,8 @@ functions: await supabase .From() - .Upsert(model, new QueryOptions { OnConflict = "name" }); + .OnConflict(x => x.Name) + .Upsert(model); ``` - id: return-the-exact-number-of-rows name: Return the exact number of rows @@ -517,7 +528,7 @@ functions: ```c# await supabase .From() - .Filter("id", Operator.Equals, 342) + .Where(x => x.Id == 342) .Delete(); ``` From 3dc3e1e4f0832d0253669f676f8a9b5e08a59eb2 Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Mon, 16 Jan 2023 20:42:05 -0600 Subject: [PATCH 04/30] Fix unmerged change --- spec/common-client-libs-sections.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec/common-client-libs-sections.json b/spec/common-client-libs-sections.json index a33b664964a..a783a914116 100644 --- a/spec/common-client-libs-sections.json +++ b/spec/common-client-libs-sections.json @@ -827,12 +827,7 @@ "title": "Retrieve public URL", "slug": "storage-from-getpublicurl", "product": "storage", -<<<<<<< HEAD - "type": "function", - "libs": ["js", "js_v1", "dart", "dart_v0", "csharp"] -======= "type": "function" ->>>>>>> master } ] }, From b6e2140ea7b4986d15f3f9c7f0c31e54c0b6ca5f Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Mon, 16 Jan 2023 21:06:35 -0600 Subject: [PATCH 05/30] Fit new docs structure expected on current state of `master` --- .../reference/RefFunctionSection.tsx | 5 +- .../docs/reference/csharp/generated/.gitkeep | 0 .../docs/reference/csharp/initializing.mdx | 67 +++++++++++++++++++ .../docs/docs/reference/csharp/installing.mdx | 33 +++++++++ .../docs/reference/csharp/introduction.mdx | 20 ++++++ .../reference/csharp/v0/release-notes.mdx | 6 ++ apps/docs/package.json | 6 +- .../docs/pages/reference/csharp/[...slug].tsx | 6 +- .../reference/csharp/crawlers/[...slug].tsx | 7 +- .../pages/reference/csharp/v0/[...slug].tsx | 6 +- .../csharp/v0/crawlers/[...slug].tsx | 5 +- package-lock.json | 2 +- 12 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 apps/docs/docs/reference/csharp/generated/.gitkeep create mode 100644 apps/docs/docs/reference/csharp/initializing.mdx create mode 100644 apps/docs/docs/reference/csharp/installing.mdx create mode 100644 apps/docs/docs/reference/csharp/introduction.mdx create mode 100644 apps/docs/docs/reference/csharp/v0/release-notes.mdx diff --git a/apps/docs/components/reference/RefFunctionSection.tsx b/apps/docs/components/reference/RefFunctionSection.tsx index 296e19ef9c7..8b228a6bfa6 100644 --- a/apps/docs/components/reference/RefFunctionSection.tsx +++ b/apps/docs/components/reference/RefFunctionSection.tsx @@ -123,7 +123,7 @@ const RefFunctionSection: React.FC = (props) => { : example?.code?.startsWith('```dart') ? 'dart' : example?.code?.startsWith('```c#') - ? 'c#' + ? 'csharp' : 'js' // ` // import { createClient } from '@supabase/supabase-js' @@ -156,7 +156,8 @@ const RefFunctionSection: React.FC = (props) => { .replace(/```/g, '') .replace('js', '') .replace('ts', '') - .replace('dart', ''))} + .replace('dart', '') + .replace('c#', ''))} {((tables && tables.length > 0) || sql) && ( diff --git a/apps/docs/docs/reference/csharp/generated/.gitkeep b/apps/docs/docs/reference/csharp/generated/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/docs/docs/reference/csharp/initializing.mdx b/apps/docs/docs/reference/csharp/initializing.mdx new file mode 100644 index 00000000000..ca29a5605a3 --- /dev/null +++ b/apps/docs/docs/reference/csharp/initializing.mdx @@ -0,0 +1,67 @@ +--- +id: initializing +title: 'Initializing' +slug: initializing +custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supabase.yml +--- + +### Initializing a new Client + + + + +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. + + + + + + + + + ```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)); + } + ``` + + + + + + diff --git a/apps/docs/docs/reference/csharp/installing.mdx b/apps/docs/docs/reference/csharp/installing.mdx new file mode 100644 index 00000000000..e274af8e280 --- /dev/null +++ b/apps/docs/docs/reference/csharp/installing.mdx @@ -0,0 +1,33 @@ +--- +id: installing +title: 'Installing & Initialization' +slug: installing +custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supabase.yml +--- + +### Install from NuGet + + + + + You can install Supabase package from [nuget.org](https://www.nuget.org/packages/supabase-csharp/) + + + + + + + + + ```sh Terminal + dotnet add package supabase-csharp + ``` + + + + + + diff --git a/apps/docs/docs/reference/csharp/introduction.mdx b/apps/docs/docs/reference/csharp/introduction.mdx new file mode 100644 index 00000000000..6c699314937 --- /dev/null +++ b/apps/docs/docs/reference/csharp/introduction.mdx @@ -0,0 +1,20 @@ +--- +id: introduction +title: Introduction +hideTitle: true +--- + +
+ +
+

C# Client Library

+

supabase-csharp

+
+
+ +
+ This reference documents every object and method available in Supabase's C# + library, [supabase-csharp](https://www.nuget.org/packages/supabase-csharp). You can + use supabase-csharp to interact with your Postgres database, listen to database changes, invoke + Deno Edge Functions, build login and user management functionality, and manage large files. +
diff --git a/apps/docs/docs/reference/csharp/v0/release-notes.mdx b/apps/docs/docs/reference/csharp/v0/release-notes.mdx new file mode 100644 index 00000000000..2ecb0ef3990 --- /dev/null +++ b/apps/docs/docs/reference/csharp/v0/release-notes.mdx @@ -0,0 +1,6 @@ +--- +id: release-notes +title: Release Notes +--- + +## dart v0 this is the release notes file. diff --git a/apps/docs/package.json b/apps/docs/package.json index 009c9759c91..c7a92350da2 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -25,8 +25,8 @@ "gen:supabase-dart:v0:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_dart_v0.yml --output ./docs/reference/dart/v0/generated", "gen:supabase-dart:v1": "npm-run-all gen:supabase-dart:v1:ref", "gen:supabase-dart:v1:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_dart_v1.yml --output ./docs/reference/dart/generated", - "gen:supabase-csharp:v0": "npm-run-all gen:supabase-dart:v1:ref", - "gen:supabase-csharp:v0:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_csharp_v1.yml --output ./docs/reference/csharp/generated", + "gen:supabase-csharp:v0": "npm-run-all gen:supabase-csharp:v0:ref", + "gen:supabase-csharp:v0:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_csharp_v0.yml --output ./docs/reference/csharp/generated", "gen:supabase-js:v1": "npm-run-all gen:supabase-js:v1:ref", "gen:supabase-js:v1:ref": "ts-node ./generator/index.ts gen --type legacy --input ../../spec/supabase_js_v1.yml --output ./docs/reference/javascript/v1/generated", "gen:supabase-js:v2": "npm-run-all gen:supabase-js:v2:ref", @@ -93,4 +93,4 @@ "tsconfig": "*", "typescript": "^4.5.3" } -} +} \ No newline at end of file diff --git a/apps/docs/pages/reference/csharp/[...slug].tsx b/apps/docs/pages/reference/csharp/[...slug].tsx index 04e731b5aeb..f3e510ece23 100644 --- a/apps/docs/pages/reference/csharp/[...slug].tsx +++ b/apps/docs/pages/reference/csharp/[...slug].tsx @@ -9,11 +9,11 @@ import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps' const sections = flattenSections(clientLibsCommonSections) export default function JSReference(props) { - return + return } -export async function getStaticProps({ params }: { params: { slug: string[] } }) { - return handleRefStaticProps(sections, params, '/csharp', '/csharp') +export async function getStaticProps() { + return handleRefStaticProps(sections, '/csharp') } export function getStaticPaths() { diff --git a/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx b/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx index c12f3cabbf2..89d58eb1478 100644 --- a/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx +++ b/apps/docs/pages/reference/csharp/crawlers/[...slug].tsx @@ -1,7 +1,7 @@ import clientLibsCommonSections from '~/../../spec/common-client-libs-sections.json' import typeSpec from '~/../../spec/enrichments/tsdoc_v2/combined.json' // @ts-expect-error -import spec from '~/../../spec/supabase_dart_v1.yml' assert { type: 'yml' } +import spec from '~/../../spec/supabase_csharp_v0.yml' assert { type: 'yml' } import RefSectionHandler from '~/components/reference/RefSectionHandler' import { flattenSections } from '~/lib/helpers' import handleRefGetStaticPaths from '~/lib/mdx/handleRefStaticPaths' @@ -29,13 +29,14 @@ export default function JSReference(props) { spec={spec} typeSpec={typeSpec} pageProps={props} + type="client-lib" /> ) } -export async function getStaticProps({ params }: { params: { slug: string[] } }) { - return handleRefStaticProps(sections, params, '/dart', '/dart') +export async function getStaticProps() { + return handleRefStaticProps(sections, '/csharp') } export function getStaticPaths() { diff --git a/apps/docs/pages/reference/csharp/v0/[...slug].tsx b/apps/docs/pages/reference/csharp/v0/[...slug].tsx index a76c3f386be..41b28c0a1ef 100644 --- a/apps/docs/pages/reference/csharp/v0/[...slug].tsx +++ b/apps/docs/pages/reference/csharp/v0/[...slug].tsx @@ -9,11 +9,11 @@ import handleRefStaticProps from '~/lib/mdx/handleRefStaticProps' const sections = flattenSections(clientLibsCommonSections) export default function JSReference(props) { - return + return } -export async function getStaticProps({ params }: { params: { slug: string[] } }) { - return handleRefStaticProps(sections, params, '/csharp/v0', '/csharp/v0') +export async function getStaticProps() { + return handleRefStaticProps(sections, '/csharp/v0') } export function getStaticPaths() { diff --git a/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx b/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx index 4c78342f556..059df1c75b1 100644 --- a/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx +++ b/apps/docs/pages/reference/csharp/v0/crawlers/[...slug].tsx @@ -28,13 +28,14 @@ export default function JSReference(props) { spec={spec} typeSpec={typeSpec} pageProps={props} + type="client-lib" /> ) } -export async function getStaticProps({ params }: { params: { slug: string[] } }) { - return handleRefStaticProps(sections, params, '/csharp/v0', '/csharp/v0') +export async function getStaticProps() { + return handleRefStaticProps(sections, '/csharp/v0') } export function getStaticPaths() { diff --git a/package-lock.json b/package-lock.json index 02ea0980a38..0feb28269d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49498,7 +49498,7 @@ "@types/react": "17.0.39", "algoliasearch": "^4.14.2", "babel": "^6.23.0", - "clsx": "*", + "clsx": "^1.2.1", "common": "*", "config": "*", "dotenv": "^16.0.3", From 9baa560366bd5fbae8fb4a86eeb1c75446c4f1d5 Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Mon, 16 Jan 2023 21:13:26 -0600 Subject: [PATCH 06/30] Update release notes for v0.7.0 --- apps/docs/docs/ref/csharp/release-notes.mdx | 169 +++++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/apps/docs/docs/ref/csharp/release-notes.mdx b/apps/docs/docs/ref/csharp/release-notes.mdx index b5e0e218918..2f30b2cbed8 100644 --- a/apps/docs/docs/ref/csharp/release-notes.mdx +++ b/apps/docs/docs/ref/csharp/release-notes.mdx @@ -3,4 +3,171 @@ id: release-notes title: Release Notes --- -## dart this is the release notes file. +## 0.7.0 - 2023-01-16 + +- Update dependency: postgrest-csharp@3.1.0 + - [Minor] Breaking API Change: `PrimaryKey` attribute defaults to `shouldInsert: false` as most uses will have the Database generate the primary key. + - Merged [#60](https://github.com/supabase-community/postgrest-csharp/pull/60) which Added linq support for `Select`, `Where`, `OnConflict`, `Columns`, `Order`, `Update`, `Set`, and `Delete` + +## 0.6.2 - 2022-11-22 + +- Update dependency: postgrest-csharp@3.0.4 + - `GetHeaders` is now passed to `ModeledResponse` and `BaseModel` so that the default `Update` and `Delete` methods use the latest credentials + - `GetHeaders` is used in `Rpc` calls (re: [#39](https://github.com/supabase-community/supabase-csharp/issues/39)) + +## 0.6.1 - 2022-11-12 + +- [Hotfix] `GetHeaders` was not passing properly to `SupabaseTable` and `Gotrue.Api` + +## 0.6.0 - 2022-11-12 + +[BREAKING CHANGES] + +- `Client` is no longer a singleton, singleton interactions (if desired) are left to the developer to implement. +- `Client` supports injection of dependent clients after initialization via property: + - `Auth` + - `Functions` + - `Realtime` + - `Postgrest` + - `Storage` +- `SupabaseModel` contains no logic but remains for backwards compatibility. (Marked `Obsolete`) +- `ClientOptions.ShouldInitializeRealtime` was removed (no longer auto initialized) +- `ClientOptions` now references an `ISupabaseSessionHandler` which specifies expected functionality for session persistence on Gotrue (replaces `ClientOptions.SessionPersistor`, `ClientOptions.SessionRetriever`, and `ClientOptions.SessionDestroyer`). +- `supabase-csharp` and all child libraries now have support `nullity` + +Other Changes: + +- Update dependency: functions-csharp@1.2.1 +- Update dependency: gotrue-csharp@3.0.2 +- Update dependency: postgrest-csharp@3.0.2 +- Update dependency: realtime-csharp@4.0.1 +- Update dependency: supabase-storage-csharp@1.2.3 +- Update dependency: supabase-core@0.0.2 + +Big thank you to [@veleek](https://github.com/veleek) for his insight into these changes. + +Re: [#35](https://github.com/supabase-community/supabase-csharp/issues/35), [#34](https://github.com/supabase-community/supabase-csharp/issues/34), [#23](https://github.com/supabase-community/supabase-csharp/issues/23), [#36](https://github.com/supabase-community/supabase-csharp/pull/36) + +## 0.5.3 - 2022-10-11 + +- Update dependency: postgrest-csharp@2.1.0 + - [Minor] Breaking API change: Remove `BaseModel.PrimaryKeyValue` and `BaseModel.PrimaryKeyColumn` in favor of a `PrimaryKey` dictionary with support for composite keys. + - Re: [#48](https://github.com/supabase-community/postgrest-csharp/issues/48) - Add support for derived models on `ReferenceAttribute` + - Re: [#49](https://github.com/supabase-community/postgrest-csharp/issues/49) - Added `Match(T model)` + +## 0.5.2 - 2022-9-13 + +- Update dependency: postgrest-csharp@2.0.12 + - Merged [#47](https://github.com/supabase-community/postgrest-csharp/pull/49) which added cancellation token support to `Table` methods. Thanks [@devpikachu](https://github.com/devpikachu)! + +## 0.5.1 - 2022-8-1 + +- Update dependency: postgrest-csharp@2.0.11 +- Update dependency: supabase-storage-csharp@1.1.1 + +## 0.5.0 - 2022-7-17 + +- Update dependency: postgrest-csharp@2.0.9 +- Update dependency: realtime-csharp@3.0.1 +- Update dependency: supabase-storage-csharp@1.1.0 + - API Change [Breaking/Minor] Library no longer uses `WebClient` and instead leverages `HttpClient`. Progress events on `Upload` and `Download` are now handled with `EventHandler` instead of `WebClient` EventHandlers. + +## 0.4.4 - 2022-5-24 + +- Update dependency: gotrue-csharp@2.4.5 +- Update dependency: postgrest-csharp@2.0.8 + +## 0.4.3 - 2022-5-13 + +- Update dependency: gotrue-csharp@2.4.4 + +## 0.4.2 - 2022-4-30 + +- Update dependency: gotrue-csharp@2.4.3 + +## 0.4.1 - 2022-4-23 + +- Update dependency: gotrue-csharp@2.4.2 + +## 0.4.0 - 2022-4-12 + +- Add support for functions-csharp@1.0.1, giving access to invoking Supabase's edge functions. +- Update dependency: gotrue-csharp@2.4.1 + +## 0.3.5 - 2022-4-11 + +- Update dependency: postgres-csharp@2.0.7 + +## 0.3.4 - 2022-03-28 + +- Update dependency: gotrue-csharp@2.4.0 + +## 0.3.3 - 2022-02-27 + +- Update dependency: gotrue-csharp@2.3.6 +- Update dependency: supabase-storage-csharp@1.0.2 + +## 0.3.2 - 2022-02-18 + +- Update dependency: realtime-csharp@3.0.0 + - Exchange existing websocket client: [WebSocketSharp](https://github.com/sta/websocket-sharp) for [Marfusios/websocket-client](https://github.com/Marfusios/websocket-client) which adds support for Blazor WASM apps. + Ref: [#14](https://github.com/supabase-community/realtime-csharp/pull/14) + +## 0.3.1 - 2022-01-20 + +- Update dependency: gotrue-csharp@2.3.5 + - [#23](https://github.com/supabase-community/gotrue-csharp/pull/23) Added `redirect_url` option for MagicLink sign in (Thanks [@MisterJimson](https://github.com/MisterJimson)) + - [#21](https://github.com/supabase-community/gotrue-csharp/pull/21) Added SignOut method to Stateless Client (Thanks [@fplaras](https://github.com/fplaras)) + +## 0.3.0 - 2021-12-30 + +- Update dependency: postgrest-csharp@2.0.6 + - Add support for `NullValueHandling` to be specified on a `Column` Attribute and for it to be honored on Inserts and Updates. Defaults to: `NullValueHandling.Include`. + - Implements [#38](https://github.com/supabase-community/postgrest-csharp/issues/38) +- Update dependency: realtime-csharp@2.0.8 + - Implement Upstream Realtime RLS Error Broadcast Handler + - Implements [#12](https://github.com/supabase-community/realtime-csharp/issues/12) + - `SocketResponse` now exposes a method: `OldModel`, that hydrates the `OldRecord` property into a model. + +## 0.2.12 - 2021-12-29 + +- Update dependency: gotrue-csharp@2.3.3 + - `SignUp` will return a `Session` with a _populated `User` object_ on an unconfirmed signup. + - Fixes [#19](https://github.com/supabase-community/gotrue-csharp/issues/19) + - Developers who were using a `null` check on `Session.User` will need to adjust accordingly. +- Update dependency: postgrest-csharp@2.0.5 + - Fix for [#37](https://github.com/supabase-community/postgrest-csharp/issues/37) - Return Type `minimal` would fail to resolve because of incorrect `Accept` headers. Added header and test to verify for future. + - Fix for [#36](https://github.com/supabase-community/postgrest-csharp/issues/36) - Inserting/Upserting bulk records would fail while doing an unnecessary generic coercion. + +## 0.2.11 - 2021-12-24 + +- Update dependency: gotrue-csharp@2.3.2 (changes CreateUser parameters to conform to `AdminUserAttributes`) + - See [#15](https://github.com/supabase-community/supabase-csharp/issues/15) + - See [#16](https://github.com/supabase-community/supabase-csharp/issues/16) +- Update dependency: realtime-csharp@2.0.7 + - See [#13](https://github.com/supabase-community/supabase-csharp/issues/13) + +## 0.2.10 - 2021-12-23 + +- Update dependency: gotrue-csharp@2.3.0 (adds metadata support for user signup, see [#14](https://github.com/supabase/community/issues/14)) + +## 0.2.9 - 2021-12-9 + +- Separate Storage client from Supabase repo and into `storage-csharp`, `supabase-csharp` now references new repo. + +## 0.2.8 - 2021-12-4 + +- Update gotrue-csharp to 2.2.4 + - Adds support for `ListUsers` (paginate, sort, filter), `GetUserById`, `CreateUser`, and `UpdateById` + +## 0.2.7 - 2021-12-2 + +- Update gotrue-csharp to 2.2.3 + - Adds support for sending password resets to users. + +## 0.2.6 - 2021-11-29 + +- Support for [#12](https://github.com/supabase-community/supabase-csharp/issues/12) +- Update realtime-csharp to 2.0.6 +- Update gotrue-csharp to 2.2.2 +- Add `StatelessClient` re:[#7](https://github.com/supabase-community/supabase-csharp/issues/7) From ad4f0507b46322e1d39f068138e21c04ee6c781d Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Fri, 27 Jan 2023 08:54:26 -0600 Subject: [PATCH 07/30] Fix capitalization --- spec/supabase_csharp_v0.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/supabase_csharp_v0.yml b/spec/supabase_csharp_v0.yml index 7ae300882d5..4291bdfbb95 100644 --- a/spec/supabase_csharp_v0.yml +++ b/spec/supabase_csharp_v0.yml @@ -169,7 +169,7 @@ functions: description: | Updates user data, if there is a logged in user. notes: | - - In order to use the `updateUser()` method, the user needs to be signed in first. + - In order to use the `UpdateUser()` method, the user needs to be signed in first. - By Default, email updates sends a confirmation link to both the user's current and new email. To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://app.supabase.com/project/_/auth/settings). examples: @@ -1136,14 +1136,14 @@ functions: description: | Filters allow you to only return rows that match certain conditions. - Filters can be used on `Select()`, `update()`, and `Delete()` queries. + Filters can be used on `Select()`, `Update()`, and `Delete()` queries. If a Database function returns a table response, you can also apply filters. examples: - id: applying-filters name: Applying Filters description: | - Filters must be applied after any of `Select()`, `update()`, `upsert()`, + Filters must be applied after any of `Select()`, `Update()`, `Upsert()`, `Delete()`, and `rpc()` and before [modifiers](/docs/reference/csharp/using-modifiers). code: | From d9dc8304cc476542e40b6ca50840a168907c0d6a Mon Sep 17 00:00:00 2001 From: Joseph Schultz Date: Fri, 27 Jan 2023 08:55:39 -0600 Subject: [PATCH 08/30] Add light icon for c# --- apps/docs/public/img/icons/menu/reference-csharp-light.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/docs/public/img/icons/menu/reference-csharp-light.svg diff --git a/apps/docs/public/img/icons/menu/reference-csharp-light.svg b/apps/docs/public/img/icons/menu/reference-csharp-light.svg new file mode 100644 index 00000000000..782f87bcc40 --- /dev/null +++ b/apps/docs/public/img/icons/menu/reference-csharp-light.svg @@ -0,0 +1 @@ + \ No newline at end of file From 78ae454b4d764997d8aab085a46ad8093466702d Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Fri, 27 Jan 2023 15:13:19 -0330 Subject: [PATCH 09/30] Small SEO nudges --- apps/docs/layouts/DefaultLayout.tsx | 2 +- apps/docs/layouts/guides/index.tsx | 10 ++++++++-- apps/docs/pages/guides/auth/auth-helpers.mdx | 2 +- apps/docs/pages/guides/database/extensions.mdx | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/docs/layouts/DefaultLayout.tsx b/apps/docs/layouts/DefaultLayout.tsx index db490d4c9e7..3e610896b8b 100644 --- a/apps/docs/layouts/DefaultLayout.tsx +++ b/apps/docs/layouts/DefaultLayout.tsx @@ -19,7 +19,7 @@ const Layout: FC = (props: Props) => { return ( <> - {props.meta?.title} | Supabase + {props.meta?.title} | Supabase Docs diff --git a/apps/docs/layouts/guides/index.tsx b/apps/docs/layouts/guides/index.tsx index 07ec7929195..35e41f3c310 100644 --- a/apps/docs/layouts/guides/index.tsx +++ b/apps/docs/layouts/guides/index.tsx @@ -65,12 +65,19 @@ const Layout: FC = (props) => { return ( <> = (props) => { ], }} /> -
Date: Fri, 27 Jan 2023 16:07:06 -0330 Subject: [PATCH 10/30] Fix missing crawler pages, missing h1 tags --- apps/docs/pages/reference/dart/crawlers/[...slug].tsx | 2 +- apps/docs/pages/reference/dart/v0/crawlers/[...slug].tsx | 2 +- .../pages/reference/javascript/crawlers/[...slug].tsx | 2 +- .../pages/reference/javascript/v1/crawlers/[...slug].tsx | 2 +- apps/www/pages/blog.tsx | 1 + apps/www/pages/blog/tags/[tag].tsx | 8 ++++---- apps/www/pages/careers/index.tsx | 8 +++++--- apps/www/public/planetpg-paul_copplestone-rss.xml | 9 ++++++++- studio/pages/project/_/[[...routeSlug]].tsx | 2 +- studio/pages/support/new.tsx | 2 +- 10 files changed, 24 insertions(+), 14 deletions(-) diff --git a/apps/docs/pages/reference/dart/crawlers/[...slug].tsx b/apps/docs/pages/reference/dart/crawlers/[...slug].tsx index 036933a1682..84497018cdb 100644 --- a/apps/docs/pages/reference/dart/crawlers/[...slug].tsx +++ b/apps/docs/pages/reference/dart/crawlers/[...slug].tsx @@ -14,7 +14,7 @@ const sections = flattenSections(clientLibsCommonSections) export default function JSReference(props) { const router = useRouter() const slug = router.query.slug[0] - const filteredSection = sections.filter((section) => section.id === slug) + const filteredSection = sections.filter((section) => section.slug === slug) const pageTitle = filteredSection[0]?.title ? `${filteredSection[0]?.title} | Supabase` diff --git a/apps/docs/pages/reference/dart/v0/crawlers/[...slug].tsx b/apps/docs/pages/reference/dart/v0/crawlers/[...slug].tsx index 8539659431d..997b56deec2 100644 --- a/apps/docs/pages/reference/dart/v0/crawlers/[...slug].tsx +++ b/apps/docs/pages/reference/dart/v0/crawlers/[...slug].tsx @@ -14,7 +14,7 @@ const sections = flattenSections(clientLibsCommonSections) export default function JSReference(props) { const router = useRouter() const slug = router.query.slug[0] - const filteredSection = sections.filter((section) => section.id === slug) + const filteredSection = sections.filter((section) => section.slug === slug) const pageTitle = filteredSection[0]?.title ? `${filteredSection[0]?.title} | Supabase` diff --git a/apps/docs/pages/reference/javascript/crawlers/[...slug].tsx b/apps/docs/pages/reference/javascript/crawlers/[...slug].tsx index 67c72c5151c..df4a97dcdc5 100644 --- a/apps/docs/pages/reference/javascript/crawlers/[...slug].tsx +++ b/apps/docs/pages/reference/javascript/crawlers/[...slug].tsx @@ -14,7 +14,7 @@ const sections = flattenSections(clientLibsCommonSections) export default function JSReference(props) { const router = useRouter() const slug = router.query.slug[0] - const filteredSection = sections.filter((section) => section.id === slug) + const filteredSection = sections.filter((section) => section.slug === slug) const pageTitle = filteredSection[0]?.title ? `${filteredSection[0]?.title} | Supabase` diff --git a/apps/docs/pages/reference/javascript/v1/crawlers/[...slug].tsx b/apps/docs/pages/reference/javascript/v1/crawlers/[...slug].tsx index 18c498125ef..19278fccd67 100644 --- a/apps/docs/pages/reference/javascript/v1/crawlers/[...slug].tsx +++ b/apps/docs/pages/reference/javascript/v1/crawlers/[...slug].tsx @@ -13,7 +13,7 @@ const sections = flattenSections(clientLibsCommonSections) export default function JSReference(props) { const router = useRouter() const slug = router.query.slug[0] - const filteredSection = sections.filter((section) => section.id === slug) + const filteredSection = sections.filter((section) => section.slug === slug) const pageTitle = filteredSection[0]?.title ? `${filteredSection[0]?.title} | Supabase` diff --git a/apps/www/pages/blog.tsx b/apps/www/pages/blog.tsx index a14bbd8feef..a96ed86cd9a 100644 --- a/apps/www/pages/blog.tsx +++ b/apps/www/pages/blog.tsx @@ -100,6 +100,7 @@ function Blog(props: any) { ]} /> +

Supabase blog

diff --git a/apps/www/pages/blog/tags/[tag].tsx b/apps/www/pages/blog/tags/[tag].tsx index b6063851ef9..49aa4a9335b 100644 --- a/apps/www/pages/blog/tags/[tag].tsx +++ b/apps/www/pages/blog/tags/[tag].tsx @@ -37,11 +37,11 @@ function TagBlogsPage(props: Props) {
-

+

Blog -

-

/

-

{`${tag}`}

+ / + {`${tag}`} +

    {blogs.map((blog: PostTypes, idx: number) => ( diff --git a/apps/www/pages/careers/index.tsx b/apps/www/pages/careers/index.tsx index d7d4ec2d29a..af3b1cff166 100644 --- a/apps/www/pages/careers/index.tsx +++ b/apps/www/pages/careers/index.tsx @@ -101,9 +101,11 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
    - Careers +

    + Supabase Careers +

    - We’re on a mission to build the best developer platform + We're on a mission to build the best developer platform

    Explore remote possibilities and join our team to help us achieve it. @@ -321,7 +323,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {

    https://supabase.com/blog Latest Postgres news from Paul Copplestone at Supabase en - Mon, 27 Jun 2022 02:02:30 +0000 + Fri, 09 Dec 2022 03:03:30 +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 + + 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 diff --git a/studio/pages/project/_/[[...routeSlug]].tsx b/studio/pages/project/_/[[...routeSlug]].tsx index f9922644dad..dacc4ed5bdb 100644 --- a/studio/pages/project/_/[[...routeSlug]].tsx +++ b/studio/pages/project/_/[[...routeSlug]].tsx @@ -55,7 +55,7 @@ const GenericProjectPage: NextPage = () => { <>
    -

    Select a project to continue

    +

    Select a project to continue

    {
    -

    Supabase support

    +

    Supabase support

    From 0f4d0bb3f0a8d33a869ef13191d011e0c4054c8d Mon Sep 17 00:00:00 2001 From: joe Date: Fri, 27 Jan 2023 14:50:53 -0500 Subject: [PATCH 11/30] chore: Fix spelling on v0.5 Migration Instructions --- apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx b/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx index 9985e50fb92..3b093bd91b4 100644 --- a/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx +++ b/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx @@ -594,7 +594,7 @@ export const config = { To make these helpers more flexible as well as more maintainable and easier to upgrade for new versions of Next.js, we're stripping them down to the most useful part which is managing the cookies and giving you an authenticated supabase-js client in any environment (client, server, middleware/edge). -Therefore we're marking the `withApiAuth`, `withPageAuth`, and `withMiddlewareAuth` higher order functions as deprectaed and they will be removed in the next **minor** release (v0.6.X). +Therefore we're marking the `withApiAuth`, `withPageAuth`, and `withMiddlewareAuth` higher order functions as deprecated and they will be removed in the next **minor** release (v0.6.X). Please follow the steps below to update your API routes, pages, and middleware handlers. Thanks! From 104a96e4f8fb941969d83f49aa0c7b3811bac5b6 Mon Sep 17 00:00:00 2001 From: Lucas Denon <30569291+Lokdien@users.noreply.github.com> Date: Fri, 27 Jan 2023 21:42:30 +0100 Subject: [PATCH 12/30] Fix: typo in cors documentation Fixed an error in the name of a file in the CORS (Cross-Origin Resource Sharing) documentation. --- apps/docs/pages/guides/functions/cors.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/pages/guides/functions/cors.mdx b/apps/docs/pages/guides/functions/cors.mdx index 14f1a1208d9..c877da1ce2f 100644 --- a/apps/docs/pages/guides/functions/cors.mdx +++ b/apps/docs/pages/guides/functions/cors.mdx @@ -12,7 +12,7 @@ See the [example on GitHub](https://github.com/supabase/supabase/blob/master/exa ### Recommended setup -We recommend adding a `corst.ts` file within a [`_shared` folder](/docs/guides/functions/quickstart#organizing-your-edge-functions) which makes it easy to reuse the CORS headers across functions: +We recommend adding a `cors.ts` file within a [`_shared` folder](/docs/guides/functions/quickstart#organizing-your-edge-functions) which makes it easy to reuse the CORS headers across functions: ```ts cors.ts export const corsHeaders = { From cb4c9c3620017daf4871e773a6bf426f4ab9e73f Mon Sep 17 00:00:00 2001 From: xpcrud Date: Sat, 28 Jan 2023 15:12:27 +0700 Subject: [PATCH 13/30] fix incorrect video link --- apps/docs/pages/guides/functions/examples/github-actions.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/pages/guides/functions/examples/github-actions.mdx b/apps/docs/pages/guides/functions/examples/github-actions.mdx index 97456f33767..58a85484ab9 100644 --- a/apps/docs/pages/guides/functions/examples/github-actions.mdx +++ b/apps/docs/pages/guides/functions/examples/github-actions.mdx @@ -8,7 +8,7 @@ export const meta = {