@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.
- package/README.md +186 -7
- package/dist/api.cjs +40 -0
- package/dist/api.d.cts +35 -0
- package/dist/api.d.ts +35 -0
- package/dist/api.js +2 -0
- package/dist/auth.cjs +10 -0
- package/dist/auth.d.cts +1 -0
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +2 -0
- package/dist/chunk-3RG5ZIWI.js +8 -0
- package/dist/chunk-UXTBBEO5.js +237 -0
- package/dist/chunk-VJEGYVBV.js +140 -0
- package/dist/cli.mjs +530 -0
- package/dist/hooks.cjs +437 -0
- package/dist/hooks.d.cts +97 -0
- package/dist/hooks.d.ts +97 -0
- package/dist/hooks.js +95 -0
- package/dist/index.cjs +345 -0
- package/dist/index.d.cts +363 -0
- package/dist/index.d.ts +363 -0
- package/dist/index.js +3 -0
- package/package.json +5 -2
- package/src/cli/index.ts +470 -35
- package/src/context/ExtensionProvider.tsx +67 -4
- package/src/extensionConfig.ts +114 -0
- package/src/index.ts +3 -0
- package/src/metadata.ts +1 -2
- package/src/types/context.ts +21 -15
- package/src/utils/createExtensionConfig.ts +34 -18
- package/templates/extension-template/README.md.template +37 -5
- package/templates/extension-template/package.json.template +13 -5
- package/templates/extension-template/playground/.gitignore.template +34 -0
- package/templates/extension-template/playground/CLAUDE.md +35 -0
- package/templates/extension-template/playground/README.md.template +76 -0
- package/templates/extension-template/playground/app/globals.css.template +19 -0
- package/templates/extension-template/playground/app/layout.tsx.template +30 -0
- package/templates/extension-template/playground/app/page.tsx.template +44 -0
- package/templates/extension-template/playground/next.config.ts.template +62 -0
- package/templates/extension-template/playground/package.json.template +33 -0
- package/templates/extension-template/playground/tsconfig.json.template +27 -0
- package/templates/extension-template/src/config.ts +1 -2
- package/templates/extension-template/src/contexts/__PROVIDER_NAME__Context.tsx +1 -1
- package/templates/extension-template/src/contexts/__PROVIDER_NAME__ExtensionProvider.tsx +1 -0
- package/templates/extension-template/src/hooks/index.ts +1 -1
- package/templates/extension-template/src/index.ts +12 -4
- package/templates/extension-template/src/utils/withSmartProvider.tsx +70 -0
- 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 '
|
|
22
|
+
code: `import { __PROVIDER_NAME__ExtensionProvider } from '__PACKAGE_NAME__/hooks';
|
|
24
23
|
|
|
25
24
|
export default function RootLayout({ children }) {
|
|
26
25
|
return (
|
|
@@ -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,9 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @djangocfg/ext-__NAME__
|
|
3
|
-
*
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
'
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
+
]);
|