Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell-wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,4 @@ nˈɛvəɹ
ˈɛniwˌʌn
ˈɛls
Synchronizable
stringifying
29 changes: 28 additions & 1 deletion docs/docs/01-fundamentals/01-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,32 +38,59 @@ For supported React Native and Expo versions, see the [Compatibility table](../0

## Installation

Installation is pretty straightforward, just use your favorite package manager.
Installation is pretty straightforward, use your package manager of choice to install the package and some peer dependencies required to streamline model downloads. If you want to implement your custom model fetching logic, see [this document](../08-resource-fetcher/02-custom-adapter.md).

<Tabs>
<TabItem value="npm" label="NPM">

```
npm install react-native-executorch
# For Expo projects
npm install react-native-executorch-expo-resource-fetcher
# For bare React Native projects
npm install react-native-executorch-bare-resource-fetcher
```

</TabItem>
<TabItem value="pnpm" label="PNPM">

```
pnpm install react-native-executorch
# For Expo projects
pnpm install react-native-executorch-expo-resource-fetcher
# For bare React Native projects
pnpm install react-native-executorch-bare-resource-fetcher

```

</TabItem>
<TabItem value="yarn" label="YARN">

```
yarn add react-native-executorch
# For Expo projects
yarn install react-native-executorch-expo-resource-fetcher
# For bare React Native projects
yarn install react-native-executorch-bare-resource-fetcher
```

</TabItem>
</Tabs>

:::warning
Before using any other API, you must call `initExecutorch` with a resource fetcher adapter at the entry point of your app:

```js
import { initExecutorch } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';
// or BareResourceFetcher for Expo projects

initExecutorch({ resourceFetcher: ExpoResourceFetcher });
```

Calling any library API without initializing first will throw a `ResourceFetcherAdapterNotInitialized` error.
:::

Our library offers support for both bare React Native and Expo projects. Please follow the instructions from [Loading models section](./02-loading-models.md) to make sure you setup your project correctly. We encourage you to use Expo project if possible. If you are planning to migrate from bare React Native to Expo project, the link (https://docs.expo.dev/bare/installing-expo-modules/) offers a guidance on setting up Expo Modules in a bare React Native environment.

If you plan on using your models via require() instead of fetching them from a url, you also need to add following lines to your `metro.config.js`:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
---
title: Resource Fetcher
title: Usage
---

This module provides functions to download and work with downloaded files stored in the application's document directory inside the `react-native-executorch/` directory. These utilities can help you manage your storage and clean up the downloaded files when they are no longer needed.
This page documents the resource fetcher APIs exposed by `react-native-executorch-expo-resource-fetcher` and `react-native-executorch-bare-resource-fetcher`. These adapters handle downloading and managing model files on disk.

:::info
All examples below use `ExpoResourceFetcher`. If you're on bare React Native, replace the import with:

```typescript
import { BareResourceFetcher } from 'react-native-executorch-bare-resource-fetcher';
```

The API is identical between both adapters.
:::

## fetch

Fetches resources (remote URLs, local files or embedded assets), downloads or stores them locally for use by React Native ExecuTorch.
Fetches resources (remote URLs, local files, or embedded assets) and stores them locally for use by React Native ExecuTorch.

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const uris = await ResourceFetcher.fetch(
const uris = await ExpoResourceFetcher.fetch(
(progress) => console.log('Total progress:', progress),
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
Expand All @@ -29,31 +39,31 @@ const uris = await ResourceFetcher.fetch(

`Promise<string[] | null>`:

- If the fetch was successful, it returns a promise which resolves to an array of local file paths for the downloaded/stored resources (without file:// prefix).
- If the fetch was successful, it returns a promise which resolves to an array of local file paths for the downloaded/stored resources (without `file://` prefix).
- If the fetch was interrupted by `pauseFetching` or `cancelFetching`, it returns a promise which resolves to `null`.

:::info
If the resource is an object, it will be saved as a JSON file on disk.
If the resource is an object, it will be saved as a JSON file on disk.
:::

## pauseFetching

Pauses an ongoing download of files.
Pauses an ongoing download.

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const uris = ResourceFetcher.fetch(
const uris = ExpoResourceFetcher.fetch(
(progress) => console.log('Total progress:', progress),
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
).then((uris) => {
console.log('URI resolved to: ', uris); // since we pause the fetch, uris is resolved to null
console.log('URI resolved to: ', uris); // null, since we paused
});

await ResourceFetcher.pauseFetching(
await ExpoResourceFetcher.pauseFetching(
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
);
Expand All @@ -69,31 +79,31 @@ await ResourceFetcher.pauseFetching(

## resumeFetching

Resumes a paused download of files.
Resumes a paused download.
Comment thread
chmjkb marked this conversation as resolved.

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const uris = ResourceFetcher.fetch(
const uris = ExpoResourceFetcher.fetch(
(progress) => console.log('Total progress:', progress),
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
).then((uris) => {
console.log('URI resolved as: ', uris); // since we pause the fetch, uris is resolved to null
console.log('URI resolved as: ', uris); // null, since we paused
});

await ResourceFetcher.pauseFetching(
await ExpoResourceFetcher.pauseFetching(
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
);

const resolvedUris = await ResourceFetcher.resumeFetching(
const resolvedUris = await ExpoResourceFetcher.resumeFetching(
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
);
//resolvedUris is resolved to file paths to fetched resources, unless explicitly paused/cancel again.
// resolvedUris resolves to file paths, unless paused/cancelled again
```

### Parameters
Expand All @@ -104,31 +114,31 @@ const resolvedUris = await ResourceFetcher.resumeFetching(

`Promise<string[] | null>`:

- If the fetch was successful, it returns a promise which resolves to an array of local file paths for the downloaded resources (without file:// prefix).
- If the fetch was again interrupted by `pauseFetching` or `cancelFetching`, it returns a promise which resolves to null.
- If the fetch was successful, it returns a promise which resolves to an array of local file paths for the downloaded resources (without `file://` prefix).
- If the fetch was again interrupted by `pauseFetching` or `cancelFetching`, it returns a promise which resolves to `null`.

:::info
The other way to resume paused resources is to simply call `fetch` again. However, `resumeFetching` is faster.
You can also resume a paused download by calling `fetch` again with the same sources. However, `resumeFetching` is faster as it resumes from where it left off.
:::

## cancelFetching

Cancels an ongoing/paused download of files.
Cancels an ongoing or paused download.

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const uris = ResourceFetcher.fetch(
const uris = ExpoResourceFetcher.fetch(
(progress) => console.log('Total progress:', progress),
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
).then((uris) => {
console.log('URI resolved as: ', uris); // since we cancel the fetch, uris is resolved to null
console.log('URI resolved as: ', uris); // null, since we cancelled
});

await ResourceFetcher.cancelFetching(
await ExpoResourceFetcher.cancelFetching(
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
);
Expand All @@ -149,9 +159,9 @@ Deletes downloaded resources from the local filesystem.
### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

await ResourceFetcher.deleteResources('https://.../llama3_2.pte');
await ExpoResourceFetcher.deleteResources('https://.../llama3_2.pte');
```

### Parameters
Expand All @@ -164,14 +174,14 @@ await ResourceFetcher.deleteResources('https://.../llama3_2.pte');

## getFilesTotalSize

Fetches the info about files size. Works only for remote files.
Fetches the combined size of remote files. Works only for remote URLs.

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const totalSize = await ResourceFetcher.getFilesTotalSize(
const totalSize = await ExpoResourceFetcher.getFilesTotalSize(
'https://.../llama3_2.pte',
'https://.../qwen3.pte'
);
Expand All @@ -183,36 +193,36 @@ const totalSize = await ResourceFetcher.getFilesTotalSize(

### Returns

`Promise<number>` – A promise that resolves to combined size of files in bytes.
`Promise<number>` – A promise that resolves to the combined size of files in bytes.

## listDownloadedFiles

Lists all the downloaded files used by React Native ExecuTorch.
Lists all files downloaded by React Native ExecuTorch.

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const filesUris = await ResourceFetcher.listDownloadedFiles();
const filesUris = await ExpoResourceFetcher.listDownloadedFiles();
```

### Returns

`Promise<string[]>` - A promise, which resolves to an array of URIs for all the downloaded files.
`Promise<string[]>` - A promise that resolves to an array of URIs for all downloaded files.

## listDownloadedModels

Lists all the downloaded models used by React Native ExecuTorch.
Lists all downloaded model files (`.pte`).

### Reference

```typescript
import { ResourceFetcher } from 'react-native-executorch';
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';

const modelsUris = await ResourceFetcher.listDownloadedModels();
const modelsUris = await ExpoResourceFetcher.listDownloadedModels();
```

### Returns

`Promise<string[]>` - A promise, which resolves to an array of URIs for all the downloaded models.
`Promise<string[]>` - A promise that resolves to an array of URIs for all downloaded model files.
56 changes: 56 additions & 0 deletions docs/docs/08-resource-fetcher/02-custom-adapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Custom Adapter
---

If the built-in `BareResourceFetcher` and `ExpoResourceFetcher` don't fit your needs, for example, you want to use a different download library, or fetch from a private server you can implement your own adapter and plug it into React Native ExecuTorch.
Comment thread
chmjkb marked this conversation as resolved.
Outdated

## The ResourceFetcherAdapter interface

Your adapter must implement the `ResourceFetcherAdapter` interface exported from `react-native-executorch`. This interface defines every method which is used under the hood by React Native ExecuTorch:

```typescript
import {
ResourceFetcherAdapter,
ResourceSource,
} from 'react-native-executorch';

interface ResourceFetcherAdapter {
fetch(
callback: (downloadProgress: number) => void,
...sources: ResourceSource[]
): Promise<string[] | null>;

readAsString(path: string): Promise<string>;
}
```

### `fetch`

This is the core method called by every model hook and module whenever it needs to resolve a model or resource to a local file path.

- `callback` — called with a progress value between `0` and `1` as downloads proceed. Called with `1` when complete.
- `...sources` — one or more `ResourceSource` values:
- `string` — a remote URL or an absolute local file path.
- `number` — a bundled asset reference from `require('./model.pte')`.
- `object` — an inline JS object (e.g. a tokenizer config) that should be JSON-serialized and written to disk. Your adapter is responsible for stringifying it and saving it as a file, then returning the local path. This allows callers to pass configs inline instead of hosting them at a URL.
- **Returns** an array of absolute local file paths (without `file://` prefix), one per source, in the same order. Return `null` if the fetch was intentionally interrupted (e.g. cancelled by the user).

### `readAsString`

Called internally to read configuration files (e.g. tokenizer configs) that were previously downloaded via `fetch`.

- `path` — absolute path to the file on disk.
- **Returns** the file contents as a UTF-8 string.

## Registering your adapter

Pass your adapter to `initExecutorch` at the entry point of your app, before any other library API is called:

```typescript
import { initExecutorch } from 'react-native-executorch';
import { MyCustomFetcher } from './MyCustomFetcher';

initExecutorch({ resourceFetcher: MyCustomFetcher });
```

Any model hook or module used after this point will route all resource fetching through your adapter.
6 changes: 6 additions & 0 deletions docs/docs/08-resource-fetcher/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"label": "Resource Fetcher",
"link": {
"type": "generated-index"
}
}
5 changes: 5 additions & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const sidebars = {
label: 'Utilities',
items: [{ type: 'autogenerated', dirName: '05-utilities' }],
},
{
type: 'category',
label: 'Resource Fetcher',
items: [{ type: 'autogenerated', dirName: '08-resource-fetcher' }],
},
{
type: 'category',
label: 'Other',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class ResourceFetcher {
static getAdapter(): ResourceFetcherAdapter {
if (!this.adapter) {
const errorMessage =
'ResourceFetcher adapter is not initialized. Please call initExecutorch({ resourceFetcher: ... }) with a valid adapter, e.g., from react-native-executorch-expo-resource-fetcher or react-native-executorch-bare-resource-fetcher. For more details please refer: https://docs.swmansion.com/react-native-executorch/docs/next/fundamentals/loading-models';
'ResourceFetcher adapter is not initialized. Please call initExecutorch({ resourceFetcher: ... }) with a valid adapter, e.g., from react-native-executorch-expo-resource-fetcher or react-native-executorch-bare-resource-fetcher. For more details please refer to: https://docs.swmansion.com/react-native-executorch/docs/next/fundamentals/loading-models';
// for sanity :)
Logger.error(errorMessage);
throw new RnExecutorchError(
Expand Down
Loading