ابرووا
شروع رایگان
☰ فهرست مستندات · React Native
به‌زودی. Abrova Storage به‌زودی فعال می‌شود. این صفحه توضیح می‌دهد چطور کار خواهد کرد؛ هنوز قابل استفاده نیست.
این صفحه هنوز ترجمه نشده — نسخه‌ی انگلیسی نمایش داده می‌شود. English

React Native SDK

Cross-platform mobile SDK for Abrova Storage on React Native. Same API as the Web SDK — sign users in with an Abrova user token (tokenProvider, Abrova Auth or your server), upload with progress, list, download, delete, header-free public image links.

React Native 0.2.1به‌روزرسانی: ۵ آبان ۱۴۰۵

Cross-platform mobile SDK for React Native. Same API as the Web SDK, written in plain TypeScript (no native modules). This page describes @abrova/storage-react-native 0.2.1.

Installation#

bash
# 1. .npmrc in your project root: @abrova packages come from Abrova Center
@abrova:registry=https://center.abrova.ir/api/packages/abrova/npm/
bash
# 2. Install
npm install @abrova/storage-react-native
# or
yarn add @abrova/storage-react-native

Usage#

typescript
import { AbrovaStorage } from '@abrova/storage-react-native';

const storage = new AbrovaStorage({
  apiKey: 'ab_live_xxxxxxxxxxxx',
  tokenProvider: () => auth.getToken(), // the signed-in user's Abrova user token, see step 3
});

// Upload, with progress (iOS and Android)
const file = await storage.upload('avatars', `users/${userId}/avatar.png`, imageBytes, {
  contentType: 'image/png',
  onProgress: ({ bytesSent, totalBytes }) => setProgress(bytesSent / totalBytes), // 0 to 1
});

// List files ({ files, nextCursor })
const result = await storage.listFiles('avatars', { prefix: `users/${userId}/`, limit: 20 });

// Download
const data = await storage.download(file.id);

// Delete (follows the bucket's delete rules)
await storage.delete(file.id);

upload takes a Uint8Array or a string. Without contentType, the type comes from the path's extension (contentTypeForPath(path) shows it). A new path can't contain ?, #, % or a . / .. part (invalid_path, nothing is sent).

Sign users in (one token for every Abrova product)#

Every file request from an app needs a signed Abrova user token, so access rules ({userId}, authenticated) see a user nobody can fake. It is the same token Abrova Sync, Chat, Push and A/B Testing accept, so one provider can serve every Abrova SDK.

With Abrova Auth (@abrova/auth-react-native), its sign-in token is the Abrova user token:

typescript
import * as Keychain from 'react-native-keychain';
import { createAbrovaAuth, keychainStorage } from '@abrova/auth-react-native';
import { AbrovaStorage } from '@abrova/storage-react-native';

const auth = createAbrovaAuth({ apiKey: 'ab_live_xxxxxxxxxxxx', storage: keychainStorage(Keychain) });

const storage = new AbrovaStorage({
  apiKey: 'ab_live_xxxxxxxxxxxx',
  tokenProvider: () => auth.getToken(), // null while signed out: file calls wait
});

auth.onAuthStateChanged(() => {
  storage.refreshUserToken(); // after sign-in, sign-out or a switch of user
});

With your own users, your server mints the token with the server secret (createUserToken(userId) in the Node.js SDK) and your tokenProvider fetches it, returning null when no one is signed in. Call await storage.refreshUserToken() when the user signs in or out, or pass a token you hold with await storage.setUserToken(token) (null clears it).

The SDK sends the token as x-user-token, renews it shortly before it expires, and on token_expired / token_invalid asks once more and retries the request once.

No token yet: file calls wait. They are not sent and do not fail until your app signs a user in, so show your sign-in screen meanwhile. storage.isAwaitingUserToken is true while calls wait, and storage.onAwaitingUserToken(callback) tells you when they start waiting (it returns a function that removes the callback). Bucket calls and getPublicUrl never wait.

Signed user tokens are always required for file calls from apps. There is no setting to turn this off.

Don't wait on file calls before sign-in. A file call made while no one is signed in finishes only after sign-in. Don't wait for it in code the user is waiting on (a button handler, a startup check): start it in the background, or after sign-in.

Leave the timeout unset. By default a call waits until sign-in, which is right for background work. Set userTokenWaitTimeout only when a screen waits for the answer and can send the user to sign-in:

typescript
const storage = new AbrovaStorage({
  apiKey: 'ab_live_xxxxxxxxxxxx',
  tokenProvider: () => auth.getToken(),
  userTokenWaitTimeout: 30000, // ms; then fails with token_required
});

A call that waited that long fails with token_required (401). The timeout option is a different setting: it limits each network request (default 30 seconds) and never covers the wait for a user.

With Abrova Auth, turn on the sign-in method you use (for example Anonymous) in Abrova Auth › Sign-in methods. If it is off, sign-in fails with METHOD_DISABLED, no one is signed in, and file calls wait without an error. While developing, log from onAwaitingUserToken (console.log('Storage: waiting for a user')) so a silent wait is easy to spot.

Upgrading from 0.2.0: userId / setUserId() are removed. Use tokenProvider.

Showing images#

For a file in a public bucket, getPublicUrl returns a link that needs no key, token or header. Pass image options for a resized or converted image:

tsx
import { Image } from 'react-native';
import { publicImageUrl } from '@abrova/storage-react-native';

const url = await storage.getPublicUrl(fileId, { width: 600, format: 'webp' });
<Image source={{ uri: url }} style={{ width: 300, height: 200 }} />

// From a public link you saved earlier: same URL, no request
const thumb = publicImageUrl(savedLink, { width: 200, height: 200, fit: 'cover', format: 'webp' });

The same options always give the same, cached URL. Use a few fixed sizes: one image keeps at most 50 variants (too_many_variants, 429). When the month's 500 free transforms are used up and your wallet cannot pay for more, image URLs answer plan_feature_locked (403); the plain public link always works. Invalid options throw invalid_transform before any request.

A private bucket has no public link (403). getTransformUrl(), getUrl() and getDownloadUrl() return API addresses that need headers: pass them in <Image source={{ uri, headers: { 'x-api-key': 'ab_live_xxxxxxxxxxxx', 'x-user-token': userToken } }} />, or ask your server for a signed link (getSignedUrl(fileId, { expiresIn }) in the Node.js SDK). See Image Transforms for transform errors.

Handling errors#

A refused request throws an AbrovaStorageException with message, statusCode and code; compare code with StorageErrorCode:

typescript
import { AbrovaStorageException, StorageErrorCode } from '@abrova/storage-react-native';

try {
  await storage.upload('avatars', 'users/u_4821/notes.md', '# Notes');
} catch (e) {
  if (e instanceof AbrovaStorageException && e.code === StorageErrorCode.TypeNotAllowed) {
    showError(e.message);
  } else throw e;
}

Common codes: type_not_allowed, file_too_large, executable_blocked (400, the bucket's settings), invalid_path, invalid_transform (400, nothing sent), path_taken (409), token_required, token_expired, token_invalid (401), access_denied (403, access rules) and server_secret_required (403, a server-only action).

Same API as Web.

The React Native SDK has the same API as the Web SDK: uploads, downloads, lists, deletes, public links, transforms and user tokens work identically, except that upload takes a Uint8Array or string (not a File/Blob).

این صفحه مفید بود؟
گزارش مشکل