@djangocfg/ext-base 1.0.2 → 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 (47) hide show
  1. package/README.md +186 -7
  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 +5 -2
  23. package/src/cli/index.ts +470 -35
  24. package/src/context/ExtensionProvider.tsx +67 -4
  25. package/src/extensionConfig.ts +114 -0
  26. package/src/index.ts +3 -0
  27. package/src/metadata.ts +1 -2
  28. package/src/types/context.ts +21 -15
  29. package/src/utils/createExtensionConfig.ts +34 -18
  30. package/templates/extension-template/README.md.template +37 -5
  31. package/templates/extension-template/package.json.template +13 -5
  32. package/templates/extension-template/playground/.gitignore.template +34 -0
  33. package/templates/extension-template/playground/CLAUDE.md +35 -0
  34. package/templates/extension-template/playground/README.md.template +76 -0
  35. package/templates/extension-template/playground/app/globals.css.template +19 -0
  36. package/templates/extension-template/playground/app/layout.tsx.template +30 -0
  37. package/templates/extension-template/playground/app/page.tsx.template +44 -0
  38. package/templates/extension-template/playground/next.config.ts.template +62 -0
  39. package/templates/extension-template/playground/package.json.template +33 -0
  40. package/templates/extension-template/playground/tsconfig.json.template +27 -0
  41. package/templates/extension-template/src/config.ts +1 -2
  42. package/templates/extension-template/src/contexts/__PROVIDER_NAME__Context.tsx +1 -1
  43. package/templates/extension-template/src/contexts/__PROVIDER_NAME__ExtensionProvider.tsx +1 -0
  44. package/templates/extension-template/src/hooks/index.ts +1 -1
  45. package/templates/extension-template/src/index.ts +12 -4
  46. package/templates/extension-template/src/utils/withSmartProvider.tsx +70 -0
  47. package/templates/extension-template/tsup.config.ts +36 -22
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Global styles for __DISPLAY_NAME__ playground
3
+ * Single entry point for all styles
4
+ *
5
+ * CRITICAL: Import order matters for Tailwind CSS v4!
6
+ * Theme variables MUST come BEFORE @import "tailwindcss"
7
+ */
8
+
9
+ /* 1. Import UI package styles FIRST (contains theme variables) */
10
+ @import "@djangocfg/ui-nextjs/styles";
11
+
12
+ /* 2. Import layouts styles (may contain additional tokens) */
13
+ @import "@djangocfg/layouts/styles";
14
+
15
+ /* 3. Import Tailwind CSS v4 (AFTER theme variables) */
16
+ @import "tailwindcss";
17
+
18
+ /* 4. Load tailwindcss-animate plugin */
19
+ @plugin "tailwindcss-animate";
@@ -0,0 +1,30 @@
1
+ import type { Metadata } from 'next';
2
+ import { Manrope } from 'next/font/google';
3
+ import { BaseApp } from '@djangocfg/layouts';
4
+ import './globals.css';
5
+
6
+ export const metadata: Metadata = {
7
+ title: '__DISPLAY_NAME__ - Development Playground',
8
+ description: 'Development environment for __DISPLAY_NAME__ extension',
9
+ };
10
+
11
+ const manrope = Manrope({
12
+ subsets: ['latin', 'cyrillic'],
13
+ weight: ['400', '500', '600', '700', '800'],
14
+ variable: '--font-manrope',
15
+ display: 'swap',
16
+ });
17
+
18
+ export default function RootLayout({
19
+ children,
20
+ }: Readonly<{
21
+ children: React.ReactNode;
22
+ }>) {
23
+ return (
24
+ <html lang="en" suppressHydrationWarning>
25
+ <body className={manrope.className} style={{ fontFamily: manrope.style.fontFamily }}>
26
+ <BaseApp>{children}</BaseApp>
27
+ </body>
28
+ </html>
29
+ );
30
+ }
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+
3
+ import { __PROVIDER_NAME__Provider } from '__PACKAGE_NAME__';
4
+
5
+ /**
6
+ * Development playground for __DISPLAY_NAME__ extension
7
+ *
8
+ * This page demonstrates how to use the extension in a Next.js application.
9
+ * The extension is wrapped with __PROVIDER_NAME__Provider which provides
10
+ * extension-specific context and state management.
11
+ *
12
+ * BaseApp (from layout.tsx) provides:
13
+ * - Theme support (light/dark mode)
14
+ * - Auth context
15
+ * - SWR configuration
16
+ * - Error tracking
17
+ *
18
+ * To start development:
19
+ * 1. Run `pnpm dev:playground` from the extension root
20
+ * 2. Open http://localhost:3333 in your browser
21
+ * 3. Make changes to src/ files and see them hot-reload
22
+ */
23
+ export default function PlaygroundPage() {
24
+ return (
25
+ <__PROVIDER_NAME__Provider>
26
+ <div style={{ padding: '2rem' }}>
27
+ <h1>__DISPLAY_NAME__ - Development Playground</h1>
28
+ <p>
29
+ This is a development environment for testing the __DISPLAY_NAME__ extension.
30
+ </p>
31
+
32
+ <div style={{ marginTop: '2rem', padding: '1rem', border: '1px solid #ccc', borderRadius: '8px' }}>
33
+ <h2>Add your components here</h2>
34
+ <p>
35
+ Import and render your extension components below to test them.
36
+ </p>
37
+
38
+ {/* TODO: Add your extension components here */}
39
+ {/* Example: <YourComponent /> */}
40
+ </div>
41
+ </div>
42
+ </__PROVIDER_NAME__Provider>
43
+ );
44
+ }
@@ -0,0 +1,62 @@
1
+ import type { NextConfig } from 'next';
2
+ import type { Configuration as WebpackConfig, Compiler } from 'webpack';
3
+
4
+ /**
5
+ * Simple webpack plugin to auto-open browser in dev mode
6
+ */
7
+ class AutoOpenBrowserPlugin {
8
+ private opened = false;
9
+
10
+ apply(compiler: Compiler): void {
11
+ compiler.hooks.done.tap('AutoOpenBrowserPlugin', () => {
12
+ if (!this.opened) {
13
+ this.opened = true;
14
+ this.openBrowser();
15
+ }
16
+ });
17
+ }
18
+
19
+ private openBrowser(): void {
20
+ setTimeout(async () => {
21
+ try {
22
+ const { exec } = await import('child_process');
23
+ const port = process.env.PORT || '3333';
24
+ const url = `http://localhost:${port}`;
25
+
26
+ const command = process.platform === 'darwin'
27
+ ? 'open'
28
+ : process.platform === 'win32'
29
+ ? 'start'
30
+ : 'xdg-open';
31
+
32
+ exec(`${command} ${url}`, (error) => {
33
+ if (error) {
34
+ console.warn(`Failed to open browser: ${error.message}`);
35
+ }
36
+ });
37
+ } catch (error) {
38
+ console.warn('Failed to open browser');
39
+ }
40
+ }, 2000);
41
+ }
42
+ }
43
+
44
+ const nextConfig: NextConfig = {
45
+ reactStrictMode: true,
46
+ transpilePackages: [
47
+ '__PACKAGE_NAME__',
48
+ '@djangocfg/api',
49
+ ],
50
+ webpack: (config: WebpackConfig, { isServer, dev }) => {
51
+ // Auto-open browser in dev mode (client-side only)
52
+ if (dev && !isServer) {
53
+ if (!config.plugins) {
54
+ config.plugins = [];
55
+ }
56
+ config.plugins.push(new AutoOpenBrowserPlugin());
57
+ }
58
+ return config;
59
+ },
60
+ };
61
+
62
+ export default nextConfig;
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "__PACKAGE_NAME__-playground",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "Development playground for __DISPLAY_NAME__ extension",
6
+ "scripts": {
7
+ "predev": "cd .. && pnpm build",
8
+ "prebuild": "cd .. && pnpm build",
9
+ "dev": "next dev --port 3333",
10
+ "build": "next build",
11
+ "start": "next start",
12
+ "ai-docs": "pnpm exec djangocfg-docs"
13
+ },
14
+ "dependencies": {
15
+ "__PACKAGE_NAME__": "workspace:*",
16
+ "@djangocfg/layouts": "workspace:*",
17
+ "@djangocfg/ui-core": "workspace:*",
18
+ "@djangocfg/ui-nextjs": "workspace:*",
19
+ "@djangocfg/nextjs": "workspace:*",
20
+ "@djangocfg/api": "workspace:*",
21
+ "next": "15.5.7",
22
+ "react": "19.2.0",
23
+ "react-dom": "19.2.0",
24
+ "tailwindcss": "^4.1.14",
25
+ "tailwindcss-animate": "^1.0.7"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^24.7.2",
29
+ "@types/react": "^19.2.7",
30
+ "@types/react-dom": "^19.2.3",
31
+ "typescript": "^5.9.3"
32
+ }
33
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./*"]
23
+ }
24
+ },
25
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26
+ "exclude": ["node_modules"]
27
+ }
@@ -8,7 +8,6 @@ import packageJson from '../package.json';
8
8
  export const extensionConfig = createExtensionConfig(packageJson, {
9
9
  name: '__NAME__',
10
10
  displayName: '__DISPLAY_NAME__',
11
- icon: '__ICON__',
12
11
  category: '__CATEGORY__',
13
12
  features: [
14
13
  'Feature 1',
@@ -20,7 +19,7 @@ export const extensionConfig = createExtensionConfig(packageJson, {
20
19
  {
21
20
  title: 'Basic Usage',
22
21
  description: 'How to use this extension',
23
- code: `import { __PROVIDER_NAME__ExtensionProvider } from '@djangocfg/ext-__NAME__/hooks';
22
+ code: `import { __PROVIDER_NAME__ExtensionProvider } from '__PACKAGE_NAME__/hooks';
24
23
 
25
24
  export default function RootLayout({ children }) {
26
25
  return (
@@ -4,7 +4,7 @@
4
4
  * Main __DISPLAY_NAME__ Context
5
5
  */
