From c09cb4ea6f79cb5b4957d7f05374a050e2cc19f9 Mon Sep 17 00:00:00 2001 From: Maximilian Krause Date: Sun, 21 Jun 2026 18:22:55 +0200 Subject: [PATCH 01/16] feat(docs): scaffold Fumadocs app shell, remove Docusaurus --- apps/docs/.gitignore | 34 ++- apps/docs/app/(home)/layout.tsx | 6 + apps/docs/app/(home)/page.tsx | 15 + apps/docs/app/api/search/route.ts | 7 + apps/docs/app/docs/[[...slug]]/page.tsx | 55 ++++ apps/docs/app/docs/layout.tsx | 11 + apps/docs/app/global.css | 21 ++ apps/docs/app/layout.tsx | 33 ++ apps/docs/app/llms-full.txt/route.ts | 13 + .../app/llms.mdx/docs/[[...slug]]/route.ts | 20 ++ apps/docs/app/llms.txt/route.ts | 13 + apps/docs/app/og/docs/[...slug]/route.tsx | 27 ++ apps/docs/components/ai/page-actions.tsx | 162 ++++++++++ apps/docs/content/docs/index.mdx | 7 + apps/docs/content/docs/meta.json | 5 + apps/docs/docs/api/CloudStorage.md | 283 ------------------ apps/docs/docs/api/CloudStorageError.md | 35 --- apps/docs/docs/api/_category_.json | 4 - .../docs/api/enums/CloudStorageErrorCode.md | 44 --- .../docs/api/enums/CloudStorageProvider.md | 46 --- apps/docs/docs/api/enums/CloudStorageScope.md | 28 -- apps/docs/docs/api/enums/_category_.json | 4 - apps/docs/docs/api/hooks/_category_.json | 4 - apps/docs/docs/api/hooks/useCloudFile.md | 57 ---- .../docs/api/hooks/useIsCloudAvailable.md | 21 -- .../api/interfaces/CloudStorageFileStat.md | 19 -- apps/docs/docs/api/interfaces/_category_.json | 4 - apps/docs/docs/example.md | 20 -- apps/docs/docs/guides/_category_.json | 4 - .../guides/google-drive-files-same-name.md | 21 -- .../docs/guides/migrating-icloud-documents.md | 61 ---- .../docs/guides/using-multiple-providers.md | 32 -- apps/docs/docs/installation/_category_.json | 4 - .../installation/configure-google-drive.md | 99 ------ apps/docs/docs/installation/expo.md | 60 ---- apps/docs/docs/installation/react-native.md | 33 -- apps/docs/docs/intro.md | 7 - apps/docs/docusaurus.config.ts | 117 -------- apps/docs/lib/cn.ts | 1 + apps/docs/lib/layout.shared.tsx | 23 ++ apps/docs/lib/source.ts | 27 ++ apps/docs/mdx-components.tsx | 13 + apps/docs/next.config.mjs | 18 ++ apps/docs/package.json | 59 ++-- apps/docs/postcss.config.mjs | 7 + apps/docs/{static/img => public}/favicon.ico | Bin .../img => public}/ios_installation.jpg | Bin apps/docs/{static/img => public}/logo.png | Bin apps/docs/sidebars.ts | 33 -- apps/docs/source.config.ts | 26 ++ .../src/components/HomepageFeatures/index.tsx | 70 ----- .../HomepageFeatures/styles.module.css | 11 - apps/docs/src/css/custom.css | 30 -- apps/docs/src/pages/index.module.css | 23 -- apps/docs/src/pages/index.tsx | 37 --- apps/docs/src/pages/markdown-page.md | 7 - apps/docs/static/.nojekyll | 0 apps/docs/static/img/undraw_dx.svg | 1 - apps/docs/static/img/undraw_easy_to_use.svg | 1 - apps/docs/static/img/undraw_expo.svg | 1 - apps/docs/tsconfig.json | 30 +- 61 files changed, 580 insertions(+), 1274 deletions(-) create mode 100644 apps/docs/app/(home)/layout.tsx create mode 100644 apps/docs/app/(home)/page.tsx create mode 100644 apps/docs/app/api/search/route.ts create mode 100644 apps/docs/app/docs/[[...slug]]/page.tsx create mode 100644 apps/docs/app/docs/layout.tsx create mode 100644 apps/docs/app/global.css create mode 100644 apps/docs/app/layout.tsx create mode 100644 apps/docs/app/llms-full.txt/route.ts create mode 100644 apps/docs/app/llms.mdx/docs/[[...slug]]/route.ts create mode 100644 apps/docs/app/llms.txt/route.ts create mode 100644 apps/docs/app/og/docs/[...slug]/route.tsx create mode 100644 apps/docs/components/ai/page-actions.tsx create mode 100644 apps/docs/content/docs/index.mdx create mode 100644 apps/docs/content/docs/meta.json delete mode 100644 apps/docs/docs/api/CloudStorage.md delete mode 100644 apps/docs/docs/api/CloudStorageError.md delete mode 100644 apps/docs/docs/api/_category_.json delete mode 100644 apps/docs/docs/api/enums/CloudStorageErrorCode.md delete mode 100644 apps/docs/docs/api/enums/CloudStorageProvider.md delete mode 100644 apps/docs/docs/api/enums/CloudStorageScope.md delete mode 100644 apps/docs/docs/api/enums/_category_.json delete mode 100644 apps/docs/docs/api/hooks/_category_.json delete mode 100644 apps/docs/docs/api/hooks/useCloudFile.md delete mode 100644 apps/docs/docs/api/hooks/useIsCloudAvailable.md delete mode 100644 apps/docs/docs/api/interfaces/CloudStorageFileStat.md delete mode 100644 apps/docs/docs/api/interfaces/_category_.json delete mode 100644 apps/docs/docs/example.md delete mode 100644 apps/docs/docs/guides/_category_.json delete mode 100644 apps/docs/docs/guides/google-drive-files-same-name.md delete mode 100644 apps/docs/docs/guides/migrating-icloud-documents.md delete mode 100644 apps/docs/docs/guides/using-multiple-providers.md delete mode 100644 apps/docs/docs/installation/_category_.json delete mode 100644 apps/docs/docs/installation/configure-google-drive.md delete mode 100644 apps/docs/docs/installation/expo.md delete mode 100644 apps/docs/docs/installation/react-native.md delete mode 100644 apps/docs/docs/intro.md delete mode 100644 apps/docs/docusaurus.config.ts create mode 100644 apps/docs/lib/cn.ts create mode 100644 apps/docs/lib/layout.shared.tsx create mode 100644 apps/docs/lib/source.ts create mode 100644 apps/docs/mdx-components.tsx create mode 100644 apps/docs/next.config.mjs create mode 100644 apps/docs/postcss.config.mjs rename apps/docs/{static/img => public}/favicon.ico (100%) rename apps/docs/{static/img => public}/ios_installation.jpg (100%) rename apps/docs/{static/img => public}/logo.png (100%) delete mode 100644 apps/docs/sidebars.ts create mode 100644 apps/docs/source.config.ts delete mode 100644 apps/docs/src/components/HomepageFeatures/index.tsx delete mode 100644 apps/docs/src/components/HomepageFeatures/styles.module.css delete mode 100644 apps/docs/src/css/custom.css delete mode 100644 apps/docs/src/pages/index.module.css delete mode 100644 apps/docs/src/pages/index.tsx delete mode 100644 apps/docs/src/pages/markdown-page.md delete mode 100644 apps/docs/static/.nojekyll delete mode 100644 apps/docs/static/img/undraw_dx.svg delete mode 100644 apps/docs/static/img/undraw_easy_to_use.svg delete mode 100644 apps/docs/static/img/undraw_expo.svg diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore index c6320b8..713c6be 100644 --- a/apps/docs/.gitignore +++ b/apps/docs/.gitignore @@ -1,19 +1,27 @@ -# Dependencies +# deps /node_modules -# Production -/build +# generated content +.source +content/docs/api -# Generated files -.docusaurus -.cache-loader +# test & build +/coverage +/.next/ +/out/ +/build +*.tsbuildinfo -# Misc +# misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - +*.pem +/.pnp +.pnp.js npm-debug.log* -pnpm-debug.log* +yarn-debug.log* +yarn-error.log* + +# others +.env*.local +.vercel +next-env.d.ts diff --git a/apps/docs/app/(home)/layout.tsx b/apps/docs/app/(home)/layout.tsx new file mode 100644 index 0000000..77379fa --- /dev/null +++ b/apps/docs/app/(home)/layout.tsx @@ -0,0 +1,6 @@ +import { HomeLayout } from 'fumadocs-ui/layouts/home'; +import { baseOptions } from '@/lib/layout.shared'; + +export default function Layout({ children }: LayoutProps<'/'>) { + return {children}; +} diff --git a/apps/docs/app/(home)/page.tsx b/apps/docs/app/(home)/page.tsx new file mode 100644 index 0000000..03ca4cf --- /dev/null +++ b/apps/docs/app/(home)/page.tsx @@ -0,0 +1,15 @@ +import Link from 'next/link'; + +export default function HomePage() { + return ( +
+

