mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
Merge branch 'supabase:master' into master
This commit is contained in:
4 files changed
+96
-22
No files matched your search
+2
-1
@@ -24,9 +24,10 @@
|
||||
|
||||
## المجتمع والدعم
|
||||
|
||||
- [مندى المجتمع](https://github.com/supabase/supabase/discussions). الأفضل لـ: المساعدة في البناء، والنقاش حول أفضل ممارسات قاعدة البيانات.
|
||||
- [منتدى المجتمع](https://github.com/supabase/supabase/discussions). الأفضل لـ: المساعدة في البناء، والنقاش حول أفضل ممارسات قاعدة البيانات.
|
||||
- [مشاكل GitHub](https://github.com/supabase/supabase/issues). الأفضل لـ: المشاكل والأخطاء التي تواجهها عند استخدامك لـ(Supabase).
|
||||
- [دعم البريد الإلكتروني](https://supabase.com/docs/support#business-support). الأفضل لـ: مشاكل مع قاعدة بياناتك أو البنية التحتية.
|
||||
- [ديسكورد](https://discord.supabase.com/). الأفضل لـ: مشاركة التطبيقات الخاصه بك وقضاء بعض الوقت مع المجتمع.
|
||||
|
||||
## الحالة
|
||||
|
||||
|
||||
@@ -72,17 +72,28 @@ test('timestamp from filter default value', async () => {
|
||||
render(<LogPanel defaultFromValue="2022-01-18T10:43:39+0000" />)
|
||||
userEvent.click(await screen.findByText('Custom'))
|
||||
await screen.findByDisplayValue('2022-01-18T10:43:39+0000')
|
||||
})
|
||||
test('timestamp from filter', async () => {
|
||||
const mockFn = jest.fn()
|
||||
render(<LogPanel onSearch={mockFn} />)
|
||||
const dropdown = await screen.findByText(/Now/)
|
||||
|
||||
// click the dropdown
|
||||
userEvent.click(dropdown)
|
||||
|
||||
// TODO: use screen.findByLabelText when https://github.com/supabase/ui/issues/310 is resolved
|
||||
await screen.findByText('From')
|
||||
await screen.findByTitle('Reset')
|
||||
})
|
||||
|
||||
test('timestamp from filter error handling', async () => {
|
||||
const mockFn = jest.fn()
|
||||
render(<LogPanel onSearch={mockFn} />)
|
||||
userEvent.click(await screen.findByText(/Now/))
|
||||
|
||||
// display iso timestamp
|
||||
const year = new Date().getFullYear()
|
||||
const input = await screen.findByDisplayValue(RegExp(year))
|
||||
userEvent.clear(input)
|
||||
userEvent.type(input, '123456')
|
||||
await screen.findByText(/[iI]nvalid ISO 8601 timestamp/)
|
||||
})
|
||||
|
||||
test('timestamp from filter value change', async () => {
|
||||
const mockFn = jest.fn()
|
||||
render(<LogPanel onSearch={mockFn} />)
|
||||
userEvent.click(await screen.findByText(/Now/))
|
||||
// display iso timestamp
|
||||
const year = new Date().getFullYear()
|
||||
const input = await screen.findByDisplayValue(RegExp(year))
|
||||
@@ -90,19 +101,12 @@ test('timestamp from filter', async () => {
|
||||
// replace the input's value
|
||||
userEvent.clear(input)
|
||||
|
||||
// type some random input to check for error handling
|
||||
userEvent.type(input, '123456')
|
||||
await screen.findByText(/[iI]nvalid ISO 8601 timestamp/)
|
||||
userEvent.clear(input)
|
||||
await expect(screen.findByText(/[iI]nvalid ISO 8601 timestamp/)).rejects.toThrow()
|
||||
|
||||
// get time 20 mins before
|
||||
const newDate = new Date()
|
||||
newDate.setMinutes(new Date().getMinutes() - 20)
|
||||
userEvent.type(input, newDate.toISOString())
|
||||
|
||||
// input actions
|
||||
await screen.findByTitle('Reset')
|
||||
const set = await screen.findByRole('button', { name: 'Set' })
|
||||
|
||||
userEvent.click(set)
|
||||
|
||||
@@ -138,6 +138,73 @@ Migrating projects can be achieved using standard PostgreSQL tooling. This is pa
|
||||
6. Run `TRUNCATE storage.objects` in the *new* project's SQL editor
|
||||
7. Run `ALTER ROLE postgres NOSUPERUSER` in the *new* project's SQL editor
|
||||
|
||||
#### Migrate storage objects
|
||||
|
||||
This script moves storage objects from one project to another. If you have more than 10k objects, we can move the objects for you. Just contact us at [support@supabase.io](mailto:support@supabase.io).
|
||||
|
||||
```js
|
||||
const { createClient } = require("@supabase/supabase-js");
|
||||
|
||||
const OLD_PROJECT_URL = "https://xxx.supabase.co";
|
||||
const OLD_PROJECT_SERVICE_KEY = "old-project-service-key-xxx";
|
||||
|
||||
const NEW_PROJECT_URL = "https://yyy.supabase.co";
|
||||
const NEW_PROJECT_SERVICE_KEY = "new-project-service-key-yyy";
|
||||
|
||||
(async () => {
|
||||
const oldSupabaseRestClient = createClient(
|
||||
OLD_PROJECT_URL,
|
||||
OLD_PROJECT_SERVICE_KEY,
|
||||
{ schema: "storage" }
|
||||
);
|
||||
const oldSupabaseClient = createClient(
|
||||
OLD_PROJECT_URL,
|
||||
OLD_PROJECT_SERVICE_KEY
|
||||
);
|
||||
const newSupabaseClient = createClient(
|
||||
NEW_PROJECT_URL,
|
||||
NEW_PROJECT_SERVICE_KEY
|
||||
);
|
||||
|
||||
// make sure you update max_rows in postgrest settings if you have a lot of objects
|
||||
// or paginate here
|
||||
const { data: oldObjects, error } = await oldSupabaseRestClient
|
||||
.from("objects")
|
||||
.select();
|
||||
if (error) {
|
||||
console.log("error getting objects from old bucket");
|
||||
throw error;
|
||||
}
|
||||
|
||||
for (const objectData of oldObjects) {
|
||||
console.log(`moving ${objectData.id}`);
|
||||
try {
|
||||
const { data, error: downloadObjectError } =
|
||||
await oldSupabaseClient.storage
|
||||
.from(objectData.bucket_id)
|
||||
.download(objectData.name);
|
||||
if (downloadObjectError) {
|
||||
throw downloadObjectError;
|
||||
}
|
||||
|
||||
const { _, error: uploadObjectError } = await newSupabaseClient.storage
|
||||
.from(objectData.bucket_id)
|
||||
.upload(objectData.name, data, {
|
||||
upsert: true,
|
||||
contentType: objectData.metadata.mimetype,
|
||||
cacheControl: objectData.metadata.cacheControl,
|
||||
});
|
||||
if (uploadObjectError) {
|
||||
throw uploadObjectError;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error moving ", objectData);
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
#### Caveats
|
||||
|
||||
- The new project will have the old project's Storage buckets, but not the objects. You will need to migrate Storage objects manually.
|
||||
|
||||
@@ -154,10 +154,12 @@ expo init supabaseReactNative
|
||||
cd supabaseReactNative
|
||||
```
|
||||
|
||||
Then let's install the only additional dependency: [supabase-js](https://github.com/supabase/supabase-js)
|
||||
Then let's install the additional dependencies: [supabase-js](https://github.com/supabase/supabase-js)
|
||||
|
||||
```bash
|
||||
yarn add @supabase/supabase-js
|
||||
yarn add react-native-elements
|
||||
yarn add react-native-safe-area-context
|
||||
```
|
||||
|
||||
Now let's create a helper file to initialize the Supabase client.
|
||||
@@ -182,7 +184,7 @@ We'll use Magic Links, so users can sign in with their email without using passw
|
||||
```jsx title="components/Auth.js"
|
||||
import React, {useState} from 'react'
|
||||
import {Alert, StyleSheet, View} from 'react-native'
|
||||
import {supabaseClient} from '../lib/initSupabase'
|
||||
import {supabase} from '../lib/supabase'
|
||||
import {Button, Input} from 'react-native-elements'
|
||||
|
||||
export default function Auth() {
|
||||
@@ -267,7 +269,7 @@ Let's create a new component for that called `Account.js`.
|
||||
|
||||
```jsx title="components/Account.js"
|
||||
import { useState, useEffect } from 'react'
|
||||
import { supabase } from '../utils/supabaseClient'
|
||||
import { supabase } from '../utils/supabase'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
|
||||
import {Button, Input} from 'react-native-elements'
|
||||
@@ -386,10 +388,10 @@ Now that we have all the components in place, let's update `app.js`:
|
||||
|
||||
```jsx title="app.js"
|
||||
import { useState, useEffect } from 'react'
|
||||
import { supabase } from './lib/supabaseClient'
|
||||
import { supabase } from './lib/supabase'
|
||||
import Auth from './components/Auth'
|
||||
import Account from './components/Account'
|
||||
import View from 'react-native'
|
||||
import { View } from 'react-native'
|
||||
|
||||
export default function App() {
|
||||
const [session, setSession] = useState(null)
|
||||
|
||||
Reference in new issue
Block a user