6
6
 
7
- import { createContext, useContext, type ReactNode } from 'react';
7
+ import React, { createContext, useContext, type ReactNode } from 'react';
8
8
 
9
9
  interface __PROVIDER_NAME__ContextValue {
10
10
  // Add your context values here
@@ -7,6 +7,7 @@
7
7
  'use client';
8
8
 
9
9
  import type { ReactNode } from 'react';
10
+ import React from 'react';
10
11
  import { ExtensionProvider } from '@djangocfg/ext-base/hooks';
11
12
  import { extensionConfig } from '../config';
12
13
  import { __PROVIDER_NAME__Provider } from './__PROVIDER_NAME__Context';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  /**
4
- * @djangocfg/ext-__NAME__/hooks
4
+ * __PACKAGE_NAME__/hooks
5
5
  * React hooks and client-only components
6
6
  *
7
7
  * This entry point includes React components, hooks, and SWR functionality.
@@ -1,9 +1,6 @@
1
1
  /**
2
2
  * @djangocfg/ext-__NAME__
3
- * Server-safe entry point (no client-only code)
4
- *
5
- * Contains types and server-safe exports only.
6
- * For React hooks and SWR, use '@djangocfg/ext-__NAME__/hooks'
3
+ * Main entry point for __DISPLAY_NAME__ extension
7
4
  */
8
5
 
9
6
  // ============================================================================
@@ -15,3 +12,14 @@ export { extensionConfig } from './config';
15
12
  // Types
16
13
  // ============================================================================
17
14
  export type * from './types';
15
+
16
+ // ============================================================================
17
+ // Context & Providers (Client-side)
18
+ // ============================================================================
19
+ export { __PROVIDER_NAME__ExtensionProvider as __PROVIDER_NAME__Provider } from './contexts/__PROVIDER_NAME__ExtensionProvider';
20
+ export { use__PROVIDER_NAME__, use__PROVIDER_NAME__Optional } from './contexts/__PROVIDER_NAME__Context';
21
+
22
+ // ============================================================================
23
+ // Smart Wrapper Utility
24
+ // ============================================================================
25
+ export { withSmartProvider } from './utils/withSmartProvider';
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Smart Provider Wrapper
3
+ *
4
+ * Automatically wraps components with ExtensionProvider only if needed.
5
+ * If provider already exists in parent tree, reuses it.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * // Component is automatically wrapped
10
+ * const SmartComponent = withSmartProvider(MyComponent);
11
+ *
12
+ * // Works standalone
13
+ * <SmartComponent />
14
+ *
15
+ * // Also works with manual provider (shares context)
16
+ * <__PROVIDER_NAME__Provider>
17
+ * <SmartComponent />
18
+ * <SmartComponent />
19
+ * </__PROVIDER_NAME__Provider>
20
+ * ```
21
+ */
22
+
23
+ 'use client';
24
+
25
+ import React, { type ComponentType, type ReactNode } from 'react';
26
+ import { __PROVIDER_NAME__ExtensionProvider } from '../contexts/__PROVIDER_NAME__ExtensionProvider';
27
+ import { use__PROVIDER_NAME__Optional } from '../contexts/__PROVIDER_NAME__Context';
28
+
29
+ /**
30
+ * HOC that wraps a component with smart provider detection
31
+ */
32
+ export function withSmartProvider<P extends object>(
33
+ Component: ComponentType<P>
34
+ ): ComponentType<P> {
35
+ const WrappedComponent = (props: P) => {
36
+ return (
37
+ <SmartProviderWrapper>
38
+ <Component {...props} />
39
+ </SmartProviderWrapper>
40
+ );
41
+ };
42
+
43
+ WrappedComponent.displayName = `withSmartProvider(${Component.displayName || Component.name || 'Component'})`;
44
+
45
+ return WrappedComponent;
46
+ }
47
+
48
+ /**
49
+ * Smart wrapper that only creates provider if not already in tree
50
+ */
51
+ function SmartProviderWrapper({ children }: { children: ReactNode }) {
52
+ const existingContext = use__PROVIDER_NAME__Optional();
53
+
54
+ // Provider already exists higher in tree - just render children
55
+ if (existingContext !== undefined) {
56
+ return <>{children}</>;
57
+ }
58
+
59
+ // No provider found - create one automatically
60
+ return (
61
+ <__PROVIDER_NAME__ExtensionProvider>
62
+ {children}
63
+ </__PROVIDER_NAME__ExtensionProvider>
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Direct component export for manual usage
69
+ */
70
+ export { SmartProviderWrapper };
@@ -1,26 +1,40 @@
1
1
  import { defineConfig } from 'tsup';
2
2
 
3
- export default defineConfig({
4
- entry: {
5
- index: 'src/index.ts',
6
- hooks: 'src/hooks/index.ts',
3
+ export default defineConfig([
4
+ // Config only (server-safe, no React)
5
+ {
6
+ entry: {
7
+ config: 'src/config.ts',
8
+ },
9
+ format: ['cjs', 'esm'],
10
+ dts: true,
11
+ external: ['@djangocfg/ext-base'],
7
12
  },
8
- format: ['esm', 'cjs'],
9
- dts: true,
10
- splitting: false,
11
- sourcemap: true,
12
- clean: true,
13
- external: [
14
- 'react',
15
- 'react-dom',
16
- 'next',
17
- 'lucide-react',
18
- '@djangocfg/ext-base',
19
- '@djangocfg/ui-nextjs',
20
- 'swr',
21
- 'consola',
22
- ],
23
- banner: {
24
- js: "'use client';",
13
+ // Client components
14
+ {
15
+ entry: {
16
+ index: 'src/index.ts',
17
+ hooks: 'src/hooks/index.ts',
18
+ },
19
+ format: ['cjs', 'esm'],
20
+ dts: true,
21
+ clean: false,
22
+ splitting: false,
23
+ sourcemap: true,
24
+ external: [
25
+ 'react',
26
+ 'react-dom',
27
+ 'next',
28
+ 'lucide-react',
29
+ '@djangocfg/ext-base',
30
+ '@djangocfg/ui-nextjs',
31
+ 'swr',
32
+ 'consola',
33
+ ],
34
+ esbuildOptions(options) {
35
+ options.banner = {
36
+ js: '"use client";',
37
+ };
38
+ },
25
39
  },
26
- });
40
+ ]);