ellmo-ai-react 0.0.15 → 0.0.17
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 +9 -0
- package/dist/EllmoApiStatic.d.ts +22 -8
- package/dist/EllmoApiStatic.d.ts.map +1 -1
- package/dist/index.d.ts +22 -8
- package/dist/index.js +23 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,3 +7,12 @@ Add Ellmo AI to your React or Next.js website to track page views and get conten
|
|
|
7
7
|
[eLLMo AI](https://www.tryellmo.ai?utm_source=npm&utm_medium=package&utm_campaign=ellmo-ai-react) is an intelligent content optimization platform that helps websites improve their search engine visibility and user experience. By analyzing your pages in real-time, Ellmo provides AI-powered content recommendations, semantic search optimization, and structured data insights to help your content perform better in search engines and engage your audience more effectively.
|
|
8
8
|
|
|
9
9
|
Visit [tryellmo.ai](https://www.tryellmo.ai?utm_source=npm&utm_medium=package&utm_campaign=ellmo-ai-react) to learn more and get started.
|
|
10
|
+
|
|
11
|
+
## Supported Rendering Methods
|
|
12
|
+
|
|
13
|
+
- **Next.js App Router (SSR)** - Server-side rendering with React Server Components
|
|
14
|
+
- **Next.js Pages Router (SSR)** - Server-side rendering with `getServerSideProps`
|
|
15
|
+
- **Next.js Pages Router (SSG)** - Static site generation with `getStaticProps` and ISR
|
|
16
|
+
- **Next.js Pages Router (Static)** - Static generation with `getInitialProps`
|
|
17
|
+
|
|
18
|
+
See [CUSTOMER_README.md](./CUSTOMER_README.md) for detailed implementation examples.
|
package/dist/EllmoApiStatic.d.ts
CHANGED
|
@@ -9,15 +9,26 @@ type AppContext = {
|
|
|
9
9
|
* Helper for _app.tsx to fetch global Ellmo data and merge with page props
|
|
10
10
|
* Automatically calls the page's getInitialProps and merges everything
|
|
11
11
|
*
|
|
12
|
+
* @param clientId - Your Ellmo client ID
|
|
13
|
+
* @param url - Function that returns the URL path from app context
|
|
14
|
+
* @param type - Content type: 'semantic' or 'structured' (default: 'semantic')
|
|
15
|
+
* @param debugging - Include pageEllmoError in props for debugging (default: false)
|
|
16
|
+
*
|
|
17
|
+
* Returns pageEllmoData in pageProps. If debugging is enabled, also includes pageEllmoError.
|
|
18
|
+
*
|
|
12
19
|
* @example
|
|
13
20
|
* ```tsx
|
|
14
21
|
* import { withEllmoApp } from 'ellmo-ai-react';
|
|
15
22
|
*
|
|
16
|
-
* function MyApp({ Component, pageProps
|
|
23
|
+
* function MyApp({ Component, pageProps }) {
|
|
17
24
|
* return (
|
|
18
25
|
* <>
|
|
19
26
|
* <header>
|
|
20
|
-
* <EllmoApiSSR
|
|
27
|
+
* <EllmoApiSSR
|
|
28
|
+
* data={pageProps.pageEllmoData}
|
|
29
|
+
* error={pageProps.pageEllmoError}
|
|
30
|
+
* showErrors={true} // Show errors in development
|
|
31
|
+
* />
|
|
21
32
|
* </header>
|
|
22
33
|
* <Component {...pageProps} />
|
|
23
34
|
* </>
|
|
@@ -26,20 +37,23 @@ type AppContext = {
|
|
|
26
37
|
*
|
|
27
38
|
* MyApp.getInitialProps = withEllmoApp({
|
|
28
39
|
* clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,
|
|
29
|
-
* url: '/global-header',
|
|
30
|
-
* type: 'structured'
|
|
40
|
+
* url: (appContext) => '/global-header',
|
|
41
|
+
* type: 'structured',
|
|
42
|
+
* debugging: process.env.NODE_ENV === 'development' // Enable error prop in development
|
|
31
43
|
* });
|
|
32
44
|
*
|
|
33
45
|
* export default MyApp;
|
|
34
46
|
* ```
|
|
35
47
|
*/
|
|
36
|
-
export declare function withEllmoApp({ clientId, url, type }: {
|
|
48
|
+
export declare function withEllmoApp({ clientId, url, type, debugging }: {
|
|
37
49
|
clientId: string;
|
|
38
50
|
url: (appContext: AppContext) => string;
|
|
39
51
|
type?: EllmoApiType;
|
|
52
|
+
debugging?: boolean;
|
|
40
53
|
}): (appContext: AppContext) => Promise<{
|
|
41
|
-
pageProps: {
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
pageProps: {
|
|
55
|
+
pageEllmoError?: string | null | undefined;
|
|
56
|
+
pageEllmoData: string | null;
|
|
57
|
+
};
|
|
44
58
|
}>;
|
|
45
59
|
//# sourceMappingURL=EllmoApiStatic.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EllmoApiStatic.d.ts","sourceRoot":"","sources":["../src/EllmoApiStatic.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7D,YAAY,EAAE,YAAY,EAAE,CAAC;AAG7B,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,GAAG,CAAC;IACf,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAGF
|
|
1
|
+
{"version":3,"file":"EllmoApiStatic.d.ts","sourceRoot":"","sources":["../src/EllmoApiStatic.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7D,YAAY,EAAE,YAAY,EAAE,CAAC;AAG7B,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,GAAG,CAAC;IACf,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,GAAG,EACH,IAAiB,EACjB,SAAiB,EAClB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,MAAM,CAAC;IACxC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,IACe,YAAY,UAAU;;;;;GAuBrC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -165,15 +165,26 @@ type AppContext = {
|
|
|
165
165
|
* Helper for _app.tsx to fetch global Ellmo data and merge with page props
|
|
166
166
|
* Automatically calls the page's getInitialProps and merges everything
|
|
167
167
|
*
|
|
168
|
+
* @param clientId - Your Ellmo client ID
|
|
169
|
+
* @param url - Function that returns the URL path from app context
|
|
170
|
+
* @param type - Content type: 'semantic' or 'structured' (default: 'semantic')
|
|
171
|
+
* @param debugging - Include pageEllmoError in props for debugging (default: false)
|
|
172
|
+
*
|
|
173
|
+
* Returns pageEllmoData in pageProps. If debugging is enabled, also includes pageEllmoError.
|
|
174
|
+
*
|
|
168
175
|
* @example
|
|
169
176
|
* ```tsx
|
|
170
177
|
* import { withEllmoApp } from 'ellmo-ai-react';
|
|
171
178
|
*
|
|
172
|
-
* function MyApp({ Component, pageProps
|
|
179
|
+
* function MyApp({ Component, pageProps }) {
|
|
173
180
|
* return (
|
|
174
181
|
* <>
|
|
175
182
|
* <header>
|
|
176
|
-
* <EllmoApiSSR
|
|
183
|
+
* <EllmoApiSSR
|
|
184
|
+
* data={pageProps.pageEllmoData}
|
|
185
|
+
* error={pageProps.pageEllmoError}
|
|
186
|
+
* showErrors={true} // Show errors in development
|
|
187
|
+
* />
|
|
177
188
|
* </header>
|
|
178
189
|
* <Component {...pageProps} />
|
|
179
190
|
* </>
|
|
@@ -182,21 +193,24 @@ type AppContext = {
|
|
|
182
193
|
*
|
|
183
194
|
* MyApp.getInitialProps = withEllmoApp({
|
|
184
195
|
* clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,
|
|
185
|
-
* url: '/global-header',
|
|
186
|
-
* type: 'structured'
|
|
196
|
+
* url: (appContext) => '/global-header',
|
|
197
|
+
* type: 'structured',
|
|
198
|
+
* debugging: process.env.NODE_ENV === 'development' // Enable error prop in development
|
|
187
199
|
* });
|
|
188
200
|
*
|
|
189
201
|
* export default MyApp;
|
|
190
202
|
* ```
|
|
191
203
|
*/
|
|
192
|
-
declare function withEllmoApp({ clientId, url, type }: {
|
|
204
|
+
declare function withEllmoApp({ clientId, url, type, debugging }: {
|
|
193
205
|
clientId: string;
|
|
194
206
|
url: (appContext: AppContext) => string;
|
|
195
207
|
type?: EllmoApiType;
|
|
208
|
+
debugging?: boolean;
|
|
196
209
|
}): (appContext: AppContext) => Promise<{
|
|
197
|
-
pageProps: {
|
|
198
|
-
|
|
199
|
-
|
|
210
|
+
pageProps: {
|
|
211
|
+
pageEllmoError?: string | null | undefined;
|
|
212
|
+
pageEllmoData: string | null;
|
|
213
|
+
};
|
|
200
214
|
}>;
|
|
201
215
|
|
|
202
216
|
/**
|
package/dist/index.js
CHANGED
|
@@ -203,15 +203,26 @@ async function fetchEllmoData({ clientId, url, type = 'semantic' }) {
|
|
|
203
203
|
* Helper for _app.tsx to fetch global Ellmo data and merge with page props
|
|
204
204
|
* Automatically calls the page's getInitialProps and merges everything
|
|
205
205
|
*
|
|
206
|
+
* @param clientId - Your Ellmo client ID
|
|
207
|
+
* @param url - Function that returns the URL path from app context
|
|
208
|
+
* @param type - Content type: 'semantic' or 'structured' (default: 'semantic')
|
|
209
|
+
* @param debugging - Include pageEllmoError in props for debugging (default: false)
|
|
210
|
+
*
|
|
211
|
+
* Returns pageEllmoData in pageProps. If debugging is enabled, also includes pageEllmoError.
|
|
212
|
+
*
|
|
206
213
|
* @example
|
|
207
214
|
* ```tsx
|
|
208
215
|
* import { withEllmoApp } from 'ellmo-ai-react';
|
|
209
216
|
*
|
|
210
|
-
* function MyApp({ Component, pageProps
|
|
217
|
+
* function MyApp({ Component, pageProps }) {
|
|
211
218
|
* return (
|
|
212
219
|
* <>
|
|
213
220
|
* <header>
|
|
214
|
-
* <EllmoApiSSR
|
|
221
|
+
* <EllmoApiSSR
|
|
222
|
+
* data={pageProps.pageEllmoData}
|
|
223
|
+
* error={pageProps.pageEllmoError}
|
|
224
|
+
* showErrors={true} // Show errors in development
|
|
225
|
+
* />
|
|
215
226
|
* </header>
|
|
216
227
|
* <Component {...pageProps} />
|
|
217
228
|
* </>
|
|
@@ -220,14 +231,15 @@ async function fetchEllmoData({ clientId, url, type = 'semantic' }) {
|
|
|
220
231
|
*
|
|
221
232
|
* MyApp.getInitialProps = withEllmoApp({
|
|
222
233
|
* clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,
|
|
223
|
-
* url: '/global-header',
|
|
224
|
-
* type: 'structured'
|
|
234
|
+
* url: (appContext) => '/global-header',
|
|
235
|
+
* type: 'structured',
|
|
236
|
+
* debugging: process.env.NODE_ENV === 'development' // Enable error prop in development
|
|
225
237
|
* });
|
|
226
238
|
*
|
|
227
239
|
* export default MyApp;
|
|
228
240
|
* ```
|
|
229
241
|
*/
|
|
230
|
-
function withEllmoApp({ clientId, url, type = 'semantic' }) {
|
|
242
|
+
function withEllmoApp({ clientId, url, type = 'semantic', debugging = false }) {
|
|
231
243
|
return async (appContext) => {
|
|
232
244
|
// Fetch global Ellmo data
|
|
233
245
|
const { data, error } = await fetchEllmoData({
|
|
@@ -240,11 +252,13 @@ function withEllmoApp({ clientId, url, type = 'semantic' }) {
|
|
|
240
252
|
if (appContext.Component.getInitialProps) {
|
|
241
253
|
pageProps = await appContext.Component.getInitialProps(appContext.ctx);
|
|
242
254
|
}
|
|
243
|
-
// Return merged props
|
|
255
|
+
// Return merged props with ellmo data inside pageProps
|
|
244
256
|
return {
|
|
245
|
-
pageProps
|
|
246
|
-
|
|
247
|
-
|
|
257
|
+
pageProps: {
|
|
258
|
+
...pageProps,
|
|
259
|
+
pageEllmoData: data,
|
|
260
|
+
...(debugging ? { pageEllmoError: error } : {}), // Only add error if debugging is enabled
|
|
261
|
+
}
|
|
248
262
|
};
|
|
249
263
|
};
|
|
250
264
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/EllmoApi.tsx","../src/EllmoApiSSR.tsx","../src/shared.ts","../src/EllmoApiStatic.tsx","../src/middleware.ts"],"sourcesContent":["import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiProps {\n /**\n * The URL path to fetch data for (required).\n * \n * With middleware (recommended):\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * const pathname = getPathnameFromHeaders(headers());\n * <EllmoApi clientId=\"...\" url={pathname || '/'} />\n * ```\n * \n * Without middleware:\n * ```tsx\n * <EllmoApi clientId=\"...\" url=\"/about\" />\n * ```\n */\n url: string;\n /**\n * The API key/client identifier (required)\n */\n clientId: string;\n /**\n * Type of data to fetch\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children to render when data is available\n */\n children?: (data: any, error: Error | null) => React.ReactNode;\n}\n\n/**\n * Server-only Ellmo API component (React Server Component)\n * This component fetches data during server rendering.\n * It requires Next.js 13+ App Router or other RSC-compatible frameworks.\n * \n * @example\n * ```tsx\n * // In a server component (app/page.tsx)\n * export default async function Page() {\n * return <EllmoApi clientId=\"your-id\" url=\"/about\" />;\n * }\n * ```\n */\nconst EllmoApi = async ({\n url,\n clientId,\n type,\n className = '',\n showErrors = false,\n children\n}: EllmoApiProps): Promise<React.ReactElement | null> => {\n let data: any = null;\n let error: Error | null = null;\n\n let translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url prop is required. Please provide the page pathname.');\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data during server render\n const response = await fetch(apiUrl, {\n cache: 'no-store', // Always fetch fresh data\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n if (type === 'structured') {\n data = await response.text();\n } else if (type === 'semantic') {\n data = await response.text();\n } else {\n throw new Error(`Invalid type: ${type}`);\n }\n } catch (err) {\n error = err instanceof Error ? err : new Error('Unknown error occurred');\n }\n\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error.message}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{JSON.stringify(data, null, 2)}</pre>\n </div>\n );\n }\n\n // Invisible component by default - just fetches data during server render\n if (type === 'structured' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n } else if (type === 'semantic' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n }\n return null;\n};\n\nexport default EllmoApi;\n","import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiSSRProps {\n /**\n * The pre-fetched data from the Ellmo API\n */\n data?: string | null;\n /**\n * Error from fetching data\n */\n error?: string | null;\n /**\n * Type of data to render\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children render prop with data and error\n */\n children?: (data: string | null, error: string | null) => React.ReactNode;\n}\n\n/**\n * Ellmo API component for traditional SSR environments (Next.js Pages Router)\n * This component receives pre-fetched data and renders it.\n * Data fetching should be done in getServerSideProps or getStaticProps.\n * \n * @example\n * ```tsx\n * // In your page file (pages/about.tsx)\n * import { EllmoApiSSR, fetchEllmoData } from 'ellmo-ai-react';\n * \n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: 'your-client-id',\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * export default function AboutPage({ ellmoData, ellmoError }) {\n * return (\n * <div>\n * <h1>About Page</h1>\n * <EllmoApiSSR data={ellmoData} error={ellmoError} />\n * </div>\n * );\n * }\n * ```\n */\nconst EllmoApiSSR: React.FC<EllmoApiSSRProps> = ({\n data = null,\n error = null,\n className = '',\n showErrors = false,\n children\n}) => {\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{data}</pre>\n </div>\n );\n }\n\n // Render HTML content if available\n if (data && !error) {\n return <div className={className} dangerouslySetInnerHTML={{ __html: data }} />;\n }\n\n // Return null if no data\n return null;\n};\n\nexport default EllmoApiSSR;\n \n","export type EllmoApiType = 'semantic' | 'structured';\n\n/**\n * Fetch data from Ellmo API\n * Use this in getServerSideProps, getStaticProps, or getInitialProps\n * \n * @example\n * ```tsx\n * // In getServerSideProps (Next.js Pages Router)\n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.ELLMO_CLIENT_ID!,\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * // In getInitialProps (older Next.js API)\n * MyPage.getInitialProps = async (ctx) => {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: ctx.asPath || '/',\n * type: 'semantic'\n * });\n * \n * return { ellmoData: data, ellmoError: error };\n * };\n * ```\n */\nexport async function fetchEllmoData({\n clientId,\n url,\n type = 'semantic'\n}: {\n clientId: string;\n url: string;\n type?: EllmoApiType;\n}): Promise<{ data: string | null; error: string | null }> {\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url is required. Please provide the page pathname.');\n }\n\n if (url.includes('.')) {\n // Sometimes urls contain a dot if they're images or other assets which are served by SSG (static generation)\n return { data: null, error: null };\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n const translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data\n const response = await fetch(apiUrl, {\n cache: 'no-store',\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n const data = await response.text();\n return { data, error: null };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';\n return { data: null, error: errorMessage };\n }\n}\n\n","import { fetchEllmoData, type EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\n// Type for Next.js App context\ntype AppContext = {\n Component: any;\n ctx: any;\n router: any;\n};\n\n\n/**\n * Helper for _app.tsx to fetch global Ellmo data and merge with page props\n * Automatically calls the page's getInitialProps and merges everything\n * \n * @example\n * ```tsx\n * import { withEllmoApp } from 'ellmo-ai-react';\n * \n * function MyApp({ Component, pageProps, globalEllmoData, globalEllmoError }) {\n * return (\n * <>\n * <header>\n * <EllmoApiSSR data={globalEllmoData} error={globalEllmoError} />\n * </header>\n * <Component {...pageProps} />\n * </>\n * );\n * }\n * \n * MyApp.getInitialProps = withEllmoApp({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: '/global-header',\n * type: 'structured'\n * });\n * \n * export default MyApp;\n * ```\n */\nexport function withEllmoApp({\n clientId,\n url,\n type = 'semantic'\n}: {\n clientId: string;\n url: (appContext: AppContext) => string;\n type?: EllmoApiType;\n}) {\n return async (appContext: AppContext) => {\n // Fetch global Ellmo data\n const { data, error } = await fetchEllmoData({\n clientId,\n url: url(appContext), // Use the function to get the URL\n type\n });\n\n // Call the page's getInitialProps if it exists\n let pageProps = {};\n if (appContext.Component.getInitialProps) {\n pageProps = await appContext.Component.getInitialProps(appContext.ctx);\n }\n\n // Return merged props\n return {\n pageProps,\n globalEllmoData: data,\n globalEllmoError: error\n };\n };\n}\n","/**\n * Custom header name for Ellmo AI to pass pathname information\n * Using 'x-ellmo-pathname' to avoid conflicts with other libraries\n */\nexport const ELLMO_PATHNAME_HEADER = 'x-ellmo-pathname';\n\n/**\n * Type definitions for Next.js middleware (to avoid requiring Next.js as a dependency)\n */\nexport interface EllmoRequest {\n nextUrl: {\n pathname: string;\n };\n}\n\nexport interface EllmoResponse {\n headers: {\n set(name: string, value: string): void;\n };\n}\n\n/**\n * Ellmo AI middleware helper for Next.js\n * \n * This is a vanilla helper that adds pathname to request headers.\n * It doesn't depend on Next.js - you provide the request/response objects.\n * \n * Usage in Next.js:\n * \n * ```ts\n * // middleware.ts\n * import { ellmoMiddleware } from 'ellmo-ai-react/middleware';\n * import { NextResponse } from 'next/server';\n * import type { NextRequest } from 'next/server';\n * \n * export function middleware(request: NextRequest) {\n * const response = NextResponse.next();\n * return ellmoMiddleware(request, response);\n * }\n * \n * export const config = {\n * matcher: [\n * '/((?!_next/static|_next/image|favicon.ico).*)',\n * ],\n * };\n * ```\n * \n * Composing with existing middleware:\n * \n * ```ts\n * export function middleware(request: NextRequest) {\n * let response = NextResponse.next();\n * \n * // Your logic here\n * if (someCondition) {\n * response = NextResponse.redirect(new URL('/login', request.url));\n * }\n * \n * // Apply Ellmo middleware\n * return ellmoMiddleware(request, response);\n * }\n * ```\n */\nexport function ellmoMiddleware<\n Req extends EllmoRequest,\n Res extends EllmoResponse\n>(\n request: Req,\n response: Res\n): Res {\n // Extract pathname from the request URL\n const pathname = request.nextUrl.pathname;\n \n // Add the pathname to a custom header\n response.headers.set(ELLMO_PATHNAME_HEADER, pathname);\n \n return response;\n}\n\n/**\n * Helper to extract pathname from headers object\n * \n * Usage in Next.js Server Components:\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * export default function Page() {\n * const headersList = headers();\n * const pathname = getPathnameFromHeaders(headersList);\n * \n * return <EllmoApi clientId=\"your-id\" url={pathname} />;\n * }\n * ```\n */\nexport function getPathnameFromHeaders(headers: { get(name: string): string | null }): string | null {\n return headers.get(ELLMO_PATHNAME_HEADER);\n}\n\nexport default ellmoMiddleware;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/EllmoApi.tsx","../src/EllmoApiSSR.tsx","../src/shared.ts","../src/EllmoApiStatic.tsx","../src/middleware.ts"],"sourcesContent":["import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiProps {\n /**\n * The URL path to fetch data for (required).\n * \n * With middleware (recommended):\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * const pathname = getPathnameFromHeaders(headers());\n * <EllmoApi clientId=\"...\" url={pathname || '/'} />\n * ```\n * \n * Without middleware:\n * ```tsx\n * <EllmoApi clientId=\"...\" url=\"/about\" />\n * ```\n */\n url: string;\n /**\n * The API key/client identifier (required)\n */\n clientId: string;\n /**\n * Type of data to fetch\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children to render when data is available\n */\n children?: (data: any, error: Error | null) => React.ReactNode;\n}\n\n/**\n * Server-only Ellmo API component (React Server Component)\n * This component fetches data during server rendering.\n * It requires Next.js 13+ App Router or other RSC-compatible frameworks.\n * \n * @example\n * ```tsx\n * // In a server component (app/page.tsx)\n * export default async function Page() {\n * return <EllmoApi clientId=\"your-id\" url=\"/about\" />;\n * }\n * ```\n */\nconst EllmoApi = async ({\n url,\n clientId,\n type,\n className = '',\n showErrors = false,\n children\n}: EllmoApiProps): Promise<React.ReactElement | null> => {\n let data: any = null;\n let error: Error | null = null;\n\n let translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url prop is required. Please provide the page pathname.');\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data during server render\n const response = await fetch(apiUrl, {\n cache: 'no-store', // Always fetch fresh data\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n if (type === 'structured') {\n data = await response.text();\n } else if (type === 'semantic') {\n data = await response.text();\n } else {\n throw new Error(`Invalid type: ${type}`);\n }\n } catch (err) {\n error = err instanceof Error ? err : new Error('Unknown error occurred');\n }\n\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error.message}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{JSON.stringify(data, null, 2)}</pre>\n </div>\n );\n }\n\n // Invisible component by default - just fetches data during server render\n if (type === 'structured' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n } else if (type === 'semantic' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n }\n return null;\n};\n\nexport default EllmoApi;\n","import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiSSRProps {\n /**\n * The pre-fetched data from the Ellmo API\n */\n data?: string | null;\n /**\n * Error from fetching data\n */\n error?: string | null;\n /**\n * Type of data to render\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children render prop with data and error\n */\n children?: (data: string | null, error: string | null) => React.ReactNode;\n}\n\n/**\n * Ellmo API component for traditional SSR environments (Next.js Pages Router)\n * This component receives pre-fetched data and renders it.\n * Data fetching should be done in getServerSideProps or getStaticProps.\n * \n * @example\n * ```tsx\n * // In your page file (pages/about.tsx)\n * import { EllmoApiSSR, fetchEllmoData } from 'ellmo-ai-react';\n * \n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: 'your-client-id',\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * export default function AboutPage({ ellmoData, ellmoError }) {\n * return (\n * <div>\n * <h1>About Page</h1>\n * <EllmoApiSSR data={ellmoData} error={ellmoError} />\n * </div>\n * );\n * }\n * ```\n */\nconst EllmoApiSSR: React.FC<EllmoApiSSRProps> = ({\n data = null,\n error = null,\n className = '',\n showErrors = false,\n children\n}) => {\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{data}</pre>\n </div>\n );\n }\n\n // Render HTML content if available\n if (data && !error) {\n return <div className={className} dangerouslySetInnerHTML={{ __html: data }} />;\n }\n\n // Return null if no data\n return null;\n};\n\nexport default EllmoApiSSR;\n \n","export type EllmoApiType = 'semantic' | 'structured';\n\n/**\n * Fetch data from Ellmo API\n * Use this in getServerSideProps, getStaticProps, or getInitialProps\n * \n * @example\n * ```tsx\n * // In getServerSideProps (Next.js Pages Router)\n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.ELLMO_CLIENT_ID!,\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * // In getInitialProps (older Next.js API)\n * MyPage.getInitialProps = async (ctx) => {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: ctx.asPath || '/',\n * type: 'semantic'\n * });\n * \n * return { ellmoData: data, ellmoError: error };\n * };\n * ```\n */\nexport async function fetchEllmoData({\n clientId,\n url,\n type = 'semantic'\n}: {\n clientId: string;\n url: string;\n type?: EllmoApiType;\n}): Promise<{ data: string | null; error: string | null }> {\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url is required. Please provide the page pathname.');\n }\n\n if (url.includes('.')) {\n // Sometimes urls contain a dot if they're images or other assets which are served by SSG (static generation)\n return { data: null, error: null };\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n const translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data\n const response = await fetch(apiUrl, {\n cache: 'no-store',\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n const data = await response.text();\n return { data, error: null };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';\n return { data: null, error: errorMessage };\n }\n}\n\n","import { fetchEllmoData, type EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\n// Type for Next.js App context\ntype AppContext = {\n Component: any;\n ctx: any;\n router: any;\n};\n\n\n/**\n * Helper for _app.tsx to fetch global Ellmo data and merge with page props\n * Automatically calls the page's getInitialProps and merges everything\n * \n * @param clientId - Your Ellmo client ID\n * @param url - Function that returns the URL path from app context\n * @param type - Content type: 'semantic' or 'structured' (default: 'semantic')\n * @param debugging - Include pageEllmoError in props for debugging (default: false)\n * \n * Returns pageEllmoData in pageProps. If debugging is enabled, also includes pageEllmoError.\n * \n * @example\n * ```tsx\n * import { withEllmoApp } from 'ellmo-ai-react';\n * \n * function MyApp({ Component, pageProps }) {\n * return (\n * <>\n * <header>\n * <EllmoApiSSR \n * data={pageProps.pageEllmoData} \n * error={pageProps.pageEllmoError} \n * showErrors={true} // Show errors in development\n * />\n * </header>\n * <Component {...pageProps} />\n * </>\n * );\n * }\n * \n * MyApp.getInitialProps = withEllmoApp({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: (appContext) => '/global-header',\n * type: 'structured',\n * debugging: process.env.NODE_ENV === 'development' // Enable error prop in development\n * });\n * \n * export default MyApp;\n * ```\n */\nexport function withEllmoApp({\n clientId,\n url,\n type = 'semantic',\n debugging = false\n}: {\n clientId: string;\n url: (appContext: AppContext) => string;\n type?: EllmoApiType;\n debugging?: boolean;\n}) {\n return async (appContext: AppContext) => {\n // Fetch global Ellmo data\n const { data, error } = await fetchEllmoData({\n clientId,\n url: url(appContext), // Use the function to get the URL\n type\n });\n\n // Call the page's getInitialProps if it exists\n let pageProps = {};\n if (appContext.Component.getInitialProps) {\n pageProps = await appContext.Component.getInitialProps(appContext.ctx);\n }\n\n // Return merged props with ellmo data inside pageProps\n return {\n pageProps: {\n ...pageProps,\n pageEllmoData: data,\n ...(debugging ? { pageEllmoError: error } : {}), // Only add error if debugging is enabled\n }\n };\n };\n}\n","/**\n * Custom header name for Ellmo AI to pass pathname information\n * Using 'x-ellmo-pathname' to avoid conflicts with other libraries\n */\nexport const ELLMO_PATHNAME_HEADER = 'x-ellmo-pathname';\n\n/**\n * Type definitions for Next.js middleware (to avoid requiring Next.js as a dependency)\n */\nexport interface EllmoRequest {\n nextUrl: {\n pathname: string;\n };\n}\n\nexport interface EllmoResponse {\n headers: {\n set(name: string, value: string): void;\n };\n}\n\n/**\n * Ellmo AI middleware helper for Next.js\n * \n * This is a vanilla helper that adds pathname to request headers.\n * It doesn't depend on Next.js - you provide the request/response objects.\n * \n * Usage in Next.js:\n * \n * ```ts\n * // middleware.ts\n * import { ellmoMiddleware } from 'ellmo-ai-react/middleware';\n * import { NextResponse } from 'next/server';\n * import type { NextRequest } from 'next/server';\n * \n * export function middleware(request: NextRequest) {\n * const response = NextResponse.next();\n * return ellmoMiddleware(request, response);\n * }\n * \n * export const config = {\n * matcher: [\n * '/((?!_next/static|_next/image|favicon.ico).*)',\n * ],\n * };\n * ```\n * \n * Composing with existing middleware:\n * \n * ```ts\n * export function middleware(request: NextRequest) {\n * let response = NextResponse.next();\n * \n * // Your logic here\n * if (someCondition) {\n * response = NextResponse.redirect(new URL('/login', request.url));\n * }\n * \n * // Apply Ellmo middleware\n * return ellmoMiddleware(request, response);\n * }\n * ```\n */\nexport function ellmoMiddleware<\n Req extends EllmoRequest,\n Res extends EllmoResponse\n>(\n request: Req,\n response: Res\n): Res {\n // Extract pathname from the request URL\n const pathname = request.nextUrl.pathname;\n \n // Add the pathname to a custom header\n response.headers.set(ELLMO_PATHNAME_HEADER, pathname);\n \n return response;\n}\n\n/**\n * Helper to extract pathname from headers object\n * \n * Usage in Next.js Server Components:\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * export default function Page() {\n * const headersList = headers();\n * const pathname = getPathnameFromHeaders(headersList);\n * \n * return <EllmoApi clientId=\"your-id\" url={pathname} />;\n * }\n * ```\n */\nexport function getPathnameFromHeaders(headers: { get(name: string): string | null }): string | null {\n return headers.get(ELLMO_PATHNAME_HEADER);\n}\n\nexport default ellmoMiddleware;\n"],"names":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -201,15 +201,26 @@ async function fetchEllmoData({ clientId, url, type = 'semantic' }) {
|
|
|
201
201
|
* Helper for _app.tsx to fetch global Ellmo data and merge with page props
|
|
202
202
|
* Automatically calls the page's getInitialProps and merges everything
|
|
203
203
|
*
|
|
204
|
+
* @param clientId - Your Ellmo client ID
|
|
205
|
+
* @param url - Function that returns the URL path from app context
|
|
206
|
+
* @param type - Content type: 'semantic' or 'structured' (default: 'semantic')
|
|
207
|
+
* @param debugging - Include pageEllmoError in props for debugging (default: false)
|
|
208
|
+
*
|
|
209
|
+
* Returns pageEllmoData in pageProps. If debugging is enabled, also includes pageEllmoError.
|
|
210
|
+
*
|
|
204
211
|
* @example
|
|
205
212
|
* ```tsx
|
|
206
213
|
* import { withEllmoApp } from 'ellmo-ai-react';
|
|
207
214
|
*
|
|
208
|
-
* function MyApp({ Component, pageProps
|
|
215
|
+
* function MyApp({ Component, pageProps }) {
|
|
209
216
|
* return (
|
|
210
217
|
* <>
|
|
211
218
|
* <header>
|
|
212
|
-
* <EllmoApiSSR
|
|
219
|
+
* <EllmoApiSSR
|
|
220
|
+
* data={pageProps.pageEllmoData}
|
|
221
|
+
* error={pageProps.pageEllmoError}
|
|
222
|
+
* showErrors={true} // Show errors in development
|
|
223
|
+
* />
|
|
213
224
|
* </header>
|
|
214
225
|
* <Component {...pageProps} />
|
|
215
226
|
* </>
|
|
@@ -218,14 +229,15 @@ async function fetchEllmoData({ clientId, url, type = 'semantic' }) {
|
|
|
218
229
|
*
|
|
219
230
|
* MyApp.getInitialProps = withEllmoApp({
|
|
220
231
|
* clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,
|
|
221
|
-
* url: '/global-header',
|
|
222
|
-
* type: 'structured'
|
|
232
|
+
* url: (appContext) => '/global-header',
|
|
233
|
+
* type: 'structured',
|
|
234
|
+
* debugging: process.env.NODE_ENV === 'development' // Enable error prop in development
|
|
223
235
|
* });
|
|
224
236
|
*
|
|
225
237
|
* export default MyApp;
|
|
226
238
|
* ```
|
|
227
239
|
*/
|
|
228
|
-
function withEllmoApp({ clientId, url, type = 'semantic' }) {
|
|
240
|
+
function withEllmoApp({ clientId, url, type = 'semantic', debugging = false }) {
|
|
229
241
|
return async (appContext) => {
|
|
230
242
|
// Fetch global Ellmo data
|
|
231
243
|
const { data, error } = await fetchEllmoData({
|
|
@@ -238,11 +250,13 @@ function withEllmoApp({ clientId, url, type = 'semantic' }) {
|
|
|
238
250
|
if (appContext.Component.getInitialProps) {
|
|
239
251
|
pageProps = await appContext.Component.getInitialProps(appContext.ctx);
|
|
240
252
|
}
|
|
241
|
-
// Return merged props
|
|
253
|
+
// Return merged props with ellmo data inside pageProps
|
|
242
254
|
return {
|
|
243
|
-
pageProps
|
|
244
|
-
|
|
245
|
-
|
|
255
|
+
pageProps: {
|
|
256
|
+
...pageProps,
|
|
257
|
+
pageEllmoData: data,
|
|
258
|
+
...(debugging ? { pageEllmoError: error } : {}), // Only add error if debugging is enabled
|
|
259
|
+
}
|
|
246
260
|
};
|
|
247
261
|
};
|
|
248
262
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/EllmoApi.tsx","../src/EllmoApiSSR.tsx","../src/shared.ts","../src/EllmoApiStatic.tsx","../src/middleware.ts"],"sourcesContent":["import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiProps {\n /**\n * The URL path to fetch data for (required).\n * \n * With middleware (recommended):\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * const pathname = getPathnameFromHeaders(headers());\n * <EllmoApi clientId=\"...\" url={pathname || '/'} />\n * ```\n * \n * Without middleware:\n * ```tsx\n * <EllmoApi clientId=\"...\" url=\"/about\" />\n * ```\n */\n url: string;\n /**\n * The API key/client identifier (required)\n */\n clientId: string;\n /**\n * Type of data to fetch\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children to render when data is available\n */\n children?: (data: any, error: Error | null) => React.ReactNode;\n}\n\n/**\n * Server-only Ellmo API component (React Server Component)\n * This component fetches data during server rendering.\n * It requires Next.js 13+ App Router or other RSC-compatible frameworks.\n * \n * @example\n * ```tsx\n * // In a server component (app/page.tsx)\n * export default async function Page() {\n * return <EllmoApi clientId=\"your-id\" url=\"/about\" />;\n * }\n * ```\n */\nconst EllmoApi = async ({\n url,\n clientId,\n type,\n className = '',\n showErrors = false,\n children\n}: EllmoApiProps): Promise<React.ReactElement | null> => {\n let data: any = null;\n let error: Error | null = null;\n\n let translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url prop is required. Please provide the page pathname.');\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data during server render\n const response = await fetch(apiUrl, {\n cache: 'no-store', // Always fetch fresh data\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n if (type === 'structured') {\n data = await response.text();\n } else if (type === 'semantic') {\n data = await response.text();\n } else {\n throw new Error(`Invalid type: ${type}`);\n }\n } catch (err) {\n error = err instanceof Error ? err : new Error('Unknown error occurred');\n }\n\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error.message}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{JSON.stringify(data, null, 2)}</pre>\n </div>\n );\n }\n\n // Invisible component by default - just fetches data during server render\n if (type === 'structured' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n } else if (type === 'semantic' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n }\n return null;\n};\n\nexport default EllmoApi;\n","import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiSSRProps {\n /**\n * The pre-fetched data from the Ellmo API\n */\n data?: string | null;\n /**\n * Error from fetching data\n */\n error?: string | null;\n /**\n * Type of data to render\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children render prop with data and error\n */\n children?: (data: string | null, error: string | null) => React.ReactNode;\n}\n\n/**\n * Ellmo API component for traditional SSR environments (Next.js Pages Router)\n * This component receives pre-fetched data and renders it.\n * Data fetching should be done in getServerSideProps or getStaticProps.\n * \n * @example\n * ```tsx\n * // In your page file (pages/about.tsx)\n * import { EllmoApiSSR, fetchEllmoData } from 'ellmo-ai-react';\n * \n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: 'your-client-id',\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * export default function AboutPage({ ellmoData, ellmoError }) {\n * return (\n * <div>\n * <h1>About Page</h1>\n * <EllmoApiSSR data={ellmoData} error={ellmoError} />\n * </div>\n * );\n * }\n * ```\n */\nconst EllmoApiSSR: React.FC<EllmoApiSSRProps> = ({\n data = null,\n error = null,\n className = '',\n showErrors = false,\n children\n}) => {\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{data}</pre>\n </div>\n );\n }\n\n // Render HTML content if available\n if (data && !error) {\n return <div className={className} dangerouslySetInnerHTML={{ __html: data }} />;\n }\n\n // Return null if no data\n return null;\n};\n\nexport default EllmoApiSSR;\n \n","export type EllmoApiType = 'semantic' | 'structured';\n\n/**\n * Fetch data from Ellmo API\n * Use this in getServerSideProps, getStaticProps, or getInitialProps\n * \n * @example\n * ```tsx\n * // In getServerSideProps (Next.js Pages Router)\n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.ELLMO_CLIENT_ID!,\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * // In getInitialProps (older Next.js API)\n * MyPage.getInitialProps = async (ctx) => {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: ctx.asPath || '/',\n * type: 'semantic'\n * });\n * \n * return { ellmoData: data, ellmoError: error };\n * };\n * ```\n */\nexport async function fetchEllmoData({\n clientId,\n url,\n type = 'semantic'\n}: {\n clientId: string;\n url: string;\n type?: EllmoApiType;\n}): Promise<{ data: string | null; error: string | null }> {\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url is required. Please provide the page pathname.');\n }\n\n if (url.includes('.')) {\n // Sometimes urls contain a dot if they're images or other assets which are served by SSG (static generation)\n return { data: null, error: null };\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n const translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data\n const response = await fetch(apiUrl, {\n cache: 'no-store',\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n const data = await response.text();\n return { data, error: null };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';\n return { data: null, error: errorMessage };\n }\n}\n\n","import { fetchEllmoData, type EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\n// Type for Next.js App context\ntype AppContext = {\n Component: any;\n ctx: any;\n router: any;\n};\n\n\n/**\n * Helper for _app.tsx to fetch global Ellmo data and merge with page props\n * Automatically calls the page's getInitialProps and merges everything\n * \n * @example\n * ```tsx\n * import { withEllmoApp } from 'ellmo-ai-react';\n * \n * function MyApp({ Component, pageProps, globalEllmoData, globalEllmoError }) {\n * return (\n * <>\n * <header>\n * <EllmoApiSSR data={globalEllmoData} error={globalEllmoError} />\n * </header>\n * <Component {...pageProps} />\n * </>\n * );\n * }\n * \n * MyApp.getInitialProps = withEllmoApp({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: '/global-header',\n * type: 'structured'\n * });\n * \n * export default MyApp;\n * ```\n */\nexport function withEllmoApp({\n clientId,\n url,\n type = 'semantic'\n}: {\n clientId: string;\n url: (appContext: AppContext) => string;\n type?: EllmoApiType;\n}) {\n return async (appContext: AppContext) => {\n // Fetch global Ellmo data\n const { data, error } = await fetchEllmoData({\n clientId,\n url: url(appContext), // Use the function to get the URL\n type\n });\n\n // Call the page's getInitialProps if it exists\n let pageProps = {};\n if (appContext.Component.getInitialProps) {\n pageProps = await appContext.Component.getInitialProps(appContext.ctx);\n }\n\n // Return merged props\n return {\n pageProps,\n globalEllmoData: data,\n globalEllmoError: error\n };\n };\n}\n","/**\n * Custom header name for Ellmo AI to pass pathname information\n * Using 'x-ellmo-pathname' to avoid conflicts with other libraries\n */\nexport const ELLMO_PATHNAME_HEADER = 'x-ellmo-pathname';\n\n/**\n * Type definitions for Next.js middleware (to avoid requiring Next.js as a dependency)\n */\nexport interface EllmoRequest {\n nextUrl: {\n pathname: string;\n };\n}\n\nexport interface EllmoResponse {\n headers: {\n set(name: string, value: string): void;\n };\n}\n\n/**\n * Ellmo AI middleware helper for Next.js\n * \n * This is a vanilla helper that adds pathname to request headers.\n * It doesn't depend on Next.js - you provide the request/response objects.\n * \n * Usage in Next.js:\n * \n * ```ts\n * // middleware.ts\n * import { ellmoMiddleware } from 'ellmo-ai-react/middleware';\n * import { NextResponse } from 'next/server';\n * import type { NextRequest } from 'next/server';\n * \n * export function middleware(request: NextRequest) {\n * const response = NextResponse.next();\n * return ellmoMiddleware(request, response);\n * }\n * \n * export const config = {\n * matcher: [\n * '/((?!_next/static|_next/image|favicon.ico).*)',\n * ],\n * };\n * ```\n * \n * Composing with existing middleware:\n * \n * ```ts\n * export function middleware(request: NextRequest) {\n * let response = NextResponse.next();\n * \n * // Your logic here\n * if (someCondition) {\n * response = NextResponse.redirect(new URL('/login', request.url));\n * }\n * \n * // Apply Ellmo middleware\n * return ellmoMiddleware(request, response);\n * }\n * ```\n */\nexport function ellmoMiddleware<\n Req extends EllmoRequest,\n Res extends EllmoResponse\n>(\n request: Req,\n response: Res\n): Res {\n // Extract pathname from the request URL\n const pathname = request.nextUrl.pathname;\n \n // Add the pathname to a custom header\n response.headers.set(ELLMO_PATHNAME_HEADER, pathname);\n \n return response;\n}\n\n/**\n * Helper to extract pathname from headers object\n * \n * Usage in Next.js Server Components:\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * export default function Page() {\n * const headersList = headers();\n * const pathname = getPathnameFromHeaders(headersList);\n * \n * return <EllmoApi clientId=\"your-id\" url={pathname} />;\n * }\n * ```\n */\nexport function getPathnameFromHeaders(headers: { get(name: string): string | null }): string | null {\n return headers.get(ELLMO_PATHNAME_HEADER);\n}\n\nexport default ellmoMiddleware;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/EllmoApi.tsx","../src/EllmoApiSSR.tsx","../src/shared.ts","../src/EllmoApiStatic.tsx","../src/middleware.ts"],"sourcesContent":["import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiProps {\n /**\n * The URL path to fetch data for (required).\n * \n * With middleware (recommended):\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * const pathname = getPathnameFromHeaders(headers());\n * <EllmoApi clientId=\"...\" url={pathname || '/'} />\n * ```\n * \n * Without middleware:\n * ```tsx\n * <EllmoApi clientId=\"...\" url=\"/about\" />\n * ```\n */\n url: string;\n /**\n * The API key/client identifier (required)\n */\n clientId: string;\n /**\n * Type of data to fetch\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children to render when data is available\n */\n children?: (data: any, error: Error | null) => React.ReactNode;\n}\n\n/**\n * Server-only Ellmo API component (React Server Component)\n * This component fetches data during server rendering.\n * It requires Next.js 13+ App Router or other RSC-compatible frameworks.\n * \n * @example\n * ```tsx\n * // In a server component (app/page.tsx)\n * export default async function Page() {\n * return <EllmoApi clientId=\"your-id\" url=\"/about\" />;\n * }\n * ```\n */\nconst EllmoApi = async ({\n url,\n clientId,\n type,\n className = '',\n showErrors = false,\n children\n}: EllmoApiProps): Promise<React.ReactElement | null> => {\n let data: any = null;\n let error: Error | null = null;\n\n let translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url prop is required. Please provide the page pathname.');\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data during server render\n const response = await fetch(apiUrl, {\n cache: 'no-store', // Always fetch fresh data\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n if (type === 'structured') {\n data = await response.text();\n } else if (type === 'semantic') {\n data = await response.text();\n } else {\n throw new Error(`Invalid type: ${type}`);\n }\n } catch (err) {\n error = err instanceof Error ? err : new Error('Unknown error occurred');\n }\n\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error.message}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{JSON.stringify(data, null, 2)}</pre>\n </div>\n );\n }\n\n // Invisible component by default - just fetches data during server render\n if (type === 'structured' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n } else if (type === 'semantic' && data) {\n return <div dangerouslySetInnerHTML={{ __html: data }} />;\n }\n return null;\n};\n\nexport default EllmoApi;\n","import React from 'react';\nimport type { EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\nexport interface EllmoApiSSRProps {\n /**\n * The pre-fetched data from the Ellmo API\n */\n data?: string | null;\n /**\n * Error from fetching data\n */\n error?: string | null;\n /**\n * Type of data to render\n */\n type?: EllmoApiType;\n /**\n * Custom className for styling\n */\n className?: string;\n /**\n * Whether to show errors\n */\n showErrors?: boolean;\n /**\n * Children render prop with data and error\n */\n children?: (data: string | null, error: string | null) => React.ReactNode;\n}\n\n/**\n * Ellmo API component for traditional SSR environments (Next.js Pages Router)\n * This component receives pre-fetched data and renders it.\n * Data fetching should be done in getServerSideProps or getStaticProps.\n * \n * @example\n * ```tsx\n * // In your page file (pages/about.tsx)\n * import { EllmoApiSSR, fetchEllmoData } from 'ellmo-ai-react';\n * \n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: 'your-client-id',\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * export default function AboutPage({ ellmoData, ellmoError }) {\n * return (\n * <div>\n * <h1>About Page</h1>\n * <EllmoApiSSR data={ellmoData} error={ellmoError} />\n * </div>\n * );\n * }\n * ```\n */\nconst EllmoApiSSR: React.FC<EllmoApiSSRProps> = ({\n data = null,\n error = null,\n className = '',\n showErrors = false,\n children\n}) => {\n // If children prop is provided, use render prop pattern\n if (children) {\n return <>{children(data, error)}</>;\n }\n\n // Show errors if enabled\n if (error && showErrors) {\n return (\n <div className={`ellmo-api-error ${className}`}>\n <div>Error: {error}</div>\n </div>\n );\n }\n\n // Show data if showErrors is enabled (for debugging)\n if (data && showErrors) {\n return (\n <div className={`ellmo-api-data ${className}`}>\n <pre>{data}</pre>\n </div>\n );\n }\n\n // Render HTML content if available\n if (data && !error) {\n return <div className={className} dangerouslySetInnerHTML={{ __html: data }} />;\n }\n\n // Return null if no data\n return null;\n};\n\nexport default EllmoApiSSR;\n \n","export type EllmoApiType = 'semantic' | 'structured';\n\n/**\n * Fetch data from Ellmo API\n * Use this in getServerSideProps, getStaticProps, or getInitialProps\n * \n * @example\n * ```tsx\n * // In getServerSideProps (Next.js Pages Router)\n * export async function getServerSideProps(context) {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.ELLMO_CLIENT_ID!,\n * url: context.resolvedUrl,\n * type: 'semantic'\n * });\n * \n * return {\n * props: { ellmoData: data, ellmoError: error }\n * };\n * }\n * \n * // In getInitialProps (older Next.js API)\n * MyPage.getInitialProps = async (ctx) => {\n * const { data, error } = await fetchEllmoData({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: ctx.asPath || '/',\n * type: 'semantic'\n * });\n * \n * return { ellmoData: data, ellmoError: error };\n * };\n * ```\n */\nexport async function fetchEllmoData({\n clientId,\n url,\n type = 'semantic'\n}: {\n clientId: string;\n url: string;\n type?: EllmoApiType;\n}): Promise<{ data: string | null; error: string | null }> {\n try {\n // Validate required props\n if (!clientId) {\n throw new Error('clientId is required. Please provide your Ellmo API client identifier.');\n }\n\n if (!url) {\n throw new Error('url is required. Please provide the page pathname.');\n }\n\n if (url.includes('.')) {\n // Sometimes urls contain a dot if they're images or other assets which are served by SSG (static generation)\n return { data: null, error: null };\n }\n\n // Encode the URL path for the API call\n const encodedUrl = encodeURIComponent(url);\n const translatedType = type === 'structured' ? 'structured' : 'semantic';\n\n // Build the API URL\n const apiUrl = `https://www.tryellmo.ai/public-api/wordpress?c=${clientId}&t=${translatedType}&u=${encodedUrl}`;\n\n // Fetch data\n const response = await fetch(apiUrl, {\n cache: 'no-store',\n });\n\n if (!response.ok) {\n throw new Error(`API request failed with status ${response.status}`);\n }\n\n const data = await response.text();\n return { data, error: null };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';\n return { data: null, error: errorMessage };\n }\n}\n\n","import { fetchEllmoData, type EllmoApiType } from './shared';\n\nexport type { EllmoApiType };\n\n// Type for Next.js App context\ntype AppContext = {\n Component: any;\n ctx: any;\n router: any;\n};\n\n\n/**\n * Helper for _app.tsx to fetch global Ellmo data and merge with page props\n * Automatically calls the page's getInitialProps and merges everything\n * \n * @param clientId - Your Ellmo client ID\n * @param url - Function that returns the URL path from app context\n * @param type - Content type: 'semantic' or 'structured' (default: 'semantic')\n * @param debugging - Include pageEllmoError in props for debugging (default: false)\n * \n * Returns pageEllmoData in pageProps. If debugging is enabled, also includes pageEllmoError.\n * \n * @example\n * ```tsx\n * import { withEllmoApp } from 'ellmo-ai-react';\n * \n * function MyApp({ Component, pageProps }) {\n * return (\n * <>\n * <header>\n * <EllmoApiSSR \n * data={pageProps.pageEllmoData} \n * error={pageProps.pageEllmoError} \n * showErrors={true} // Show errors in development\n * />\n * </header>\n * <Component {...pageProps} />\n * </>\n * );\n * }\n * \n * MyApp.getInitialProps = withEllmoApp({\n * clientId: process.env.NEXT_PUBLIC_ELLMO_CLIENT_ID!,\n * url: (appContext) => '/global-header',\n * type: 'structured',\n * debugging: process.env.NODE_ENV === 'development' // Enable error prop in development\n * });\n * \n * export default MyApp;\n * ```\n */\nexport function withEllmoApp({\n clientId,\n url,\n type = 'semantic',\n debugging = false\n}: {\n clientId: string;\n url: (appContext: AppContext) => string;\n type?: EllmoApiType;\n debugging?: boolean;\n}) {\n return async (appContext: AppContext) => {\n // Fetch global Ellmo data\n const { data, error } = await fetchEllmoData({\n clientId,\n url: url(appContext), // Use the function to get the URL\n type\n });\n\n // Call the page's getInitialProps if it exists\n let pageProps = {};\n if (appContext.Component.getInitialProps) {\n pageProps = await appContext.Component.getInitialProps(appContext.ctx);\n }\n\n // Return merged props with ellmo data inside pageProps\n return {\n pageProps: {\n ...pageProps,\n pageEllmoData: data,\n ...(debugging ? { pageEllmoError: error } : {}), // Only add error if debugging is enabled\n }\n };\n };\n}\n","/**\n * Custom header name for Ellmo AI to pass pathname information\n * Using 'x-ellmo-pathname' to avoid conflicts with other libraries\n */\nexport const ELLMO_PATHNAME_HEADER = 'x-ellmo-pathname';\n\n/**\n * Type definitions for Next.js middleware (to avoid requiring Next.js as a dependency)\n */\nexport interface EllmoRequest {\n nextUrl: {\n pathname: string;\n };\n}\n\nexport interface EllmoResponse {\n headers: {\n set(name: string, value: string): void;\n };\n}\n\n/**\n * Ellmo AI middleware helper for Next.js\n * \n * This is a vanilla helper that adds pathname to request headers.\n * It doesn't depend on Next.js - you provide the request/response objects.\n * \n * Usage in Next.js:\n * \n * ```ts\n * // middleware.ts\n * import { ellmoMiddleware } from 'ellmo-ai-react/middleware';\n * import { NextResponse } from 'next/server';\n * import type { NextRequest } from 'next/server';\n * \n * export function middleware(request: NextRequest) {\n * const response = NextResponse.next();\n * return ellmoMiddleware(request, response);\n * }\n * \n * export const config = {\n * matcher: [\n * '/((?!_next/static|_next/image|favicon.ico).*)',\n * ],\n * };\n * ```\n * \n * Composing with existing middleware:\n * \n * ```ts\n * export function middleware(request: NextRequest) {\n * let response = NextResponse.next();\n * \n * // Your logic here\n * if (someCondition) {\n * response = NextResponse.redirect(new URL('/login', request.url));\n * }\n * \n * // Apply Ellmo middleware\n * return ellmoMiddleware(request, response);\n * }\n * ```\n */\nexport function ellmoMiddleware<\n Req extends EllmoRequest,\n Res extends EllmoResponse\n>(\n request: Req,\n response: Res\n): Res {\n // Extract pathname from the request URL\n const pathname = request.nextUrl.pathname;\n \n // Add the pathname to a custom header\n response.headers.set(ELLMO_PATHNAME_HEADER, pathname);\n \n return response;\n}\n\n/**\n * Helper to extract pathname from headers object\n * \n * Usage in Next.js Server Components:\n * ```tsx\n * import { headers } from 'next/headers';\n * import { getPathnameFromHeaders } from 'ellmo-ai-react/middleware';\n * \n * export default function Page() {\n * const headersList = headers();\n * const pathname = getPathnameFromHeaders(headersList);\n * \n * return <EllmoApi clientId=\"your-id\" url={pathname} />;\n * }\n * ```\n */\nexport function getPathnameFromHeaders(headers: { get(name: string): string | null }): string | null {\n return headers.get(ELLMO_PATHNAME_HEADER);\n}\n\nexport default ellmoMiddleware;\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ellmo-ai-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"website": "https://www.tryellmo.ai?utm_source=npm&utm_medium=package&utm_campaign=ellmo-ai-react",
|
|
5
5
|
"description": "React component for integration with Ellmo AI Platform",
|
|
6
6
|
"main": "dist/index.js",
|