@demokit-ai/next 0.3.0 → 0.4.1
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/dist/client.cjs +88 -9
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -3
- package/dist/client.d.ts +4 -3
- package/dist/client.js +88 -9
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +10 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -3
- package/dist/index.d.ts +31 -3
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.cts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/{types-Cvq5JUP1.d.cts → types-Brt8EaFz.d.cts} +38 -1
- package/dist/{types-Cvq5JUP1.d.ts → types-Brt8EaFz.d.ts} +38 -1
- package/package.json +11 -10
package/dist/client.cjs
CHANGED
|
@@ -58,10 +58,62 @@ function DemoKitNextProvider({
|
|
|
58
58
|
storageKey = "demokit-mode",
|
|
59
59
|
cookieName = "demokit-mode",
|
|
60
60
|
initialEnabled,
|
|
61
|
-
baseUrl
|
|
61
|
+
baseUrl,
|
|
62
|
+
source
|
|
62
63
|
}) {
|
|
64
|
+
console.log("[DemoKit Provider] source prop received:", source);
|
|
63
65
|
const [isHydrated, setIsHydrated] = (0, import_react.useState)(false);
|
|
64
66
|
const [scenario, setScenario] = (0, import_react.useState)(null);
|
|
67
|
+
const [remoteFixtures, setRemoteFixtures] = (0, import_react.useState)(null);
|
|
68
|
+
const [remoteError, setRemoteError] = (0, import_react.useState)(null);
|
|
69
|
+
const [sourceMode, setSourceMode] = (0, import_react.useState)("auto");
|
|
70
|
+
(0, import_react.useEffect)(() => {
|
|
71
|
+
if (typeof window === "undefined") return;
|
|
72
|
+
const params = new URLSearchParams(window.location.search);
|
|
73
|
+
const sourceParam = params.get("source");
|
|
74
|
+
if (sourceParam === "local" || sourceParam === "remote") {
|
|
75
|
+
setSourceMode(sourceParam);
|
|
76
|
+
console.log("[DemoKit] Source mode from URL:", sourceParam);
|
|
77
|
+
}
|
|
78
|
+
}, []);
|
|
79
|
+
(0, import_react.useEffect)(() => {
|
|
80
|
+
const apiKey = source?.apiKey;
|
|
81
|
+
const apiUrl = source?.apiUrl;
|
|
82
|
+
console.log("[DemoKit] Remote config check:", { apiKey: !!apiKey, apiUrl, sourceMode });
|
|
83
|
+
if (sourceMode === "local") {
|
|
84
|
+
console.log("[DemoKit] Skipping remote fetch - source=local");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!apiKey || !apiUrl) {
|
|
88
|
+
console.log("[DemoKit] Missing apiKey or apiUrl, skipping remote fetch");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const fetchRemoteFixtures = async () => {
|
|
92
|
+
try {
|
|
93
|
+
console.log("[DemoKit] Fetching remote fixtures from:", apiUrl);
|
|
94
|
+
const response = await fetch(`${apiUrl}/fixtures`, {
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${apiKey}`,
|
|
97
|
+
"Content-Type": "application/json"
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
throw new Error(`Failed to fetch fixtures: ${response.status} ${response.statusText}`);
|
|
102
|
+
}
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
console.log("[DemoKit] Received remote fixtures:", data);
|
|
105
|
+
const fixtureMap = {};
|
|
106
|
+
for (const [pattern, fixtureData] of Object.entries(data.fixtures || data)) {
|
|
107
|
+
fixtureMap[pattern] = () => fixtureData;
|
|
108
|
+
}
|
|
109
|
+
setRemoteFixtures(fixtureMap);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error("[DemoKit] Failed to fetch remote fixtures:", error);
|
|
112
|
+
setRemoteError(error instanceof Error ? error : new Error(String(error)));
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
fetchRemoteFixtures();
|
|
116
|
+
}, [source, sourceMode]);
|
|
65
117
|
(0, import_react.useEffect)(() => {
|
|
66
118
|
const cookieEnabled = getDemoModeFromCookie(cookieName);
|
|
67
119
|
const cookieScenario = getScenarioFromCookie(cookieName);
|
|
@@ -69,11 +121,31 @@ function DemoKitNextProvider({
|
|
|
69
121
|
setIsHydrated(true);
|
|
70
122
|
}, [cookieName]);
|
|
71
123
|
const activeFixtures = (0, import_react.useMemo)(() => {
|
|
124
|
+
let result;
|
|
125
|
+
if (sourceMode === "local") {
|
|
126
|
+
result = fixtures;
|
|
127
|
+
console.log("[DemoKit Provider] Using LOCAL fixtures (forced)");
|
|
128
|
+
} else if (sourceMode === "remote" && remoteFixtures) {
|
|
129
|
+
result = remoteFixtures;
|
|
130
|
+
console.log("[DemoKit Provider] Using REMOTE fixtures (forced)");
|
|
131
|
+
} else if (remoteFixtures) {
|
|
132
|
+
result = { ...fixtures, ...remoteFixtures };
|
|
133
|
+
console.log("[DemoKit Provider] Using MERGED fixtures (local + remote)");
|
|
134
|
+
} else {
|
|
135
|
+
result = fixtures;
|
|
136
|
+
console.log("[DemoKit Provider] Using LOCAL fixtures (remote not available)");
|
|
137
|
+
}
|
|
72
138
|
if (scenario && scenarios[scenario]) {
|
|
73
|
-
|
|
139
|
+
result = { ...result, ...scenarios[scenario] };
|
|
140
|
+
}
|
|
141
|
+
console.log("[DemoKit Provider] Active fixtures:", Object.keys(result));
|
|
142
|
+
console.log("[DemoKit Provider] Scenario:", scenario);
|
|
143
|
+
console.log("[DemoKit Provider] Source mode:", sourceMode);
|
|
144
|
+
if (remoteError) {
|
|
145
|
+
console.warn("[DemoKit Provider] Remote fixture error:", remoteError.message);
|
|
74
146
|
}
|
|
75
|
-
return
|
|
76
|
-
}, [fixtures, scenarios, scenario]);
|
|
147
|
+
return result;
|
|
148
|
+
}, [fixtures, scenarios, scenario, remoteFixtures, remoteError, sourceMode]);
|
|
77
149
|
const enabled = (0, import_react.useMemo)(() => {
|
|
78
150
|
if (initialEnabled !== void 0) {
|
|
79
151
|
return initialEnabled;
|
|
@@ -81,8 +153,11 @@ function DemoKitNextProvider({
|
|
|
81
153
|
if (!isHydrated) {
|
|
82
154
|
return false;
|
|
83
155
|
}
|
|
84
|
-
|
|
156
|
+
const cookieValue = getDemoModeFromCookie(cookieName);
|
|
157
|
+
console.log("[DemoKit Next Provider] Demo mode from cookie:", { cookieName, enabled: cookieValue });
|
|
158
|
+
return cookieValue;
|
|
85
159
|
}, [initialEnabled, isHydrated, cookieName]);
|
|
160
|
+
const providerKey = isHydrated ? `hydrated-${enabled}` : "pre-hydration";
|
|
86
161
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
87
162
|
import_react2.DemoKitProvider,
|
|
88
163
|
{
|
|
@@ -91,7 +166,8 @@ function DemoKitNextProvider({
|
|
|
91
166
|
initialEnabled: enabled,
|
|
92
167
|
baseUrl,
|
|
93
168
|
children
|
|
94
|
-
}
|
|
169
|
+
},
|
|
170
|
+
providerKey
|
|
95
171
|
);
|
|
96
172
|
}
|
|
97
173
|
|
|
@@ -107,22 +183,25 @@ function useNextDemoMode(options = {}) {
|
|
|
107
183
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
108
184
|
const enableWithScenario = (0, import_react3.useCallback)(
|
|
109
185
|
(scenario) => {
|
|
186
|
+
demoMode.enable();
|
|
110
187
|
const params = new URLSearchParams(searchParams.toString());
|
|
111
188
|
params.set(urlParam, scenario);
|
|
112
189
|
router.push(`?${params.toString()}`);
|
|
113
190
|
},
|
|
114
|
-
[router, searchParams, urlParam]
|
|
191
|
+
[router, searchParams, urlParam, demoMode]
|
|
115
192
|
);
|
|
116
193
|
const enableDemo = (0, import_react3.useCallback)(() => {
|
|
194
|
+
demoMode.enable();
|
|
117
195
|
const params = new URLSearchParams(searchParams.toString());
|
|
118
196
|
params.set(urlParam, "true");
|
|
119
197
|
router.push(`?${params.toString()}`);
|
|
120
|
-
}, [router, searchParams, urlParam]);
|
|
198
|
+
}, [router, searchParams, urlParam, demoMode]);
|
|
121
199
|
const disableDemo = (0, import_react3.useCallback)(() => {
|
|
200
|
+
demoMode.disable();
|
|
122
201
|
const params = new URLSearchParams(searchParams.toString());
|
|
123
202
|
params.set(urlParam, "false");
|
|
124
203
|
router.push(`?${params.toString()}`);
|
|
125
|
-
}, [router, searchParams, urlParam]);
|
|
204
|
+
}, [router, searchParams, urlParam, demoMode]);
|
|
126
205
|
const currentScenario = searchParams.get(urlParam);
|
|
127
206
|
const isScenario = currentScenario !== null && currentScenario !== "true" && currentScenario !== "false" && currentScenario !== "1" && currentScenario !== "0";
|
|
128
207
|
return {
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/client/provider.tsx","../src/client/hooks.ts","../src/client/banner.tsx"],"sourcesContent":["/**\n * Client-side exports for @demokit-ai/next\n *\n * Import from '@demokit-ai/next/client' for client components.\n *\n * @example\n * 'use client'\n * import { DemoKitNextProvider, useNextDemoMode, NextDemoModeBanner } from '@demokit-ai/next/client'\n */\n\nexport * from './client/index'\n","'use client'\n\nimport { useEffect, useState, useMemo } from 'react'\nimport { DemoKitProvider, type DemoKitProviderProps } from '@demokit-ai/react'\nimport type { DemoKitNextProviderProps } from '../types'\n\n/**\n * Get initial demo mode state from cookie\n */\nfunction getDemoModeFromCookie(cookieName: string): boolean {\n if (typeof document === 'undefined') return false\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n return demoCookie !== undefined\n}\n\n/**\n * Get scenario from cookie\n */\nfunction getScenarioFromCookie(cookieName: string): string | null {\n if (typeof document === 'undefined') return null\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n if (!demoCookie) return null\n\n const value = demoCookie.split('=')[1]?.trim()\n if (!value || value === 'true') return null\n\n return value\n}\n\n/**\n * Next.js-aware DemoKit provider\n *\n * This provider:\n * - Reads initial state from cookies (set by middleware)\n * - Supports scenario switching\n * - Works with both App Router and Pages Router\n *\n * @example\n * // app/providers.tsx\n * 'use client'\n *\n * import { DemoKitNextProvider } from '@demokit-ai/next/client'\n * import { fixtures, scenarios } from '@/lib/demo-fixtures'\n *\n * export function Providers({ children }: { children: React.ReactNode }) {\n * return (\n * <DemoKitNextProvider\n * fixtures={fixtures}\n * scenarios={scenarios}\n * >\n * {children}\n * </DemoKitNextProvider>\n * )\n * }\n */\nexport function DemoKitNextProvider({\n children,\n fixtures,\n scenarios = {},\n storageKey = 'demokit-mode',\n cookieName = 'demokit-mode',\n initialEnabled,\n baseUrl,\n}: DemoKitNextProviderProps) {\n const [isHydrated, setIsHydrated] = useState(false)\n const [scenario, setScenario] = useState<string | null>(null)\n\n // Read initial state from cookie on mount\n useEffect(() => {\n const cookieEnabled = getDemoModeFromCookie(cookieName)\n const cookieScenario = getScenarioFromCookie(cookieName)\n setScenario(cookieScenario)\n setIsHydrated(true)\n }, [cookieName])\n\n // Merge fixtures with scenario fixtures\n const activeFixtures = useMemo(() => {\n if (scenario && scenarios[scenario]) {\n return { ...fixtures, ...scenarios[scenario] }\n }\n return fixtures\n }, [fixtures, scenarios, scenario])\n\n // Determine initial enabled state\n const enabled = useMemo(() => {\n if (initialEnabled !== undefined) {\n return initialEnabled\n }\n if (!isHydrated) {\n return false\n }\n return getDemoModeFromCookie(cookieName)\n }, [initialEnabled, isHydrated, cookieName])\n\n return (\n <DemoKitProvider\n fixtures={activeFixtures}\n storageKey={storageKey}\n initialEnabled={enabled}\n baseUrl={baseUrl}\n >\n {children}\n </DemoKitProvider>\n )\n}\n","'use client'\n\nimport { useCallback } from 'react'\nimport { useDemoMode } from '@demokit-ai/react'\nimport { useRouter, useSearchParams } from 'next/navigation'\n\n/**\n * Hook for Next.js-specific demo mode controls\n *\n * Extends useDemoMode with URL-based scenario switching\n *\n * @example\n * function DemoControls() {\n * const { isDemoMode, enableWithScenario, disableDemo, currentScenario } = useNextDemoMode()\n *\n * return (\n * <div>\n * <button onClick={() => enableWithScenario('empty-state')}>\n * Empty State Demo\n * </button>\n * <button onClick={() => enableWithScenario('error-state')}>\n * Error State Demo\n * </button>\n * <button onClick={disableDemo}>\n * Exit Demo\n * </button>\n * {currentScenario && <span>Scenario: {currentScenario}</span>}\n * </div>\n * )\n * }\n */\nexport function useNextDemoMode(options: { urlParam?: string } = {}) {\n const { urlParam = 'demo' } = options\n const demoMode = useDemoMode()\n const router = useRouter()\n const searchParams = useSearchParams()\n\n /**\n * Enable demo mode with a specific scenario via URL\n */\n const enableWithScenario = useCallback(\n (scenario: string) => {\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, scenario)\n router.push(`?${params.toString()}`)\n },\n [router, searchParams, urlParam]\n )\n\n /**\n * Enable demo mode without a scenario\n */\n const enableDemo = useCallback(() => {\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'true')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam])\n\n /**\n * Disable demo mode via URL\n */\n const disableDemo = useCallback(() => {\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'false')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam])\n\n /**\n * Get current scenario from URL\n */\n const currentScenario = searchParams.get(urlParam)\n const isScenario =\n currentScenario !== null &&\n currentScenario !== 'true' &&\n currentScenario !== 'false' &&\n currentScenario !== '1' &&\n currentScenario !== '0'\n\n return {\n ...demoMode,\n enableWithScenario,\n enableDemo,\n disableDemo,\n currentScenario: isScenario ? currentScenario : null,\n }\n}\n\n/**\n * Hook to check if we're in demo mode on the client\n * Shorthand for useNextDemoMode().isDemoMode\n */\nexport function useIsNextDemoMode(): boolean {\n return useNextDemoMode().isDemoMode\n}\n\n// Re-export base hooks from @demokit-ai/react\nexport { useDemoMode, useIsDemoMode, useIsHydrated, useDemoSession } from '@demokit-ai/react'\n","'use client'\n\nimport { DemoModeBanner, type DemoModeBannerProps } from '@demokit-ai/react'\nimport { useNextDemoMode } from './hooks'\n\nexport interface NextDemoModeBannerProps extends Omit<DemoModeBannerProps, 'onExit'> {\n /**\n * Whether to include the current scenario in the banner\n * @default true\n */\n showScenario?: boolean\n\n /**\n * Custom exit handler\n * If not provided, will use URL-based navigation\n */\n onExit?: () => void\n}\n\n/**\n * Demo mode banner for Next.js\n *\n * Extends DemoModeBanner with scenario display and URL-based exit\n *\n * @example\n * // In your layout\n * <NextDemoModeBanner />\n *\n * // With custom labels\n * <NextDemoModeBanner\n * demoLabel=\"Preview Mode\"\n * exitLabel=\"Exit Preview\"\n * showScenario={true}\n * />\n */\nexport function NextDemoModeBanner({\n showScenario = true,\n onExit,\n description,\n ...props\n}: NextDemoModeBannerProps) {\n const { currentScenario, disableDemo, isDemoMode, isHydrated } = useNextDemoMode()\n\n // Don't render if not hydrated or not in demo mode\n if (!isHydrated || !isDemoMode) {\n return null\n }\n\n // Build description with scenario\n let bannerDescription = description ?? 'Changes are simulated and not saved'\n if (showScenario && currentScenario) {\n bannerDescription = `Scenario: ${currentScenario} • ${bannerDescription}`\n }\n\n return (\n <DemoModeBanner\n {...props}\n description={bannerDescription}\n onExit={onExit ?? disableDemo}\n />\n )\n}\n\n// Re-export base banner\nexport { DemoModeBanner } from '@demokit-ai/react'\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/client/provider.tsx","../src/client/hooks.ts","../src/client/banner.tsx"],"sourcesContent":["/**\n * Client-side exports for @demokit-ai/next\n *\n * Import from '@demokit-ai/next/client' for client components.\n *\n * @example\n * 'use client'\n * import { DemoKitNextProvider, useNextDemoMode, NextDemoModeBanner } from '@demokit-ai/next/client'\n */\n\nexport * from './client/index'\n","'use client'\n\nimport { useEffect, useState, useMemo } from 'react'\nimport { DemoKitProvider, type DemoKitProviderProps } from '@demokit-ai/react'\nimport type { FixtureMap } from '@demokit-ai/core'\nimport type { DemoKitNextProviderProps } from '../types'\n\n/**\n * Get initial demo mode state from cookie\n */\nfunction getDemoModeFromCookie(cookieName: string): boolean {\n if (typeof document === 'undefined') return false\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n return demoCookie !== undefined\n}\n\n/**\n * Get scenario from cookie\n */\nfunction getScenarioFromCookie(cookieName: string): string | null {\n if (typeof document === 'undefined') return null\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n if (!demoCookie) return null\n\n const value = demoCookie.split('=')[1]?.trim()\n if (!value || value === 'true') return null\n\n return value\n}\n\n/**\n * Next.js-aware DemoKit provider\n *\n * This provider:\n * - Reads initial state from cookies (set by middleware)\n * - Supports scenario switching\n * - Works with both App Router and Pages Router\n *\n * @example\n * // app/providers.tsx\n * 'use client'\n *\n * import { DemoKitNextProvider } from '@demokit-ai/next/client'\n * import { fixtures, scenarios } from '@/lib/demo-fixtures'\n *\n * export function Providers({ children }: { children: React.ReactNode }) {\n * return (\n * <DemoKitNextProvider\n * fixtures={fixtures}\n * scenarios={scenarios}\n * >\n * {children}\n * </DemoKitNextProvider>\n * )\n * }\n */\nexport function DemoKitNextProvider({\n children,\n fixtures,\n scenarios = {},\n storageKey = 'demokit-mode',\n cookieName = 'demokit-mode',\n initialEnabled,\n baseUrl,\n source,\n}: DemoKitNextProviderProps) {\n // Debug: log source prop on every render\n console.log('[DemoKit Provider] source prop received:', source)\n\n const [isHydrated, setIsHydrated] = useState(false)\n const [scenario, setScenario] = useState<string | null>(null)\n const [remoteFixtures, setRemoteFixtures] = useState<FixtureMap | null>(null)\n const [remoteError, setRemoteError] = useState<Error | null>(null)\n const [sourceMode, setSourceMode] = useState<'local' | 'remote' | 'auto'>('auto')\n\n // Check URL for source parameter on mount\n useEffect(() => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n const sourceParam = params.get('source')\n if (sourceParam === 'local' || sourceParam === 'remote') {\n setSourceMode(sourceParam)\n console.log('[DemoKit] Source mode from URL:', sourceParam)\n }\n }, [])\n\n // Fetch remote fixtures from DemoKit Cloud if configured\n useEffect(() => {\n const apiKey = source?.apiKey\n const apiUrl = source?.apiUrl\n\n console.log('[DemoKit] Remote config check:', { apiKey: !!apiKey, apiUrl, sourceMode })\n\n // Skip if source=local is set\n if (sourceMode === 'local') {\n console.log('[DemoKit] Skipping remote fetch - source=local')\n return\n }\n\n if (!apiKey || !apiUrl) {\n console.log('[DemoKit] Missing apiKey or apiUrl, skipping remote fetch')\n return\n }\n\n const fetchRemoteFixtures = async () => {\n try {\n console.log('[DemoKit] Fetching remote fixtures from:', apiUrl)\n const response = await fetch(`${apiUrl}/fixtures`, {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch fixtures: ${response.status} ${response.statusText}`)\n }\n\n const data = await response.json()\n console.log('[DemoKit] Received remote fixtures:', data)\n\n // Convert remote fixture data to FixtureMap handlers\n const fixtureMap: FixtureMap = {}\n for (const [pattern, fixtureData] of Object.entries(data.fixtures || data)) {\n fixtureMap[pattern] = () => fixtureData\n }\n\n setRemoteFixtures(fixtureMap)\n } catch (error) {\n console.error('[DemoKit] Failed to fetch remote fixtures:', error)\n setRemoteError(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n fetchRemoteFixtures()\n }, [source, sourceMode])\n\n // Read initial state from cookie on mount\n useEffect(() => {\n const cookieEnabled = getDemoModeFromCookie(cookieName)\n const cookieScenario = getScenarioFromCookie(cookieName)\n setScenario(cookieScenario)\n setIsHydrated(true)\n }, [cookieName])\n\n // Merge fixtures with scenario fixtures and remote fixtures\n const activeFixtures = useMemo(() => {\n let result: FixtureMap\n\n // Determine which fixtures to use based on source mode\n if (sourceMode === 'local') {\n // Force local only\n result = fixtures\n console.log('[DemoKit Provider] Using LOCAL fixtures (forced)')\n } else if (sourceMode === 'remote' && remoteFixtures) {\n // Force remote only (if available)\n result = remoteFixtures\n console.log('[DemoKit Provider] Using REMOTE fixtures (forced)')\n } else if (remoteFixtures) {\n // Auto mode: merge local + remote (remote overrides)\n result = { ...fixtures, ...remoteFixtures }\n console.log('[DemoKit Provider] Using MERGED fixtures (local + remote)')\n } else {\n // No remote fixtures available, use local\n result = fixtures\n console.log('[DemoKit Provider] Using LOCAL fixtures (remote not available)')\n }\n\n // Apply scenario overrides\n if (scenario && scenarios[scenario]) {\n result = { ...result, ...scenarios[scenario] }\n }\n\n console.log('[DemoKit Provider] Active fixtures:', Object.keys(result))\n console.log('[DemoKit Provider] Scenario:', scenario)\n console.log('[DemoKit Provider] Source mode:', sourceMode)\n if (remoteError) {\n console.warn('[DemoKit Provider] Remote fixture error:', remoteError.message)\n }\n return result\n }, [fixtures, scenarios, scenario, remoteFixtures, remoteError, sourceMode])\n\n // Determine initial enabled state from cookie\n const enabled = useMemo(() => {\n if (initialEnabled !== undefined) {\n return initialEnabled\n }\n if (!isHydrated) {\n return false // Will be updated once hydrated\n }\n const cookieValue = getDemoModeFromCookie(cookieName)\n console.log('[DemoKit Next Provider] Demo mode from cookie:', { cookieName, enabled: cookieValue })\n return cookieValue\n }, [initialEnabled, isHydrated, cookieName])\n\n // Use key to force DemoKitProvider to re-mount when hydration completes\n // This ensures it initializes with the correct cookie value\n const providerKey = isHydrated ? `hydrated-${enabled}` : 'pre-hydration'\n\n return (\n <DemoKitProvider\n key={providerKey}\n fixtures={activeFixtures}\n storageKey={storageKey}\n initialEnabled={enabled}\n baseUrl={baseUrl}\n >\n {children}\n </DemoKitProvider>\n )\n}\n","'use client'\n\nimport { useCallback } from 'react'\nimport { useDemoMode } from '@demokit-ai/react'\nimport { useRouter, useSearchParams } from 'next/navigation'\n\n/**\n * Hook for Next.js-specific demo mode controls\n *\n * Extends useDemoMode with URL-based scenario switching\n *\n * @example\n * function DemoControls() {\n * const { isDemoMode, enableWithScenario, disableDemo, currentScenario } = useNextDemoMode()\n *\n * return (\n * <div>\n * <button onClick={() => enableWithScenario('empty-state')}>\n * Empty State Demo\n * </button>\n * <button onClick={() => enableWithScenario('error-state')}>\n * Error State Demo\n * </button>\n * <button onClick={disableDemo}>\n * Exit Demo\n * </button>\n * {currentScenario && <span>Scenario: {currentScenario}</span>}\n * </div>\n * )\n * }\n */\nexport function useNextDemoMode(options: { urlParam?: string } = {}) {\n const { urlParam = 'demo' } = options\n const demoMode = useDemoMode()\n const router = useRouter()\n const searchParams = useSearchParams()\n\n /**\n * Enable demo mode with a specific scenario via URL\n */\n const enableWithScenario = useCallback(\n (scenario: string) => {\n // Enable demo mode in the interceptor\n demoMode.enable()\n // Update URL for persistence and middleware\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, scenario)\n router.push(`?${params.toString()}`)\n },\n [router, searchParams, urlParam, demoMode]\n )\n\n /**\n * Enable demo mode without a scenario\n */\n const enableDemo = useCallback(() => {\n // Enable demo mode in the interceptor\n demoMode.enable()\n // Update URL for persistence and middleware\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'true')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam, demoMode])\n\n /**\n * Disable demo mode via URL\n */\n const disableDemo = useCallback(() => {\n // Disable demo mode in the interceptor\n demoMode.disable()\n // Update URL for persistence and middleware\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'false')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam, demoMode])\n\n /**\n * Get current scenario from URL\n */\n const currentScenario = searchParams.get(urlParam)\n const isScenario =\n currentScenario !== null &&\n currentScenario !== 'true' &&\n currentScenario !== 'false' &&\n currentScenario !== '1' &&\n currentScenario !== '0'\n\n return {\n ...demoMode,\n enableWithScenario,\n enableDemo,\n disableDemo,\n currentScenario: isScenario ? currentScenario : null,\n }\n}\n\n/**\n * Hook to check if we're in demo mode on the client\n * Shorthand for useNextDemoMode().isDemoMode\n */\nexport function useIsNextDemoMode(): boolean {\n return useNextDemoMode().isDemoMode\n}\n\n// Re-export base hooks from @demokit-ai/react\nexport { useDemoMode, useIsDemoMode, useIsHydrated, useDemoSession } from '@demokit-ai/react'\n","'use client'\n\nimport { DemoModeBanner, type DemoModeBannerProps } from '@demokit-ai/react'\nimport { useNextDemoMode } from './hooks'\n\nexport interface NextDemoModeBannerProps extends Omit<DemoModeBannerProps, 'onExit'> {\n /**\n * Whether to include the current scenario in the banner\n * @default true\n */\n showScenario?: boolean\n\n /**\n * Custom exit handler\n * If not provided, will use URL-based navigation\n */\n onExit?: () => void\n}\n\n/**\n * Demo mode banner for Next.js\n *\n * Extends DemoModeBanner with scenario display and URL-based exit\n *\n * @example\n * // In your layout\n * <NextDemoModeBanner />\n *\n * // With custom labels\n * <NextDemoModeBanner\n * demoLabel=\"Preview Mode\"\n * exitLabel=\"Exit Preview\"\n * showScenario={true}\n * />\n */\nexport function NextDemoModeBanner({\n showScenario = true,\n onExit,\n description,\n ...props\n}: NextDemoModeBannerProps) {\n const { currentScenario, disableDemo, isDemoMode, isHydrated } = useNextDemoMode()\n\n // Don't render if not hydrated or not in demo mode\n if (!isHydrated || !isDemoMode) {\n return null\n }\n\n // Build description with scenario\n let bannerDescription = description ?? 'Changes are simulated and not saved'\n if (showScenario && currentScenario) {\n bannerDescription = `Scenario: ${currentScenario} • ${bannerDescription}`\n }\n\n return (\n <DemoModeBanner\n {...props}\n description={bannerDescription}\n onExit={onExit ?? disableDemo}\n />\n )\n}\n\n// Re-export base banner\nexport { DemoModeBanner } from '@demokit-ai/react'\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_jsx_runtime"]}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { b as DemoKitNextProviderProps } from './types-
|
|
2
|
+
import { b as DemoKitNextProviderProps } from './types-Brt8EaFz.cjs';
|
|
3
3
|
import * as _demokit_ai_core from '@demokit-ai/core';
|
|
4
4
|
import { DemoModeBannerProps } from '@demokit-ai/react';
|
|
5
5
|
export { DemoModeBanner, useDemoMode, useDemoSession, useIsDemoMode, useIsHydrated } from '@demokit-ai/react';
|
|
@@ -32,7 +32,7 @@ import 'next/server';
|
|
|
32
32
|
* )
|
|
33
33
|
* }
|
|
34
34
|
*/
|
|
35
|
-
declare function DemoKitNextProvider({ children, fixtures, scenarios, storageKey, cookieName, initialEnabled, baseUrl, }: DemoKitNextProviderProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function DemoKitNextProvider({ children, fixtures, scenarios, storageKey, cookieName, initialEnabled, baseUrl, source, }: DemoKitNextProviderProps): react_jsx_runtime.JSX.Element;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Hook for Next.js-specific demo mode controls
|
|
@@ -68,11 +68,12 @@ declare function useNextDemoMode(options?: {
|
|
|
68
68
|
currentScenario: string | null;
|
|
69
69
|
isDemoMode: boolean;
|
|
70
70
|
isHydrated: boolean;
|
|
71
|
+
isPublicDemo: boolean;
|
|
71
72
|
isLoading: boolean;
|
|
72
73
|
remoteError: Error | null;
|
|
73
74
|
remoteVersion: string | null;
|
|
74
75
|
enable(): void;
|
|
75
|
-
disable():
|
|
76
|
+
disable(): boolean | string;
|
|
76
77
|
toggle(): void;
|
|
77
78
|
setDemoMode(enabled: boolean): void;
|
|
78
79
|
resetSession(): void;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { b as DemoKitNextProviderProps } from './types-
|
|
2
|
+
import { b as DemoKitNextProviderProps } from './types-Brt8EaFz.js';
|
|
3
3
|
import * as _demokit_ai_core from '@demokit-ai/core';
|
|
4
4
|
import { DemoModeBannerProps } from '@demokit-ai/react';
|
|
5
5
|
export { DemoModeBanner, useDemoMode, useDemoSession, useIsDemoMode, useIsHydrated } from '@demokit-ai/react';
|
|
@@ -32,7 +32,7 @@ import 'next/server';
|
|
|
32
32
|
* )
|
|
33
33
|
* }
|
|
34
34
|
*/
|
|
35
|
-
declare function DemoKitNextProvider({ children, fixtures, scenarios, storageKey, cookieName, initialEnabled, baseUrl, }: DemoKitNextProviderProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function DemoKitNextProvider({ children, fixtures, scenarios, storageKey, cookieName, initialEnabled, baseUrl, source, }: DemoKitNextProviderProps): react_jsx_runtime.JSX.Element;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Hook for Next.js-specific demo mode controls
|
|
@@ -68,11 +68,12 @@ declare function useNextDemoMode(options?: {
|
|
|
68
68
|
currentScenario: string | null;
|
|
69
69
|
isDemoMode: boolean;
|
|
70
70
|
isHydrated: boolean;
|
|
71
|
+
isPublicDemo: boolean;
|
|
71
72
|
isLoading: boolean;
|
|
72
73
|
remoteError: Error | null;
|
|
73
74
|
remoteVersion: string | null;
|
|
74
75
|
enable(): void;
|
|
75
|
-
disable():
|
|
76
|
+
disable(): boolean | string;
|
|
76
77
|
toggle(): void;
|
|
77
78
|
setDemoMode(enabled: boolean): void;
|
|
78
79
|
resetSession(): void;
|
package/dist/client.js
CHANGED
|
@@ -24,10 +24,62 @@ function DemoKitNextProvider({
|
|
|
24
24
|
storageKey = "demokit-mode",
|
|
25
25
|
cookieName = "demokit-mode",
|
|
26
26
|
initialEnabled,
|
|
27
|
-
baseUrl
|
|
27
|
+
baseUrl,
|
|
28
|
+
source
|
|
28
29
|
}) {
|
|
30
|
+
console.log("[DemoKit Provider] source prop received:", source);
|
|
29
31
|
const [isHydrated, setIsHydrated] = useState(false);
|
|
30
32
|
const [scenario, setScenario] = useState(null);
|
|
33
|
+
const [remoteFixtures, setRemoteFixtures] = useState(null);
|
|
34
|
+
const [remoteError, setRemoteError] = useState(null);
|
|
35
|
+
const [sourceMode, setSourceMode] = useState("auto");
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (typeof window === "undefined") return;
|
|
38
|
+
const params = new URLSearchParams(window.location.search);
|
|
39
|
+
const sourceParam = params.get("source");
|
|
40
|
+
if (sourceParam === "local" || sourceParam === "remote") {
|
|
41
|
+
setSourceMode(sourceParam);
|
|
42
|
+
console.log("[DemoKit] Source mode from URL:", sourceParam);
|
|
43
|
+
}
|
|
44
|
+
}, []);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const apiKey = source?.apiKey;
|
|
47
|
+
const apiUrl = source?.apiUrl;
|
|
48
|
+
console.log("[DemoKit] Remote config check:", { apiKey: !!apiKey, apiUrl, sourceMode });
|
|
49
|
+
if (sourceMode === "local") {
|
|
50
|
+
console.log("[DemoKit] Skipping remote fetch - source=local");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!apiKey || !apiUrl) {
|
|
54
|
+
console.log("[DemoKit] Missing apiKey or apiUrl, skipping remote fetch");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const fetchRemoteFixtures = async () => {
|
|
58
|
+
try {
|
|
59
|
+
console.log("[DemoKit] Fetching remote fixtures from:", apiUrl);
|
|
60
|
+
const response = await fetch(`${apiUrl}/fixtures`, {
|
|
61
|
+
headers: {
|
|
62
|
+
Authorization: `Bearer ${apiKey}`,
|
|
63
|
+
"Content-Type": "application/json"
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
throw new Error(`Failed to fetch fixtures: ${response.status} ${response.statusText}`);
|
|
68
|
+
}
|
|
69
|
+
const data = await response.json();
|
|
70
|
+
console.log("[DemoKit] Received remote fixtures:", data);
|
|
71
|
+
const fixtureMap = {};
|
|
72
|
+
for (const [pattern, fixtureData] of Object.entries(data.fixtures || data)) {
|
|
73
|
+
fixtureMap[pattern] = () => fixtureData;
|
|
74
|
+
}
|
|
75
|
+
setRemoteFixtures(fixtureMap);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error("[DemoKit] Failed to fetch remote fixtures:", error);
|
|
78
|
+
setRemoteError(error instanceof Error ? error : new Error(String(error)));
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
fetchRemoteFixtures();
|
|
82
|
+
}, [source, sourceMode]);
|
|
31
83
|
useEffect(() => {
|
|
32
84
|
const cookieEnabled = getDemoModeFromCookie(cookieName);
|
|
33
85
|
const cookieScenario = getScenarioFromCookie(cookieName);
|
|
@@ -35,11 +87,31 @@ function DemoKitNextProvider({
|
|
|
35
87
|
setIsHydrated(true);
|
|
36
88
|
}, [cookieName]);
|
|
37
89
|
const activeFixtures = useMemo(() => {
|
|
90
|
+
let result;
|
|
91
|
+
if (sourceMode === "local") {
|
|
92
|
+
result = fixtures;
|
|
93
|
+
console.log("[DemoKit Provider] Using LOCAL fixtures (forced)");
|
|
94
|
+
} else if (sourceMode === "remote" && remoteFixtures) {
|
|
95
|
+
result = remoteFixtures;
|
|
96
|
+
console.log("[DemoKit Provider] Using REMOTE fixtures (forced)");
|
|
97
|
+
} else if (remoteFixtures) {
|
|
98
|
+
result = { ...fixtures, ...remoteFixtures };
|
|
99
|
+
console.log("[DemoKit Provider] Using MERGED fixtures (local + remote)");
|
|
100
|
+
} else {
|
|
101
|
+
result = fixtures;
|
|
102
|
+
console.log("[DemoKit Provider] Using LOCAL fixtures (remote not available)");
|
|
103
|
+
}
|
|
38
104
|
if (scenario && scenarios[scenario]) {
|
|
39
|
-
|
|
105
|
+
result = { ...result, ...scenarios[scenario] };
|
|
106
|
+
}
|
|
107
|
+
console.log("[DemoKit Provider] Active fixtures:", Object.keys(result));
|
|
108
|
+
console.log("[DemoKit Provider] Scenario:", scenario);
|
|
109
|
+
console.log("[DemoKit Provider] Source mode:", sourceMode);
|
|
110
|
+
if (remoteError) {
|
|
111
|
+
console.warn("[DemoKit Provider] Remote fixture error:", remoteError.message);
|
|
40
112
|
}
|
|
41
|
-
return
|
|
42
|
-
}, [fixtures, scenarios, scenario]);
|
|
113
|
+
return result;
|
|
114
|
+
}, [fixtures, scenarios, scenario, remoteFixtures, remoteError, sourceMode]);
|
|
43
115
|
const enabled = useMemo(() => {
|
|
44
116
|
if (initialEnabled !== void 0) {
|
|
45
117
|
return initialEnabled;
|
|
@@ -47,8 +119,11 @@ function DemoKitNextProvider({
|
|
|
47
119
|
if (!isHydrated) {
|
|
48
120
|
return false;
|
|
49
121
|
}
|
|
50
|
-
|
|
122
|
+
const cookieValue = getDemoModeFromCookie(cookieName);
|
|
123
|
+
console.log("[DemoKit Next Provider] Demo mode from cookie:", { cookieName, enabled: cookieValue });
|
|
124
|
+
return cookieValue;
|
|
51
125
|
}, [initialEnabled, isHydrated, cookieName]);
|
|
126
|
+
const providerKey = isHydrated ? `hydrated-${enabled}` : "pre-hydration";
|
|
52
127
|
return /* @__PURE__ */ jsx(
|
|
53
128
|
DemoKitProvider,
|
|
54
129
|
{
|
|
@@ -57,7 +132,8 @@ function DemoKitNextProvider({
|
|
|
57
132
|
initialEnabled: enabled,
|
|
58
133
|
baseUrl,
|
|
59
134
|
children
|
|
60
|
-
}
|
|
135
|
+
},
|
|
136
|
+
providerKey
|
|
61
137
|
);
|
|
62
138
|
}
|
|
63
139
|
|
|
@@ -73,22 +149,25 @@ function useNextDemoMode(options = {}) {
|
|
|
73
149
|
const searchParams = useSearchParams();
|
|
74
150
|
const enableWithScenario = useCallback(
|
|
75
151
|
(scenario) => {
|
|
152
|
+
demoMode.enable();
|
|
76
153
|
const params = new URLSearchParams(searchParams.toString());
|
|
77
154
|
params.set(urlParam, scenario);
|
|
78
155
|
router.push(`?${params.toString()}`);
|
|
79
156
|
},
|
|
80
|
-
[router, searchParams, urlParam]
|
|
157
|
+
[router, searchParams, urlParam, demoMode]
|
|
81
158
|
);
|
|
82
159
|
const enableDemo = useCallback(() => {
|
|
160
|
+
demoMode.enable();
|
|
83
161
|
const params = new URLSearchParams(searchParams.toString());
|
|
84
162
|
params.set(urlParam, "true");
|
|
85
163
|
router.push(`?${params.toString()}`);
|
|
86
|
-
}, [router, searchParams, urlParam]);
|
|
164
|
+
}, [router, searchParams, urlParam, demoMode]);
|
|
87
165
|
const disableDemo = useCallback(() => {
|
|
166
|
+
demoMode.disable();
|
|
88
167
|
const params = new URLSearchParams(searchParams.toString());
|
|
89
168
|
params.set(urlParam, "false");
|
|
90
169
|
router.push(`?${params.toString()}`);
|
|
91
|
-
}, [router, searchParams, urlParam]);
|
|
170
|
+
}, [router, searchParams, urlParam, demoMode]);
|
|
92
171
|
const currentScenario = searchParams.get(urlParam);
|
|
93
172
|
const isScenario = currentScenario !== null && currentScenario !== "true" && currentScenario !== "false" && currentScenario !== "1" && currentScenario !== "0";
|
|
94
173
|
return {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/provider.tsx","../src/client/hooks.ts","../src/client/banner.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState, useMemo } from 'react'\nimport { DemoKitProvider, type DemoKitProviderProps } from '@demokit-ai/react'\nimport type { DemoKitNextProviderProps } from '../types'\n\n/**\n * Get initial demo mode state from cookie\n */\nfunction getDemoModeFromCookie(cookieName: string): boolean {\n if (typeof document === 'undefined') return false\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n return demoCookie !== undefined\n}\n\n/**\n * Get scenario from cookie\n */\nfunction getScenarioFromCookie(cookieName: string): string | null {\n if (typeof document === 'undefined') return null\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n if (!demoCookie) return null\n\n const value = demoCookie.split('=')[1]?.trim()\n if (!value || value === 'true') return null\n\n return value\n}\n\n/**\n * Next.js-aware DemoKit provider\n *\n * This provider:\n * - Reads initial state from cookies (set by middleware)\n * - Supports scenario switching\n * - Works with both App Router and Pages Router\n *\n * @example\n * // app/providers.tsx\n * 'use client'\n *\n * import { DemoKitNextProvider } from '@demokit-ai/next/client'\n * import { fixtures, scenarios } from '@/lib/demo-fixtures'\n *\n * export function Providers({ children }: { children: React.ReactNode }) {\n * return (\n * <DemoKitNextProvider\n * fixtures={fixtures}\n * scenarios={scenarios}\n * >\n * {children}\n * </DemoKitNextProvider>\n * )\n * }\n */\nexport function DemoKitNextProvider({\n children,\n fixtures,\n scenarios = {},\n storageKey = 'demokit-mode',\n cookieName = 'demokit-mode',\n initialEnabled,\n baseUrl,\n}: DemoKitNextProviderProps) {\n const [isHydrated, setIsHydrated] = useState(false)\n const [scenario, setScenario] = useState<string | null>(null)\n\n // Read initial state from cookie on mount\n useEffect(() => {\n const cookieEnabled = getDemoModeFromCookie(cookieName)\n const cookieScenario = getScenarioFromCookie(cookieName)\n setScenario(cookieScenario)\n setIsHydrated(true)\n }, [cookieName])\n\n // Merge fixtures with scenario fixtures\n const activeFixtures = useMemo(() => {\n if (scenario && scenarios[scenario]) {\n return { ...fixtures, ...scenarios[scenario] }\n }\n return fixtures\n }, [fixtures, scenarios, scenario])\n\n // Determine initial enabled state\n const enabled = useMemo(() => {\n if (initialEnabled !== undefined) {\n return initialEnabled\n }\n if (!isHydrated) {\n return false\n }\n return getDemoModeFromCookie(cookieName)\n }, [initialEnabled, isHydrated, cookieName])\n\n return (\n <DemoKitProvider\n fixtures={activeFixtures}\n storageKey={storageKey}\n initialEnabled={enabled}\n baseUrl={baseUrl}\n >\n {children}\n </DemoKitProvider>\n )\n}\n","'use client'\n\nimport { useCallback } from 'react'\nimport { useDemoMode } from '@demokit-ai/react'\nimport { useRouter, useSearchParams } from 'next/navigation'\n\n/**\n * Hook for Next.js-specific demo mode controls\n *\n * Extends useDemoMode with URL-based scenario switching\n *\n * @example\n * function DemoControls() {\n * const { isDemoMode, enableWithScenario, disableDemo, currentScenario } = useNextDemoMode()\n *\n * return (\n * <div>\n * <button onClick={() => enableWithScenario('empty-state')}>\n * Empty State Demo\n * </button>\n * <button onClick={() => enableWithScenario('error-state')}>\n * Error State Demo\n * </button>\n * <button onClick={disableDemo}>\n * Exit Demo\n * </button>\n * {currentScenario && <span>Scenario: {currentScenario}</span>}\n * </div>\n * )\n * }\n */\nexport function useNextDemoMode(options: { urlParam?: string } = {}) {\n const { urlParam = 'demo' } = options\n const demoMode = useDemoMode()\n const router = useRouter()\n const searchParams = useSearchParams()\n\n /**\n * Enable demo mode with a specific scenario via URL\n */\n const enableWithScenario = useCallback(\n (scenario: string) => {\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, scenario)\n router.push(`?${params.toString()}`)\n },\n [router, searchParams, urlParam]\n )\n\n /**\n * Enable demo mode without a scenario\n */\n const enableDemo = useCallback(() => {\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'true')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam])\n\n /**\n * Disable demo mode via URL\n */\n const disableDemo = useCallback(() => {\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'false')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam])\n\n /**\n * Get current scenario from URL\n */\n const currentScenario = searchParams.get(urlParam)\n const isScenario =\n currentScenario !== null &&\n currentScenario !== 'true' &&\n currentScenario !== 'false' &&\n currentScenario !== '1' &&\n currentScenario !== '0'\n\n return {\n ...demoMode,\n enableWithScenario,\n enableDemo,\n disableDemo,\n currentScenario: isScenario ? currentScenario : null,\n }\n}\n\n/**\n * Hook to check if we're in demo mode on the client\n * Shorthand for useNextDemoMode().isDemoMode\n */\nexport function useIsNextDemoMode(): boolean {\n return useNextDemoMode().isDemoMode\n}\n\n// Re-export base hooks from @demokit-ai/react\nexport { useDemoMode, useIsDemoMode, useIsHydrated, useDemoSession } from '@demokit-ai/react'\n","'use client'\n\nimport { DemoModeBanner, type DemoModeBannerProps } from '@demokit-ai/react'\nimport { useNextDemoMode } from './hooks'\n\nexport interface NextDemoModeBannerProps extends Omit<DemoModeBannerProps, 'onExit'> {\n /**\n * Whether to include the current scenario in the banner\n * @default true\n */\n showScenario?: boolean\n\n /**\n * Custom exit handler\n * If not provided, will use URL-based navigation\n */\n onExit?: () => void\n}\n\n/**\n * Demo mode banner for Next.js\n *\n * Extends DemoModeBanner with scenario display and URL-based exit\n *\n * @example\n * // In your layout\n * <NextDemoModeBanner />\n *\n * // With custom labels\n * <NextDemoModeBanner\n * demoLabel=\"Preview Mode\"\n * exitLabel=\"Exit Preview\"\n * showScenario={true}\n * />\n */\nexport function NextDemoModeBanner({\n showScenario = true,\n onExit,\n description,\n ...props\n}: NextDemoModeBannerProps) {\n const { currentScenario, disableDemo, isDemoMode, isHydrated } = useNextDemoMode()\n\n // Don't render if not hydrated or not in demo mode\n if (!isHydrated || !isDemoMode) {\n return null\n }\n\n // Build description with scenario\n let bannerDescription = description ?? 'Changes are simulated and not saved'\n if (showScenario && currentScenario) {\n bannerDescription = `Scenario: ${currentScenario} • ${bannerDescription}`\n }\n\n return (\n <DemoModeBanner\n {...props}\n description={bannerDescription}\n onExit={onExit ?? disableDemo}\n />\n )\n}\n\n// Re-export base banner\nexport { DemoModeBanner } from '@demokit-ai/react'\n"],"mappings":"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","names":["useDemoMode","DemoModeBanner","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/provider.tsx","../src/client/hooks.ts","../src/client/banner.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState, useMemo } from 'react'\nimport { DemoKitProvider, type DemoKitProviderProps } from '@demokit-ai/react'\nimport type { FixtureMap } from '@demokit-ai/core'\nimport type { DemoKitNextProviderProps } from '../types'\n\n/**\n * Get initial demo mode state from cookie\n */\nfunction getDemoModeFromCookie(cookieName: string): boolean {\n if (typeof document === 'undefined') return false\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n return demoCookie !== undefined\n}\n\n/**\n * Get scenario from cookie\n */\nfunction getScenarioFromCookie(cookieName: string): string | null {\n if (typeof document === 'undefined') return null\n\n const cookies = document.cookie.split(';')\n const demoCookie = cookies.find((c) => c.trim().startsWith(`${cookieName}=`))\n\n if (!demoCookie) return null\n\n const value = demoCookie.split('=')[1]?.trim()\n if (!value || value === 'true') return null\n\n return value\n}\n\n/**\n * Next.js-aware DemoKit provider\n *\n * This provider:\n * - Reads initial state from cookies (set by middleware)\n * - Supports scenario switching\n * - Works with both App Router and Pages Router\n *\n * @example\n * // app/providers.tsx\n * 'use client'\n *\n * import { DemoKitNextProvider } from '@demokit-ai/next/client'\n * import { fixtures, scenarios } from '@/lib/demo-fixtures'\n *\n * export function Providers({ children }: { children: React.ReactNode }) {\n * return (\n * <DemoKitNextProvider\n * fixtures={fixtures}\n * scenarios={scenarios}\n * >\n * {children}\n * </DemoKitNextProvider>\n * )\n * }\n */\nexport function DemoKitNextProvider({\n children,\n fixtures,\n scenarios = {},\n storageKey = 'demokit-mode',\n cookieName = 'demokit-mode',\n initialEnabled,\n baseUrl,\n source,\n}: DemoKitNextProviderProps) {\n // Debug: log source prop on every render\n console.log('[DemoKit Provider] source prop received:', source)\n\n const [isHydrated, setIsHydrated] = useState(false)\n const [scenario, setScenario] = useState<string | null>(null)\n const [remoteFixtures, setRemoteFixtures] = useState<FixtureMap | null>(null)\n const [remoteError, setRemoteError] = useState<Error | null>(null)\n const [sourceMode, setSourceMode] = useState<'local' | 'remote' | 'auto'>('auto')\n\n // Check URL for source parameter on mount\n useEffect(() => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n const sourceParam = params.get('source')\n if (sourceParam === 'local' || sourceParam === 'remote') {\n setSourceMode(sourceParam)\n console.log('[DemoKit] Source mode from URL:', sourceParam)\n }\n }, [])\n\n // Fetch remote fixtures from DemoKit Cloud if configured\n useEffect(() => {\n const apiKey = source?.apiKey\n const apiUrl = source?.apiUrl\n\n console.log('[DemoKit] Remote config check:', { apiKey: !!apiKey, apiUrl, sourceMode })\n\n // Skip if source=local is set\n if (sourceMode === 'local') {\n console.log('[DemoKit] Skipping remote fetch - source=local')\n return\n }\n\n if (!apiKey || !apiUrl) {\n console.log('[DemoKit] Missing apiKey or apiUrl, skipping remote fetch')\n return\n }\n\n const fetchRemoteFixtures = async () => {\n try {\n console.log('[DemoKit] Fetching remote fixtures from:', apiUrl)\n const response = await fetch(`${apiUrl}/fixtures`, {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch fixtures: ${response.status} ${response.statusText}`)\n }\n\n const data = await response.json()\n console.log('[DemoKit] Received remote fixtures:', data)\n\n // Convert remote fixture data to FixtureMap handlers\n const fixtureMap: FixtureMap = {}\n for (const [pattern, fixtureData] of Object.entries(data.fixtures || data)) {\n fixtureMap[pattern] = () => fixtureData\n }\n\n setRemoteFixtures(fixtureMap)\n } catch (error) {\n console.error('[DemoKit] Failed to fetch remote fixtures:', error)\n setRemoteError(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n fetchRemoteFixtures()\n }, [source, sourceMode])\n\n // Read initial state from cookie on mount\n useEffect(() => {\n const cookieEnabled = getDemoModeFromCookie(cookieName)\n const cookieScenario = getScenarioFromCookie(cookieName)\n setScenario(cookieScenario)\n setIsHydrated(true)\n }, [cookieName])\n\n // Merge fixtures with scenario fixtures and remote fixtures\n const activeFixtures = useMemo(() => {\n let result: FixtureMap\n\n // Determine which fixtures to use based on source mode\n if (sourceMode === 'local') {\n // Force local only\n result = fixtures\n console.log('[DemoKit Provider] Using LOCAL fixtures (forced)')\n } else if (sourceMode === 'remote' && remoteFixtures) {\n // Force remote only (if available)\n result = remoteFixtures\n console.log('[DemoKit Provider] Using REMOTE fixtures (forced)')\n } else if (remoteFixtures) {\n // Auto mode: merge local + remote (remote overrides)\n result = { ...fixtures, ...remoteFixtures }\n console.log('[DemoKit Provider] Using MERGED fixtures (local + remote)')\n } else {\n // No remote fixtures available, use local\n result = fixtures\n console.log('[DemoKit Provider] Using LOCAL fixtures (remote not available)')\n }\n\n // Apply scenario overrides\n if (scenario && scenarios[scenario]) {\n result = { ...result, ...scenarios[scenario] }\n }\n\n console.log('[DemoKit Provider] Active fixtures:', Object.keys(result))\n console.log('[DemoKit Provider] Scenario:', scenario)\n console.log('[DemoKit Provider] Source mode:', sourceMode)\n if (remoteError) {\n console.warn('[DemoKit Provider] Remote fixture error:', remoteError.message)\n }\n return result\n }, [fixtures, scenarios, scenario, remoteFixtures, remoteError, sourceMode])\n\n // Determine initial enabled state from cookie\n const enabled = useMemo(() => {\n if (initialEnabled !== undefined) {\n return initialEnabled\n }\n if (!isHydrated) {\n return false // Will be updated once hydrated\n }\n const cookieValue = getDemoModeFromCookie(cookieName)\n console.log('[DemoKit Next Provider] Demo mode from cookie:', { cookieName, enabled: cookieValue })\n return cookieValue\n }, [initialEnabled, isHydrated, cookieName])\n\n // Use key to force DemoKitProvider to re-mount when hydration completes\n // This ensures it initializes with the correct cookie value\n const providerKey = isHydrated ? `hydrated-${enabled}` : 'pre-hydration'\n\n return (\n <DemoKitProvider\n key={providerKey}\n fixtures={activeFixtures}\n storageKey={storageKey}\n initialEnabled={enabled}\n baseUrl={baseUrl}\n >\n {children}\n </DemoKitProvider>\n )\n}\n","'use client'\n\nimport { useCallback } from 'react'\nimport { useDemoMode } from '@demokit-ai/react'\nimport { useRouter, useSearchParams } from 'next/navigation'\n\n/**\n * Hook for Next.js-specific demo mode controls\n *\n * Extends useDemoMode with URL-based scenario switching\n *\n * @example\n * function DemoControls() {\n * const { isDemoMode, enableWithScenario, disableDemo, currentScenario } = useNextDemoMode()\n *\n * return (\n * <div>\n * <button onClick={() => enableWithScenario('empty-state')}>\n * Empty State Demo\n * </button>\n * <button onClick={() => enableWithScenario('error-state')}>\n * Error State Demo\n * </button>\n * <button onClick={disableDemo}>\n * Exit Demo\n * </button>\n * {currentScenario && <span>Scenario: {currentScenario}</span>}\n * </div>\n * )\n * }\n */\nexport function useNextDemoMode(options: { urlParam?: string } = {}) {\n const { urlParam = 'demo' } = options\n const demoMode = useDemoMode()\n const router = useRouter()\n const searchParams = useSearchParams()\n\n /**\n * Enable demo mode with a specific scenario via URL\n */\n const enableWithScenario = useCallback(\n (scenario: string) => {\n // Enable demo mode in the interceptor\n demoMode.enable()\n // Update URL for persistence and middleware\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, scenario)\n router.push(`?${params.toString()}`)\n },\n [router, searchParams, urlParam, demoMode]\n )\n\n /**\n * Enable demo mode without a scenario\n */\n const enableDemo = useCallback(() => {\n // Enable demo mode in the interceptor\n demoMode.enable()\n // Update URL for persistence and middleware\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'true')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam, demoMode])\n\n /**\n * Disable demo mode via URL\n */\n const disableDemo = useCallback(() => {\n // Disable demo mode in the interceptor\n demoMode.disable()\n // Update URL for persistence and middleware\n const params = new URLSearchParams(searchParams.toString())\n params.set(urlParam, 'false')\n router.push(`?${params.toString()}`)\n }, [router, searchParams, urlParam, demoMode])\n\n /**\n * Get current scenario from URL\n */\n const currentScenario = searchParams.get(urlParam)\n const isScenario =\n currentScenario !== null &&\n currentScenario !== 'true' &&\n currentScenario !== 'false' &&\n currentScenario !== '1' &&\n currentScenario !== '0'\n\n return {\n ...demoMode,\n enableWithScenario,\n enableDemo,\n disableDemo,\n currentScenario: isScenario ? currentScenario : null,\n }\n}\n\n/**\n * Hook to check if we're in demo mode on the client\n * Shorthand for useNextDemoMode().isDemoMode\n */\nexport function useIsNextDemoMode(): boolean {\n return useNextDemoMode().isDemoMode\n}\n\n// Re-export base hooks from @demokit-ai/react\nexport { useDemoMode, useIsDemoMode, useIsHydrated, useDemoSession } from '@demokit-ai/react'\n","'use client'\n\nimport { DemoModeBanner, type DemoModeBannerProps } from '@demokit-ai/react'\nimport { useNextDemoMode } from './hooks'\n\nexport interface NextDemoModeBannerProps extends Omit<DemoModeBannerProps, 'onExit'> {\n /**\n * Whether to include the current scenario in the banner\n * @default true\n */\n showScenario?: boolean\n\n /**\n * Custom exit handler\n * If not provided, will use URL-based navigation\n */\n onExit?: () => void\n}\n\n/**\n * Demo mode banner for Next.js\n *\n * Extends DemoModeBanner with scenario display and URL-based exit\n *\n * @example\n * // In your layout\n * <NextDemoModeBanner />\n *\n * // With custom labels\n * <NextDemoModeBanner\n * demoLabel=\"Preview Mode\"\n * exitLabel=\"Exit Preview\"\n * showScenario={true}\n * />\n */\nexport function NextDemoModeBanner({\n showScenario = true,\n onExit,\n description,\n ...props\n}: NextDemoModeBannerProps) {\n const { currentScenario, disableDemo, isDemoMode, isHydrated } = useNextDemoMode()\n\n // Don't render if not hydrated or not in demo mode\n if (!isHydrated || !isDemoMode) {\n return null\n }\n\n // Build description with scenario\n let bannerDescription = description ?? 'Changes are simulated and not saved'\n if (showScenario && currentScenario) {\n bannerDescription = `Scenario: ${currentScenario} • ${bannerDescription}`\n }\n\n return (\n <DemoModeBanner\n {...props}\n description={bannerDescription}\n onExit={onExit ?? disableDemo}\n />\n )\n}\n\n// Re-export base banner\nexport { DemoModeBanner } from '@demokit-ai/react'\n"],"mappings":"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","names":["useDemoMode","DemoModeBanner","jsx"]}
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
createDemoConfig: () => createDemoConfig,
|
|
24
|
+
createRemoteSource: () => createRemoteSource,
|
|
24
25
|
createScenario: () => createScenario,
|
|
25
26
|
defineFixtures: () => defineFixtures,
|
|
26
27
|
defineScenarios: () => defineScenarios,
|
|
@@ -49,9 +50,18 @@ function createDemoConfig(config) {
|
|
|
49
50
|
...config
|
|
50
51
|
};
|
|
51
52
|
}
|
|
53
|
+
function createRemoteSource(config) {
|
|
54
|
+
return {
|
|
55
|
+
timeout: 1e4,
|
|
56
|
+
retry: true,
|
|
57
|
+
maxRetries: 3,
|
|
58
|
+
...config
|
|
59
|
+
};
|
|
60
|
+
}
|
|
52
61
|
// Annotate the CommonJS export names for ESM import in node:
|
|
53
62
|
0 && (module.exports = {
|
|
54
63
|
createDemoConfig,
|
|
64
|
+
createRemoteSource,
|
|
55
65
|
createScenario,
|
|
56
66
|
defineFixtures,
|
|
57
67
|
defineScenarios,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts"],"sourcesContent":["/**\n * @demokit-ai/next\n *\n * Next.js adapter for DemoKit.\n * Full integration with App Router, middleware, and API routes.\n *\n * @example\n * // 1. Define your fixtures and scenarios\n * import { defineFixtures, defineScenarios, createDemoConfig } from '@demokit-ai/next'\n *\n * export const demoConfig = createDemoConfig({\n * fixtures: defineFixtures({\n * 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],\n * }),\n * scenarios: defineScenarios({\n * 'empty': { 'GET /api/users': () => [] },\n * }),\n * })\n *\n * // 2. Add middleware (middleware.ts)\n * import { demoMiddleware } from '@demokit-ai/next/middleware'\n * export const middleware = demoMiddleware()\n *\n * // 3. Wrap your app (app/providers.tsx)\n * import { DemoKitNextProvider } from '@demokit-ai/next/client'\n * import { demoConfig } from '@/lib/demo'\n *\n * export function Providers({ children }) {\n * return (\n * <DemoKitNextProvider {...demoConfig}>\n * {children}\n * </DemoKitNextProvider>\n * )\n * }\n *\n * // 4. Enable demo mode via URL: ?demo=true or ?demo=scenario-name\n *\n * @packageDocumentation\n */\n\n// Configuration helpers\nexport {\n defineFixtures,\n defineScenarios,\n createScenario,\n mergeFixtures,\n createDemoConfig,\n} from './config'\n\n// Types\nexport type {\n DemoKitNextConfig,\n DemoKitNextProviderProps,\n DemoMiddlewareConfig,\n MiddlewareResult,\n DemoScenario,\n DefineFixtures,\n DefineScenarios,\n} from './types'\n\n// Re-export core types\nexport type { FixtureMap, FixtureHandler, RequestContext } from '@demokit-ai/core'\n","import type { FixtureMap } from '@demokit-ai/core'\nimport type { DemoKitNextConfig, DemoScenario } from './types'\n\n/**\n * Helper to define fixtures with type safety\n *\n * @example\n * const fixtures = defineFixtures({\n * 'GET /api/users': () => [\n * { id: '1', name: 'Demo User' },\n * ],\n * 'GET /api/users/:id': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * 'POST /api/users': async ({ body }) => ({\n * id: crypto.randomUUID(),\n * ...body,\n * }),\n * })\n */\nexport function defineFixtures<T extends FixtureMap>(fixtures: T): T {\n return fixtures\n}\n\n/**\n * Helper to define scenarios with type safety\n *\n * @example\n * const scenarios = defineScenarios({\n * 'empty-state': {\n * 'GET /api/users': () => [],\n * 'GET /api/projects': () => [],\n * },\n * 'error-state': {\n * 'GET /api/users': () => {\n * throw new Error('API Error')\n * },\n * },\n * 'new-user': {\n * 'GET /api/users': () => [\n * { id: '1', name: 'Welcome, New User!', isNew: true },\n * ],\n * },\n * })\n */\nexport function defineScenarios<T extends Record<string, FixtureMap>>(scenarios: T): T {\n return scenarios\n}\n\n/**\n * Helper to create a scenario object\n *\n * @example\n * const emptyStateScenario = createScenario({\n * name: 'empty-state',\n * description: 'Shows the app with no data',\n * fixtures: {\n * 'GET /api/users': () => [],\n * },\n * })\n */\nexport function createScenario(scenario: DemoScenario): DemoScenario {\n return scenario\n}\n\n/**\n * Merge multiple fixture maps\n *\n * @example\n * const allFixtures = mergeFixtures(\n * baseFixtures,\n * usersFixtures,\n * projectsFixtures\n * )\n */\nexport function mergeFixtures(...fixtureMaps: FixtureMap[]): FixtureMap {\n return Object.assign({}, ...fixtureMaps)\n}\n\n/**\n * Create a complete DemoKit Next.js configuration\n *\n * @example\n * // lib/demo.ts\n * import { createDemoConfig, defineFixtures, defineScenarios } from '@demokit-ai/next'\n *\n * export const demoConfig = createDemoConfig({\n * fixtures: defineFixtures({\n * 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],\n * }),\n * scenarios: defineScenarios({\n * 'empty': { 'GET /api/users': () => [] },\n * }),\n * })\n */\nexport function createDemoConfig(config: DemoKitNextConfig): DemoKitNextConfig {\n return {\n storageKey: 'demokit-mode',\n cookieName: 'demokit-mode',\n urlParam: 'demo',\n ...config,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqBO,SAAS,eAAqC,UAAgB;AACnE,SAAO;AACT;AAuBO,SAAS,gBAAsD,WAAiB;AACrF,SAAO;AACT;AAcO,SAAS,eAAe,UAAsC;AACnE,SAAO;AACT;AAYO,SAAS,iBAAiB,aAAuC;AACtE,SAAO,OAAO,OAAO,CAAC,GAAG,GAAG,WAAW;AACzC;AAkBO,SAAS,iBAAiB,QAA8C;AAC7E,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,GAAG;AAAA,EACL;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts"],"sourcesContent":["/**\n * @demokit-ai/next\n *\n * Next.js adapter for DemoKit.\n * Full integration with App Router, middleware, and API routes.\n *\n * @example\n * // 1. Define your fixtures and scenarios\n * import { defineFixtures, defineScenarios, createDemoConfig } from '@demokit-ai/next'\n *\n * export const demoConfig = createDemoConfig({\n * fixtures: defineFixtures({\n * 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],\n * }),\n * scenarios: defineScenarios({\n * 'empty': { 'GET /api/users': () => [] },\n * }),\n * })\n *\n * // 2. Add middleware (middleware.ts)\n * import { demoMiddleware } from '@demokit-ai/next/middleware'\n * export const middleware = demoMiddleware()\n *\n * // 3. Wrap your app (app/providers.tsx)\n * import { DemoKitNextProvider } from '@demokit-ai/next/client'\n * import { demoConfig } from '@/lib/demo'\n *\n * export function Providers({ children }) {\n * return (\n * <DemoKitNextProvider {...demoConfig}>\n * {children}\n * </DemoKitNextProvider>\n * )\n * }\n *\n * // 4. Enable demo mode via URL: ?demo=true or ?demo=scenario-name\n *\n * @packageDocumentation\n */\n\n// Configuration helpers\nexport {\n defineFixtures,\n defineScenarios,\n createScenario,\n mergeFixtures,\n createDemoConfig,\n createRemoteSource,\n} from './config'\n\n// Types\nexport type {\n DemoKitNextConfig,\n DemoKitNextProviderProps,\n DemoMiddlewareConfig,\n MiddlewareResult,\n DemoScenario,\n DefineFixtures,\n DefineScenarios,\n RemoteSourceConfig,\n} from './types'\n\n// Re-export core types\nexport type { FixtureMap, FixtureHandler, RequestContext } from '@demokit-ai/core'\n","import type { FixtureMap } from '@demokit-ai/core'\nimport type { DemoKitNextConfig, DemoScenario, RemoteSourceConfig } from './types'\n\n/**\n * Helper to define fixtures with type safety\n *\n * @example\n * const fixtures = defineFixtures({\n * 'GET /api/users': () => [\n * { id: '1', name: 'Demo User' },\n * ],\n * 'GET /api/users/:id': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * 'POST /api/users': async ({ body }) => ({\n * id: crypto.randomUUID(),\n * ...body,\n * }),\n * })\n */\nexport function defineFixtures<T extends FixtureMap>(fixtures: T): T {\n return fixtures\n}\n\n/**\n * Helper to define scenarios with type safety\n *\n * @example\n * const scenarios = defineScenarios({\n * 'empty-state': {\n * 'GET /api/users': () => [],\n * 'GET /api/projects': () => [],\n * },\n * 'error-state': {\n * 'GET /api/users': () => {\n * throw new Error('API Error')\n * },\n * },\n * 'new-user': {\n * 'GET /api/users': () => [\n * { id: '1', name: 'Welcome, New User!', isNew: true },\n * ],\n * },\n * })\n */\nexport function defineScenarios<T extends Record<string, FixtureMap>>(scenarios: T): T {\n return scenarios\n}\n\n/**\n * Helper to create a scenario object\n *\n * @example\n * const emptyStateScenario = createScenario({\n * name: 'empty-state',\n * description: 'Shows the app with no data',\n * fixtures: {\n * 'GET /api/users': () => [],\n * },\n * })\n */\nexport function createScenario(scenario: DemoScenario): DemoScenario {\n return scenario\n}\n\n/**\n * Merge multiple fixture maps\n *\n * @example\n * const allFixtures = mergeFixtures(\n * baseFixtures,\n * usersFixtures,\n * projectsFixtures\n * )\n */\nexport function mergeFixtures(...fixtureMaps: FixtureMap[]): FixtureMap {\n return Object.assign({}, ...fixtureMaps)\n}\n\n/**\n * Create a complete DemoKit Next.js configuration\n *\n * @example\n * // lib/demo.ts\n * import { createDemoConfig, defineFixtures, defineScenarios } from '@demokit-ai/next'\n *\n * export const demoConfig = createDemoConfig({\n * fixtures: defineFixtures({\n * 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],\n * }),\n * scenarios: defineScenarios({\n * 'empty': { 'GET /api/users': () => [] },\n * }),\n * })\n */\nexport function createDemoConfig(config: DemoKitNextConfig): DemoKitNextConfig {\n return {\n storageKey: 'demokit-mode',\n cookieName: 'demokit-mode',\n urlParam: 'demo',\n ...config,\n }\n}\n\n/**\n * Create a remote source configuration for fetching fixtures from DemoKit Cloud\n *\n * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.\n *\n * @example\n * ```typescript\n * // lib/demokit-config.ts\n * import { createRemoteSource } from '@demokit-ai/next'\n *\n * // .env.local:\n * // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api\n * // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx\n *\n * export const demokitSource = createRemoteSource({\n * apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,\n * apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,\n * })\n *\n * // Then in providers.tsx:\n * import { demokitSource } from '@/lib/demokit-config'\n *\n * <DemoKitNextProvider source={demokitSource}>\n * {children}\n * </DemoKitNextProvider>\n * ```\n */\nexport function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig {\n return {\n timeout: 10000,\n retry: true,\n maxRetries: 3,\n ...config,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqBO,SAAS,eAAqC,UAAgB;AACnE,SAAO;AACT;AAuBO,SAAS,gBAAsD,WAAiB;AACrF,SAAO;AACT;AAcO,SAAS,eAAe,UAAsC;AACnE,SAAO;AACT;AAYO,SAAS,iBAAiB,aAAuC;AACtE,SAAO,OAAO,OAAO,CAAC,GAAG,GAAG,WAAW;AACzC;AAkBO,SAAS,iBAAiB,QAA8C;AAC7E,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,GAAG;AAAA,EACL;AACF;AA6BO,SAAS,mBAAmB,QAAgD;AACjF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,GAAG;AAAA,EACL;AACF;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FixtureMap } from '@demokit-ai/core';
|
|
2
2
|
export { FixtureHandler, FixtureMap, RequestContext } from '@demokit-ai/core';
|
|
3
|
-
import { D as DemoScenario, a as DemoKitNextConfig } from './types-
|
|
4
|
-
export { d as DefineFixtures, e as DefineScenarios, b as DemoKitNextProviderProps, c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-
|
|
3
|
+
import { D as DemoScenario, a as DemoKitNextConfig, R as RemoteSourceConfig } from './types-Brt8EaFz.cjs';
|
|
4
|
+
export { d as DefineFixtures, e as DefineScenarios, b as DemoKitNextProviderProps, c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-Brt8EaFz.cjs';
|
|
5
5
|
import 'react';
|
|
6
6
|
import 'next/server';
|
|
7
7
|
|
|
@@ -87,5 +87,33 @@ declare function mergeFixtures(...fixtureMaps: FixtureMap[]): FixtureMap;
|
|
|
87
87
|
* })
|
|
88
88
|
*/
|
|
89
89
|
declare function createDemoConfig(config: DemoKitNextConfig): DemoKitNextConfig;
|
|
90
|
+
/**
|
|
91
|
+
* Create a remote source configuration for fetching fixtures from DemoKit Cloud
|
|
92
|
+
*
|
|
93
|
+
* The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // lib/demokit-config.ts
|
|
98
|
+
* import { createRemoteSource } from '@demokit-ai/next'
|
|
99
|
+
*
|
|
100
|
+
* // .env.local:
|
|
101
|
+
* // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
|
|
102
|
+
* // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx
|
|
103
|
+
*
|
|
104
|
+
* export const demokitSource = createRemoteSource({
|
|
105
|
+
* apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,
|
|
106
|
+
* apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,
|
|
107
|
+
* })
|
|
108
|
+
*
|
|
109
|
+
* // Then in providers.tsx:
|
|
110
|
+
* import { demokitSource } from '@/lib/demokit-config'
|
|
111
|
+
*
|
|
112
|
+
* <DemoKitNextProvider source={demokitSource}>
|
|
113
|
+
* {children}
|
|
114
|
+
* </DemoKitNextProvider>
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
|
|
90
118
|
|
|
91
|
-
export { DemoKitNextConfig, DemoScenario, createDemoConfig, createScenario, defineFixtures, defineScenarios, mergeFixtures };
|
|
119
|
+
export { DemoKitNextConfig, DemoScenario, RemoteSourceConfig, createDemoConfig, createRemoteSource, createScenario, defineFixtures, defineScenarios, mergeFixtures };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FixtureMap } from '@demokit-ai/core';
|
|
2
2
|
export { FixtureHandler, FixtureMap, RequestContext } from '@demokit-ai/core';
|
|
3
|
-
import { D as DemoScenario, a as DemoKitNextConfig } from './types-
|
|
4
|
-
export { d as DefineFixtures, e as DefineScenarios, b as DemoKitNextProviderProps, c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-
|
|
3
|
+
import { D as DemoScenario, a as DemoKitNextConfig, R as RemoteSourceConfig } from './types-Brt8EaFz.js';
|
|
4
|
+
export { d as DefineFixtures, e as DefineScenarios, b as DemoKitNextProviderProps, c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-Brt8EaFz.js';
|
|
5
5
|
import 'react';
|
|
6
6
|
import 'next/server';
|
|
7
7
|
|
|
@@ -87,5 +87,33 @@ declare function mergeFixtures(...fixtureMaps: FixtureMap[]): FixtureMap;
|
|
|
87
87
|
* })
|
|
88
88
|
*/
|
|
89
89
|
declare function createDemoConfig(config: DemoKitNextConfig): DemoKitNextConfig;
|
|
90
|
+
/**
|
|
91
|
+
* Create a remote source configuration for fetching fixtures from DemoKit Cloud
|
|
92
|
+
*
|
|
93
|
+
* The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // lib/demokit-config.ts
|
|
98
|
+
* import { createRemoteSource } from '@demokit-ai/next'
|
|
99
|
+
*
|
|
100
|
+
* // .env.local:
|
|
101
|
+
* // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
|
|
102
|
+
* // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx
|
|
103
|
+
*
|
|
104
|
+
* export const demokitSource = createRemoteSource({
|
|
105
|
+
* apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,
|
|
106
|
+
* apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,
|
|
107
|
+
* })
|
|
108
|
+
*
|
|
109
|
+
* // Then in providers.tsx:
|
|
110
|
+
* import { demokitSource } from '@/lib/demokit-config'
|
|
111
|
+
*
|
|
112
|
+
* <DemoKitNextProvider source={demokitSource}>
|
|
113
|
+
* {children}
|
|
114
|
+
* </DemoKitNextProvider>
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
|
|
90
118
|
|
|
91
|
-
export { DemoKitNextConfig, DemoScenario, createDemoConfig, createScenario, defineFixtures, defineScenarios, mergeFixtures };
|
|
119
|
+
export { DemoKitNextConfig, DemoScenario, RemoteSourceConfig, createDemoConfig, createRemoteSource, createScenario, defineFixtures, defineScenarios, mergeFixtures };
|
package/dist/index.js
CHANGED
|
@@ -19,8 +19,17 @@ function createDemoConfig(config) {
|
|
|
19
19
|
...config
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
+
function createRemoteSource(config) {
|
|
23
|
+
return {
|
|
24
|
+
timeout: 1e4,
|
|
25
|
+
retry: true,
|
|
26
|
+
maxRetries: 3,
|
|
27
|
+
...config
|
|
28
|
+
};
|
|
29
|
+
}
|
|
22
30
|
export {
|
|
23
31
|
createDemoConfig,
|
|
32
|
+
createRemoteSource,
|
|
24
33
|
createScenario,
|
|
25
34
|
defineFixtures,
|
|
26
35
|
defineScenarios,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["import type { FixtureMap } from '@demokit-ai/core'\nimport type { DemoKitNextConfig, DemoScenario } from './types'\n\n/**\n * Helper to define fixtures with type safety\n *\n * @example\n * const fixtures = defineFixtures({\n * 'GET /api/users': () => [\n * { id: '1', name: 'Demo User' },\n * ],\n * 'GET /api/users/:id': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * 'POST /api/users': async ({ body }) => ({\n * id: crypto.randomUUID(),\n * ...body,\n * }),\n * })\n */\nexport function defineFixtures<T extends FixtureMap>(fixtures: T): T {\n return fixtures\n}\n\n/**\n * Helper to define scenarios with type safety\n *\n * @example\n * const scenarios = defineScenarios({\n * 'empty-state': {\n * 'GET /api/users': () => [],\n * 'GET /api/projects': () => [],\n * },\n * 'error-state': {\n * 'GET /api/users': () => {\n * throw new Error('API Error')\n * },\n * },\n * 'new-user': {\n * 'GET /api/users': () => [\n * { id: '1', name: 'Welcome, New User!', isNew: true },\n * ],\n * },\n * })\n */\nexport function defineScenarios<T extends Record<string, FixtureMap>>(scenarios: T): T {\n return scenarios\n}\n\n/**\n * Helper to create a scenario object\n *\n * @example\n * const emptyStateScenario = createScenario({\n * name: 'empty-state',\n * description: 'Shows the app with no data',\n * fixtures: {\n * 'GET /api/users': () => [],\n * },\n * })\n */\nexport function createScenario(scenario: DemoScenario): DemoScenario {\n return scenario\n}\n\n/**\n * Merge multiple fixture maps\n *\n * @example\n * const allFixtures = mergeFixtures(\n * baseFixtures,\n * usersFixtures,\n * projectsFixtures\n * )\n */\nexport function mergeFixtures(...fixtureMaps: FixtureMap[]): FixtureMap {\n return Object.assign({}, ...fixtureMaps)\n}\n\n/**\n * Create a complete DemoKit Next.js configuration\n *\n * @example\n * // lib/demo.ts\n * import { createDemoConfig, defineFixtures, defineScenarios } from '@demokit-ai/next'\n *\n * export const demoConfig = createDemoConfig({\n * fixtures: defineFixtures({\n * 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],\n * }),\n * scenarios: defineScenarios({\n * 'empty': { 'GET /api/users': () => [] },\n * }),\n * })\n */\nexport function createDemoConfig(config: DemoKitNextConfig): DemoKitNextConfig {\n return {\n storageKey: 'demokit-mode',\n cookieName: 'demokit-mode',\n urlParam: 'demo',\n ...config,\n }\n}\n"],"mappings":";AAqBO,SAAS,eAAqC,UAAgB;AACnE,SAAO;AACT;AAuBO,SAAS,gBAAsD,WAAiB;AACrF,SAAO;AACT;AAcO,SAAS,eAAe,UAAsC;AACnE,SAAO;AACT;AAYO,SAAS,iBAAiB,aAAuC;AACtE,SAAO,OAAO,OAAO,CAAC,GAAG,GAAG,WAAW;AACzC;AAkBO,SAAS,iBAAiB,QAA8C;AAC7E,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,GAAG;AAAA,EACL;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["import type { FixtureMap } from '@demokit-ai/core'\nimport type { DemoKitNextConfig, DemoScenario, RemoteSourceConfig } from './types'\n\n/**\n * Helper to define fixtures with type safety\n *\n * @example\n * const fixtures = defineFixtures({\n * 'GET /api/users': () => [\n * { id: '1', name: 'Demo User' },\n * ],\n * 'GET /api/users/:id': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * 'POST /api/users': async ({ body }) => ({\n * id: crypto.randomUUID(),\n * ...body,\n * }),\n * })\n */\nexport function defineFixtures<T extends FixtureMap>(fixtures: T): T {\n return fixtures\n}\n\n/**\n * Helper to define scenarios with type safety\n *\n * @example\n * const scenarios = defineScenarios({\n * 'empty-state': {\n * 'GET /api/users': () => [],\n * 'GET /api/projects': () => [],\n * },\n * 'error-state': {\n * 'GET /api/users': () => {\n * throw new Error('API Error')\n * },\n * },\n * 'new-user': {\n * 'GET /api/users': () => [\n * { id: '1', name: 'Welcome, New User!', isNew: true },\n * ],\n * },\n * })\n */\nexport function defineScenarios<T extends Record<string, FixtureMap>>(scenarios: T): T {\n return scenarios\n}\n\n/**\n * Helper to create a scenario object\n *\n * @example\n * const emptyStateScenario = createScenario({\n * name: 'empty-state',\n * description: 'Shows the app with no data',\n * fixtures: {\n * 'GET /api/users': () => [],\n * },\n * })\n */\nexport function createScenario(scenario: DemoScenario): DemoScenario {\n return scenario\n}\n\n/**\n * Merge multiple fixture maps\n *\n * @example\n * const allFixtures = mergeFixtures(\n * baseFixtures,\n * usersFixtures,\n * projectsFixtures\n * )\n */\nexport function mergeFixtures(...fixtureMaps: FixtureMap[]): FixtureMap {\n return Object.assign({}, ...fixtureMaps)\n}\n\n/**\n * Create a complete DemoKit Next.js configuration\n *\n * @example\n * // lib/demo.ts\n * import { createDemoConfig, defineFixtures, defineScenarios } from '@demokit-ai/next'\n *\n * export const demoConfig = createDemoConfig({\n * fixtures: defineFixtures({\n * 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],\n * }),\n * scenarios: defineScenarios({\n * 'empty': { 'GET /api/users': () => [] },\n * }),\n * })\n */\nexport function createDemoConfig(config: DemoKitNextConfig): DemoKitNextConfig {\n return {\n storageKey: 'demokit-mode',\n cookieName: 'demokit-mode',\n urlParam: 'demo',\n ...config,\n }\n}\n\n/**\n * Create a remote source configuration for fetching fixtures from DemoKit Cloud\n *\n * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.\n *\n * @example\n * ```typescript\n * // lib/demokit-config.ts\n * import { createRemoteSource } from '@demokit-ai/next'\n *\n * // .env.local:\n * // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api\n * // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx\n *\n * export const demokitSource = createRemoteSource({\n * apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,\n * apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,\n * })\n *\n * // Then in providers.tsx:\n * import { demokitSource } from '@/lib/demokit-config'\n *\n * <DemoKitNextProvider source={demokitSource}>\n * {children}\n * </DemoKitNextProvider>\n * ```\n */\nexport function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig {\n return {\n timeout: 10000,\n retry: true,\n maxRetries: 3,\n ...config,\n }\n}\n"],"mappings":";AAqBO,SAAS,eAAqC,UAAgB;AACnE,SAAO;AACT;AAuBO,SAAS,gBAAsD,WAAiB;AACrF,SAAO;AACT;AAcO,SAAS,eAAe,UAAsC;AACnE,SAAO;AACT;AAYO,SAAS,iBAAiB,aAAuC;AACtE,SAAO,OAAO,OAAO,CAAC,GAAG,GAAG,WAAW;AACzC;AAkBO,SAAS,iBAAiB,QAA8C;AAC7E,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,GAAG;AAAA,EACL;AACF;AA6BO,SAAS,mBAAmB,QAAgD;AACjF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,GAAG;AAAA,EACL;AACF;","names":[]}
|
package/dist/middleware.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-
|
|
2
|
+
import { c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-Brt8EaFz.cjs';
|
|
3
3
|
import '@demokit-ai/core';
|
|
4
4
|
import 'react';
|
|
5
5
|
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-
|
|
2
|
+
import { c as DemoMiddlewareConfig, M as MiddlewareResult } from './types-Brt8EaFz.js';
|
|
3
3
|
import '@demokit-ai/core';
|
|
4
4
|
import 'react';
|
|
5
5
|
|
package/dist/server.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
2
2
|
import { FixtureMap, DemoInterceptor, RequestContext } from '@demokit-ai/core';
|
|
3
3
|
export { createDemoMiddleware, demoMiddleware, getDemoScenario, isDemoRequest } from './middleware.cjs';
|
|
4
4
|
import 'next/server';
|
|
5
|
-
import './types-
|
|
5
|
+
import './types-Brt8EaFz.cjs';
|
|
6
6
|
import 'react';
|
|
7
7
|
|
|
8
8
|
/**
|
package/dist/server.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
2
2
|
import { FixtureMap, DemoInterceptor, RequestContext } from '@demokit-ai/core';
|
|
3
3
|
export { createDemoMiddleware, demoMiddleware, getDemoScenario, isDemoRequest } from './middleware.js';
|
|
4
4
|
import 'next/server';
|
|
5
|
-
import './types-
|
|
5
|
+
import './types-Brt8EaFz.js';
|
|
6
6
|
import 'react';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -48,6 +48,11 @@ interface DemoKitNextProviderProps extends DemoKitNextConfig {
|
|
|
48
48
|
* If not provided, will read from cookie/localStorage
|
|
49
49
|
*/
|
|
50
50
|
initialEnabled?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Remote source configuration for fetching fixtures from DemoKit Cloud
|
|
53
|
+
* Create using createRemoteSource()
|
|
54
|
+
*/
|
|
55
|
+
source?: RemoteSourceConfig;
|
|
51
56
|
}
|
|
52
57
|
/**
|
|
53
58
|
* Configuration for createDemoMiddleware
|
|
@@ -125,5 +130,37 @@ type DefineFixtures<T extends Record<string, FixtureHandler>> = T;
|
|
|
125
130
|
* Helper type for defining scenarios with type safety
|
|
126
131
|
*/
|
|
127
132
|
type DefineScenarios<T extends Record<string, FixtureMap>> = T;
|
|
133
|
+
/**
|
|
134
|
+
* Configuration for remote fixture source (DemoKit Cloud)
|
|
135
|
+
*/
|
|
136
|
+
interface RemoteSourceConfig {
|
|
137
|
+
/**
|
|
138
|
+
* DemoKit Cloud API URL (versioned base URL)
|
|
139
|
+
* The SDK will append `/fixtures` to this URL.
|
|
140
|
+
* @example 'https://demokit-cloud.kasava.dev/api'
|
|
141
|
+
* @default 'https://api.demokit.cloud/api'
|
|
142
|
+
*/
|
|
143
|
+
apiUrl: string;
|
|
144
|
+
/**
|
|
145
|
+
* DemoKit Cloud API key
|
|
146
|
+
* Format: dk_live_xxx
|
|
147
|
+
*/
|
|
148
|
+
apiKey: string;
|
|
149
|
+
/**
|
|
150
|
+
* Request timeout in milliseconds
|
|
151
|
+
* @default 10000
|
|
152
|
+
*/
|
|
153
|
+
timeout?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Whether to retry failed requests
|
|
156
|
+
* @default true
|
|
157
|
+
*/
|
|
158
|
+
retry?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Maximum number of retries
|
|
161
|
+
* @default 3
|
|
162
|
+
*/
|
|
163
|
+
maxRetries?: number;
|
|
164
|
+
}
|
|
128
165
|
|
|
129
|
-
export type { DemoScenario as D, MiddlewareResult as M, DemoKitNextConfig as a, DemoKitNextProviderProps as b, DemoMiddlewareConfig as c, DefineFixtures as d, DefineScenarios as e };
|
|
166
|
+
export type { DemoScenario as D, MiddlewareResult as M, RemoteSourceConfig as R, DemoKitNextConfig as a, DemoKitNextProviderProps as b, DemoMiddlewareConfig as c, DefineFixtures as d, DefineScenarios as e };
|
|
@@ -48,6 +48,11 @@ interface DemoKitNextProviderProps extends DemoKitNextConfig {
|
|
|
48
48
|
* If not provided, will read from cookie/localStorage
|
|
49
49
|
*/
|
|
50
50
|
initialEnabled?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Remote source configuration for fetching fixtures from DemoKit Cloud
|
|
53
|
+
* Create using createRemoteSource()
|
|
54
|
+
*/
|
|
55
|
+
source?: RemoteSourceConfig;
|
|
51
56
|
}
|
|
52
57
|
/**
|
|
53
58
|
* Configuration for createDemoMiddleware
|
|
@@ -125,5 +130,37 @@ type DefineFixtures<T extends Record<string, FixtureHandler>> = T;
|
|
|
125
130
|
* Helper type for defining scenarios with type safety
|
|
126
131
|
*/
|
|
127
132
|
type DefineScenarios<T extends Record<string, FixtureMap>> = T;
|
|
133
|
+
/**
|
|
134
|
+
* Configuration for remote fixture source (DemoKit Cloud)
|
|
135
|
+
*/
|
|
136
|
+
interface RemoteSourceConfig {
|
|
137
|
+
/**
|
|
138
|
+
* DemoKit Cloud API URL (versioned base URL)
|
|
139
|
+
* The SDK will append `/fixtures` to this URL.
|
|
140
|
+
* @example 'https://demokit-cloud.kasava.dev/api'
|
|
141
|
+
* @default 'https://api.demokit.cloud/api'
|
|
142
|
+
*/
|
|
143
|
+
apiUrl: string;
|
|
144
|
+
/**
|
|
145
|
+
* DemoKit Cloud API key
|
|
146
|
+
* Format: dk_live_xxx
|
|
147
|
+
*/
|
|
148
|
+
apiKey: string;
|
|
149
|
+
/**
|
|
150
|
+
* Request timeout in milliseconds
|
|
151
|
+
* @default 10000
|
|
152
|
+
*/
|
|
153
|
+
timeout?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Whether to retry failed requests
|
|
156
|
+
* @default true
|
|
157
|
+
*/
|
|
158
|
+
retry?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Maximum number of retries
|
|
161
|
+
* @default 3
|
|
162
|
+
*/
|
|
163
|
+
maxRetries?: number;
|
|
164
|
+
}
|
|
128
165
|
|
|
129
|
-
export type { DemoScenario as D, MiddlewareResult as M, DemoKitNextConfig as a, DemoKitNextProviderProps as b, DemoMiddlewareConfig as c, DefineFixtures as d, DefineScenarios as e };
|
|
166
|
+
export type { DemoScenario as D, MiddlewareResult as M, RemoteSourceConfig as R, DemoKitNextConfig as a, DemoKitNextProviderProps as b, DemoMiddlewareConfig as c, DefineFixtures as d, DefineScenarios as e };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demokit-ai/next",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Next.js adapter for DemoKit - SSR support and middleware",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -52,19 +52,20 @@
|
|
|
52
52
|
"dist"
|
|
53
53
|
],
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@demokit-ai/core": "0.
|
|
56
|
-
"@demokit-ai/react": "0.
|
|
55
|
+
"@demokit-ai/core": "0.4.2",
|
|
56
|
+
"@demokit-ai/react": "0.4.1"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@types/
|
|
60
|
-
"@types/react
|
|
61
|
-
"
|
|
62
|
-
"
|
|
59
|
+
"@types/node": "^22.0.0",
|
|
60
|
+
"@types/react": "^19.2.14",
|
|
61
|
+
"@types/react-dom": "^19.2.3",
|
|
62
|
+
"tsup": "^8.5.1",
|
|
63
|
+
"typescript": "^6.0.2"
|
|
63
64
|
},
|
|
64
65
|
"peerDependencies": {
|
|
65
|
-
"next": ">=
|
|
66
|
-
"react": ">=
|
|
67
|
-
"react-dom": ">=
|
|
66
|
+
"next": ">=15.0.0",
|
|
67
|
+
"react": ">=18.0.0",
|
|
68
|
+
"react-dom": ">=18.0.0"
|
|
68
69
|
},
|
|
69
70
|
"engines": {
|
|
70
71
|
"node": ">=18"
|