diff --git a/examples/django-react-site/backend/testapp/apps.py b/examples/django-react-site/backend/testapp/apps.py index 6988360..6bbdcee 100644 --- a/examples/django-react-site/backend/testapp/apps.py +++ b/examples/django-react-site/backend/testapp/apps.py @@ -6,4 +6,4 @@ class TestAppConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" def ready(self): - import testapp.mizan_clients # noqa: F401 + import testapp.djarea_clients # noqa: F401 diff --git a/examples/django-react-site/harness/package.json b/examples/django-react-site/harness/package.json index 628b659..56b0dfa 100644 --- a/examples/django-react-site/harness/package.json +++ b/examples/django-react-site/harness/package.json @@ -7,7 +7,7 @@ "dev": "vite --port 5174" }, "dependencies": { - "@rythazhur/mizan": "file:../../react", + "@rythazhur/mizan": "file:../../../packages/mizan-react", "react": "^19.0.0", "react-dom": "^19.0.0", "zod": "^4.3.6" diff --git a/examples/django-react-site/harness/src/api/generated.django.server.ts b/examples/django-react-site/harness/src/api/generated.django.server.ts deleted file mode 100644 index 4f54d02..0000000 --- a/examples/django-react-site/harness/src/api/generated.django.server.ts +++ /dev/null @@ -1,62 +0,0 @@ -// AUTO-GENERATED by mizan - do not edit manually -// Regenerate with: npm run schemas -// -// Server-side functions for SSR hydration. -// These run in Next.js server components/layouts. - -import type { currentUserOutput, greetOutput } from './generated.mizan' - -// ============================================================================ -// Hydration Types -// ============================================================================ - -/** Typed hydration data for SSR */ -export interface DjangoHydration { - currentUser?: currentUserOutput - greet?: greetOutput -} - -// ============================================================================ -// SSR Hydration Helper -// ============================================================================ - -/** - * Fetch hydration data for SSR. - * - * Call this in your server component: - * const hydration = await getDjangoHydration(client) - * return ... - */ -export async function getDjangoHydration( - client: { request: (method: string, url: string, body?: unknown) => Promise } -): Promise { - const hydration: DjangoHydration = {} - - const results = await Promise.allSettled([ - client.request('POST', '/api/mizan/call/', { fn: 'current_user', args: {} }), - client.request('POST', '/api/mizan/call/', { fn: 'greet', args: {} }), - ]) - - if (results[0].status === 'fulfilled') { - const data = await (results[0] as PromiseFulfilledResult).value.json() - if (data.error) { - console.error('[getDjangoHydration] current_user failed:', data.code, data.message) - } else { - hydration.currentUser = data.data - } - } else { - console.error('[getDjangoHydration] current_user request failed:', (results[0] as PromiseRejectedResult).reason) - } - if (results[1].status === 'fulfilled') { - const data = await (results[1] as PromiseFulfilledResult).value.json() - if (data.error) { - console.error('[getDjangoHydration] greet failed:', data.code, data.message) - } else { - hydration.greet = data.data - } - } else { - console.error('[getDjangoHydration] greet request failed:', (results[1] as PromiseRejectedResult).reason) - } - - return hydration -} diff --git a/examples/django-react-site/harness/src/api/generated.django.tsx b/examples/django-react-site/harness/src/api/generated.django.tsx deleted file mode 100644 index d672dff..0000000 --- a/examples/django-react-site/harness/src/api/generated.django.tsx +++ /dev/null @@ -1,257 +0,0 @@ -'use client' - -// AUTO-GENERATED by mizan - do not edit manually -// Regenerate with: npm run schemas - -// This file provides typed wrappers around the mizan library. -// - DjangoContext: Typed provider wrapping mizanProvider -// - Typed hooks: useAuthStatus(), useUser(), etc. - -import { type ReactNode, useCallback } from 'react' -import { - mizanProvider, - usemizan, - usemizanContext, - usemizanCall, - type mizanHydration, - type Transport, -} from 'mizan' -import { ChannelProvider, ChannelConnection } from 'mizan/channels' -import { useRef } from 'react' - -import type { addEmailSchemaOutput, addEmailValidateInput, addEmailValidateOutput, addInput, addOutput, buggyFnOutput, contactSchemaInput, contactSchemaOutput, contactSubmitOutput, contactValidateInput, contactValidateOutput, currentUserOutput, echoInput, echoOutput, greetInput, greetOutput, httpOnlyEchoInput, httpOnlyEchoOutput, itemFormsetSchemaInput, itemFormsetSchemaOutput, itemFormsetSubmitInput, itemFormsetSubmitOutput, itemFormsetValidateInput, itemFormsetValidateOutput, itemSchemaInput, itemSchemaOutput, itemSubmitOutput, itemValidateInput, itemValidateOutput, jwtObtainOutput, jwtRefreshInput, jwtRefreshOutput, loginSchemaOutput, loginSubmitInput, loginSubmitOutput, loginValidateInput, loginValidateOutput, multiplyInput, multiplyOutput, notImplementedFnOutput, permissionCheckFnInput, permissionCheckFnOutput, signupSchemaOutput, signupSubmitInput, signupSubmitOutput, signupValidateInput, signupValidateOutput, staffOnlyOutput, superuserOnlyOutput, verifiedOnlyOutput, whoamiOutput, wsWhoamiOutput } from './generated.mizan' - -// ============================================================================ -// Hydration Types -// ============================================================================ - -/** Typed hydration data for SSR */ -export interface DjangoHydration { - currentUser?: currentUserOutput - greet?: greetOutput -} - -/** Convert typed hydration to mizan format */ -function tomizanHydration(hydration?: DjangoHydration): mizanHydration | undefined { - if (!hydration) return undefined - const result: mizanHydration = {} - if (hydration.currentUser !== undefined) result['current_user'] = hydration.currentUser - if (hydration.greet !== undefined) result['greet'] = hydration.greet - return result -} - -// ============================================================================ -// Provider -// ============================================================================ - -export interface DjangoContextProps { - children: ReactNode - /** SSR hydration data */ - hydration?: DjangoHydration - /** WebSocket URL for RPC calls (default: /ws/) */ - wsUrl?: string - /** Base URL for HTTP fallback (default: /api/mizan) */ - baseUrl?: string -} - -/** - * Typed Django context provider. - * - * Wraps mizanProvider with: - * - Typed hydration - * - Auto-fetch for registered contexts - * - * Usage: - * - * - * - */ -export function DjangoContext({ - children, - hydration, - wsUrl, - baseUrl, -}: DjangoContextProps) { - const connectionRef = useRef(null) - if (!connectionRef.current) { - connectionRef.current = new ChannelConnection({ url: wsUrl || '/ws/' }) - } - - return ( - - - {children} - - - ) -} - -// ============================================================================ -// Context Hooks (typed wrappers) -// ============================================================================ - -/** - * Get current_user context data. - * @throws if context not loaded yet - */ -export function useCurrentUser(): currentUserOutput { - const data = usemizanContext('current_user') - if (data === undefined) { - throw new Error('useCurrentUser: context not loaded yet') - } - return data -} - -/** - * Get greet context data. - * @throws if context not loaded yet - */ -export function useGreet(): greetOutput { - const data = usemizanContext('greet') - if (data === undefined) { - throw new Error('useGreet: context not loaded yet') - } - return data -} - -/** - * Get context refresh functions without subscribing to data changes. - * Use this in components that only need to trigger refreshes. - */ -export function useDjangoRefresh() { - const { refreshContext, refreshAllContexts } = usemizan() - return { - refreshCurrentUser: () => refreshContext('current_user'), - refreshGreet: () => refreshContext('greet'), - refreshAll: refreshAllContexts, - } -} - -// ============================================================================ -// Function Hooks (typed wrappers) -// ============================================================================ - -/** - * Call echo server function. - * Transport: websocket - */ -export function useEcho() { - return usemizanCall('echo', 'websocket') -} - -/** - * Call add server function. - * Transport: websocket - */ -export function useAdd() { - return usemizanCall('add', 'websocket') -} - -/** - * Call whoami server function. - * Transport: http - */ -export function useWhoami() { - return usemizanCall('whoami', 'http') -} - -/** - * Call http_only_echo server function. - * Transport: http - */ -export function useHttpOnlyEcho() { - return usemizanCall('http_only_echo', 'http') -} - -/** - * Call staff_only server function. - * Transport: http - */ -export function useStaffOnly() { - return usemizanCall('staff_only', 'http') -} - -/** - * Call superuser_only server function. - * Transport: http - */ -export function useSuperuserOnly() { - return usemizanCall('superuser_only', 'http') -} - -/** - * Call verified_only server function. - * Transport: http - */ -export function useVerifiedOnly() { - return usemizanCall('verified_only', 'http') -} - -/** - * Call multiply server function. - * Transport: http - */ -export function useMultiply() { - return usemizanCall('multiply', 'http') -} - -/** - * Call not_implemented_fn server function. - * Transport: http - */ -export function useNotImplementedFn() { - return usemizanCall('not_implemented_fn', 'http') -} - -/** - * Call buggy_fn server function. - * Transport: http - */ -export function useBuggyFn() { - return usemizanCall('buggy_fn', 'http') -} - -/** - * Call permission_check_fn server function. - * Transport: http - */ -export function usePermissionCheckFn() { - return usemizanCall('permission_check_fn', 'http') -} - -/** - * Call ws_whoami server function. - * Transport: websocket - */ -export function useWsWhoami() { - return usemizanCall('ws_whoami', 'websocket') -} - -/** - * Call jwt_obtain server function. - * Transport: http - */ -export function useJwtObtain() { - return usemizanCall('jwt_obtain', 'http') -} - -/** - * Call jwt_refresh server function. - * Transport: http - */ -export function useJwtRefresh() { - return usemizanCall('jwt_refresh', 'http') -} - -// ============================================================================ -// Re-exports from mizan library -// ============================================================================ - -export { usemizan, usemizanStatus, usePush, DjangoError } from 'mizan' -export type { ConnectionStatus, PushMessage, PushListener } from 'mizan' diff --git a/examples/django-react-site/harness/src/api/generated.forms.ts b/examples/django-react-site/harness/src/api/generated.forms.ts index ed05078..bec9816 100644 --- a/examples/django-react-site/harness/src/api/generated.forms.ts +++ b/examples/django-react-site/harness/src/api/generated.forms.ts @@ -192,7 +192,7 @@ export function useItemFormset( // Form Registry // ============================================================================ -export const DJANGO_FORMS = { +export const MIZAN_FORMS = { login: { name: 'login', schema: LoginSchema, diff --git a/examples/django-react-site/harness/src/api/index.ts b/examples/django-react-site/harness/src/api/index.ts index a7dbf09..c0bb864 100644 --- a/examples/django-react-site/harness/src/api/index.ts +++ b/examples/django-react-site/harness/src/api/index.ts @@ -6,11 +6,10 @@ * @example * ```tsx * import { - * DjangoContext, - * useUser, + * MizanContext, + * useCurrentUser, * useEcho, * useChatChannel, - * DjangoError, * } from '@/api' * ``` */ @@ -23,22 +22,30 @@ // ============================================================================= export { + getMizanHydration, getDjangoHydration, + type MizanHydrationData, type DjangoHydration, -} from './generated.django.server' +} from './generated.server' export { // Provider + MizanContext, + type MizanContextProps, DjangoContext, type DjangoContextProps, - // Context hooks + // Global context hooks useCurrentUser, - useGreet, // Refresh hooks + useMizanRefresh, useDjangoRefresh, + // Named context providers + LocalContext, + useGreet, + // Function hooks useEcho, useAdd, @@ -56,14 +63,14 @@ export { useJwtRefresh, // Re-exports from mizan library - usemizan, - usemizanStatus, + useMizan, + useMizanStatus, usePush, DjangoError, type ConnectionStatus, type PushMessage, type PushListener, -} from './generated.django' +} from './generated.provider' // ============================================================================= // Channel Hooks diff --git a/examples/django-react-site/harness/src/fixtures.tsx b/examples/django-react-site/harness/src/fixtures.tsx index 86d9d5b..04fe4ea 100644 --- a/examples/django-react-site/harness/src/fixtures.tsx +++ b/examples/django-react-site/harness/src/fixtures.tsx @@ -11,7 +11,7 @@ import { useState, useEffect, useRef } from 'react' // Generated typed hooks — the actual mizan API import { - DjangoContext, + MizanContext, useEcho, useAdd, useMultiply, @@ -25,9 +25,9 @@ import { useCurrentUser, DjangoError, useMizan, -} from './api/generated.django' + useChatChannel, +} from './api' import { useContactForm, useLoginForm } from './api/generated.forms' -import { useChatChannel } from './api/generated.channels.hooks' // ─── Fixture router ───────────────────────────────────────────────────────── @@ -228,7 +228,7 @@ function FormContactSubmit() { // ─── Channel fixtures ─────────────────────────────────────────────────────── function ChannelChatFixture() { - // DjangoContext already includes ChannelProvider + // MizanContext already includes ChannelProvider return } diff --git a/examples/django-react-site/harness/src/main.tsx b/examples/django-react-site/harness/src/main.tsx index eecd4c8..edcb61f 100644 --- a/examples/django-react-site/harness/src/main.tsx +++ b/examples/django-react-site/harness/src/main.tsx @@ -1,12 +1,12 @@ import { createRoot } from 'react-dom/client' -import { DjangoContext } from './api/generated.django' +import { MizanContext } from './api' import { Fixtures } from './fixtures' function App() { return ( - + - + ) } diff --git a/packages/mizan-django/generate/generator/lib/fetch.mjs b/packages/mizan-django/generate/generator/lib/fetch.mjs index 8884e3e..78e7aff 100644 --- a/packages/mizan-django/generate/generator/lib/fetch.mjs +++ b/packages/mizan-django/generate/generator/lib/fetch.mjs @@ -84,5 +84,5 @@ export async function fetchMizanSchema(source, cwd) { if (!source.django) { throw new Error('mizan schema export requires django source configuration') } - return runDjangoCommand(source, cwd, 'export_mizan_schema') + return runDjangoCommand(source, cwd, 'export_djarea_schema') } diff --git a/packages/mizan-django/generate/package.json b/packages/mizan-django/generate/package.json new file mode 100644 index 0000000..53545a8 --- /dev/null +++ b/packages/mizan-django/generate/package.json @@ -0,0 +1,16 @@ +{ + "name": "generate", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "commonjs", + "dependencies": { + "openapi-typescript": "^7.13.0" + } +}