@djangocfg/ext-base 1.0.3 → 1.0.4

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.
Files changed (40) hide show
  1. package/README.md +134 -8
  2. package/dist/api.cjs +40 -0
  3. package/dist/api.d.cts +35 -0
  4. package/dist/api.d.ts +35 -0
  5. package/dist/api.js +2 -0
  6. package/dist/auth.cjs +10 -0
  7. package/dist/auth.d.cts +1 -0
  8. package/dist/auth.d.ts +1 -0
  9. package/dist/auth.js +2 -0
  10. package/dist/chunk-3RG5ZIWI.js +8 -0
  11. package/dist/chunk-UXTBBEO5.js +237 -0
  12. package/dist/chunk-VJEGYVBV.js +140 -0
  13. package/dist/cli.mjs +530 -0
  14. package/dist/hooks.cjs +437 -0
  15. package/dist/hooks.d.cts +97 -0
  16. package/dist/hooks.d.ts +97 -0
  17. package/dist/hooks.js +95 -0
  18. package/dist/index.cjs +345 -0
  19. package/dist/index.d.cts +363 -0
  20. package/dist/index.d.ts +363 -0
  21. package/dist/index.js +3 -0
  22. package/package.json +3 -1
  23. package/src/cli/index.ts +281 -15
  24. package/src/context/ExtensionProvider.tsx +67 -4
  25. package/src/extensionConfig.ts +77 -28
  26. package/templates/extension-template/README.md.template +30 -0
  27. package/templates/extension-template/package.json.template +2 -1
  28. package/templates/extension-template/playground/.gitignore.template +34 -0
  29. package/templates/extension-template/playground/CLAUDE.md +35 -0
  30. package/templates/extension-template/playground/README.md.template +76 -0
  31. package/templates/extension-template/playground/app/globals.css.template +19 -0
  32. package/templates/extension-template/playground/app/layout.tsx.template +30 -0
  33. package/templates/extension-template/playground/app/page.tsx.template +44 -0
  34. package/templates/extension-template/playground/next.config.ts.template +62 -0
  35. package/templates/extension-template/playground/package.json.template +33 -0
  36. package/templates/extension-template/playground/tsconfig.json.template +27 -0
  37. package/templates/extension-template/src/contexts/__PROVIDER_NAME__Context.tsx +1 -1
  38. package/templates/extension-template/src/contexts/__PROVIDER_NAME__ExtensionProvider.tsx +1 -0
  39. package/templates/extension-template/src/index.ts +12 -4
  40. package/templates/extension-template/src/utils/withSmartProvider.tsx +70 -0
