diff --git a/AGENTS.md b/AGENTS.md index 025b258..92dab1d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,12 +18,62 @@ This is a monorepo for **React Auth**, a library that simplifies authentication ### Examples -Located in `examples/`. These are **not** published — they exist for documentation and manual testing only. +Located in `examples/`. These are **not** published — they exist for documentation and manual testing only. They are **not** part of the pnpm workspace; each example manages its own dependencies. -- `examples/base/` — minimal Vite + React example -- `examples/reqres/` — authenticates against the ReqRes API -- `examples/refresh-token/` — demonstrates token refresh with Axios interceptors -- `examples/expo/` — React Native (Expo) integration +| Example | Path | Description | +| --- | --- | --- | +| Base | `examples/base/` | Minimal Vite + React example | +| ReqRes | `examples/reqres/` | Authenticates against the ReqRes API | +| Refresh Token | `examples/refresh-token/` | Token refresh with Axios interceptors | +| Expo | `examples/expo/` | React Native (Expo) integration | +| Showcase | `examples/showcase/` | Comprehensive example of all library features | + +#### Convention: referencing the core library in examples + +All examples follow a **two-layer** convention for depending on `@forward-software/react-auth`: + +1. **`package.json`** — lists the latest published version (e.g. `"2.1.0"`). This makes the example buildable as a standalone project. +2. **Build-tool / TypeScript alias** — when developing inside the monorepo, the bundler resolves the import to the local lib source (`../../lib/src/index.ts`), so changes to `lib/` are reflected immediately without a separate build step. + +**Vite-based examples** add the alias in `vite.config.ts`: + +```ts +resolve: { + alias: { + '@forward-software/react-auth': path.resolve(__dirname, '../../lib/src/index.ts'), + }, +}, +``` + +And a matching `paths` entry in `tsconfig.json` under `compilerOptions`: + +```json +{ + "paths": { + "@forward-software/react-auth": ["./../../lib/src/index.ts"] + } +} +``` + +**Expo / React Native examples** use `babel-plugin-module-resolver` in `babel.config.js`: + +```js +plugins: [ + ['module-resolver', { alias: { '@forward-software/react-auth': '../../lib' } }], +], +``` + +And a matching `paths` entry in `tsconfig.json` under `compilerOptions` for IDE/tsc resolution (uses a wildcard because `expo/tsconfig.base` does not need `baseUrl`): + +```json +{ + "paths": { + "@forward-software/react-auth/*": ["../../lib/*"] + } +} +``` + +When adding a new example, apply the same two-layer setup and update the tables in `CONTRIBUTING.md`, `AGENTS.md`, and `examples/README.md`. --- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a686fb..d034fb6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,6 +80,7 @@ Located in `examples/`. These are **not** published — they exist for documenta - `examples/reqres/` — authenticates against the ReqRes API - `examples/refresh-token/` — demonstrates token refresh with Axios interceptors - `examples/expo/` — React Native (Expo) integration +- `examples/showcase/` — comprehensive example of all library features ### Core library (`lib/`) @@ -188,6 +189,78 @@ Adapter packages live under `packages/` and should follow these conventions: - `AGENTS.md` — update the Project overview packages table and any architecture sections that reference existing packages. - Create a `README.md` in the package directory with install instructions, quick start, API reference, and consistent badges/footer (follow the structure of `packages/google-signin/README.md`). +## Contributing examples + +Examples live in `examples/` and exist for documentation and manual testing. They are **not** published and are **not** part of the pnpm workspace. + +### Convention: referencing the core library + +Example apps follow a **two-layer** convention for depending on `@forward-software/react-auth`: + +1. **`package.json`** — lists the latest published version (e.g. `"2.1.0"`). This makes the example buildable as a standalone project. +2. **Build-tool / TypeScript alias** — when developing inside the monorepo, the bundler resolves the import to the local lib source (`../../lib/src/index.ts`), so changes to `lib/` are reflected immediately without a separate build step. + +**Vite-based examples** configure the alias in `vite.config.ts` and `tsconfig.json`: + +```ts +// vite.config.ts +import path from 'node:path'; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@forward-software/react-auth': path.resolve(__dirname, '../../lib/src/index.ts'), + }, + }, +}); +``` + +```json +// tsconfig.json — under "compilerOptions" +{ + "paths": { + "@forward-software/react-auth": ["./../../lib/src/index.ts"] + } +} +``` + +**Expo / React Native examples** configure the alias in `babel.config.js` via `babel-plugin-module-resolver`: + +```js +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: [ + ['module-resolver', { alias: { '@forward-software/react-auth': '../../lib' } }], + ], + }; +}; +``` + +And a matching `paths` entry in `tsconfig.json` under `compilerOptions` for IDE/tsc resolution (uses a wildcard because `expo/tsconfig.base` does not need `baseUrl`): + +```json +// tsconfig.json — under "compilerOptions" +{ + "paths": { + "@forward-software/react-auth/*": ["../../lib/*"] + } +} +``` + +### Adding a new example + +1. Create the example under `examples//`. +2. Add `@forward-software/react-auth` as a dependency with the **current published version** in `package.json`. +3. Configure the bundler path alias and TypeScript `paths` mapping as shown above. +4. Mark the package as `"private": true` in `package.json`. +5. Do **not** add the example to `pnpm-workspace.yaml` — examples install their own dependencies independently. +6. Add the example to the tables in `CONTRIBUTING.md`, `AGENTS.md`, and `examples/README.md`. + ## Testing All packages use **Vitest** with **jsdom**, **@testing-library/react**, and **@testing-library/jest-dom**. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..3eb8ef2 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,106 @@ +# Examples + +This directory contains example applications that demonstrate how to use `@forward-software/react-auth`. They exist for documentation and manual testing purposes only — they are **not** published to npm and are **not** part of the pnpm workspace. + +## Available examples + +| Example | Path | Description | +| --- | --- | --- | +| Base | `base/` | Minimal Vite + React example | +| ReqRes | `reqres/` | Authenticates against the [ReqRes](https://reqres.in/) API | +| Refresh Token | `refresh-token/` | Token refresh with Axios interceptors | +| Expo | `expo/` | React Native (Expo) integration | +| Showcase | `showcase/` | Comprehensive example of all library features | + +## Running an example + +Each example manages its own dependencies. To run one, install its dependencies first and then start the dev server: + +```sh +# Vite-based examples (base, reqres, refresh-token, showcase) +cd examples/ +pnpm install +pnpm dev + +# Expo example +cd examples/expo +pnpm install # or: npx pod-install (iOS only, after pnpm install) +npx expo start +``` + +> **Tip**: If you have already run `pnpm install` at the monorepo root, the examples resolve `@forward-software/react-auth` to the local lib source automatically (see below). You still need to `pnpm install` inside the example directory to install its own dependencies. + +## Convention: referencing the core library + +Example apps follow a **two-layer** convention for depending on `@forward-software/react-auth`: + +1. **`package.json`** — lists the latest published version (e.g. `"2.1.0"`). This makes the example usable as a standalone project after cloning. + +2. **Build-tool / TypeScript alias** — when developing inside the monorepo, the bundler resolves the import to the local lib source (`../../lib/src/index.ts`). This means any change you make to `lib/` is reflected immediately in the example without a separate build step. + +### Vite-based examples + +Configure the alias in two places: + +**`vite.config.ts`** + +```ts +import path from 'node:path'; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@forward-software/react-auth': path.resolve(__dirname, '../../lib/src/index.ts'), + }, + }, + // ... +}); +``` + +**`tsconfig.json`** (under `compilerOptions`) + +```json +{ + "paths": { + "@forward-software/react-auth": ["./../../lib/src/index.ts"] + } +} +``` + +### Expo / React Native examples + +Configure the alias in `babel.config.js` using [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver): + +```js +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: [ + ['module-resolver', { alias: { '@forward-software/react-auth': '../../lib' } }], + ], + }; +}; +``` + +And a matching `paths` entry in `tsconfig.json` under `compilerOptions` for IDE/tsc resolution (uses a wildcard because `expo/tsconfig.base` does not need `baseUrl`): + +```json +{ + "paths": { + "@forward-software/react-auth/*": ["../../lib/*"] + } +} +``` + +## Adding a new example + +1. Create the example under `examples//`. +2. Add `@forward-software/react-auth` as a dependency with the **current published version** in `package.json`. +3. Configure the bundler path alias and TypeScript `paths` mapping as shown above. +4. Mark the package as `"private": true` in `package.json`. +5. Do **not** add the example to `pnpm-workspace.yaml` — examples manage their own dependencies independently. +6. Add the example to the table in this README and to the examples list in `CONTRIBUTING.md` and `AGENTS.md`. diff --git a/examples/base/tsconfig.json b/examples/base/tsconfig.json index 8264c3f..a78dbd0 100644 --- a/examples/base/tsconfig.json +++ b/examples/base/tsconfig.json @@ -16,7 +16,11 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "esModuleInterop": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "baseUrl": ".", + "paths": { + "@forward-software/react-auth": ["./../../lib/src/index.ts"] + } }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/base/vite.config.ts b/examples/base/vite.config.ts index ff3916e..308f945 100644 --- a/examples/base/vite.config.ts +++ b/examples/base/vite.config.ts @@ -1,8 +1,14 @@ +import path from 'node:path' import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], + resolve: { + alias: { + '@forward-software/react-auth': path.resolve(__dirname, '../../lib/src/index.ts'), + }, + }, server: { port: 3000, open: true diff --git a/examples/refresh-token/tsconfig.json b/examples/refresh-token/tsconfig.json index 8264c3f..a78dbd0 100644 --- a/examples/refresh-token/tsconfig.json +++ b/examples/refresh-token/tsconfig.json @@ -16,7 +16,11 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "esModuleInterop": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "baseUrl": ".", + "paths": { + "@forward-software/react-auth": ["./../../lib/src/index.ts"] + } }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/refresh-token/vite.config.ts b/examples/refresh-token/vite.config.ts index 9daae9c..ba2235a 100644 --- a/examples/refresh-token/vite.config.ts +++ b/examples/refresh-token/vite.config.ts @@ -1,8 +1,14 @@ +import path from 'node:path' import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], + resolve: { + alias: { + '@forward-software/react-auth': path.resolve(__dirname, '../../lib/src/index.ts'), + }, + }, server: { port: 3002, open: true diff --git a/examples/reqres/tsconfig.json b/examples/reqres/tsconfig.json index 8264c3f..a78dbd0 100644 --- a/examples/reqres/tsconfig.json +++ b/examples/reqres/tsconfig.json @@ -16,7 +16,11 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "esModuleInterop": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "baseUrl": ".", + "paths": { + "@forward-software/react-auth": ["./../../lib/src/index.ts"] + } }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/examples/reqres/vite.config.ts b/examples/reqres/vite.config.ts index b785528..f222ce9 100644 --- a/examples/reqres/vite.config.ts +++ b/examples/reqres/vite.config.ts @@ -1,8 +1,14 @@ +import path from 'node:path' import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], + resolve: { + alias: { + '@forward-software/react-auth': path.resolve(__dirname, '../../lib/src/index.ts'), + }, + }, server: { port: 3001, open: true