diff --git a/README.md b/README.md index 6c7b641..ec0eadd 100644 --- a/README.md +++ b/README.md @@ -488,6 +488,23 @@ queue() factory | `@neovici/cosmoz-queue/list/more/render` | `renderLoadMore()` -- "Load more" button | | `@neovici/cosmoz-queue/util/fetch` | `fetch()`, `setBaseInit()`, `handleJSON()`, `RequestError` | +## Deprecation notices + +### `api` property → `details` + +The `api` property on `useQueue()` / `queue()` is **deprecated** and will be +removed in v2.0.0. Use `details` instead: + +```ts +// Before (deprecated) +queue({ api: (id, item) => apiUrl(`items/${id}`) }) + +// After +queue({ details: (item) => fetch(apiUrl(`items/${item.id}`)).then(r => r.json()) }) +``` + +See [Migration guide](docs/migration-api-to-details.md) for more patterns. + ## License [Apache-2.0](LICENSE) diff --git a/docs/migration-api-to-details.md b/docs/migration-api-to-details.md new file mode 100644 index 0000000..e7bf03e --- /dev/null +++ b/docs/migration-api-to-details.md @@ -0,0 +1,54 @@ +# Migration: `api` → `details` + +The `api` property on `useQueue()` / `queue()` is deprecated and will be removed in v2.0.0. + +## Quick reference + +| `api` (deprecated) | `details` (recommended) | +| --- | --- | +| `(id, item) => urlString` | `(item) => Promise` | +| Two params — `id` and `item` | One param — `item` | +| Returns a URL string | Returns a Promise resolving to data | +| Uses internal `json()` utility | Uses standard `fetch()` or any async source | + +## Migration patterns + +### Basic URL + +```ts +// Before +api: (id, item) => `/api/items/${id}` + +// After +details: (item) => fetch(`/api/items/${item.id}`).then(r => r.json()) +``` + +### With `apiUrl` helper + +```ts +// Before +api: (id, item) => apiUrl(`api/items/${id}`, { includeDetails: true }) + +// After +details: (item) => + fetch(apiUrl(`api/items/${item.id}`, { includeDetails: true })) + .then(r => r.json()) +``` + +### Async / await with error handling + +```ts +details: async (item) => { + const response = await fetch(`/api/items/${item.id}`); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + return response.json(); +}; +``` + +## Timeline + +| Version | Status | +| --- | --- | +| **v1.7.0** | `api` deprecated — runtime `console.warn` emitted | +| **v1.x** | `api` continues to work with warnings | +| **v2.0.0** | `api` removed — migrate before this release | diff --git a/src/queue/use-queue.ts b/src/queue/use-queue.ts index 89c21ff..49c96c9 100644 --- a/src/queue/use-queue.ts +++ b/src/queue/use-queue.ts @@ -24,9 +24,35 @@ const useQNav = ({ items, ...thru }: { + /** + * @deprecated Use the `details` property instead. The `api` property will be removed in v2.0.0. + * + * Migration example: + * ```ts + * // Before: + * api: (id, item) => apiUrl(`api/items/${id}`) + * + * // After: + * details: (item) => fetch(apiUrl(`api/items/${item.id}`)).then(res => res.json()) + * ``` + */ api?: (id: string, item: I) => string; items: I[]; } & UseDataNav) => { + // Deprecation warning + /* eslint-disable no-console, no-template-curly-in-string */ + if (api && typeof console !== 'undefined' && console.warn) { + console.warn( + '[cosmoz-queue] DEPRECATED: The `api` property is deprecated and will be removed in v2.0.0. ' + + 'Please migrate to the `details` property for better control and performance.\n\n' + + 'Migration guide:\n' + + ' Before: api: (id, item) => apiUrl(\'api/items/${id}\')\n' + + ' After: details: (item) => fetch(apiUrl(\'api/items/${item.id}\')).then(res => res.json())\n\n' + + 'See: https://github.com/Neovici/cosmoz-queue#migration-from-api-to-details', + ); + } + /* eslint-enable no-console, no-template-curly-in-string */ + const details = useMemo( () => api && memoize((item: I) => json(api(id(item), item))), [id, api], @@ -45,6 +71,25 @@ interface Opts tabHashParam?: string; idHashParam?: string; onActivate?: (name: string) => void; + /** + * @deprecated Use the `details` property instead. The `api` property will be removed in v2.0.0. + * + * The `api` property uses deprecated utilities and is less flexible than `details`. + * With `details`, you have full control over the fetch operation and can return any Promise. + * + * Migration example: + * ```ts + * // Before: + * useQueue({ + * api: (id, item) => apiUrl(`api/items/${id}`) + * }) + * + * // After: + * useQueue({ + * details: (item) => fetch(apiUrl(`api/items/${item.id}`)).then(res => res.json()) + * }) + * ``` + */ api?: (id: string, item: I) => string; id?: (i: I) => string; split?: SplitOpts;