React Native Cloud Storage

+

iCloud and Google Drive for React Native, simplified.

+ + Read docs + +
+ ); +} diff --git a/apps/docs/app/api/search/route.ts b/apps/docs/app/api/search/route.ts new file mode 100644 index 0000000..7ba7e82 --- /dev/null +++ b/apps/docs/app/api/search/route.ts @@ -0,0 +1,7 @@ +import { source } from '@/lib/source'; +import { createFromSource } from 'fumadocs-core/search/server'; + +export const { GET } = createFromSource(source, { + // https://docs.orama.com/docs/orama-js/supported-languages + language: 'english', +}); diff --git a/apps/docs/app/docs/[[...slug]]/page.tsx b/apps/docs/app/docs/[[...slug]]/page.tsx new file mode 100644 index 0000000..b5afced --- /dev/null +++ b/apps/docs/app/docs/[[...slug]]/page.tsx @@ -0,0 +1,55 @@ +import { getPageImage, source } from '@/lib/source'; +import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page'; +import { notFound } from 'next/navigation'; +import { getMDXComponents } from '@/mdx-components'; +import type { Metadata } from 'next'; +import { createRelativeLink } from 'fumadocs-ui/mdx'; +import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions'; +import { gitConfig } from '@/lib/layout.shared'; + +export default async function Page(props: PageProps<'/docs/[[...slug]]'>) { + const params = await props.params; + const page = source.getPage(params.slug); + if (!page) notFound(); + + const MDX = page.data.body; + + return ( + + {page.data.title} + {page.data.description} +
+ + +
+ + + +
+ ); +} + +export async function generateStaticParams() { + return source.generateParams(); +} + +export async function generateMetadata(props: PageProps<'/docs/[[...slug]]'>): Promise { + const params = await props.params; + const page = source.getPage(params.slug); + if (!page) notFound(); + + return { + title: page.data.title, + description: page.data.description, + openGraph: { + images: getPageImage(page).url, + }, + }; +} diff --git a/apps/docs/app/docs/layout.tsx b/apps/docs/app/docs/layout.tsx new file mode 100644 index 0000000..a373143 --- /dev/null +++ b/apps/docs/app/docs/layout.tsx @@ -0,0 +1,11 @@ +import { source } from '@/lib/source'; +import { DocsLayout } from 'fumadocs-ui/layouts/docs'; +import { baseOptions } from '@/lib/layout.shared'; + +export default function Layout({ children }: LayoutProps<'/docs'>) { + return ( + + {children} + + ); +} diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css new file mode 100644 index 0000000..11923d7 --- /dev/null +++ b/apps/docs/app/global.css @@ -0,0 +1,21 @@ +@import 'tailwindcss'; +@import 'fumadocs-ui/css/neutral.css'; +@import 'fumadocs-ui/css/preset.css'; + +:root { + --color-fd-primary: #0ea5e9; + --color-fd-primary-foreground: #04293a; + --color-fd-ring: #0ea5e9; + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +.dark { + --color-fd-primary: #38bdf8; + --color-fd-primary-foreground: #04293a; + --color-fd-ring: #38bdf8; +} + +body { + font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; +} diff --git a/apps/docs/app/layout.tsx b/apps/docs/app/layout.tsx new file mode 100644 index 0000000..dc908bb --- /dev/null +++ b/apps/docs/app/layout.tsx @@ -0,0 +1,33 @@ +import { RootProvider } from 'fumadocs-ui/provider/next'; +import './global.css'; +import { Geist, Geist_Mono } from 'next/font/google'; +import type { Metadata } from 'next'; + +const geist = Geist({ + subsets: ['latin'], + variable: '--font-geist-sans', +}); + +const geistMono = Geist_Mono({ + subsets: ['latin'], + variable: '--font-geist-mono', +}); + +export const metadata: Metadata = { + metadataBase: new URL('https://react-native-cloud-storage.oss.kuatsu.de'), + title: { + default: 'React Native Cloud Storage', + template: '%s | React Native Cloud Storage', + }, + description: 'iCloud and Google Drive for React Native, simplified.', +}; + +export default function Layout({ children }: LayoutProps<'/'>) { + return ( + + + {children} + + + ); +} diff --git a/apps/docs/app/llms-full.txt/route.ts b/apps/docs/app/llms-full.txt/route.ts new file mode 100644 index 0000000..0603b36 --- /dev/null +++ b/apps/docs/app/llms-full.txt/route.ts @@ -0,0 +1,13 @@ +import { getLLMText, source } from '@/lib/source'; + +export const revalidate = false; + +export async function GET() { + const scan = []; + for (const page of source.getPages()) { + scan.push(getLLMText(page)); + } + const scanned = await Promise.all(scan); + + return new Response(scanned.join('\n\n')); +} diff --git a/apps/docs/app/llms.mdx/docs/[[...slug]]/route.ts b/apps/docs/app/llms.mdx/docs/[[...slug]]/route.ts new file mode 100644 index 0000000..fde26d9 --- /dev/null +++ b/apps/docs/app/llms.mdx/docs/[[...slug]]/route.ts @@ -0,0 +1,20 @@ +import { getLLMText, source } from '@/lib/source'; +import { notFound } from 'next/navigation'; + +export const revalidate = false; + +export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) { + const { slug } = await params; + const page = source.getPage(slug); + if (!page) notFound(); + + return new Response(await getLLMText(page), { + headers: { + 'Content-Type': 'text/markdown', + }, + }); +} + +export function generateStaticParams() { + return source.generateParams(); +} diff --git a/apps/docs/app/llms.txt/route.ts b/apps/docs/app/llms.txt/route.ts new file mode 100644 index 0000000..6639c25 --- /dev/null +++ b/apps/docs/app/llms.txt/route.ts @@ -0,0 +1,13 @@ +import { source } from '@/lib/source'; + +export const revalidate = false; + +export async function GET() { + const lines: string[] = []; + lines.push('# Documentation'); + lines.push(''); + for (const page of source.getPages()) { + lines.push(`- [${page.data.title}](${page.url}): ${page.data.description}`); + } + return new Response(lines.join('\n')); +} diff --git a/apps/docs/app/og/docs/[...slug]/route.tsx b/apps/docs/app/og/docs/[...slug]/route.tsx new file mode 100644 index 0000000..b29e8d6 --- /dev/null +++ b/apps/docs/app/og/docs/[...slug]/route.tsx @@ -0,0 +1,27 @@ +import { getPageImage, source } from '@/lib/source'; +import { notFound } from 'next/navigation'; +import { ImageResponse } from 'next/og'; +import { generate as DefaultImage } from 'fumadocs-ui/og'; + +export const revalidate = false; + +export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[...slug]'>) { + const { slug } = await params; + const page = source.getPage(slug.slice(0, -1)); + if (!page) notFound(); + + return new ImageResponse( + , + { + width: 1200, + height: 630, + } + ); +} + +export function generateStaticParams() { + return source.getPages().map((page) => ({ + lang: page.locale, + slug: getPageImage(page).segments, + })); +} diff --git a/apps/docs/components/ai/page-actions.tsx b/apps/docs/components/ai/page-actions.tsx new file mode 100644 index 0000000..bfa507f --- /dev/null +++ b/apps/docs/components/ai/page-actions.tsx @@ -0,0 +1,162 @@ +'use client'; +import { useMemo, useState } from 'react'; +import { Check, ChevronDown, Copy, ExternalLinkIcon, TextIcon } from 'lucide-react'; +import { cn } from '@/lib/cn'; +import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button'; +import { buttonVariants } from 'fumadocs-ui/components/ui/button'; +import { Popover, PopoverContent, PopoverTrigger } from 'fumadocs-ui/components/ui/popover'; + +const cache = new Map(); + +export function LLMCopyButton({ + /** + * A URL to fetch the raw Markdown/MDX content of page + */ + markdownUrl, +}: { + markdownUrl: string; +}) { + const [isLoading, setLoading] = useState(false); + const [checked, onClick] = useCopyButton(async () => { + const cached = cache.get(markdownUrl); + if (cached) return navigator.clipboard.writeText(cached); + + setLoading(true); + + try { + await navigator.clipboard.write([ + new ClipboardItem({ + 'text/plain': fetch(markdownUrl).then(async (res) => { + const content = await res.text(); + cache.set(markdownUrl, content); + + return content; + }), + }), + ]); + } finally { + setLoading(false); + } + }); + + return ( + + ); +} + +export function ViewOptions({ + markdownUrl, + githubUrl, +}: { + /** + * A URL to the raw Markdown/MDX content of page + */ + markdownUrl: string; + + /** + * Source file URL on GitHub + */ + githubUrl: string; +}) { + const items = useMemo(() => { + const pageUrl = (globalThis as { location?: { href: string } }).location?.href ?? 'loading'; + const q = `Read ${pageUrl}, I want to ask questions about it.`; + + return [ + { + title: 'Open in GitHub', + href: githubUrl, + icon: ( + + GitHub + + + ), + }, + { + title: 'View as Markdown', + href: markdownUrl, + icon: , + }, + { + title: 'Open in ChatGPT', + href: `https://chatgpt.com/?${new URLSearchParams({ + hints: 'search', + q, + })}`, + icon: ( + + OpenAI + + + ), + }, + { + title: 'Open in Claude', + href: `https://claude.ai/new?${new URLSearchParams({ + q, + })}`, + icon: ( + + Anthropic + + + ), + }, + { + title: 'Open in Cursor', + icon: ( + + Cursor + + + ), + href: `https://cursor.com/link/prompt?${new URLSearchParams({ + text: q, + })}`, + }, + ]; + }, [githubUrl, markdownUrl]); + + return ( + + + Open + + + + {items.map((item) => ( + + {item.icon} + {item.title} + + + ))} + + + ); +} diff --git a/apps/docs/content/docs/index.mdx b/apps/docs/content/docs/index.mdx new file mode 100644 index 0000000..e29cc68 --- /dev/null +++ b/apps/docs/content/docs/index.mdx @@ -0,0 +1,7 @@ +--- +title: Introduction +description: iCloud and Google Drive for React Native, simplified. +--- + +React Native Cloud Storage allows you to use iCloud (iOS only) and Google Drive as file storage in your +React Native app. diff --git a/apps/docs/content/docs/meta.json b/apps/docs/content/docs/meta.json new file mode 100644 index 0000000..03502a2 --- /dev/null +++ b/apps/docs/content/docs/meta.json @@ -0,0 +1,5 @@ +{ + "title": "React Native Cloud Storage", + "root": true, + "pages": ["index"] +} diff --git a/apps/docs/docs/api/CloudStorage.md b/apps/docs/docs/api/CloudStorage.md deleted file mode 100644 index 0244c58..0000000 --- a/apps/docs/docs/api/CloudStorage.md +++ /dev/null @@ -1,283 +0,0 @@ ---- -sidebar_position: 1 ---- - -# CloudStorage - -The `CloudStorage` class provides the core functionality of the library. File operations loosely follow the conventions of Node's `fs`. - -The class can both be used as a static class and be instantiated. This means you can use both `CloudStorage.readFile()` and `cloudStorageInstance.readFile()`. The former will use a default cloud storage provider based on the platform, while the latter will use a provider of your choice. [Learn more](../guides/using-multiple-providers). All file system operations are available on both the static class and instances, while the available configuration methods differ between the two (see below). - -```ts -import { CloudStorage } from 'react-native-cloud-storage'; -``` - -## Definitions - -### `path` / `remotePath` / `localPath` - -When a method takes a `path`, `remotePath` or `localPath` parameter, you should provide a full path on the remote cloud storage or local file system respectively with a leading slash, but no trailing slashes: - -- ❌ `some/file.txt` -- ❌ `file:///some/file.txt` -- ❌ `/some/directory/` -- ✅ `/some/file.txt` -- ✅ `/some/directory` - -:::caution - -When creating files or directories, always make sure that all parent directories in the tree already exist. Otherwise the library will throw a [`CloudStorageErrorCode.DIRECTORY_NOT_FOUND`](./enums/CloudStorageErrorCode). - -::: - -## Constructor - -### `new CloudStorage(provider, options)` - -Creates a new `CloudStorage` instance using the given provider. - -**Parameters**: - -- `provider` ([`CloudStorageProvider`](./enums/CloudStorageProvider)): Optional. The provider to use. Defaults to the default provider of the current platform. -- `options` (`object`): Optional. The options to set for the provider. [See here](./enums/CloudStorageProvider#provider-options) for a list of available options per provider. - -## Configuration methods - -### `getDefaultInstance()` - -- **Available on static class**: ✅ Yes -- **Available on instances**: ❌ No - -Gets the internal default instance of `CloudStorage`. - -**Returns**: The default `CloudStorage` instance, used when calling static methods. - -### `getDefaultProvider()` - -- **Available on static class**: ✅ Yes -- **Available on instances**: ❌ No - -Gets the default cloud storage provider for the current platform. - -**Returns**: The default [`CloudStorageProvider`](./enums/CloudStorageProvider) for the current platform (e.g. [`CloudStorageProvider.ICloud`](./enums/CloudStorageProvider) on iOS and [`CloudStorageProvider.GoogleDrive`](./enums/CloudStorageProvider) on all other platforms). - -### `getProvider()` - -- **Available on static class**: ✅ Yes (gets the provider of the static default instance) -- **Available on instances**: ✅ Yes - -Gets the cloud storage provider currently in use. - -**Returns**: The currently used [`CloudStorageProvider`](./enums/CloudStorageProvider). - -### `getProviderOptions()` - -- **Available on static class**: ✅ Yes (gets the options of the static default instance) -- **Available on instances**: ✅ Yes - -Gets the currently set options of the current provider. - -**Returns**: The options of the given provider. - -### `getSupportedProviders()` - -- **Available on static class**: ✅ Yes -- **Available on instances**: ❌ No - -Gets the list of supported cloud storage providers on the current platform. - -**Returns**: An array of [`CloudStorageProvider`](./enums/CloudStorageProvider) values. - -### `setProvider(provider)` - -- **Available on static class**: ✅ Yes (sets the provider of the static default instance) -- **Available on instances**: ✅ Yes - -Sets the cloud storage provider to use. - -:::tip - -Use `Platform.select` to set the provider based on the platform: - -```ts -import { Platform } from 'react-native'; -import { CloudStorage, CloudStorageProvider } from 'react-native-cloud-storage'; - -CloudStorage.setProvider( - Platform.select({ - ios: CloudStorageProvider.ICloud, - default: CloudStorageProvider.GoogleDrive, - }) -); -``` - -::: - -**Parameters**: - -- `provider` ([`CloudStorageProvider`](./enums/CloudStorageProvider)): Required. The provider to set. - -**Returns**: `void`. - -### `setProviderOptions(options)` - -- **Available on static class**: ✅ Yes (sets the options of the static default instance) -- **Available on instances**: ✅ Yes - -Sets the options of the current provider. For a list of available options per provider, [see here](./enums/CloudStorageProvider#provider-options). - -**Parameters**: - -- `options` (`object`): Required. The options to set. [See here](./enums/CloudStorageProvider#provider-options) for a list of available options per provider. - -**Returns**: `void`. - -## File system operations - -All file system operations are available on both the static class and instances. When using the static class, the operation will be performed using the default provider (or the provider set via [`setProvider()`](#setproviderprovider)). - -### `appendFile(path, data, scope)` - -Appends the data to the file at the given path. Creates the file if it doesn't exist yet. - -**Parameters**: - -- `path` (`string`): Required. The path including the filename to append data to. -- `content` (`string`): Required. The content to append. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to `void` once the data has been appended. - -### `downloadFile(remotePath, localPath, scope)` - -Downloads the file at the given remote path to the given local path. - -**Parameters**: - -- `remotePath` (`string`): Required. The remote path of the file to download. -- `localPath` (`string`): Required. The local path to download the file to, including the filename of the downloaded file. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to `void` once the file has been downloaded. - -### `exists(path, scope)` - -Tests whether or not the file or directory at the given path exists. - -**Parameters**: - -- `path` (`string`): Required. The path to test. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to a `boolean`. `true` if a file or directory exists at the given path, `false` otherwise. - -### `isCloudAvailable()` - -Tests whether or not the cloud storage is available. -When using iCloud, this actually verifies with the system whether or not iCloud is available. This might not be the case right at app launch or when the user is not logged into iCloud. -For Google Drive, this simply checks whether or not an access token has been set within the provider options. - -**Returns**: A `Promise` that resolves to a `boolean`. `true` if the cloud storage is available, `false` otherwise. - -### `mkdir(path, scope)` - -Creates a new directory at the given path. - -**Parameters**: - -- `path` (`string`): Required. The path of the new directory to create. All parent directories must already exist. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves once the directory has been created. - -### `readdir(path, scope)` - -Reads the files and directories contained in the directory at the given path. Does not include `.` and `..` entries. - -**Parameters**: - -- `path` (`string`): Required. The full pathname of the directory to read. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to an array of `string`s containing the names of the files and directories in the given directory. - -### `readFile(path, scope)` - -Reads the file at the given path into a `string`. - -**Parameters**: - -- `path` (`string`): Required. The full pathname of the file to read. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to a `string` containing the file's content. - -### `rmdir(path, options, scope)` - -Deletes the directory at the given path. Can optionally delete the directory including all its contents (recursively). - -**Parameters**: - -- `path` (`string`): Required. The full pathname of the directory to delete. -- `options` (`{ recursive?: boolean }`): Optional. An object containing the `recursive` property which, if set to `true`, will delete the directory including all its contents (recursively). If set to `false` (or omitted), the library will throw a [`CloudStorageErrorCode.DIRECTORY_NOT_EMPTY`](./enums/CloudStorageErrorCode) if the directory is not empty. Defaults to `{ recursive: false }`. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves once the directory has been deleted. - -### `stat(path, scope)` - -Gets several file statistics of the file at the given path. - -**Parameters**: - -- `path` (`string`): Required. The full pathname of the file to stat. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to [`CloudStorageFileStat`](./interfaces/CloudStorageFileStat) object containing the statistics. - -### `triggerSync(path, scope)` - -When a file has been uploaded to iCloud, it is not immediately synced across devices. In this case, those files will have an `.icloud` extension, so trying to read them will fail. This method will download the file from iCloud so you can safely process it afterwards. If it has already been synced, this will not do anything and immediately return. Does not have any effect on Google Drive. - -**Parameters**: - -- `path` (`string`): Required. The path including the filename to download. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to `void` once the download has been triggered. - -### `unlink(path, scope)` - -Deletes the file at the given path. - -**Parameters**: - -- `path` (`string`): Required. The full pathname of the file to delete. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to `void` once the file has been deleted. - -### `uploadFile(remotePath, localPath, options, scope)` - -Uploads the file at the given local path to the given remote path, creating it if it doesn't exist or overwriting it if it does. - -**Parameters**: - -- `remotePath` (`string`): Required. The remote path to upload to. -- `localPath` (`string`): Required. The local path of the file to upload. -- `options` (`{ mimeType: string }`): Required. The options for the upload. Must contain a `mimeType` property. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to `void` once the file has been uploaded. - -### `writeFile(path, data, scope)` - -Writes the data to the given path. Creates the file if it doesn't exist yet and overwrites it otherwise. - -**Parameters**: - -- `path` (`string`): Required. The path including the filename to write to. -- `content` (`string`): Required. The content to write. -- `scope` ([`CloudStorageScope`](./enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](./enums/CloudStorageScope), unless the default scope has been changed via [`setProviderOptions()`](#setprovideroptionsoptions). - -**Returns**: A `Promise` that resolves to `void` once the file has been written. diff --git a/apps/docs/docs/api/CloudStorageError.md b/apps/docs/docs/api/CloudStorageError.md deleted file mode 100644 index 0c30b7c..0000000 --- a/apps/docs/docs/api/CloudStorageError.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -sidebar_position: 2 ---- - -# CloudStorageError - -`CloudStorageError` is a custom error class which wraps most of the errors produced by the library. - -```ts -import { CloudStorageError } from 'react-native-cloud-storage'; -``` - -## API - -The class provides three properties: - -- `message` (`string`): The error message. -- `code` ([`CloudStorageErrorCode`](./enums/CloudStorageErrorCode)): The error code which can be used to determine the type of the error. -- `details` (`any`): Optionally, any details like raw errors. - -## Example - -```ts -import { CloudStorage, CloudStorageError, CloudStorageErrorCode } from 'react-native-cloud-storage'; - -try { - await CloudStorage.stat('test.txt'); -} catch (e: unknown) { - if (e instanceof CloudStorageError && e.code === CloudStorageErrorCode.FILE_NOT_FOUND) { - console.log('File not found'); - } else { - console.warn(e); - } -} -``` diff --git a/apps/docs/docs/api/_category_.json b/apps/docs/docs/api/_category_.json deleted file mode 100644 index 7e1d166..0000000 --- a/apps/docs/docs/api/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "API Reference", - "position": 3 -} diff --git a/apps/docs/docs/api/enums/CloudStorageErrorCode.md b/apps/docs/docs/api/enums/CloudStorageErrorCode.md deleted file mode 100644 index dd05851..0000000 --- a/apps/docs/docs/api/enums/CloudStorageErrorCode.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -sidebar_position: 3 ---- - -# CloudStorageErrorCode - -`CloudStorageErrorCode` is a TypeScript enum containing the possible error codes of a [`CloudStorageError`](../CloudStorageError). - -```ts -import { CloudStorageErrorCode } from 'react-native-cloud-storage'; -``` - -## Definition - -```ts -enum CloudStorageErrorCode { - INVALID_SCOPE = 'ERR_INVALID_SCOPE', - FILE_NOT_FOUND = 'ERR_FILE_NOT_FOUND', - PATH_IS_DIRECTORY = 'ERR_PATH_IS_DIRECTORY', - PATH_IS_FILE = 'ERR_PATH_IS_FILE', - DIRECTORY_NOT_FOUND = 'ERR_DIRECTORY_NOT_FOUND', - DIRECTORY_NOT_EMPTY = 'ERR_DIRECTORY_NOT_EMPTY', - FILE_ALREADY_EXISTS = 'ERR_FILE_EXISTS', // also used when a directory already exists - MULTIPLE_FILES_SAME_NAME = 'ERR_MULTIPLE_FILES_SAME_NAME', - AUTHENTICATION_FAILED = 'ERR_AUTHENTICATION_FAILED', - WRITE_ERROR = 'ERR_WRITE_ERROR', - READ_ERROR = 'ERR_READ_ERROR', - DELETE_ERROR = 'ERR_DELETE_ERROR', - STAT_ERROR = 'ERR_STAT_ERROR', - UNKNOWN = 'ERR_UNKNOWN', - FILE_NOT_DOWNLOADABLE = 'ERR_FILE_NOT_DOWNLOADABLE', - ACCESS_TOKEN_MISSING = 'ERR_ACCESS_TOKEN_MISSING', - INVALID_URL = 'ERR_INVALID_URL', - NETWORK_ERROR = 'ERR_NETWORK_ERROR', -} -``` - -When using pure JavaScript, simply use the corresponding values: - -```js -if (e instanceof CloudStorageError && e.code === 'FILE_NOT_FOUND') { - /* do something */ -} -``` diff --git a/apps/docs/docs/api/enums/CloudStorageProvider.md b/apps/docs/docs/api/enums/CloudStorageProvider.md deleted file mode 100644 index 410dbfc..0000000 --- a/apps/docs/docs/api/enums/CloudStorageProvider.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -sidebar_position: 1 ---- - -# CloudStorageProvider - -The `CloudStorageProvider` defines which cloud storage is used. Currently, only iCloud and Google Drive are supported. - -By default, the provider is set based on the device's platform. On iOS, iCloud is used, while on all other platforms, Google Drive is used. This can be overriden by calling [`setProvider()`](../CloudStorage#setproviderprovider). You can therefore optionally use Google Drive on iOS, too, instead of iCloud. - -```ts -import { CloudStorageScope } from 'react-native-cloud-storage'; -``` - -## Definition - -```ts -enum CloudStorageProvider { - ICloud = 'icloud', - GoogleDrive = 'googledrive', -} -``` - -When using pure JavaScript, simply use the corresponding values: - -```js -CloudStorage.setProvider('googledrive'); -``` - -## Provider options - -The provider options can be set via [`setProviderOptions()`](../CloudStorage#setprovideroptionsoptions). The following options are available: - -### `CloudStorageProvider.ICloud` - -- `scope` (`CloudStorageScope`): The directory scope to use. Default: `CloudStorageScope.AppData`. -- `documentsMode` (`'icloud' | 'legacy_sandbox'`): Defines how `CloudStorageScope.Documents` is resolved. Use `'icloud'` for the iCloud `Documents` folder (default) or `'legacy_sandbox'` to use the local app sandbox `Documents` folder (which was the default before react-native-cloud-storage v3). - -If you need to move existing files from legacy sandbox storage into the user-facing iCloud Documents folder, see [this migration guide](../../guides/migrating-icloud-documents). - -### `CloudStorageProvider.GoogleDrive` - -- `accessToken` (`string`): The access token to use. Required. -- `scope` (`CloudStorageScope`): The directory scope to use. Default: `CloudStorageScope.AppData`. -- `strictFilenames` (`boolean`): If set to `true`, the library will check for files with duplicate filenames and throw an error if found. File operations will not be carried out in that case. For more information, [see here](../../guides/google-drive-files-same-name). Default: `false`. -- `timeout` (`number`): The timeout in milliseconds for requests. Default: 3000. diff --git a/apps/docs/docs/api/enums/CloudStorageScope.md b/apps/docs/docs/api/enums/CloudStorageScope.md deleted file mode 100644 index 182cfe8..0000000 --- a/apps/docs/docs/api/enums/CloudStorageScope.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -sidebar_position: 2 ---- - -# CloudStorageScope - -`CloudStorageScope` is a TypeScript enum containing the possible values for the `scope` parameters of the rest of the API. - -Available scopes are `documents` and `app_data`. When using `documents`, data will be stored in the user-visible root directory of the cloud storage. When using `app_data`, the directory for app-specific data, usually hidden from the user, will be used. By default, all methods will use the `app_data` scope. This can either be overriden by explicitly providing a scope to the method or by setting a default scope on the provider using [`setProviderOptions({ scope })`](../CloudStorage#setprovideroptionsoptions). On iCloud, you can temporarily opt into the old sandbox-based behavior of `documents` with [`documentsMode: 'legacy_sandbox'`](./CloudStorageProvider#provider-options). - -```ts -import { CloudStorageScope } from 'react-native-cloud-storage'; -``` - -## Definition - -```ts -enum CloudStorageScope { - Documents = 'documents', - AppData = 'app_data', -} -``` - -When using pure JavaScript, simply use the corresponding values: - -```js -CloudStorage.exists('/test.txt', 'documents'); -``` diff --git a/apps/docs/docs/api/enums/_category_.json b/apps/docs/docs/api/enums/_category_.json deleted file mode 100644 index ab2a23e..0000000 --- a/apps/docs/docs/api/enums/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Enums", - "position": 5 -} diff --git a/apps/docs/docs/api/hooks/_category_.json b/apps/docs/docs/api/hooks/_category_.json deleted file mode 100644 index 5080206..0000000 --- a/apps/docs/docs/api/hooks/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Hooks", - "position": 3 -} diff --git a/apps/docs/docs/api/hooks/useCloudFile.md b/apps/docs/docs/api/hooks/useCloudFile.md deleted file mode 100644 index fbae271..0000000 --- a/apps/docs/docs/api/hooks/useCloudFile.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -sidebar_position: 1 ---- - -# useCloudFile - -The `useCloudFile` hook is a helper hook designed to improve the developer experience when working with a single file in the cloud. This is especially useful when, for example, working with a single file containing the app's state as backup. - -```ts -import { useCloudFile } from 'react-native-cloud-storage'; -``` - -## API - -**Parameters**: - -- `path` (`string`): Required. The full pathname of the file to use. See [the definition of this parameter in `CloudStorage`](../CloudStorage#path). -- `scope` ([`CloudStorageScope`](../enums/CloudStorageScope)): Optional. The storage scope (documents/app data) to use. Defaults to [`CloudStorageScope.AppData`](../enums/CloudStorageScope), unless the default scope of the provider has been changed via [`setProviderOptions()`](../CloudStorage#setprovideroptionsoptions). -- `cloudStorageInstance` ([`CloudStorage`](../CloudStorage)): Optional. An instance of [`CloudStorage`](../CloudStorage). If not specified, the default static instance will be used. - -**Returns**: An object containing the following properties: - -- `content`: The content of the file (`string`, or `null` if the file does not exist). -- `sync()`: Function to sync the file's content from iCloud to the device. Refer to [`triggerSync()`](../CloudStorage#triggersyncpath-scope) for more information. -- `read()`: Function to re-read the file (automatically called on every `write` call and change of `path` or `scope`). -- `write(newContent)`: Function to write the content of the first parameter (`string`) to the file. **Note**: This will overwrite the file's current content. Automatically calls `read()` afterwards. -- `remove()`: Function to delete the file. - -## Example - -```tsx -import React, { useState, useEffect } from 'react'; -import { useCloudFile } from 'react-native-cloud-storage'; - -const App: React.FC = () => { - const { content, read, write, remove } = useCloudFile('/test.txt'); - - const [counter, setCounter] = useState(0); - - useEffect(() => { - write(counter); - }, [counter]); - - const increase = () => { - setCounter((prevCounter) => prevCounter + 1); - }; - - return ( - - {content ?? 'File not found'} -