package/dist/hooks.cjs ADDED
@@ -0,0 +1,437 @@
1
+ 'use strict';
2
+
3
+ var consola = require('consola');
4
+ var React = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var swr = require('swr');
7
+ var auth = require('@djangocfg/api/auth');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var React__default = /*#__PURE__*/_interopDefault(React);
12
+
13
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
14
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
15
+ }) : x)(function(x) {
16
+ if (typeof require !== "undefined") return require.apply(this, arguments);
17
+ throw Error('Dynamic require of "' + x + '" is not supported');
18
+ });
19
+
20
+ // src/types/context.ts
21
+ var EXTENSION_CATEGORIES = [
22
+ { title: "Forms", value: "forms" },
23
+ { title: "Payments", value: "payments" },
24
+ { title: "Content", value: "content" },
25
+ { title: "Support", value: "support" },
26
+ { title: "Utilities", value: "utilities" },
27
+ { title: "Analytics", value: "analytics" },
28
+ { title: "Security", value: "security" },
29
+ { title: "Integration", value: "integration" },
30
+ { title: "Other", value: "other" }
31
+ ];
32
+
33
+ // src/utils/createExtensionConfig.ts
34
+ function replaceWorkspaceDeps(deps) {
35
+ if (!deps) return void 0;
36
+ const result = {};
37
+ for (const [key, value] of Object.entries(deps)) {
38
+ result[key] = value === "workspace:*" ? "latest" : value;
39
+ }
40
+ return result;
41
+ }
42
+ function createExtensionConfig(packageJson, config) {
43
+ const author = typeof packageJson.author === "string" ? packageJson.author : packageJson.author?.name || "Unknown";
44
+ const githubUrl = typeof packageJson.repository === "string" ? packageJson.repository : packageJson.repository?.url;
45
+ const packageNameWithoutScope = packageJson.name.split("/").pop() || packageJson.name;
46
+ const downloadUrl = `https://registry.npmjs.org/${packageJson.name}/-/${packageNameWithoutScope}-${packageJson.version}.tgz`;
47
+ const marketplaceId = packageJson.name.replace("@", "").replace("/", "-");
48
+ return {
49
+ // From package.json
50
+ name: config.name,
51
+ version: packageJson.version,
52
+ author,
53
+ description: packageJson.description,
54
+ keywords: packageJson.keywords,
55
+ license: packageJson.license,
56
+ homepage: packageJson.homepage,
57
+ githubUrl,
58
+ packageDependencies: replaceWorkspaceDeps(packageJson.dependencies),
59
+ packagePeerDependencies: replaceWorkspaceDeps(packageJson.peerDependencies),
60
+ packageDevDependencies: replaceWorkspaceDeps(packageJson.devDependencies),
61
+ // From manual config
62
+ displayName: config.displayName,
63
+ category: config.category,
64
+ features: config.features,
65
+ examples: config.examples,
66
+ minVersion: config.minVersion,
67
+ githubStars: config.githubStars,
68
+ // Auto-generated
69
+ npmUrl: `https://www.npmjs.com/package/${packageJson.name}`,
70
+ marketplaceId,
71
+ // Only generate marketplace URL for official @djangocfg extensions
72
+ marketplaceUrl: packageJson.name.startsWith("@djangocfg/ext-") ? `https://hub.djangocfg.com/extensions/${marketplaceId}` : void 0,
73
+ installCommand: `pnpm add ${packageJson.name}`,
74
+ downloadUrl,
75
+ tags: packageJson.keywords,
76
+ preview: `https://unpkg.com/${packageJson.name}@latest/preview.png`
77
+ };
78
+ }
79
+
80
+ // package.json
81
+ var package_default = {
82
+ name: "@djangocfg/ext-base",
83
+ version: "1.0.4",
84
+ description: "Base utilities and common code for DjangoCFG extensions",
85
+ keywords: [
86
+ "django",
87
+ "djangocfg",
88
+ "extension",
89
+ "base",
90
+ "utilities",
91
+ "typescript",
92
+ "react"
93
+ ],
94
+ author: {
95
+ name: "DjangoCFG",
96
+ url: "https://djangocfg.com"
97
+ },
98
+ homepage: "https://hub.djangocfg.com/extensions/djangocfg-ext-base",
99
+ repository: {
100
+ type: "git",
101
+ url: "https://github.com/markolofsen/django-cfg.git",
102
+ directory: "extensions/base"
103
+ },
104
+ license: "MIT",
105
+ peerDependencies: {
106
+ "@djangocfg/api": "workspace:*",
107
+ consola: "^3.4.2",
108
+ react: "^18 || ^19",
109
+ "react-dom": "^18 || ^19",
110
+ swr: "^2.3.7"
111
+ },
112
+ dependencies: {
113
+ chalk: "^5.3.0",
114
+ consola: "^3.4.2",
115
+ picocolors: "^1.1.1",
116
+ prompts: "^2.4.2"
117
+ },
118
+ devDependencies: {
119
+ "@djangocfg/api": "workspace:*",
120
+ "@djangocfg/typescript-config": "workspace:*",
121
+ "@types/node": "^24.7.2",
122
+ "@types/prompts": "^2.4.9",
123
+ "@types/react": "^19.0.0",
124
+ swr: "^2.3.7",
125
+ tsup: "^8.5.0",
126
+ tsx: "^4.19.2",
127
+ typescript: "^5.9.3"
128
+ }
129
+ };
130
+
131
+ // src/extensionConfig.ts
132
+ var extensionConfig = createExtensionConfig(package_default, {
133
+ name: "base",
134
+ displayName: "Extension Base",
135
+ category: "utilities",
136
+ features: [
137
+ "CLI for creating extensions",
138
+ "Next.js 15 playground for rapid development",
139
+ "Smart Provider Pattern for flexible component usage",
140
+ "Extension context and provider system",
141
+ "Pagination hooks (standard & infinite scroll)",
142
+ "API client utilities with auth integration",
143
+ "Type-safe context creation helpers",
144
+ "Logging system with structured output",
145
+ "Environment detection (dev, prod, static)",
146
+ "TypeScript types and utilities"
147
+ ],
148
+ minVersion: "2.0.0",
149
+ examples: [
150
+ {
151
+ title: "Create Extension with CLI",
152
+ description: "Interactive wizard with playground environment",
153
+ code: `# Create extension with interactive wizard
154
+ pnpm dlx @djangocfg/ext-base create
155
+
156
+ # Quick test extension (auto-cleanup)
157
+ pnpm dlx @djangocfg/ext-base test
158
+
159
+ # List all extensions
160
+ pnpm dlx @djangocfg/ext-base list`,
161
+ language: "bash"
162
+ },
163
+ {
164
+ title: "Development with Playground",
165
+ description: "Start Next.js playground for rapid testing",
166
+ code: `cd your-extension
167
+
168
+ # Start playground (auto-builds extension + opens browser)
169
+ pnpm dev:playground
170
+
171
+ # Build for production
172
+ pnpm build
173
+
174
+ # Type check
175
+ pnpm check`,
176
+ language: "bash"
177
+ },
178
+ {
179
+ title: "Smart Provider Pattern",
180
+ description: "Components that work standalone or with shared context",
181
+ code: `import { withSmartProvider } from '@your-org/my-extension';
182
+
183
+ // Your component
184
+ function MyComponent() {
185
+ const { data } = useMyExtension();
186
+ return <div>{data}</div>;
187
+ }
188
+
189
+ // Wrap with smart provider
190
+ export const MySmartComponent = withSmartProvider(MyComponent);
191
+
192
+ // Usage 1: Standalone (auto-wrapped)
193
+ <MySmartComponent />
194
+
195
+ // Usage 2: Manual provider (shared context)
196
+ <MyExtensionProvider>
197
+ <MySmartComponent />
198
+ <MySmartComponent />
199
+ </MyExtensionProvider>`,
200
+ language: "tsx"
201
+ },
202
+ {
203
+ title: "Extension Provider",
204
+ description: "Register and wrap your extension",
205
+ code: `import { ExtensionProvider } from '@djangocfg/ext-base/hooks';
206
+ import { extensionConfig } from './config';
207
+
208
+ export function MyExtensionProvider({ children }) {
209
+ return (
210
+ <ExtensionProvider metadata={extensionConfig}>
211
+ {children}
212
+ </ExtensionProvider>
213
+ );
214
+ }`,
215
+ language: "tsx"
216
+ },
217
+ {
218
+ title: "Pagination Hooks",
219
+ description: "Built-in hooks for standard and infinite scroll",
220
+ code: `import { usePagination, useInfinitePagination } from '@djangocfg/ext-base/hooks';
221
+
222
+ // Standard pagination
223
+ const { items, page, totalPages, nextPage, prevPage } = usePagination({
224
+ keyPrefix: 'articles',
225
+ fetcher: async (page, pageSize) => api.articles.list({ page, page_size: pageSize }),
226
+ pageSize: 20,
227
+ });
228
+
229
+ // Infinite scroll
230
+ const { items, isLoading, hasMore, loadMore } = useInfinitePagination({
231
+ keyPrefix: 'articles',
232
+ fetcher: async (page, pageSize) => api.articles.list({ page, page_size: pageSize }),
233
+ pageSize: 20,
234
+ });`,
235
+ language: "tsx"
236
+ }
237
+ ]
238
+ });
239
+
240
+ // src/metadata.ts
241
+ ({
242
+ version: package_default.version,
243
+ npmUrl: `https://www.npmjs.com/package/${package_default.name}`,
244
+ installCommand: `pnpm add ${package_default.name}`,
245
+ packagePeerDependencies: package_default.peerDependencies});
246
+
247
+ // src/config.ts
248
+ var isDevelopment = process.env.NODE_ENV === "development";
249
+ var isProduction = process.env.NODE_ENV === "production";
250
+ var isStaticBuild = process.env.STATIC_BUILD === "true";
251
+ function getApiUrl() {
252
+ return process.env.NEXT_PUBLIC_API_URL || "/api";
253
+ }
254
+
255
+ // src/api/createExtensionAPI.ts
256
+ function createExtensionAPI(APIClass) {
257
+ let storage;
258
+ try {
259
+ const { api: accountsApi } = __require("@djangocfg/api");
260
+ storage = accountsApi._storage;
261
+ } catch (error) {
262
+ storage = void 0;
263
+ }
264
+ const apiUrl = isStaticBuild ? "" : getApiUrl();
265
+ return new APIClass(apiUrl, storage ? { storage } : void 0);
266
+ }
267
+ function getSharedAuthStorage() {
268
+ try {
269
+ const { api: accountsApi } = __require("@djangocfg/api");
270
+ return accountsApi._storage;
271
+ } catch (error) {
272
+ return void 0;
273
+ }
274
+ }
275
+
276
+ // src/utils/errors.ts
277
+ function isExtensionError(error) {
278
+ return typeof error === "object" && error !== null && "message" in error && "timestamp" in error;
279
+ }
280
+ function createExtensionError(error, code, details) {
281
+ const message = error instanceof Error ? error.message : String(error);
282
+ return {
283
+ message,
284
+ code,
285
+ details,
286
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
287
+ };
288
+ }
289
+ function formatErrorMessage(error) {
290
+ if (isExtensionError(error)) {
291
+ return error.code ? `[${error.code}] ${error.message}` : error.message;
292
+ }
293
+ if (error instanceof Error) {
294
+ return error.message;
295
+ }
296
+ return String(error);
297
+ }
298
+ function handleExtensionError(error, logger, callback) {
299
+ const extensionError = isExtensionError(error) ? error : createExtensionError(error);
300
+ if (logger) {
301
+ logger.error("Extension error:", extensionError);
302
+ }
303
+ if (callback) {
304
+ callback(extensionError);
305
+ }
306
+ }
307
+ var isDevelopment2 = process.env.NODE_ENV === "development";
308
+ var LEVEL_MAP = {
309
+ debug: 4,
310
+ info: 3,
311
+ warn: 2,
312
+ error: 1
313
+ };
314
+ function createExtensionLogger(options) {
315
+ const { tag, level = "info", enabled = true } = options;
316
+ if (!enabled) {
317
+ const noop = () => {
318
+ };
319
+ return {
320
+ info: noop,
321
+ warn: noop,
322
+ error: noop,
323
+ debug: noop,
324
+ success: noop
325
+ };
326
+ }
327
+ const logLevel = isDevelopment2 ? LEVEL_MAP[level] : LEVEL_MAP.error;
328
+ const consola2 = consola.createConsola({
329
+ level: logLevel
330
+ }).withTag(tag);
331
+ return {
332
+ info: (...args) => consola2.info(...args),
333
+ warn: (...args) => consola2.warn(...args),
334
+ error: (...args) => consola2.error(...args),
335
+ debug: (...args) => consola2.debug(...args),
336
+ success: (...args) => consola2.success(...args)
337
+ };
338
+ }
339
+ function createExtensionContext({
340
+ displayName,
341
+ errorMessage
342
+ }) {
343
+ const Context = React.createContext(void 0);
344
+ Context.displayName = displayName;
345
+ const Provider = ({ value, children }) => {
346
+ return /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
347
+ };
348
+ const useContextHook = () => {
349
+ const context = React.useContext(Context);
350
+ if (context === void 0) {
351
+ throw new Error(
352
+ errorMessage || `use${displayName} must be used within ${displayName}Provider`
353
+ );
354
+ }
355
+ return context;
356
+ };
357
+ return {
358
+ Context,
359
+ Provider,
360
+ useContext: useContextHook
361
+ };
362
+ }
363
+ var DEFAULT_OPTIONS = {
364
+ revalidateOnFocus: false,
365
+ revalidateOnReconnect: false,
366
+ revalidateIfStale: false
367
+ };
368
+ var registeredExtensions = /* @__PURE__ */ new Set();
369
+ var authWarningShown = false;
370
+ function AuthChecker({ children }) {
371
+ auth.useAuth();
372
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
373
+ }
374
+ var AuthErrorBoundary = class extends React__default.default.Component {
375
+ state = { hasError: false, errorMessage: "" };
376
+ static getDerivedStateFromError(error) {
377
+ if (error?.message?.includes("useAuth must be used within an AuthProvider")) {
378
+ return { hasError: true, errorMessage: error.message };
379
+ }
380
+ return null;
381
+ }
382
+ componentDidCatch(error) {
383
+ if (this.state.hasError && !authWarningShown) {
384
+ authWarningShown = true;
385
+ consola.consola.error(
386
+ "\u274C AuthProvider not found in parent component!\n Extension components require AuthProvider wrapper.\n Auto-wrapping applied as a safety measure.\n\n Please wrap your page with <BaseApp> or <AuthProvider>:\n\n import { BaseApp } from '@djangocfg/layouts';\n \n <BaseApp>\n <YourPageWithExtensions />\n </BaseApp>"
387
+ );
388
+ }
389
+ }
390
+ render() {
391
+ if (this.state.hasError) {
392
+ return /* @__PURE__ */ jsxRuntime.jsx(auth.AuthProvider, { children: this.props.children });
393
+ }
394
+ return this.props.children;
395
+ }
396
+ };
397
+ function ExtensionProvider({ children, metadata, options = {} }) {
398
+ const config = { ...DEFAULT_OPTIONS, ...options };
399
+ React.useEffect(() => {
400
+ if (registeredExtensions.has(metadata.name)) {
401
+ if (isDevelopment) {
402
+ console.warn(
403
+ `[ExtensionProvider] Extension "${metadata.name}" is already registered. This might indicate that the extension is mounted multiple times.`
404
+ );
405
+ }
406
+ return;
407
+ }
408
+ registeredExtensions.add(metadata.name);
409
+ if (isDevelopment) {
410
+ const logger = createExtensionLogger({ tag: "ext-base", level: "info" });
411
+ logger.info(
412
+ `Extension registered: ${metadata.displayName || metadata.name} v${metadata.version}`
413
+ );
414
+ }
415
+ return () => {
416
+ registeredExtensions.delete(metadata.name);
417
+ };
418
+ }, [metadata.name, metadata.version, metadata.displayName]);
419
+ return /* @__PURE__ */ jsxRuntime.jsx(AuthErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(AuthChecker, { children: /* @__PURE__ */ jsxRuntime.jsx(swr.SWRConfig, { value: config, children }) }) });
420
+ }
421
+
422
+ exports.EXTENSION_CATEGORIES = EXTENSION_CATEGORIES;
423
+ exports.ExtensionProvider = ExtensionProvider;
424
+ exports.createExtensionAPI = createExtensionAPI;
425
+ exports.createExtensionConfig = createExtensionConfig;
426
+ exports.createExtensionContext = createExtensionContext;
427
+ exports.createExtensionError = createExtensionError;
428
+ exports.createExtensionLogger = createExtensionLogger;
429
+ exports.extensionConfig = extensionConfig;
430
+ exports.formatErrorMessage = formatErrorMessage;
431
+ exports.getApiUrl = getApiUrl;
432
+ exports.getSharedAuthStorage = getSharedAuthStorage;
433
+ exports.handleExtensionError = handleExtensionError;
434
+ exports.isDevelopment = isDevelopment;
435
+ exports.isExtensionError = isExtensionError;
436
+ exports.isProduction = isProduction;
437
+ exports.isStaticBuild = isStaticBuild;
@@ -0,0 +1,97 @@
1
+ import { ExtensionProviderProps } from './index.cjs';
2
+ export { EXTENSION_CATEGORIES, ErrorHandler, ExtensionCategory, ExtensionConfigInput, ExtensionContextOptions, ExtensionError, ExtensionExample, ExtensionLogger, ExtensionMetadata, InfinitePaginationOptions, InfinitePaginationReturn, LoggerOptions, PaginatedResponse, PaginationParams, PaginationState, createExtensionConfig, createExtensionError, createExtensionLogger, extensionConfig, formatErrorMessage, getApiUrl, handleExtensionError, isDevelopment, isExtensionError, isProduction, isStaticBuild } from './index.cjs';
3
+ export { createExtensionAPI, getSharedAuthStorage } from './api.cjs';
4
+ import { Context, ReactNode, ReactElement } from 'react';
5
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
+
7
+ /**
8
+ * Utility for creating typed React contexts for extensions
9
+ */
10
+
11
+ interface CreateExtensionContextOptions<T> {
12
+ /** Display name for the context (for debugging) */
13
+ displayName: string;
14
+ /** Error message when hook is used outside provider */
15
+ errorMessage?: string;
16
+ }
17
+ interface ExtensionContextReturn<T> {
18
+ /** The React Context */
19
+ Context: Context<T | undefined>;
20
+ /** Provider component */
21
+ Provider: (props: {
22
+ value: T;
23
+ children: ReactNode;
24
+ }) => ReactElement;
25
+ /** Hook to access context value */
26
+ useContext: () => T;
27
+ }
28
+ /**
29
+ * Creates a typed React context with provider and hook
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * interface MyContextValue {
34
+ * data: string[];
35
+ * isLoading: boolean;
36
+ * }
37
+ *
38
+ * const { Provider, useContext } = createExtensionContext<MyContextValue>({
39
+ * displayName: 'MyContext'
40
+ * });
41
+ *
42
+ * // In provider component:
43
+ * <Provider value={{ data: [], isLoading: false }}>
44
+ * {children}
45
+ * </Provider>
46
+ *
47
+ * // In consumer component:
48
+ * const { data, isLoading } = useContext();
49
+ * ```
50
+ */
51
+ declare function createExtensionContext<T>({ displayName, errorMessage, }: CreateExtensionContextOptions<T>): ExtensionContextReturn<T>;
52
+
53
+ /**
54
+ * Base provider with SWR configuration for extension contexts
55
+ *
56
+ * Provides:
57
+ * - SWR configuration for data fetching
58
+ * - Extension registration and metadata management
59
+ * - Auth context protection (auto-wraps if missing, shows error)
60
+ * - Auth context from @djangocfg/api (automatically available via useAuth)
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * // In extension package:
65
+ * export function NewsletterProvider({ children }: { children: ReactNode }) {
66
+ * return (
67
+ * <ExtensionProvider
68
+ * metadata={{
69
+ * name: 'newsletter',
70
+ * version: '1.0.0',
71
+ * author: 'DjangoCFG',
72
+ * displayName: 'Newsletter',
73
+ * description: 'Newsletter subscription management',
74
+ * icon: '📧',
75
+ * license: 'MIT',
76
+ * githubUrl: 'https://github.com/markolofsen/django-cfg',
77
+ * keywords: ['newsletter', 'email', 'subscription'],
78
+ * }}
79
+ * options={{ revalidateOnFocus: true }}
80
+ * >
81
+ * {children}
82
+ * </ExtensionProvider>
83
+ * );
84
+ * }
85
+ *
86
+ * // In components:
87
+ * import { useAuth } from '@djangocfg/api/auth';
88
+ *
89
+ * function MyComponent() {
90
+ * const { user, isAuthenticated } = useAuth();
91
+ * // Auth is automatically available!
92
+ * }
93
+ * ```
94
+ */
95
+ declare function ExtensionProvider({ children, metadata, options }: ExtensionProviderProps): react_jsx_runtime.JSX.Element;
96
+
97
+ export { type CreateExtensionContextOptions, type ExtensionContextReturn, ExtensionProvider, ExtensionProviderProps, createExtensionContext };
@@ -0,0 +1,97 @@
1
+ import { ExtensionProviderProps } from './index.js';
2
+ export { EXTENSION_CATEGORIES, ErrorHandler, ExtensionCategory, ExtensionConfigInput, ExtensionContextOptions, ExtensionError, ExtensionExample, ExtensionLogger, ExtensionMetadata, InfinitePaginationOptions, InfinitePaginationReturn, LoggerOptions, PaginatedResponse, PaginationParams, PaginationState, createExtensionConfig, createExtensionError, createExtensionLogger, extensionConfig, formatErrorMessage, getApiUrl, handleExtensionError, isDevelopment, isExtensionError, isProduction, isStaticBuild } from './index.js';
3
+ export { createExtensionAPI, getSharedAuthStorage } from './api.js';
4
+ import { Context, ReactNode, ReactElement } from 'react';
5
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
+
7
+ /**
8
+ * Utility for creating typed React contexts for extensions
9
+ */
10
+
11
+ interface CreateExtensionContextOptions<T> {
12
+ /** Display name for the context (for debugging) */
13
+ displayName: string;
14
+ /** Error message when hook is used outside provider */
15
+ errorMessage?: string;
16
+ }
17
+ interface ExtensionContextReturn<T> {
18
+ /** The React Context */
19
+ Context: Context<T | undefined>;
20
+ /** Provider component */
21
+ Provider: (props: {
22
+ value: T;
23
+ children: ReactNode;
24
+ }) => ReactElement;
25
+ /** Hook to access context value */
26
+ useContext: () => T;
27
+ }
28
+ /**
29
+ * Creates a typed React context with provider and hook
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * interface MyContextValue {
34
+ * data: string[];
35
+ * isLoading: boolean;
36
+ * }
37
+ *
38
+ * const { Provider, useContext } = createExtensionContext<MyContextValue>({
39
+ * displayName: 'MyContext'
40
+ * });
41
+ *
42
+ * // In provider component:
43
+ * <Provider value={{ data: [], isLoading: false }}>
44
+ * {children}
45
+ * </Provider>
46
+ *
47
+ * // In consumer component:
48
+ * const { data, isLoading } = useContext();
49
+ * ```
50
+ */
51
+ declare function createExtensionContext<T>({ displayName, errorMessage, }: CreateExtensionContextOptions<T>): ExtensionContextReturn<T>;
52
+
53
+ /**
54
+ * Base provider with SWR configuration for extension contexts
55
+ *
56
+ * Provides:
57
+ * - SWR configuration for data fetching
58
+ * - Extension registration and metadata management
59
+ * - Auth context protection (auto-wraps if missing, shows error)
60
+ * - Auth context from @djangocfg/api (automatically available via useAuth)
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * // In extension package:
65
+ * export function NewsletterProvider({ children }: { children: ReactNode }) {
66
+ * return (
67
+ * <ExtensionProvider
68
+ * metadata={{
69
+ * name: 'newsletter',
70
+ * version: '1.0.0',
71
+ * author: 'DjangoCFG',
72
+ * displayName: 'Newsletter',
73
+ * description: 'Newsletter subscription management',
74
+ * icon: '📧',
75
+ * license: 'MIT',
76
+ * githubUrl: 'https://github.com/markolofsen/django-cfg',
77
+ * keywords: ['newsletter', 'email', 'subscription'],
78
+ * }}
79
+ * options={{ revalidateOnFocus: true }}
80
+ * >
81
+ * {children}
82
+ * </ExtensionProvider>
83
+ * );
84
+ * }
85
+ *
86
+ * // In components:
87
+ * import { useAuth } from '@djangocfg/api/auth';
88
+ *
89
+ * function MyComponent() {
90
+ * const { user, isAuthenticated } = useAuth();
91
+ * // Auth is automatically available!
92
+ * }
93
+ * ```
94
+ */
95
+ declare function ExtensionProvider({ children, metadata, options }: ExtensionProviderProps): react_jsx_runtime.JSX.Element;
96
+
97
+ export { type CreateExtensionContextOptions, type ExtensionContextReturn, ExtensionProvider, ExtensionProviderProps, createExtensionContext };