@lyeve-labs/client-react 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # @lyeve/cms-client-react
1
+ # @lyeve-labs/client-react
2
2
 
3
3
  React hooks for the LyEve Core. Typed, reactive data fetching built on
4
- `@lyeve/cms-client`.
4
+ `@lyeve-labs/client`.
5
5
 
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
7
  [![React](https://img.shields.io/badge/React-18+-61dafb.svg)](https://react.dev)
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178c6.svg)](https://www.typescriptlang.org)
9
9
 
10
10
  ```bash
11
- pnpm add @lyeve/cms-client @lyeve/cms-client-react
11
+ pnpm add @lyeve-labs/client @lyeve-labs/client-react
12
12
  ```
13
13
 
14
14
  ```tsx
15
- import { CmsProvider, useQuery, useMutation } from "@lyeve/cms-client-react";
16
- import { getSchemas, createSchema } from "@lyeve/cms-client-rest";
15
+ import { CmsProvider, useQuery, useMutation } from "@lyeve-labs/client-react";
16
+ import { getSchemas, createSchema } from "@lyeve-labs/client-rest";
17
17
 
18
18
  function App() {
19
19
  return (
@@ -51,14 +51,14 @@ loading, refetch }`. Preserves existing data on fetch errors to prevent UI flash
51
51
 
52
52
  - **Node 20** or newer
53
53
  - **React 18** or newer
54
- - **[@lyeve/cms-client](https://www.npmjs.com/package/@lyeve/cms-client)** `>=0.1.0`
54
+ - **[@lyeve-labs/client](https://www.npmjs.com/package/@lyeve-labs/client)** `>=0.1.0`
55
55
 
56
56
  ## Install
57
57
 
58
58
  ```bash
59
- pnpm add @lyeve/cms-client @lyeve/cms-client-react
60
- # or npm install @lyeve/cms-client @lyeve/cms-client-react
61
- # or yarn add @lyeve/cms-client @lyeve/cms-client-react
59
+ pnpm add @lyeve-labs/client @lyeve-labs/client-react
60
+ # or npm install @lyeve-labs/client @lyeve-labs/client-react
61
+ # or yarn add @lyeve-labs/client @lyeve-labs/client-react
62
62
  ```
63
63
 
64
64
  ## Use
@@ -68,7 +68,7 @@ pnpm add @lyeve/cms-client @lyeve/cms-client-react
68
68
  Wrap your app once at the root:
69
69
 
70
70
  ```tsx
71
- import { CmsProvider } from "@lyeve/cms-client-react";
71
+ import { CmsProvider } from "@lyeve-labs/client-react";
72
72
 
73
73
  function App() {
74
74
  return (
@@ -87,8 +87,8 @@ function App() {
87
87
  ### useQuery
88
88
 
89
89
  ```tsx
90
- import { useQuery } from "@lyeve/cms-client-react";
91
- import { getSchemas } from "@lyeve/cms-client-rest";
90
+ import { useQuery } from "@lyeve-labs/client-react";
91
+ import { getSchemas } from "@lyeve-labs/client-rest";
92
92
 
93
93
  function SchemaList() {
94
94
  const { data, error, loading, refetch } = useQuery((client) =>
@@ -111,8 +111,8 @@ function SchemaList() {
111
111
  ### useMutation
112
112
 
113
113
  ```tsx
114
- import { useMutation } from "@lyeve/cms-client-react";
115
- import { createSchema } from "@lyeve/cms-client-rest";
114
+ import { useMutation } from "@lyeve-labs/client-react";
115
+ import { createSchema } from "@lyeve-labs/client-rest";
116
116
 
117
117
  function CreateForm() {
118
118
  const [create, { loading, error }] = useMutation(
@@ -197,7 +197,7 @@ tests/ # vitest test suite
197
197
 
198
198
  ## Versioning
199
199
 
200
- `@lyeve/cms-client-react` follows [SemVer](https://semver.org). While under `1.0`,
200
+ `@lyeve-labs/client-react` follows [SemVer](https://semver.org). While under `1.0`,
201
201
  breaking changes bump the **minor** version; additive changes bump the **patch**.
202
202
  Every release is logged in [`CHANGELOG.md`](CHANGELOG.md).
203
203
 
package/dist/index.cjs CHANGED
@@ -25,7 +25,7 @@ __export(src_exports, {
25
25
  useQuery: () => useQuery
26
26
  });
27
27
  module.exports = __toCommonJS(src_exports);
28
- var import_cms_client = require("@lyeve/cms-client");
28
+ var import_client = require("@lyeve-labs/client");
29
29
  var import_react = require("react");
30
30
  var import_jsx_runtime = require("react/jsx-runtime");
31
31
  var CmsContext = (0, import_react.createContext)(null);
@@ -42,7 +42,7 @@ function useClient() {
42
42
  }
43
43
  return (0, import_react.useMemo)(() => {
44
44
  const base = config.baseUrl ?? "";
45
- return (0, import_cms_client.createClient)((url, init) => {
45
+ return (0, import_client.createClient)((url, init) => {
46
46
  const fullUrl = typeof url === "string" ? `${base}${url}` : url;
47
47
  return fetch(fullUrl, {
48
48
  ...init,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["/**\n * LyEve CMS React hooks - typed, reactive data fetching.\n *\n * Thin wrapper around {@link @lyeve/cms-client} that makes the client\n * available via context and provides `useQuery` / `useMutation` hooks.\n *\n * @example\n * ```tsx\n * import { CmsProvider, useQuery } from '@lyeve/cms-client-react';\n * import { getSchemas } from '@lyeve/cms-client-rest';\n *\n * function App() {\n * return (\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com', getHeaders: () => ({ Authorization: `Bearer ${token}` }) }}>\n * <SchemaManager />\n * </CmsProvider>\n * );\n * }\n *\n * function SchemaManager() {\n * const { data: schemas, loading } = useQuery((client) => getSchemas(client));\n * // ...\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { createClient, type HttpClient } from '@lyeve/cms-client';\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\n// Provider\n\nexport interface CmsConfig {\n /** Base URL prepended to every request path. */\n baseUrl?: string;\n /**\n * Callback returning headers added to every request.\n * Called on every request so auth tokens can be refreshed without\n * recreating the provider.\n */\n getHeaders?: () => Record<string, string>;\n}\n\nconst CmsContext = createContext<CmsConfig | null>(null);\n\n/**\n * Context provider that makes the CMS client available to all descendant\n * hooks.\n *\n * @example\n * ```tsx\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com' }}>\n * <App />\n * </CmsProvider>\n * ```\n */\nexport function CmsProvider({\n config,\n children,\n}: {\n config: CmsConfig;\n children: ReactNode;\n}) {\n return <CmsContext.Provider value={config}>{children}</CmsContext.Provider>;\n}\n\n/**\n * Returns a memoized HttpClient instance configured from the nearest\n * {@link CmsProvider}.\n */\nfunction useClient(): HttpClient {\n const config = useContext(CmsContext);\n if (!config) {\n throw new Error('CmsProvider must wrap your component tree');\n }\n // Re-create when config changes so getHeaders/auth tokens stay current.\n return useMemo(() => {\n const base = config.baseUrl ?? '';\n return createClient((url, init) => {\n const fullUrl = typeof url === 'string' ? `${base}${url}` : url;\n return fetch(fullUrl, {\n ...init,\n headers: { ...init?.headers, ...config.getHeaders?.() },\n });\n });\n }, [config.baseUrl, config.getHeaders]);\n}\n\n// Hooks\n\nexport interface AsyncState<T> {\n data: T | null;\n error: Error | null;\n loading: boolean;\n}\n\n/**\n * Reactive query hook. Runs `fetcher` on mount and whenever `deps` change.\n *\n * @param fetcher - Function that receives the configured HttpClient and returns a promise.\n * @param deps - Optional dependency array controlling when to refetch (default: `[]`).\n *\n * @example\n * ```ts\n * const { data, error, loading, refetch } = useQuery(\n * (client) => getSchemas(client),\n * );\n * ```\n */\nexport function useQuery<T>(\n fetcher: (client: HttpClient) => Promise<T>,\n deps: unknown[] = [],\n): AsyncState<T> & { refetch: () => void } {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: true,\n });\n\n const run = useCallback(() => {\n setState((s) => ({ ...s, loading: true }));\n\n fetcher(client)\n .then((data) => setState({ data, error: null, loading: false }))\n .catch((error) =>\n setState((s) => ({ ...s, error: error as Error, loading: false })),\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, ...deps]);\n\n useEffect(() => {\n run();\n }, [run]);\n\n return { ...state, refetch: run };\n}\n\n/**\n * Mutation hook. Returns a trigger function and the current state.\n *\n * @param mutator - Function that receives the configured HttpClient and variables.\n *\n * @example\n * ```ts\n * const [create, { loading, error }] = useMutation(\n * (client, vars: { title: string }) => createArticle(client, vars),\n * );\n * // await create({ title: 'Hello' })\n * ```\n */\nexport function useMutation<T, V>(\n mutator: (client: HttpClient, vars: V) => Promise<T>,\n): [(vars: V) => Promise<T>, AsyncState<T>] {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: false,\n });\n\n const run = useCallback(\n async (vars: V) => {\n setState((s) => ({ ...s, loading: true }));\n try {\n const data = await mutator(client, vars);\n setState({ data, error: null, loading: false });\n return data;\n } catch (error) {\n setState({ data: null, error: error as Error, loading: false });\n throw error;\n }\n },\n [client],\n );\n\n return [run, state];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BA,wBAA8C;AAC9C,mBAQO;AAmCE;AApBT,IAAM,iBAAa,4BAAgC,IAAI;AAahD,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,SAAO,4CAAC,WAAW,UAAX,EAAoB,OAAO,QAAS,UAAS;AACvD;AAMA,SAAS,YAAwB;AAC/B,QAAM,aAAS,yBAAW,UAAU;AACpC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,aAAO,sBAAQ,MAAM;AACnB,UAAM,OAAO,OAAO,WAAW;AAC/B,eAAO,gCAAa,CAAC,KAAK,SAAS;AACjC,YAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,aAAO,MAAM,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,SAAS,OAAO,UAAU,CAAC;AACxC;AAuBO,SAAS,SACd,SACA,OAAkB,CAAC,GACsB;AACzC,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,UAAM,0BAAY,MAAM;AAC5B,aAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AAEzC,YAAQ,MAAM,EACX,KAAK,CAAC,SAAS,SAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,CAAC,EAC9D;AAAA,MAAM,CAAC,UACN,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAuB,SAAS,MAAM,EAAE;AAAA,IACnE;AAAA,EAEJ,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;AAEpB,8BAAU,MAAM;AACd,QAAI;AAAA,EACN,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,EAAE,GAAG,OAAO,SAAS,IAAI;AAClC;AAeO,SAAS,YACd,SAC0C;AAC1C,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,UAAM;AAAA,IACV,OAAO,SAAY;AACjB,eAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AACzC,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,iBAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC;AAC9C,eAAO;AAAA,MACT,SAAS,OAAO;AACd,iBAAS,EAAE,MAAM,MAAM,OAAuB,SAAS,MAAM,CAAC;AAC9D,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,SAAO,CAAC,KAAK,KAAK;AACpB;","names":[]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["/**\n * LyEve CMS React hooks - typed, reactive data fetching.\n *\n * Thin wrapper around {@link @lyeve-labs/client} that makes the client\n * available via context and provides `useQuery` / `useMutation` hooks.\n *\n * @example\n * ```tsx\n * import { CmsProvider, useQuery } from '@lyeve-labs/client-react';\n * import { getSchemas } from '@lyeve-labs/client-rest';\n *\n * function App() {\n * return (\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com', getHeaders: () => ({ Authorization: `Bearer ${token}` }) }}>\n * <SchemaManager />\n * </CmsProvider>\n * );\n * }\n *\n * function SchemaManager() {\n * const { data: schemas, loading } = useQuery((client) => getSchemas(client));\n * // ...\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { createClient, type HttpClient } from \"@lyeve-labs/client\";\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\n\n// Provider\n\nexport interface CmsConfig {\n /** Base URL prepended to every request path. */\n baseUrl?: string;\n /**\n * Callback returning headers added to every request.\n * Called on every request so auth tokens can be refreshed without\n * recreating the provider.\n */\n getHeaders?: () => Record<string, string>;\n}\n\nconst CmsContext = createContext<CmsConfig | null>(null);\n\n/**\n * Context provider that makes the CMS client available to all descendant\n * hooks.\n *\n * @example\n * ```tsx\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com' }}>\n * <App />\n * </CmsProvider>\n * ```\n */\nexport function CmsProvider({\n config,\n children,\n}: {\n config: CmsConfig;\n children: ReactNode;\n}) {\n return <CmsContext.Provider value={config}>{children}</CmsContext.Provider>;\n}\n\n/**\n * Returns a memoized HttpClient instance configured from the nearest\n * {@link CmsProvider}.\n */\nfunction useClient(): HttpClient {\n const config = useContext(CmsContext);\n if (!config) {\n throw new Error(\"CmsProvider must wrap your component tree\");\n }\n // Re-create when config changes so getHeaders/auth tokens stay current.\n return useMemo(() => {\n const base = config.baseUrl ?? \"\";\n return createClient((url, init) => {\n const fullUrl = typeof url === \"string\" ? `${base}${url}` : url;\n return fetch(fullUrl, {\n ...init,\n headers: { ...init?.headers, ...config.getHeaders?.() },\n });\n });\n }, [config.baseUrl, config.getHeaders]);\n}\n\n// Hooks\n\nexport interface AsyncState<T> {\n data: T | null;\n error: Error | null;\n loading: boolean;\n}\n\n/**\n * Reactive query hook. Runs `fetcher` on mount and whenever `deps` change.\n *\n * @param fetcher - Function that receives the configured HttpClient and returns a promise.\n * @param deps - Optional dependency array controlling when to refetch (default: `[]`).\n *\n * @example\n * ```ts\n * const { data, error, loading, refetch } = useQuery(\n * (client) => getSchemas(client),\n * );\n * ```\n */\nexport function useQuery<T>(\n fetcher: (client: HttpClient) => Promise<T>,\n deps: unknown[] = [],\n): AsyncState<T> & { refetch: () => void } {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: true,\n });\n\n const run = useCallback(() => {\n setState((s) => ({ ...s, loading: true }));\n\n fetcher(client)\n .then((data) => setState({ data, error: null, loading: false }))\n .catch((error) =>\n setState((s) => ({ ...s, error: error as Error, loading: false })),\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, ...deps]);\n\n useEffect(() => {\n run();\n }, [run]);\n\n return { ...state, refetch: run };\n}\n\n/**\n * Mutation hook. Returns a trigger function and the current state.\n *\n * @param mutator - Function that receives the configured HttpClient and variables.\n *\n * @example\n * ```ts\n * const [create, { loading, error }] = useMutation(\n * (client, vars: { title: string }) => createArticle(client, vars),\n * );\n * // await create({ title: 'Hello' })\n * ```\n */\nexport function useMutation<T, V>(\n mutator: (client: HttpClient, vars: V) => Promise<T>,\n): [(vars: V) => Promise<T>, AsyncState<T>] {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: false,\n });\n\n const run = useCallback(\n async (vars: V) => {\n setState((s) => ({ ...s, loading: true }));\n try {\n const data = await mutator(client, vars);\n setState({ data, error: null, loading: false });\n return data;\n } catch (error) {\n setState({ data: null, error: error as Error, loading: false });\n throw error;\n }\n },\n [client],\n );\n\n return [run, state];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BA,oBAA8C;AAC9C,mBAQO;AAmCE;AApBT,IAAM,iBAAa,4BAAgC,IAAI;AAahD,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,SAAO,4CAAC,WAAW,UAAX,EAAoB,OAAO,QAAS,UAAS;AACvD;AAMA,SAAS,YAAwB;AAC/B,QAAM,aAAS,yBAAW,UAAU;AACpC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,aAAO,sBAAQ,MAAM;AACnB,UAAM,OAAO,OAAO,WAAW;AAC/B,eAAO,4BAAa,CAAC,KAAK,SAAS;AACjC,YAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,aAAO,MAAM,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,SAAS,OAAO,UAAU,CAAC;AACxC;AAuBO,SAAS,SACd,SACA,OAAkB,CAAC,GACsB;AACzC,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,UAAM,0BAAY,MAAM;AAC5B,aAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AAEzC,YAAQ,MAAM,EACX,KAAK,CAAC,SAAS,SAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,CAAC,EAC9D;AAAA,MAAM,CAAC,UACN,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAuB,SAAS,MAAM,EAAE;AAAA,IACnE;AAAA,EAEJ,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;AAEpB,8BAAU,MAAM;AACd,QAAI;AAAA,EACN,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,EAAE,GAAG,OAAO,SAAS,IAAI;AAClC;AAeO,SAAS,YACd,SAC0C;AAC1C,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,UAAM;AAAA,IACV,OAAO,SAAY;AACjB,eAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AACzC,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,iBAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC;AAC9C,eAAO;AAAA,MACT,SAAS,OAAO;AACd,iBAAS,EAAE,MAAM,MAAM,OAAuB,SAAS,MAAM,CAAC;AAC9D,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,SAAO,CAAC,KAAK,KAAK;AACpB;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { HttpClient } from '@lyeve/cms-client';
3
+ import { HttpClient } from '@lyeve-labs/client';
4
4
 
5
5
  interface CmsConfig {
6
6
  /** Base URL prepended to every request path. */
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { HttpClient } from '@lyeve/cms-client';
3
+ import { HttpClient } from '@lyeve-labs/client';
4
4
 
5
5
  interface CmsConfig {
6
6
  /** Base URL prepended to every request path. */
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.tsx
2
- import { createClient } from "@lyeve/cms-client";
2
+ import { createClient } from "@lyeve-labs/client";
3
3
  import {
4
4
  createContext,
5
5
  useContext,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["/**\n * LyEve CMS React hooks - typed, reactive data fetching.\n *\n * Thin wrapper around {@link @lyeve/cms-client} that makes the client\n * available via context and provides `useQuery` / `useMutation` hooks.\n *\n * @example\n * ```tsx\n * import { CmsProvider, useQuery } from '@lyeve/cms-client-react';\n * import { getSchemas } from '@lyeve/cms-client-rest';\n *\n * function App() {\n * return (\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com', getHeaders: () => ({ Authorization: `Bearer ${token}` }) }}>\n * <SchemaManager />\n * </CmsProvider>\n * );\n * }\n *\n * function SchemaManager() {\n * const { data: schemas, loading } = useQuery((client) => getSchemas(client));\n * // ...\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { createClient, type HttpClient } from '@lyeve/cms-client';\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\n// Provider\n\nexport interface CmsConfig {\n /** Base URL prepended to every request path. */\n baseUrl?: string;\n /**\n * Callback returning headers added to every request.\n * Called on every request so auth tokens can be refreshed without\n * recreating the provider.\n */\n getHeaders?: () => Record<string, string>;\n}\n\nconst CmsContext = createContext<CmsConfig | null>(null);\n\n/**\n * Context provider that makes the CMS client available to all descendant\n * hooks.\n *\n * @example\n * ```tsx\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com' }}>\n * <App />\n * </CmsProvider>\n * ```\n */\nexport function CmsProvider({\n config,\n children,\n}: {\n config: CmsConfig;\n children: ReactNode;\n}) {\n return <CmsContext.Provider value={config}>{children}</CmsContext.Provider>;\n}\n\n/**\n * Returns a memoized HttpClient instance configured from the nearest\n * {@link CmsProvider}.\n */\nfunction useClient(): HttpClient {\n const config = useContext(CmsContext);\n if (!config) {\n throw new Error('CmsProvider must wrap your component tree');\n }\n // Re-create when config changes so getHeaders/auth tokens stay current.\n return useMemo(() => {\n const base = config.baseUrl ?? '';\n return createClient((url, init) => {\n const fullUrl = typeof url === 'string' ? `${base}${url}` : url;\n return fetch(fullUrl, {\n ...init,\n headers: { ...init?.headers, ...config.getHeaders?.() },\n });\n });\n }, [config.baseUrl, config.getHeaders]);\n}\n\n// Hooks\n\nexport interface AsyncState<T> {\n data: T | null;\n error: Error | null;\n loading: boolean;\n}\n\n/**\n * Reactive query hook. Runs `fetcher` on mount and whenever `deps` change.\n *\n * @param fetcher - Function that receives the configured HttpClient and returns a promise.\n * @param deps - Optional dependency array controlling when to refetch (default: `[]`).\n *\n * @example\n * ```ts\n * const { data, error, loading, refetch } = useQuery(\n * (client) => getSchemas(client),\n * );\n * ```\n */\nexport function useQuery<T>(\n fetcher: (client: HttpClient) => Promise<T>,\n deps: unknown[] = [],\n): AsyncState<T> & { refetch: () => void } {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: true,\n });\n\n const run = useCallback(() => {\n setState((s) => ({ ...s, loading: true }));\n\n fetcher(client)\n .then((data) => setState({ data, error: null, loading: false }))\n .catch((error) =>\n setState((s) => ({ ...s, error: error as Error, loading: false })),\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, ...deps]);\n\n useEffect(() => {\n run();\n }, [run]);\n\n return { ...state, refetch: run };\n}\n\n/**\n * Mutation hook. Returns a trigger function and the current state.\n *\n * @param mutator - Function that receives the configured HttpClient and variables.\n *\n * @example\n * ```ts\n * const [create, { loading, error }] = useMutation(\n * (client, vars: { title: string }) => createArticle(client, vars),\n * );\n * // await create({ title: 'Hello' })\n * ```\n */\nexport function useMutation<T, V>(\n mutator: (client: HttpClient, vars: V) => Promise<T>,\n): [(vars: V) => Promise<T>, AsyncState<T>] {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: false,\n });\n\n const run = useCallback(\n async (vars: V) => {\n setState((s) => ({ ...s, loading: true }));\n try {\n const data = await mutator(client, vars);\n setState({ data, error: null, loading: false });\n return data;\n } catch (error) {\n setState({ data: null, error: error as Error, loading: false });\n throw error;\n }\n },\n [client],\n );\n\n return [run, state];\n}\n"],"mappings":";AA4BA,SAAS,oBAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAmCE;AApBT,IAAM,aAAa,cAAgC,IAAI;AAahD,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,SAAO,oBAAC,WAAW,UAAX,EAAoB,OAAO,QAAS,UAAS;AACvD;AAMA,SAAS,YAAwB;AAC/B,QAAM,SAAS,WAAW,UAAU;AACpC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,SAAO,QAAQ,MAAM;AACnB,UAAM,OAAO,OAAO,WAAW;AAC/B,WAAO,aAAa,CAAC,KAAK,SAAS;AACjC,YAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,aAAO,MAAM,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,SAAS,OAAO,UAAU,CAAC;AACxC;AAuBO,SAAS,SACd,SACA,OAAkB,CAAC,GACsB;AACzC,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,MAAM,YAAY,MAAM;AAC5B,aAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AAEzC,YAAQ,MAAM,EACX,KAAK,CAAC,SAAS,SAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,CAAC,EAC9D;AAAA,MAAM,CAAC,UACN,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAuB,SAAS,MAAM,EAAE;AAAA,IACnE;AAAA,EAEJ,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;AAEpB,YAAU,MAAM;AACd,QAAI;AAAA,EACN,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,EAAE,GAAG,OAAO,SAAS,IAAI;AAClC;AAeO,SAAS,YACd,SAC0C;AAC1C,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,MAAM;AAAA,IACV,OAAO,SAAY;AACjB,eAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AACzC,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,iBAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC;AAC9C,eAAO;AAAA,MACT,SAAS,OAAO;AACd,iBAAS,EAAE,MAAM,MAAM,OAAuB,SAAS,MAAM,CAAC;AAC9D,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,SAAO,CAAC,KAAK,KAAK;AACpB;","names":[]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["/**\n * LyEve CMS React hooks - typed, reactive data fetching.\n *\n * Thin wrapper around {@link @lyeve-labs/client} that makes the client\n * available via context and provides `useQuery` / `useMutation` hooks.\n *\n * @example\n * ```tsx\n * import { CmsProvider, useQuery } from '@lyeve-labs/client-react';\n * import { getSchemas } from '@lyeve-labs/client-rest';\n *\n * function App() {\n * return (\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com', getHeaders: () => ({ Authorization: `Bearer ${token}` }) }}>\n * <SchemaManager />\n * </CmsProvider>\n * );\n * }\n *\n * function SchemaManager() {\n * const { data: schemas, loading } = useQuery((client) => getSchemas(client));\n * // ...\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { createClient, type HttpClient } from \"@lyeve-labs/client\";\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\n\n// Provider\n\nexport interface CmsConfig {\n /** Base URL prepended to every request path. */\n baseUrl?: string;\n /**\n * Callback returning headers added to every request.\n * Called on every request so auth tokens can be refreshed without\n * recreating the provider.\n */\n getHeaders?: () => Record<string, string>;\n}\n\nconst CmsContext = createContext<CmsConfig | null>(null);\n\n/**\n * Context provider that makes the CMS client available to all descendant\n * hooks.\n *\n * @example\n * ```tsx\n * <CmsProvider config={{ baseUrl: 'https://cms.example.com' }}>\n * <App />\n * </CmsProvider>\n * ```\n */\nexport function CmsProvider({\n config,\n children,\n}: {\n config: CmsConfig;\n children: ReactNode;\n}) {\n return <CmsContext.Provider value={config}>{children}</CmsContext.Provider>;\n}\n\n/**\n * Returns a memoized HttpClient instance configured from the nearest\n * {@link CmsProvider}.\n */\nfunction useClient(): HttpClient {\n const config = useContext(CmsContext);\n if (!config) {\n throw new Error(\"CmsProvider must wrap your component tree\");\n }\n // Re-create when config changes so getHeaders/auth tokens stay current.\n return useMemo(() => {\n const base = config.baseUrl ?? \"\";\n return createClient((url, init) => {\n const fullUrl = typeof url === \"string\" ? `${base}${url}` : url;\n return fetch(fullUrl, {\n ...init,\n headers: { ...init?.headers, ...config.getHeaders?.() },\n });\n });\n }, [config.baseUrl, config.getHeaders]);\n}\n\n// Hooks\n\nexport interface AsyncState<T> {\n data: T | null;\n error: Error | null;\n loading: boolean;\n}\n\n/**\n * Reactive query hook. Runs `fetcher` on mount and whenever `deps` change.\n *\n * @param fetcher - Function that receives the configured HttpClient and returns a promise.\n * @param deps - Optional dependency array controlling when to refetch (default: `[]`).\n *\n * @example\n * ```ts\n * const { data, error, loading, refetch } = useQuery(\n * (client) => getSchemas(client),\n * );\n * ```\n */\nexport function useQuery<T>(\n fetcher: (client: HttpClient) => Promise<T>,\n deps: unknown[] = [],\n): AsyncState<T> & { refetch: () => void } {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: true,\n });\n\n const run = useCallback(() => {\n setState((s) => ({ ...s, loading: true }));\n\n fetcher(client)\n .then((data) => setState({ data, error: null, loading: false }))\n .catch((error) =>\n setState((s) => ({ ...s, error: error as Error, loading: false })),\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, ...deps]);\n\n useEffect(() => {\n run();\n }, [run]);\n\n return { ...state, refetch: run };\n}\n\n/**\n * Mutation hook. Returns a trigger function and the current state.\n *\n * @param mutator - Function that receives the configured HttpClient and variables.\n *\n * @example\n * ```ts\n * const [create, { loading, error }] = useMutation(\n * (client, vars: { title: string }) => createArticle(client, vars),\n * );\n * // await create({ title: 'Hello' })\n * ```\n */\nexport function useMutation<T, V>(\n mutator: (client: HttpClient, vars: V) => Promise<T>,\n): [(vars: V) => Promise<T>, AsyncState<T>] {\n const client = useClient();\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n error: null,\n loading: false,\n });\n\n const run = useCallback(\n async (vars: V) => {\n setState((s) => ({ ...s, loading: true }));\n try {\n const data = await mutator(client, vars);\n setState({ data, error: null, loading: false });\n return data;\n } catch (error) {\n setState({ data: null, error: error as Error, loading: false });\n throw error;\n }\n },\n [client],\n );\n\n return [run, state];\n}\n"],"mappings":";AA4BA,SAAS,oBAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAmCE;AApBT,IAAM,aAAa,cAAgC,IAAI;AAahD,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,SAAO,oBAAC,WAAW,UAAX,EAAoB,OAAO,QAAS,UAAS;AACvD;AAMA,SAAS,YAAwB;AAC/B,QAAM,SAAS,WAAW,UAAU;AACpC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,SAAO,QAAQ,MAAM;AACnB,UAAM,OAAO,OAAO,WAAW;AAC/B,WAAO,aAAa,CAAC,KAAK,SAAS;AACjC,YAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,aAAO,MAAM,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,SAAS,OAAO,UAAU,CAAC;AACxC;AAuBO,SAAS,SACd,SACA,OAAkB,CAAC,GACsB;AACzC,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,MAAM,YAAY,MAAM;AAC5B,aAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AAEzC,YAAQ,MAAM,EACX,KAAK,CAAC,SAAS,SAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,CAAC,EAC9D;AAAA,MAAM,CAAC,UACN,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAuB,SAAS,MAAM,EAAE;AAAA,IACnE;AAAA,EAEJ,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;AAEpB,YAAU,MAAM;AACd,QAAI;AAAA,EACN,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,EAAE,GAAG,OAAO,SAAS,IAAI;AAClC;AAeO,SAAS,YACd,SAC0C;AAC1C,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AAED,QAAM,MAAM;AAAA,IACV,OAAO,SAAY;AACjB,eAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AACzC,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,iBAAS,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC;AAC9C,eAAO;AAAA,MACT,SAAS,OAAO;AACd,iBAAS,EAAE,MAAM,MAAM,OAAuB,SAAS,MAAM,CAAC;AAC9D,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,SAAO,CAAC,KAAK,KAAK;AACpB;","names":[]}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@lyeve-labs/client-react",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "React hooks for LyEve Core - typed, reactive data fetching",
5
5
  "license": "MIT",
6
- "author": "LyEve Labs <hello@lyeve.com>",
6
+ "author": "LyEve Labs <info@lyeve.com>",
7
7
  "type": "module",
8
+ "packageManager": "pnpm@9.15.0",
8
9
  "engines": {
9
10
  "node": ">=20"
10
11
  },
@@ -14,9 +15,14 @@
14
15
  "sideEffects": false,
15
16
  "exports": {
16
17
  ".": {
17
- "types": "./dist/index.d.ts",
18
- "import": "./dist/index.js",
19
- "require": "./dist/index.cjs"
18
+ "import": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/index.d.cts",
24
+ "default": "./dist/index.cjs"
25
+ }
20
26
  },
21
27
  "./package.json": "./package.json"
22
28
  },
@@ -28,12 +34,21 @@
28
34
  "publishConfig": {
29
35
  "access": "public"
30
36
  },
37
+ "scripts": {
38
+ "build": "tsup && publint && node scripts/check-dist.mjs",
39
+ "check": "tsc --noEmit",
40
+ "test": "vitest run",
41
+ "dev": "tsup --watch",
42
+ "test:watch": "vitest",
43
+ "format": "prettier --write .",
44
+ "format:check": "prettier --check ."
45
+ },
31
46
  "peerDependencies": {
32
- "@lyeve-labs/client-react": ">=0.1.0",
47
+ "@lyeve-labs/client": ">=0.2.0",
33
48
  "react": ">=18.0.0"
34
49
  },
35
50
  "devDependencies": {
36
- "@lyeve-labs/client-react": "^0.1.0",
51
+ "@lyeve-labs/client": "^0.2.0",
37
52
  "@testing-library/react": "^16.3.2",
38
53
  "@types/react": "^19.2.0",
39
54
  "jsdom": "^29.1.1",
@@ -44,14 +59,5 @@
44
59
  "tsup": "^8.4.0",
45
60
  "typescript": "^5.7.0",
46
61
  "vitest": "^2.1.0"
47
- },
48
- "scripts": {
49
- "build": "tsup && publint",
50
- "check": "tsc --noEmit",
51
- "test": "vitest run",
52
- "dev": "tsup --watch",
53
- "test:watch": "vitest",
54
- "format": "prettier --write .",
55
- "format:check": "prettier --check ."
56
62
  }
57
- }
63
+ }