frontend-hamroun 1.2.80 → 1.2.82
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/bin/cli.js +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/basic-app/src/App.jsx +16 -0
- package/templates/basic-app/src/client.jsx +5 -0
- package/templates/basic-app/src/components/Counter.jsx +13 -0
- package/templates/basic-app/src/jsx-shim.js +3 -0
- package/templates/basic-app/src/jsx-shim.ts +7 -0
- package/templates/basic-app/src/main.jsx +98 -0
- package/templates/basic-app/src/server.js +47 -0
- package/templates/complete-app/api/hello.js +0 -0
- package/templates/complete-app/lib/frontend-hamroun.js +182 -0
- package/templates/complete-app/package.json +18 -0
- package/templates/complete-app/pages/about.js +119 -0
- package/templates/complete-app/pages/about.jsx +0 -0
- package/templates/complete-app/pages/index.js +157 -0
- package/templates/complete-app/pages/index.jsx +0 -0
- package/templates/complete-app/pages/wasm-demo.js +290 -0
- package/templates/complete-app/pages/wasm-demo.jsx +0 -0
- package/templates/complete-app/public/client.js +89 -0
- package/templates/complete-app/public/index.html +118 -0
- package/templates/complete-app/public/styles.css +76 -0
- package/templates/complete-app/server.js +226 -0
- package/templates/complete-app/src/App.tsx +59 -0
- package/templates/complete-app/src/client.tsx +18 -0
- package/templates/complete-app/src/server.ts +218 -0
- package/templates/complete-app/tsconfig.json +22 -0
- package/templates/complete-app/tsconfig.server.json +19 -0
- package/templates/{ssr-template → complete-app}/vite.config.js +16 -5
- package/templates/complete-app/vite.config.ts +30 -0
- package/templates/complete-app/wasm/build.bat +0 -0
- package/templates/complete-app/wasm/build.sh +0 -0
- package/templates/complete-app/wasm/example.go +0 -0
- package/templates/fullstack-app/build/main.css +874 -874
- package/templates/fullstack-app/build/main.css.map +7 -7
- package/templates/fullstack-app/build/main.js +996 -967
- package/templates/fullstack-app/build/main.js.map +7 -7
- package/templates/fullstack-app/package-lock.json +6301 -0
- package/templates/fullstack-app/public/styles.css +768 -768
- package/templates/go/example.go +154 -99
- package/templates/ssr-template/esbuild.config.js +33 -0
- package/templates/ssr-template/jsx-shim.js +1 -0
- package/templates/ssr-template/package.json +22 -16
- package/templates/ssr-template/src/App.tsx +12 -52
- package/templates/ssr-template/src/client.tsx +3 -17
- package/templates/ssr-template/src/server.ts +21 -204
- package/templates/ssr-template/tsconfig.json +10 -13
- package/templates/ssr-template/tsconfig.server.json +6 -14
- package/templates/wasm/build-wasm.js +228 -0
- package/templates/wasm/esbuild.config.js +63 -0
- package/templates/wasm/go/main.go +256 -0
- package/templates/wasm/go/wasm_exec.js +0 -0
- package/templates/wasm/index.html +97 -0
- package/templates/wasm/jsx-shim.js +9 -0
- package/templates/wasm/package-lock.json +5307 -0
- package/templates/wasm/package.json +42 -0
- package/templates/wasm/public/example.wasm +0 -0
- package/templates/{go-wasm-app/public/wasm → wasm/public}/wasm_exec.js +561 -561
- package/templates/wasm/src/App.tsx +564 -0
- package/templates/wasm/src/client.tsx +220 -0
- package/templates/wasm/src/index.tsx +21 -0
- package/templates/wasm/src/server.ts +145 -0
- package/templates/wasm/tsconfig.json +21 -0
- package/templates/wasm/tsconfig.node.json +13 -0
- package/templates/wasm/tsconfig.server.json +23 -0
- package/templates/wasm/vite.config.ts +56 -0
- package/templates/wasm/wasm-loader.js +103 -0
- package/templates/basic-app/bun.lock +0 -196
- package/templates/basic-app/docs/rapport_pfe.aux +0 -27
- package/templates/basic-app/docs/rapport_pfe.out +0 -10
- package/templates/basic-app/docs/rapport_pfe.pdf +0 -0
- package/templates/basic-app/docs/rapport_pfe.tex +0 -68
- package/templates/basic-app/docs/rapport_pfe.toc +0 -14
- package/templates/basic-app/package-lock.json +0 -4185
- package/templates/go-wasm-app/README.md +0 -38
- package/templates/go-wasm-app/babel.config.js +0 -15
- package/templates/go-wasm-app/build-client.js +0 -49
- package/templates/go-wasm-app/build-wasm.js +0 -237
- package/templates/go-wasm-app/package.json +0 -23
- package/templates/go-wasm-app/public/index.html +0 -128
- package/templates/go-wasm-app/public/styles.css +0 -197
- package/templates/go-wasm-app/public/wasm/example.wasm +0 -0
- package/templates/go-wasm-app/public/wasm/wasm_exec_node.js +0 -39
- package/templates/go-wasm-app/server.js +0 -521
- package/templates/go-wasm-app/src/App.jsx +0 -38
- package/templates/go-wasm-app/src/app.js +0 -153
- package/templates/go-wasm-app/src/client.js +0 -57
- package/templates/go-wasm-app/src/components/Footer.jsx +0 -13
- package/templates/go-wasm-app/src/components/Header.jsx +0 -19
- package/templates/go-wasm-app/src/components/WasmDemo.jsx +0 -120
- package/templates/go-wasm-app/src/main.jsx +0 -12
- package/templates/go-wasm-app/src/wasm/example.go +0 -75
- package/templates/go-wasm-app/tsconfig.server.json +0 -18
- package/templates/go-wasm-app/vite.config.js +0 -34
- package/templates/ssr-template/package-lock.json +0 -2478
- package/templates/ssr-template/public/index.html +0 -47
- package/templates/ssr-template/server.js +0 -369
- /package/templates/{ssr-template → complete-app}/client.js +0 -0
- /package/templates/{ssr-template → complete-app}/readme.md +0 -0
- /package/templates/{ssr-template → complete-app}/server.ts +0 -0
- /package/templates/{ssr-template → complete-app}/src/client.ts +0 -0
- /package/templates/{ssr-template → complete-app}/src/pages/index.tsx +0 -0
package/bin/cli.js
CHANGED
package/dist/index.cjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/wasm.ts","../src/vdom.ts","../src/component.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Go WebAssembly Integration Utilities\r\n * \r\n * This module provides tools for loading and interacting with Go WASM modules\r\n * in browser and server environments.\r\n */\r\n\r\n// Type definitions for Go WASM integration\r\nexport interface GoWasmInstance {\r\n instance: WebAssembly.Instance;\r\n module: WebAssembly.Module;\r\n exports: any;\r\n functions: Record<string, Function>;\r\n}\r\n\r\nexport interface GoWasmOptions {\r\n importObject?: WebAssembly.Imports;\r\n goWasmPath?: string;\r\n loadGo?: boolean;\r\n onLoad?: (instance: GoWasmInstance) => void;\r\n debug?: boolean;\r\n}\r\n\r\nconst DEFAULT_GO_WASM_PATH = '/wasm_exec.js';\r\n\r\n/**\r\n * Load a Go WASM module from a URL\r\n */\r\nexport async function loadGoWasm(\r\n wasmUrl: string, \r\n options: GoWasmOptions = {}\r\n): Promise<GoWasmInstance> {\r\n const {\r\n importObject = {},\r\n goWasmPath = DEFAULT_GO_WASM_PATH,\r\n loadGo = true,\r\n onLoad,\r\n debug = false\r\n } = options;\r\n\r\n // In browser environment, load the Go WASM runtime\r\n if (typeof window !== 'undefined' && loadGo) {\r\n await loadGoRuntime(goWasmPath);\r\n }\r\n\r\n try {\r\n // Create Go instance for WASM\r\n // @ts-ignore - Go is loaded from the global scope\r\n const go = typeof Go !== 'undefined' ? new Go() : null;\r\n \r\n // Fetch and instantiate the WASM module\r\n if (debug) console.log(`[WASM] Loading module from ${wasmUrl}`);\r\n \r\n const response = await fetch(wasmUrl);\r\n \r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch WASM module: ${response.statusText}`);\r\n }\r\n \r\n const buffer = await response.arrayBuffer();\r\n const module = await WebAssembly.compile(buffer);\r\n \r\n // Create imports object, combining Go runtime with custom imports\r\n const finalImportObject = go ? {\r\n ...go.importObject,\r\n ...importObject\r\n } : importObject;\r\n \r\n // Instantiate the WASM module\r\n const instance = await WebAssembly.instantiate(module, finalImportObject);\r\n \r\n // Initialize Go runtime if available\r\n if (go) {\r\n go.run(instance);\r\n }\r\n \r\n // Extract exported functions\r\n const exports = instance.exports;\r\n const functions: Record<string, Function> = {};\r\n \r\n // Generate wrapper functions for all exports that are functions\r\n for (const key in exports) {\r\n if (typeof exports[key] === 'function') {\r\n // Type assertion to ensure the exports[key] is callable\r\n const exportedFn = exports[key] as unknown as Function;\r\n functions[key] = (...args: any[]) => exportedFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n\r\n // Add any globally exported functions from Go\r\n if (typeof window !== 'undefined') {\r\n for (const key in window) {\r\n if (key.startsWith('go') && typeof (window as any)[key] === 'function') {\r\n // Type assertion to ensure the window[key] is callable\r\n const globalFn = (window as any)[key] as Function;\r\n functions[key] = (...args: any[]) => globalFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling global ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n }\r\n \r\n const wasmInstance: GoWasmInstance = {\r\n instance,\r\n module,\r\n exports,\r\n functions\r\n };\r\n \r\n // Run onLoad callback if provided\r\n if (onLoad) {\r\n onLoad(wasmInstance);\r\n }\r\n \r\n return wasmInstance;\r\n } catch (error) {\r\n console.error('[WASM] Failed to load Go WASM module:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load the Go WASM runtime script\r\n */\r\nasync function loadGoRuntime(path: string = DEFAULT_GO_WASM_PATH): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n \r\n // Check if Go runtime is already loaded\r\n if (typeof (window as any).Go !== 'undefined') {\r\n return;\r\n }\r\n \r\n // Load the Go WASM runtime script\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = path;\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error(`Failed to load Go WASM runtime from ${path}`));\r\n document.head.appendChild(script);\r\n });\r\n}\r\n\r\n/**\r\n * Create a TypeScript-friendly wrapper for Go WASM functions\r\n */\r\nexport function createTypedWasmFunction<T extends (...args: any[]) => any>(\r\n instance: GoWasmInstance,\r\n functionName: string\r\n): T {\r\n if (!instance.functions[functionName]) {\r\n throw new Error(`WASM function \"${functionName}\" not found`);\r\n }\r\n \r\n return instance.functions[functionName] as T;\r\n}\r\n\r\n/**\r\n * Helper to convert JavaScript values to Go-compatible formats\r\n */\r\nexport const goValues = {\r\n // Convert JS string to Go string (returns memory pointer)\r\n stringToGo: (instance: GoWasmInstance, str: string): number => {\r\n if (!instance.functions.__stringToGo) {\r\n throw new Error('__stringToGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringToGo(str);\r\n },\r\n \r\n // Convert Go string (memory pointer) to JS string\r\n stringFromGo: (instance: GoWasmInstance, ptr: number): string => {\r\n if (!instance.functions.__stringFromGo) {\r\n throw new Error('__stringFromGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringFromGo(ptr);\r\n },\r\n \r\n // Convert JS object to Go (returns memory pointer)\r\n objectToGo: (instance: GoWasmInstance, obj: any): number => {\r\n if (!instance.functions.__objectToGo) {\r\n throw new Error('__objectToGo function not found in WASM module');\r\n }\r\n return instance.functions.__objectToGo(JSON.stringify(obj));\r\n },\r\n \r\n // Convert Go object (memory pointer) to JS object\r\n objectFromGo: (instance: GoWasmInstance, ptr: number): any => {\r\n if (!instance.functions.__objectFromGo) {\r\n throw new Error('__objectFromGo function not found in WASM module');\r\n }\r\n const str = instance.functions.__objectFromGo(ptr);\r\n return JSON.parse(str);\r\n }\r\n};\r\n","interface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n key?: string | number;\r\n}\r\n\r\nfunction arePropsEqual(oldProps: any, newProps: any): boolean {\r\n const oldKeys = Object.keys(oldProps).filter(k => k !== 'children');\r\n const newKeys = Object.keys(newProps).filter(k => k !== 'children');\r\n \r\n if (oldKeys.length !== newKeys.length) return false;\r\n return oldKeys.every(key => oldProps[key] === newProps[key]);\r\n}\r\n\r\nexport function diff(oldNode: VNode | any, newNode: VNode | any): boolean {\r\n if (oldNode == null || newNode == null) return oldNode !== newNode;\r\n if (typeof oldNode !== typeof newNode) return true;\r\n if (typeof newNode === 'string' || typeof newNode === 'number')\r\n return oldNode !== newNode;\r\n if (newNode.type !== oldNode.type) return true;\r\n return !arePropsEqual(oldNode.props, newNode.props);\r\n}\r\n\r\nexport function shouldComponentUpdate(oldProps: any, newProps: any): boolean {\r\n return !arePropsEqual(oldProps, newProps);\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\n\r\nexport class Component {\r\n state: any = {};\r\n props: any;\r\n element: HTMLElement | null = null;\r\n private _mounted: boolean = false;\r\n\r\n constructor(props: any = {}) {\r\n this.props = props;\r\n }\r\n\r\n componentDidMount() {\r\n // Hook for after component is mounted\r\n }\r\n\r\n async setState(newState: any) {\r\n const prevState = { ...this.state };\r\n this.state = { ...prevState, ...newState };\r\n console.log(`${this.constructor.name} state updated:`, {\r\n prev: prevState,\r\n next: this.state\r\n });\r\n \r\n await Promise.resolve(); // Ensure state is updated before re-render\r\n if (this._mounted) {\r\n await this.update();\r\n } else {\r\n await this.update();\r\n }\r\n }\r\n\r\n private _replayEvents(oldElement: HTMLElement, newElement: HTMLElement) {\r\n const oldEvents = (oldElement as any).__events || {};\r\n Object.entries(oldEvents).forEach(([event, handler]) => {\r\n newElement.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n (newElement as any).__events = oldEvents;\r\n }\r\n\r\n private _deepCloneWithEvents(node: HTMLElement): HTMLElement {\r\n const clone = node.cloneNode(false) as HTMLElement;\r\n \r\n // Copy events from original element\r\n const events = (node as any).__events || {};\r\n (clone as any).__events = events;\r\n Object.entries(events).forEach(([event, handler]) => {\r\n clone.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n\r\n // Clone children\r\n Array.from(node.childNodes).forEach(child => {\r\n if (child instanceof HTMLElement) {\r\n clone.appendChild(this._deepCloneWithEvents(child));\r\n } else {\r\n clone.appendChild(child.cloneNode(true));\r\n }\r\n });\r\n\r\n return clone;\r\n }\r\n\r\n async update() {\r\n const vdom = this.render();\r\n if (!vdom) return document.createTextNode('');\r\n \r\n const rendered = await createElement(vdom);\r\n if (rendered instanceof HTMLElement) {\r\n return this._updateElement(rendered);\r\n }\r\n \r\n const wrapper = document.createElement('div');\r\n wrapper.appendChild(rendered);\r\n return this._updateElement(wrapper);\r\n }\r\n\r\n private async _updateElement(rendered: HTMLElement) {\r\n const newElement = this._deepCloneWithEvents(rendered);\r\n (newElement as any).__instance = this;\r\n \r\n if (!this.element) {\r\n this.element = newElement;\r\n if (!this._mounted) {\r\n this._mounted = true;\r\n queueMicrotask(() => this.componentDidMount());\r\n }\r\n } else if (this.element.parentNode) {\r\n this.element.parentNode.replaceChild(newElement, this.element);\r\n this.element = newElement;\r\n }\r\n \r\n return this.element;\r\n }\r\n\r\n render(): any {\r\n throw new Error('Component must implement render() method');\r\n }\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks.js';\r\nimport { \r\n loadGoWasm as loadGoWasmImpl, \r\n createTypedWasmFunction as createTypedWasmFunctionImpl,\r\n goValues as goValuesImpl,\r\n type GoWasmInstance,\r\n type GoWasmOptions\r\n} from './wasm.js';\r\n\r\n// Import items needed for the default export\r\nimport { jsx, jsxs, jsxDEV, Fragment } from './jsx-runtime.js';\r\nimport { render, hydrate } from './renderer.js';\r\nimport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary\r\n} from './hooks.js';\r\nimport { createContext } from './context.js';\r\nimport { renderToString } from './server-renderer.js';\r\nimport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\nimport { diff, shouldComponentUpdate } from './vdom.js';\r\nimport { Component } from './component.js';\r\n\r\n// Re-export core modules with explicit names to ensure they appear in bundle\r\nexport { render, hydrate } from './renderer.js';\r\nexport { \r\n jsx, \r\n jsxs, \r\n jsxDEV,\r\n Fragment, \r\n createElement \r\n} from './jsx-runtime.js';\r\n\r\nexport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary,\r\n prepareRender,\r\n finishRender,\r\n setRenderCallback\r\n} from './hooks.js';\r\n\r\n// Context API\r\nexport { createContext } from './context.js';\r\n\r\n// Server-side rendering\r\nexport { renderToString } from './server-renderer.js';\r\n\r\n// Batch updates utility\r\nexport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\n\r\n// VDOM utilities\r\nexport { diff, shouldComponentUpdate } from './vdom.js';\r\n\r\n// Export Component class\r\nexport { Component } from './component.js';\r\n\r\n// Server module stub for browser environments\r\nexport const server = {\r\n async getServer() {\r\n throw new Error(\"Server module can only be used in Node.js environment\");\r\n }\r\n};\r\n\r\n// Export WASM functionality explicitly\r\nexport const loadGoWasm = loadGoWasmImpl;\r\nexport const createTypedWasmFunction = createTypedWasmFunctionImpl;\r\nexport const goValues = goValuesImpl;\r\nexport type { GoWasmInstance, GoWasmOptions } from './wasm.js';\r\n\r\n// Add wasm object to ensure compatibility with existing dist/index.js\r\nexport const wasm = {\r\n loadGoWasm: loadGoWasmImpl,\r\n createTypedWasmFunction: createTypedWasmFunctionImpl,\r\n goValues: goValuesImpl\r\n};\r\n\r\n// Re-export types\r\nexport type { Context } from './context.js';\r\nexport type { VNode } from './types.js';\r\n\r\n// Export server types from the safe type-only file\r\nexport type { \r\n Server, \r\n ServerConfig, \r\n User, \r\n DbConfig, \r\n MiddlewareFunction \r\n} from './server-types.js';\r\n\r\n// Export this so it can be properly identified in the bundle\r\nexport let isHydrating = false;\r\nimport { AuthService } from './server/auth.js';\r\n// Default export for compatibility with some module systems\r\nexport default {\r\n Fragment: Fragment,\r\n jsx: jsx,\r\n jsxs: jsxs,\r\n createElement: createElement,\r\n render: render, \r\n hydrate: hydrate,\r\n useState: useState,\r\n useEffect: useEffect,\r\n useMemo: useMemo,\r\n useRef: useRef,\r\n useContext: useContext,\r\n useErrorBoundary: useErrorBoundary,\r\n createContext: createContext,\r\n renderToString: renderToString,\r\n batchUpdates: batchUpdates,\r\n server: server,\r\n loadGoWasm: loadGoWasm,\r\n createTypedWasmFunction: createTypedWasmFunction,\r\n goValues: goValues,\r\n wasm: wasm,\r\n Component: Component,\r\n diff: diff,\r\n shouldComponentUpdate: shouldComponentUpdate\r\n};\r\n"],"names":["DEFAULT_GO_WASM_PATH","async","loadGoWasm","wasmUrl","options","importObject","goWasmPath","loadGo","onLoad","debug","window","path","Go","Promise","resolve","reject","script","document","createElement","src","onload","onerror","Error","head","appendChild","loadGoRuntime","go","console","log","response","fetch","ok","statusText","buffer","arrayBuffer","module","WebAssembly","compile","finalImportObject","instance","instantiate","run","exports","functions","key","exportedFn","args","originalFn","join","result","startsWith","globalFn","wasmInstance","error","createTypedWasmFunction","functionName","goValues","stringToGo","str","__stringToGo","stringFromGo","ptr","__stringFromGo","objectToGo","obj","__objectToGo","JSON","stringify","objectFromGo","__objectFromGo","parse","arePropsEqual","oldProps","newProps","oldKeys","Object","keys","filter","k","newKeys","length","every","diff","oldNode","newNode","type","props","shouldComponentUpdate","Component","constructor","this","state","element","_mounted","componentDidMount","setState","newState","prevState","name","prev","next","update","_replayEvents","oldElement","newElement","oldEvents","__events","entries","forEach","event","handler","addEventListener","_deepCloneWithEvents","node","clone","cloneNode","events","Array","from","childNodes","child","HTMLElement","vdom","render","createTextNode","rendered","_updateElement","wrapper","__instance","parentNode","replaceChild","queueMicrotask","server","getServer","loadGoWasmImpl","createTypedWasmFunctionImpl","goValuesImpl","wasm","index","Fragment","jsx","jsxs","hydrate","useState","useEffect","useMemo","useRef","useContext","useErrorBoundary","createContext","renderToString","batchUpdates"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/wasm.ts","../src/vdom.ts","../src/component.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Go WebAssembly Integration Utilities\r\n * \r\n * This module provides tools for loading and interacting with Go WASM modules\r\n * in browser and server environments.\r\n */\r\n\r\n// Type definitions for Go WASM integration\r\nexport interface GoWasmInstance {\r\n instance: WebAssembly.Instance;\r\n module: WebAssembly.Module;\r\n exports: any;\r\n functions: Record<string, Function>;\r\n}\r\n\r\nexport interface GoWasmOptions {\r\n importObject?: WebAssembly.Imports;\r\n goWasmPath?: string;\r\n loadGo?: boolean;\r\n onLoad?: (instance: GoWasmInstance) => void;\r\n debug?: boolean;\r\n}\r\n\r\nconst DEFAULT_GO_WASM_PATH = '/wasm_exec.js';\r\n\r\n/**\r\n * Load a Go WASM module from a URL\r\n */\r\nexport async function loadGoWasm(\r\n wasmUrl: string, \r\n options: GoWasmOptions = {}\r\n): Promise<GoWasmInstance> {\r\n const {\r\n importObject = {},\r\n goWasmPath = DEFAULT_GO_WASM_PATH,\r\n loadGo = true,\r\n onLoad,\r\n debug = false\r\n } = options;\r\n\r\n // In browser environment, load the Go WASM runtime\r\n if (typeof window !== 'undefined' && loadGo) {\r\n await loadGoRuntime(goWasmPath);\r\n }\r\n\r\n try {\r\n // Create Go instance for WASM\r\n // @ts-ignore - Go is loaded from the global scope\r\n const go = typeof Go !== 'undefined' ? new Go() : null;\r\n \r\n // Fetch and instantiate the WASM module\r\n if (debug) console.log(`[WASM] Loading module from ${wasmUrl}`);\r\n \r\n const response = await fetch(wasmUrl);\r\n \r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch WASM module: ${response.statusText}`);\r\n }\r\n \r\n const buffer = await response.arrayBuffer();\r\n const module = await WebAssembly.compile(buffer);\r\n \r\n // Create imports object, combining Go runtime with custom imports\r\n const finalImportObject = go ? {\r\n ...go.importObject,\r\n ...importObject\r\n } : importObject;\r\n \r\n // Instantiate the WASM module\r\n const instance = await WebAssembly.instantiate(module, finalImportObject);\r\n \r\n // Initialize Go runtime if available\r\n if (go) {\r\n go.run(instance);\r\n }\r\n \r\n // Extract exported functions\r\n const exports = instance.exports;\r\n const functions: Record<string, Function> = {};\r\n \r\n // Generate wrapper functions for all exports that are functions\r\n for (const key in exports) {\r\n if (typeof exports[key] === 'function') {\r\n // Type assertion to ensure the exports[key] is callable\r\n const exportedFn = exports[key] as unknown as Function;\r\n functions[key] = (...args: any[]) => exportedFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n\r\n // Add any globally exported functions from Go\r\n if (typeof window !== 'undefined') {\r\n for (const key in window) {\r\n if (key.startsWith('go') && typeof (window as any)[key] === 'function') {\r\n // Type assertion to ensure the window[key] is callable\r\n const globalFn = (window as any)[key] as Function;\r\n functions[key] = (...args: any[]) => globalFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling global ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n }\r\n \r\n const wasmInstance: GoWasmInstance = {\r\n instance,\r\n module,\r\n exports,\r\n functions\r\n };\r\n \r\n // Run onLoad callback if provided\r\n if (onLoad) {\r\n onLoad(wasmInstance);\r\n }\r\n \r\n return wasmInstance;\r\n } catch (error) {\r\n console.error('[WASM] Failed to load Go WASM module:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load the Go WASM runtime script\r\n */\r\nasync function loadGoRuntime(path: string = DEFAULT_GO_WASM_PATH): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n \r\n // Check if Go runtime is already loaded\r\n if (typeof (window as any).Go !== 'undefined') {\r\n return;\r\n }\r\n \r\n // Load the Go WASM runtime script\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = path;\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error(`Failed to load Go WASM runtime from ${path}`));\r\n document.head.appendChild(script);\r\n });\r\n}\r\n\r\n/**\r\n * Create a TypeScript-friendly wrapper for Go WASM functions\r\n */\r\nexport function createTypedWasmFunction<T extends (...args: any[]) => any>(\r\n instance: GoWasmInstance,\r\n functionName: string\r\n): T {\r\n if (!instance.functions[functionName]) {\r\n throw new Error(`WASM function \"${functionName}\" not found`);\r\n }\r\n \r\n return instance.functions[functionName] as T;\r\n}\r\n\r\n/**\r\n * Helper to convert JavaScript values to Go-compatible formats\r\n */\r\nexport const goValues = {\r\n // Convert JS string to Go string (returns memory pointer)\r\n stringToGo: (instance: GoWasmInstance, str: string): number => {\r\n if (!instance.functions.__stringToGo) {\r\n throw new Error('__stringToGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringToGo(str);\r\n },\r\n \r\n // Convert Go string (memory pointer) to JS string\r\n stringFromGo: (instance: GoWasmInstance, ptr: number): string => {\r\n if (!instance.functions.__stringFromGo) {\r\n throw new Error('__stringFromGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringFromGo(ptr);\r\n },\r\n \r\n // Convert JS object to Go (returns memory pointer)\r\n objectToGo: (instance: GoWasmInstance, obj: any): number => {\r\n if (!instance.functions.__objectToGo) {\r\n throw new Error('__objectToGo function not found in WASM module');\r\n }\r\n return instance.functions.__objectToGo(JSON.stringify(obj));\r\n },\r\n \r\n // Convert Go object (memory pointer) to JS object\r\n objectFromGo: (instance: GoWasmInstance, ptr: number): any => {\r\n if (!instance.functions.__objectFromGo) {\r\n throw new Error('__objectFromGo function not found in WASM module');\r\n }\r\n const str = instance.functions.__objectFromGo(ptr);\r\n return JSON.parse(str);\r\n }\r\n};\r\n","interface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n key?: string | number;\r\n}\r\n\r\nfunction arePropsEqual(oldProps: any, newProps: any): boolean {\r\n const oldKeys = Object.keys(oldProps).filter(k => k !== 'children');\r\n const newKeys = Object.keys(newProps).filter(k => k !== 'children');\r\n \r\n if (oldKeys.length !== newKeys.length) return false;\r\n return oldKeys.every(key => oldProps[key] === newProps[key]);\r\n}\r\n\r\nexport function diff(oldNode: VNode | any, newNode: VNode | any): boolean {\r\n if (oldNode == null || newNode == null) return oldNode !== newNode;\r\n if (typeof oldNode !== typeof newNode) return true;\r\n if (typeof newNode === 'string' || typeof newNode === 'number')\r\n return oldNode !== newNode;\r\n if (newNode.type !== oldNode.type) return true;\r\n return !arePropsEqual(oldNode.props, newNode.props);\r\n}\r\n\r\nexport function shouldComponentUpdate(oldProps: any, newProps: any): boolean {\r\n return !arePropsEqual(oldProps, newProps);\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\n\r\nexport class Component {\r\n state: any = {};\r\n props: any;\r\n element: HTMLElement | null = null;\r\n private _mounted: boolean = false;\r\n\r\n constructor(props: any = {}) {\r\n this.props = props;\r\n }\r\n\r\n componentDidMount() {\r\n // Hook for after component is mounted\r\n }\r\n\r\n async setState(newState: any) {\r\n const prevState = { ...this.state };\r\n this.state = { ...prevState, ...newState };\r\n console.log(`${this.constructor.name} state updated:`, {\r\n prev: prevState,\r\n next: this.state\r\n });\r\n \r\n await Promise.resolve(); // Ensure state is updated before re-render\r\n if (this._mounted) {\r\n await this.update();\r\n } else {\r\n await this.update();\r\n }\r\n }\r\n\r\n private _replayEvents(oldElement: HTMLElement, newElement: HTMLElement) {\r\n const oldEvents = (oldElement as any).__events || {};\r\n Object.entries(oldEvents).forEach(([event, handler]) => {\r\n newElement.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n (newElement as any).__events = oldEvents;\r\n }\r\n\r\n private _deepCloneWithEvents(node: HTMLElement): HTMLElement {\r\n const clone = node.cloneNode(false) as HTMLElement;\r\n \r\n // Copy events from original element\r\n const events = (node as any).__events || {};\r\n (clone as any).__events = events;\r\n Object.entries(events).forEach(([event, handler]) => {\r\n clone.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n\r\n // Clone children\r\n Array.from(node.childNodes).forEach(child => {\r\n if (child instanceof HTMLElement) {\r\n clone.appendChild(this._deepCloneWithEvents(child));\r\n } else {\r\n clone.appendChild(child.cloneNode(true));\r\n }\r\n });\r\n\r\n return clone;\r\n }\r\n\r\n async update() {\r\n const vdom = this.render();\r\n if (!vdom) return document.createTextNode('');\r\n \r\n const rendered = await createElement(vdom);\r\n if (rendered instanceof HTMLElement) {\r\n return this._updateElement(rendered);\r\n }\r\n \r\n const wrapper = document.createElement('div');\r\n wrapper.appendChild(rendered);\r\n return this._updateElement(wrapper);\r\n }\r\n\r\n private async _updateElement(rendered: HTMLElement) {\r\n const newElement = this._deepCloneWithEvents(rendered);\r\n (newElement as any).__instance = this;\r\n \r\n if (!this.element) {\r\n this.element = newElement;\r\n if (!this._mounted) {\r\n this._mounted = true;\r\n queueMicrotask(() => this.componentDidMount());\r\n }\r\n } else if (this.element.parentNode) {\r\n this.element.parentNode.replaceChild(newElement, this.element);\r\n this.element = newElement;\r\n }\r\n \r\n return this.element;\r\n }\r\n\r\n render(): any {\r\n throw new Error('Component must implement render() method');\r\n }\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks.js';\r\nimport { \r\n loadGoWasm as loadGoWasmImpl, \r\n createTypedWasmFunction as createTypedWasmFunctionImpl,\r\n goValues as goValuesImpl,\r\n type GoWasmInstance,\r\n type GoWasmOptions\r\n} from './wasm.js';\r\n\r\n// Import items needed for the default export\r\nimport { jsx, jsxs, jsxDEV, Fragment } from './jsx-runtime.js';\r\nimport { render, hydrate } from './renderer.js';\r\nimport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary\r\n} from './hooks.js';\r\nimport { createContext } from './context.js';\r\nimport { renderToString } from './server-renderer.js';\r\nimport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\nimport { diff, shouldComponentUpdate } from './vdom.js';\r\nimport { Component } from './component.js';\r\n\r\n// Re-export core modules with explicit names to ensure they appear in bundle\r\nexport { render, hydrate } from './renderer.js';\r\nexport { \r\n jsx, \r\n jsxs, \r\n jsxDEV,\r\n Fragment, \r\n createElement \r\n} from './jsx-runtime.js';\r\n\r\nexport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary,\r\n prepareRender,\r\n finishRender,\r\n setRenderCallback\r\n} from './hooks.js';\r\n\r\n// Context API\r\nexport { createContext } from './context.js';\r\n\r\n// Server-side rendering\r\nexport { renderToString } from './server-renderer.js';\r\n\r\n// Batch updates utility\r\nexport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\n\r\n// VDOM utilities\r\nexport { diff, shouldComponentUpdate } from './vdom.js';\r\n\r\n// Export Component class\r\nexport { Component } from './component.js';\r\n\r\n// Server module stub for browser environments\r\nexport const server = {\r\n async getServer() {\r\n throw new Error(\"Server module can only be used in Node.js environment\");\r\n }\r\n};\r\n\r\n// Export WASM functionality explicitly\r\nexport const loadGoWasm = loadGoWasmImpl;\r\nexport const createTypedWasmFunction = createTypedWasmFunctionImpl;\r\nexport const goValues = goValuesImpl;\r\nexport type { GoWasmInstance, GoWasmOptions } from './wasm.js';\r\n\r\n// Add wasm object to ensure compatibility with existing dist/index.js\r\nexport const wasm = {\r\n loadGoWasm: loadGoWasmImpl,\r\n createTypedWasmFunction: createTypedWasmFunctionImpl,\r\n goValues: goValuesImpl\r\n};\r\n\r\n// Re-export types\r\nexport type { Context } from './context.js';\r\nexport type { VNode } from './types.js';\r\n\r\n// Export server types from the safe type-only file\r\nexport type { \r\n Server, \r\n ServerConfig, \r\n User, \r\n DbConfig, \r\n MiddlewareFunction \r\n} from './server-types.js';\r\n\r\n// Export this so it can be properly identified in the bundle\r\nexport let isHydrating = false;\r\n\r\n// Default export for compatibility with some module systems\r\nexport default {\r\n Fragment,\r\n jsx,\r\n jsxs,\r\n createElement,\r\n render, \r\n hydrate,\r\n useState,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useContext,\r\n useErrorBoundary,\r\n createContext,\r\n renderToString,\r\n batchUpdates,\r\n server,\r\n loadGoWasm,\r\n createTypedWasmFunction,\r\n goValues,\r\n wasm,\r\n Component,\r\n diff,\r\n shouldComponentUpdate\r\n // Server functionality is exposed through the server export\r\n};\r\n"],"names":["DEFAULT_GO_WASM_PATH","async","loadGoWasm","wasmUrl","options","importObject","goWasmPath","loadGo","onLoad","debug","window","path","Go","Promise","resolve","reject","script","document","createElement","src","onload","onerror","Error","head","appendChild","loadGoRuntime","go","console","log","response","fetch","ok","statusText","buffer","arrayBuffer","module","WebAssembly","compile","finalImportObject","instance","instantiate","run","exports","functions","key","exportedFn","args","originalFn","join","result","startsWith","globalFn","wasmInstance","error","createTypedWasmFunction","functionName","goValues","stringToGo","str","__stringToGo","stringFromGo","ptr","__stringFromGo","objectToGo","obj","__objectToGo","JSON","stringify","objectFromGo","__objectFromGo","parse","arePropsEqual","oldProps","newProps","oldKeys","Object","keys","filter","k","newKeys","length","every","diff","oldNode","newNode","type","props","shouldComponentUpdate","Component","constructor","this","state","element","_mounted","componentDidMount","setState","newState","prevState","name","prev","next","update","_replayEvents","oldElement","newElement","oldEvents","__events","entries","forEach","event","handler","addEventListener","_deepCloneWithEvents","node","clone","cloneNode","events","Array","from","childNodes","child","HTMLElement","vdom","render","createTextNode","rendered","_updateElement","wrapper","__instance","parentNode","replaceChild","queueMicrotask","server","getServer","loadGoWasmImpl","createTypedWasmFunctionImpl","goValuesImpl","wasm","index","Fragment","jsx","jsxs","hydrate","useState","useEffect","useMemo","useRef","useContext","useErrorBoundary","createContext","renderToString","batchUpdates"],"mappings":"kOAuBMA,EAAuB,gBAK7BC,eAAsBC,EACpBC,EACAC,EAAyB,IAEnB,MAAAC,aACJA,EAAe,CAAC,EAAAC,WAChBA,EAAaN,EAAAO,OACbA,GAAS,EAAAC,OACTA,EAAAC,MACAA,GAAQ,GACNL,EAGkB,oBAAXM,QAA0BH,SAqGvCN,eAA6BU,EAAeX,GACtC,GAAkB,oBAAXU,OAAwB,OAG/B,QAA8B,IAAtBA,OAAeE,GACzB,OAIF,OAAO,IAAIC,SAAQ,CAACC,EAASC,KACrB,MAAAC,EAASC,SAASC,cAAc,UACtCF,EAAOG,IAAMR,EACNK,EAAAI,OAAS,IAAMN,IACfE,EAAAK,QAAU,IAAMN,EAAO,IAAIO,MAAM,uCAAuCX,MACtEM,SAAAM,KAAKC,YAAYR,EAAM,GAEpC,CApHUS,CAAcnB,GAGlB,IAGF,MAAMoB,EAAmB,oBAAPd,GAAqB,IAAIA,GAAO,KAG9CH,GAAOkB,QAAQC,IAAI,8BAA8BzB,KAE/C,MAAA0B,QAAiBC,MAAM3B,GAEzB,IAAC0B,EAASE,GACZ,MAAM,IAAIT,MAAM,gCAAgCO,EAASG,cAGrD,MAAAC,QAAeJ,EAASK,cACxBC,QAAeC,YAAYC,QAAQJ,GAGnCK,EAAoBZ,EAAK,IAC1BA,EAAGrB,gBACHA,GACDA,EAGEkC,QAAiBH,YAAYI,YAAYL,EAAQG,GAGnDZ,GACFA,EAAGe,IAAIF,GAIT,MAAMG,EAAUH,EAASG,QACnBC,EAAsC,CAAC,EAG7C,IAAA,MAAWC,KAAOF,EAChB,GAA4B,mBAAjBA,EAAQE,GAAqB,CAEhC,MAAAC,EAAaH,EAAQE,GAG3B,GAFAD,EAAUC,GAAO,IAAIE,IAAgBD,KAAcC,GAE/CrC,EAAO,CACH,MAAAsC,EAAaJ,EAAUC,GACnBD,EAAAC,GAAO,IAAIE,KACXnB,QAAAC,IAAI,kBAAkBgB,KAAOE,EAAKE,KAAK,UACzC,MAAAC,EAASF,KAAcD,GAEtB,OADPnB,QAAQC,IAAI,UAAUgB,cAAiBK,GAChCA,CAAA,CACT,CACF,CAKA,GAAkB,oBAAXvC,OACT,IAAA,MAAWkC,KAAOlC,OACZ,GAAAkC,EAAIM,WAAW,OAAyC,mBAAxBxC,OAAekC,GAAqB,CAEhE,MAAAO,EAAYzC,OAAekC,GAGjC,GAFAD,EAAUC,GAAO,IAAIE,IAAgBK,KAAYL,GAE7CrC,EAAO,CACH,MAAAsC,EAAaJ,EAAUC,GACnBD,EAAAC,GAAO,IAAIE,KACXnB,QAAAC,IAAI,yBAAyBgB,KAAOE,EAAKE,KAAK,UAChD,MAAAC,EAASF,KAAcD,GAEtB,OADPnB,QAAQC,IAAI,UAAUgB,cAAiBK,GAChCA,CAAA,CACT,CACF,CAKN,MAAMG,EAA+B,CACnCb,WACAJ,OAAAA,EACAO,QAAAA,EACAC,aAQK,OAJHnC,GACFA,EAAO4C,GAGFA,QACAC,GAED,MADE1B,QAAA0B,MAAM,wCAAyCA,GACjDA,CAAA,CAEV,CA0BgB,SAAAC,EACdf,EACAgB,GAEA,IAAKhB,EAASI,UAAUY,GACtB,MAAM,IAAIjC,MAAM,kBAAkBiC,gBAG7B,OAAAhB,EAASI,UAAUY,EAC5B,CAKO,MAAMC,EAAW,CAEtBC,WAAY,CAAClB,EAA0BmB,KACjC,IAACnB,EAASI,UAAUgB,aAChB,MAAA,IAAIrC,MAAM,kDAEX,OAAAiB,EAASI,UAAUgB,aAAaD,EAAG,EAI5CE,aAAc,CAACrB,EAA0BsB,KACnC,IAACtB,EAASI,UAAUmB,eAChB,MAAA,IAAIxC,MAAM,oDAEX,OAAAiB,EAASI,UAAUmB,eAAeD,EAAG,EAI9CE,WAAY,CAACxB,EAA0ByB,KACjC,IAACzB,EAASI,UAAUsB,aAChB,MAAA,IAAI3C,MAAM,kDAElB,OAAOiB,EAASI,UAAUsB,aAAaC,KAAKC,UAAUH,GAAI,EAI5DI,aAAc,CAAC7B,EAA0BsB,KACnC,IAACtB,EAASI,UAAU0B,eAChB,MAAA,IAAI/C,MAAM,oDAElB,MAAMoC,EAAMnB,EAASI,UAAU0B,eAAeR,GACvC,OAAAK,KAAKI,MAAMZ,EAAG,GC1MzB,SAASa,EAAcC,EAAeC,GAC9B,MAAAC,EAAUC,OAAOC,KAAKJ,GAAUK,QAAOC,GAAW,aAANA,IAC5CC,EAAUJ,OAAOC,KAAKH,GAAUI,QAAOC,GAAW,aAANA,IAElD,OAAIJ,EAAQM,SAAWD,EAAQC,QACxBN,EAAQO,OAAarC,GAAA4B,EAAS5B,KAAS6B,EAAS7B,IACzD,CAEgB,SAAAsC,EAAKC,EAAsBC,GACzC,OAAe,MAAXD,GAA8B,MAAXC,EAAwBD,IAAYC,SAChDD,UAAmBC,IACP,iBAAZA,GAA2C,iBAAZA,EACjCD,IAAYC,EACjBA,EAAQC,OAASF,EAAQE,OACrBd,EAAcY,EAAQG,MAAOF,EAAQE,OAC/C,CAEgB,SAAAC,EAAsBf,EAAeC,GAC5C,OAACF,EAAcC,EAAUC,EAClC,CCvBO,MAAMe,EAMX,WAAAC,CAAYH,EAAa,IALzBI,KAAAC,MAAa,CAAC,EAEgBD,KAAAE,QAAA,KAC9BF,KAAQG,UAAoB,EAG1BH,KAAKJ,MAAQA,CAAA,CAGf,iBAAAQ,GAAoB,CAIpB,cAAMC,CAASC,GACb,MAAMC,EAAY,IAAKP,KAAKC,OAC5BD,KAAKC,MAAQ,IAAKM,KAAcD,GAChCrE,QAAQC,IAAI,GAAG8D,KAAKD,YAAYS,sBAAuB,CACrDC,KAAMF,EACNG,KAAMV,KAAKC,cAGP9E,QAAQC,UACV4E,KAAKG,eACDH,KAAKW,QAGb,CAGM,aAAAC,CAAcC,EAAyBC,GACvC,MAAAC,EAAaF,EAAmBG,UAAY,CAAC,EAC5C/B,OAAAgC,QAAQF,GAAWG,SAAQ,EAAEC,EAAOC,MAC9BN,EAAAO,iBAAiBF,EAAoCC,EAAwB,IAEzFN,EAAmBE,SAAWD,CAAA,CAGzB,oBAAAO,CAAqBC,GACrB,MAAAC,EAAQD,EAAKE,WAAU,GAGvBC,EAAUH,EAAaP,UAAY,CAAC,EAenC,OAdNQ,EAAcR,SAAWU,EACnBzC,OAAAgC,QAAQS,GAAQR,SAAQ,EAAEC,EAAOC,MAChCI,EAAAH,iBAAiBF,EAAoCC,EAAwB,IAIrFO,MAAMC,KAAKL,EAAKM,YAAYX,SAAiBY,IACvCA,aAAiBC,YACnBP,EAAM1F,YAAYkE,KAAKsB,qBAAqBQ,IAE5CN,EAAM1F,YAAYgG,EAAML,WAAU,GAAK,IAIpCD,CAAA,CAGT,YAAMb,GACE,MAAAqB,EAAOhC,KAAKiC,SAClB,IAAKD,EAAa,OAAAzG,SAAS2G,eAAe,IAEpC,MAAAC,QAAiB3G,EAAAA,cAAcwG,GACrC,GAAIG,aAAoBJ,YACf,OAAA/B,KAAKoC,eAAeD,GAGvB,MAAAE,EAAU9G,SAASC,cAAc,OAEhC,OADP6G,EAAQvG,YAAYqG,GACbnC,KAAKoC,eAAeC,EAAO,CAGpC,oBAAcD,CAAeD,GACrB,MAAArB,EAAad,KAAKsB,qBAAqBa,GAc7C,OAbCrB,EAAmBwB,WAAatC,KAE5BA,KAAKE,QAMCF,KAAKE,QAAQqC,aACtBvC,KAAKE,QAAQqC,WAAWC,aAAa1B,EAAYd,KAAKE,SACtDF,KAAKE,QAAUY,IAPfd,KAAKE,QAAUY,EACVd,KAAKG,WACRH,KAAKG,UAAW,EACDsC,gBAAA,IAAMzC,KAAKI,wBAOvBJ,KAAKE,OAAA,CAGd,MAAA+B,GACQ,MAAA,IAAIrG,MAAM,2CAA0C,EC9BvD,MAAM8G,EAAS,CACpB,eAAMC,GACE,MAAA,IAAI/G,MAAM,wDAAuD,GAK9DpB,EAAaoI,EACbhF,EAA0BiF,EAC1B/E,EAAWgF,EAIXC,EAAO,CAClBvI,WAAYoI,EACZhF,wBAAyBiF,EACzB/E,SAAUgF,GAoBZ,MAAeE,EAAA,CAAAC,SACbA,EAAAA,SAAAC,IACAA,EAAAA,IAAAC,KACAA,EAAAD,IAAA1H,cACAA,EAAAA,cAAAyG,OACAA,EAAAA,OAAAmB,QACAA,EAAAA,QAAAC,SACAA,EAAAA,SAAAC,UACAA,EAAAA,UAAAC,QACAA,EAAAA,QAAAC,OACAA,EAAAA,OAAAC,WACAA,EAAAA,WAAAC,iBACAA,EAAAA,iBAAAC,cACAA,EAAAA,cAAAC,eACAA,EAAAA,eAAAC,aACAA,EAAAA,aACAnB,SACAlI,aACAoD,0BACAE,WACAiF,OACAjD,YACAN,OACAK,+1BA1BuB"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/wasm.ts","../src/vdom.ts","../src/component.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Go WebAssembly Integration Utilities\r\n * \r\n * This module provides tools for loading and interacting with Go WASM modules\r\n * in browser and server environments.\r\n */\r\n\r\n// Type definitions for Go WASM integration\r\nexport interface GoWasmInstance {\r\n instance: WebAssembly.Instance;\r\n module: WebAssembly.Module;\r\n exports: any;\r\n functions: Record<string, Function>;\r\n}\r\n\r\nexport interface GoWasmOptions {\r\n importObject?: WebAssembly.Imports;\r\n goWasmPath?: string;\r\n loadGo?: boolean;\r\n onLoad?: (instance: GoWasmInstance) => void;\r\n debug?: boolean;\r\n}\r\n\r\nconst DEFAULT_GO_WASM_PATH = '/wasm_exec.js';\r\n\r\n/**\r\n * Load a Go WASM module from a URL\r\n */\r\nexport async function loadGoWasm(\r\n wasmUrl: string, \r\n options: GoWasmOptions = {}\r\n): Promise<GoWasmInstance> {\r\n const {\r\n importObject = {},\r\n goWasmPath = DEFAULT_GO_WASM_PATH,\r\n loadGo = true,\r\n onLoad,\r\n debug = false\r\n } = options;\r\n\r\n // In browser environment, load the Go WASM runtime\r\n if (typeof window !== 'undefined' && loadGo) {\r\n await loadGoRuntime(goWasmPath);\r\n }\r\n\r\n try {\r\n // Create Go instance for WASM\r\n // @ts-ignore - Go is loaded from the global scope\r\n const go = typeof Go !== 'undefined' ? new Go() : null;\r\n \r\n // Fetch and instantiate the WASM module\r\n if (debug) console.log(`[WASM] Loading module from ${wasmUrl}`);\r\n \r\n const response = await fetch(wasmUrl);\r\n \r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch WASM module: ${response.statusText}`);\r\n }\r\n \r\n const buffer = await response.arrayBuffer();\r\n const module = await WebAssembly.compile(buffer);\r\n \r\n // Create imports object, combining Go runtime with custom imports\r\n const finalImportObject = go ? {\r\n ...go.importObject,\r\n ...importObject\r\n } : importObject;\r\n \r\n // Instantiate the WASM module\r\n const instance = await WebAssembly.instantiate(module, finalImportObject);\r\n \r\n // Initialize Go runtime if available\r\n if (go) {\r\n go.run(instance);\r\n }\r\n \r\n // Extract exported functions\r\n const exports = instance.exports;\r\n const functions: Record<string, Function> = {};\r\n \r\n // Generate wrapper functions for all exports that are functions\r\n for (const key in exports) {\r\n if (typeof exports[key] === 'function') {\r\n // Type assertion to ensure the exports[key] is callable\r\n const exportedFn = exports[key] as unknown as Function;\r\n functions[key] = (...args: any[]) => exportedFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n\r\n // Add any globally exported functions from Go\r\n if (typeof window !== 'undefined') {\r\n for (const key in window) {\r\n if (key.startsWith('go') && typeof (window as any)[key] === 'function') {\r\n // Type assertion to ensure the window[key] is callable\r\n const globalFn = (window as any)[key] as Function;\r\n functions[key] = (...args: any[]) => globalFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling global ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n }\r\n \r\n const wasmInstance: GoWasmInstance = {\r\n instance,\r\n module,\r\n exports,\r\n functions\r\n };\r\n \r\n // Run onLoad callback if provided\r\n if (onLoad) {\r\n onLoad(wasmInstance);\r\n }\r\n \r\n return wasmInstance;\r\n } catch (error) {\r\n console.error('[WASM] Failed to load Go WASM module:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load the Go WASM runtime script\r\n */\r\nasync function loadGoRuntime(path: string = DEFAULT_GO_WASM_PATH): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n \r\n // Check if Go runtime is already loaded\r\n if (typeof (window as any).Go !== 'undefined') {\r\n return;\r\n }\r\n \r\n // Load the Go WASM runtime script\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = path;\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error(`Failed to load Go WASM runtime from ${path}`));\r\n document.head.appendChild(script);\r\n });\r\n}\r\n\r\n/**\r\n * Create a TypeScript-friendly wrapper for Go WASM functions\r\n */\r\nexport function createTypedWasmFunction<T extends (...args: any[]) => any>(\r\n instance: GoWasmInstance,\r\n functionName: string\r\n): T {\r\n if (!instance.functions[functionName]) {\r\n throw new Error(`WASM function \"${functionName}\" not found`);\r\n }\r\n \r\n return instance.functions[functionName] as T;\r\n}\r\n\r\n/**\r\n * Helper to convert JavaScript values to Go-compatible formats\r\n */\r\nexport const goValues = {\r\n // Convert JS string to Go string (returns memory pointer)\r\n stringToGo: (instance: GoWasmInstance, str: string): number => {\r\n if (!instance.functions.__stringToGo) {\r\n throw new Error('__stringToGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringToGo(str);\r\n },\r\n \r\n // Convert Go string (memory pointer) to JS string\r\n stringFromGo: (instance: GoWasmInstance, ptr: number): string => {\r\n if (!instance.functions.__stringFromGo) {\r\n throw new Error('__stringFromGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringFromGo(ptr);\r\n },\r\n \r\n // Convert JS object to Go (returns memory pointer)\r\n objectToGo: (instance: GoWasmInstance, obj: any): number => {\r\n if (!instance.functions.__objectToGo) {\r\n throw new Error('__objectToGo function not found in WASM module');\r\n }\r\n return instance.functions.__objectToGo(JSON.stringify(obj));\r\n },\r\n \r\n // Convert Go object (memory pointer) to JS object\r\n objectFromGo: (instance: GoWasmInstance, ptr: number): any => {\r\n if (!instance.functions.__objectFromGo) {\r\n throw new Error('__objectFromGo function not found in WASM module');\r\n }\r\n const str = instance.functions.__objectFromGo(ptr);\r\n return JSON.parse(str);\r\n }\r\n};\r\n","interface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n key?: string | number;\r\n}\r\n\r\nfunction arePropsEqual(oldProps: any, newProps: any): boolean {\r\n const oldKeys = Object.keys(oldProps).filter(k => k !== 'children');\r\n const newKeys = Object.keys(newProps).filter(k => k !== 'children');\r\n \r\n if (oldKeys.length !== newKeys.length) return false;\r\n return oldKeys.every(key => oldProps[key] === newProps[key]);\r\n}\r\n\r\nexport function diff(oldNode: VNode | any, newNode: VNode | any): boolean {\r\n if (oldNode == null || newNode == null) return oldNode !== newNode;\r\n if (typeof oldNode !== typeof newNode) return true;\r\n if (typeof newNode === 'string' || typeof newNode === 'number')\r\n return oldNode !== newNode;\r\n if (newNode.type !== oldNode.type) return true;\r\n return !arePropsEqual(oldNode.props, newNode.props);\r\n}\r\n\r\nexport function shouldComponentUpdate(oldProps: any, newProps: any): boolean {\r\n return !arePropsEqual(oldProps, newProps);\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\n\r\nexport class Component {\r\n state: any = {};\r\n props: any;\r\n element: HTMLElement | null = null;\r\n private _mounted: boolean = false;\r\n\r\n constructor(props: any = {}) {\r\n this.props = props;\r\n }\r\n\r\n componentDidMount() {\r\n // Hook for after component is mounted\r\n }\r\n\r\n async setState(newState: any) {\r\n const prevState = { ...this.state };\r\n this.state = { ...prevState, ...newState };\r\n console.log(`${this.constructor.name} state updated:`, {\r\n prev: prevState,\r\n next: this.state\r\n });\r\n \r\n await Promise.resolve(); // Ensure state is updated before re-render\r\n if (this._mounted) {\r\n await this.update();\r\n } else {\r\n await this.update();\r\n }\r\n }\r\n\r\n private _replayEvents(oldElement: HTMLElement, newElement: HTMLElement) {\r\n const oldEvents = (oldElement as any).__events || {};\r\n Object.entries(oldEvents).forEach(([event, handler]) => {\r\n newElement.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n (newElement as any).__events = oldEvents;\r\n }\r\n\r\n private _deepCloneWithEvents(node: HTMLElement): HTMLElement {\r\n const clone = node.cloneNode(false) as HTMLElement;\r\n \r\n // Copy events from original element\r\n const events = (node as any).__events || {};\r\n (clone as any).__events = events;\r\n Object.entries(events).forEach(([event, handler]) => {\r\n clone.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n\r\n // Clone children\r\n Array.from(node.childNodes).forEach(child => {\r\n if (child instanceof HTMLElement) {\r\n clone.appendChild(this._deepCloneWithEvents(child));\r\n } else {\r\n clone.appendChild(child.cloneNode(true));\r\n }\r\n });\r\n\r\n return clone;\r\n }\r\n\r\n async update() {\r\n const vdom = this.render();\r\n if (!vdom) return document.createTextNode('');\r\n \r\n const rendered = await createElement(vdom);\r\n if (rendered instanceof HTMLElement) {\r\n return this._updateElement(rendered);\r\n }\r\n \r\n const wrapper = document.createElement('div');\r\n wrapper.appendChild(rendered);\r\n return this._updateElement(wrapper);\r\n }\r\n\r\n private async _updateElement(rendered: HTMLElement) {\r\n const newElement = this._deepCloneWithEvents(rendered);\r\n (newElement as any).__instance = this;\r\n \r\n if (!this.element) {\r\n this.element = newElement;\r\n if (!this._mounted) {\r\n this._mounted = true;\r\n queueMicrotask(() => this.componentDidMount());\r\n }\r\n } else if (this.element.parentNode) {\r\n this.element.parentNode.replaceChild(newElement, this.element);\r\n this.element = newElement;\r\n }\r\n \r\n return this.element;\r\n }\r\n\r\n render(): any {\r\n throw new Error('Component must implement render() method');\r\n }\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks.js';\r\nimport { \r\n loadGoWasm as loadGoWasmImpl, \r\n createTypedWasmFunction as createTypedWasmFunctionImpl,\r\n goValues as goValuesImpl,\r\n type GoWasmInstance,\r\n type GoWasmOptions\r\n} from './wasm.js';\r\n\r\n// Import items needed for the default export\r\nimport { jsx, jsxs, jsxDEV, Fragment } from './jsx-runtime.js';\r\nimport { render, hydrate } from './renderer.js';\r\nimport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary\r\n} from './hooks.js';\r\nimport { createContext } from './context.js';\r\nimport { renderToString } from './server-renderer.js';\r\nimport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\nimport { diff, shouldComponentUpdate } from './vdom.js';\r\nimport { Component } from './component.js';\r\n\r\n// Re-export core modules with explicit names to ensure they appear in bundle\r\nexport { render, hydrate } from './renderer.js';\r\nexport { \r\n jsx, \r\n jsxs, \r\n jsxDEV,\r\n Fragment, \r\n createElement \r\n} from './jsx-runtime.js';\r\n\r\nexport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary,\r\n prepareRender,\r\n finishRender,\r\n setRenderCallback\r\n} from './hooks.js';\r\n\r\n// Context API\r\nexport { createContext } from './context.js';\r\n\r\n// Server-side rendering\r\nexport { renderToString } from './server-renderer.js';\r\n\r\n// Batch updates utility\r\nexport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\n\r\n// VDOM utilities\r\nexport { diff, shouldComponentUpdate } from './vdom.js';\r\n\r\n// Export Component class\r\nexport { Component } from './component.js';\r\n\r\n// Server module stub for browser environments\r\nexport const server = {\r\n async getServer() {\r\n throw new Error(\"Server module can only be used in Node.js environment\");\r\n }\r\n};\r\n\r\n// Export WASM functionality explicitly\r\nexport const loadGoWasm = loadGoWasmImpl;\r\nexport const createTypedWasmFunction = createTypedWasmFunctionImpl;\r\nexport const goValues = goValuesImpl;\r\nexport type { GoWasmInstance, GoWasmOptions } from './wasm.js';\r\n\r\n// Add wasm object to ensure compatibility with existing dist/index.js\r\nexport const wasm = {\r\n loadGoWasm: loadGoWasmImpl,\r\n createTypedWasmFunction: createTypedWasmFunctionImpl,\r\n goValues: goValuesImpl\r\n};\r\n\r\n// Re-export types\r\nexport type { Context } from './context.js';\r\nexport type { VNode } from './types.js';\r\n\r\n// Export server types from the safe type-only file\r\nexport type { \r\n Server, \r\n ServerConfig, \r\n User, \r\n DbConfig, \r\n MiddlewareFunction \r\n} from './server-types.js';\r\n\r\n// Export this so it can be properly identified in the bundle\r\nexport let isHydrating = false;\r\nimport { AuthService } from './server/auth.js';\r\n// Default export for compatibility with some module systems\r\nexport default {\r\n Fragment: Fragment,\r\n jsx: jsx,\r\n jsxs: jsxs,\r\n createElement: createElement,\r\n render: render, \r\n hydrate: hydrate,\r\n useState: useState,\r\n useEffect: useEffect,\r\n useMemo: useMemo,\r\n useRef: useRef,\r\n useContext: useContext,\r\n useErrorBoundary: useErrorBoundary,\r\n createContext: createContext,\r\n renderToString: renderToString,\r\n batchUpdates: batchUpdates,\r\n server: server,\r\n loadGoWasm: loadGoWasm,\r\n createTypedWasmFunction: createTypedWasmFunction,\r\n goValues: goValues,\r\n wasm: wasm,\r\n Component: Component,\r\n diff: diff,\r\n shouldComponentUpdate: shouldComponentUpdate\r\n};\r\n"],"names":["loadGoWasm","createTypedWasmFunction","goValues","loadGoWasmImpl","createTypedWasmFunctionImpl","goValuesImpl","jsxs"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/wasm.ts","../src/vdom.ts","../src/component.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Go WebAssembly Integration Utilities\r\n * \r\n * This module provides tools for loading and interacting with Go WASM modules\r\n * in browser and server environments.\r\n */\r\n\r\n// Type definitions for Go WASM integration\r\nexport interface GoWasmInstance {\r\n instance: WebAssembly.Instance;\r\n module: WebAssembly.Module;\r\n exports: any;\r\n functions: Record<string, Function>;\r\n}\r\n\r\nexport interface GoWasmOptions {\r\n importObject?: WebAssembly.Imports;\r\n goWasmPath?: string;\r\n loadGo?: boolean;\r\n onLoad?: (instance: GoWasmInstance) => void;\r\n debug?: boolean;\r\n}\r\n\r\nconst DEFAULT_GO_WASM_PATH = '/wasm_exec.js';\r\n\r\n/**\r\n * Load a Go WASM module from a URL\r\n */\r\nexport async function loadGoWasm(\r\n wasmUrl: string, \r\n options: GoWasmOptions = {}\r\n): Promise<GoWasmInstance> {\r\n const {\r\n importObject = {},\r\n goWasmPath = DEFAULT_GO_WASM_PATH,\r\n loadGo = true,\r\n onLoad,\r\n debug = false\r\n } = options;\r\n\r\n // In browser environment, load the Go WASM runtime\r\n if (typeof window !== 'undefined' && loadGo) {\r\n await loadGoRuntime(goWasmPath);\r\n }\r\n\r\n try {\r\n // Create Go instance for WASM\r\n // @ts-ignore - Go is loaded from the global scope\r\n const go = typeof Go !== 'undefined' ? new Go() : null;\r\n \r\n // Fetch and instantiate the WASM module\r\n if (debug) console.log(`[WASM] Loading module from ${wasmUrl}`);\r\n \r\n const response = await fetch(wasmUrl);\r\n \r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch WASM module: ${response.statusText}`);\r\n }\r\n \r\n const buffer = await response.arrayBuffer();\r\n const module = await WebAssembly.compile(buffer);\r\n \r\n // Create imports object, combining Go runtime with custom imports\r\n const finalImportObject = go ? {\r\n ...go.importObject,\r\n ...importObject\r\n } : importObject;\r\n \r\n // Instantiate the WASM module\r\n const instance = await WebAssembly.instantiate(module, finalImportObject);\r\n \r\n // Initialize Go runtime if available\r\n if (go) {\r\n go.run(instance);\r\n }\r\n \r\n // Extract exported functions\r\n const exports = instance.exports;\r\n const functions: Record<string, Function> = {};\r\n \r\n // Generate wrapper functions for all exports that are functions\r\n for (const key in exports) {\r\n if (typeof exports[key] === 'function') {\r\n // Type assertion to ensure the exports[key] is callable\r\n const exportedFn = exports[key] as unknown as Function;\r\n functions[key] = (...args: any[]) => exportedFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n\r\n // Add any globally exported functions from Go\r\n if (typeof window !== 'undefined') {\r\n for (const key in window) {\r\n if (key.startsWith('go') && typeof (window as any)[key] === 'function') {\r\n // Type assertion to ensure the window[key] is callable\r\n const globalFn = (window as any)[key] as Function;\r\n functions[key] = (...args: any[]) => globalFn(...args);\r\n \r\n if (debug) {\r\n const originalFn = functions[key];\r\n functions[key] = (...args: any[]) => {\r\n console.log(`[WASM] Calling global ${key}(${args.join(', ')})`);\r\n const result = originalFn(...args);\r\n console.log(`[WASM] ${key} returned:`, result);\r\n return result;\r\n };\r\n }\r\n }\r\n }\r\n }\r\n \r\n const wasmInstance: GoWasmInstance = {\r\n instance,\r\n module,\r\n exports,\r\n functions\r\n };\r\n \r\n // Run onLoad callback if provided\r\n if (onLoad) {\r\n onLoad(wasmInstance);\r\n }\r\n \r\n return wasmInstance;\r\n } catch (error) {\r\n console.error('[WASM] Failed to load Go WASM module:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load the Go WASM runtime script\r\n */\r\nasync function loadGoRuntime(path: string = DEFAULT_GO_WASM_PATH): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n \r\n // Check if Go runtime is already loaded\r\n if (typeof (window as any).Go !== 'undefined') {\r\n return;\r\n }\r\n \r\n // Load the Go WASM runtime script\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = path;\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error(`Failed to load Go WASM runtime from ${path}`));\r\n document.head.appendChild(script);\r\n });\r\n}\r\n\r\n/**\r\n * Create a TypeScript-friendly wrapper for Go WASM functions\r\n */\r\nexport function createTypedWasmFunction<T extends (...args: any[]) => any>(\r\n instance: GoWasmInstance,\r\n functionName: string\r\n): T {\r\n if (!instance.functions[functionName]) {\r\n throw new Error(`WASM function \"${functionName}\" not found`);\r\n }\r\n \r\n return instance.functions[functionName] as T;\r\n}\r\n\r\n/**\r\n * Helper to convert JavaScript values to Go-compatible formats\r\n */\r\nexport const goValues = {\r\n // Convert JS string to Go string (returns memory pointer)\r\n stringToGo: (instance: GoWasmInstance, str: string): number => {\r\n if (!instance.functions.__stringToGo) {\r\n throw new Error('__stringToGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringToGo(str);\r\n },\r\n \r\n // Convert Go string (memory pointer) to JS string\r\n stringFromGo: (instance: GoWasmInstance, ptr: number): string => {\r\n if (!instance.functions.__stringFromGo) {\r\n throw new Error('__stringFromGo function not found in WASM module');\r\n }\r\n return instance.functions.__stringFromGo(ptr);\r\n },\r\n \r\n // Convert JS object to Go (returns memory pointer)\r\n objectToGo: (instance: GoWasmInstance, obj: any): number => {\r\n if (!instance.functions.__objectToGo) {\r\n throw new Error('__objectToGo function not found in WASM module');\r\n }\r\n return instance.functions.__objectToGo(JSON.stringify(obj));\r\n },\r\n \r\n // Convert Go object (memory pointer) to JS object\r\n objectFromGo: (instance: GoWasmInstance, ptr: number): any => {\r\n if (!instance.functions.__objectFromGo) {\r\n throw new Error('__objectFromGo function not found in WASM module');\r\n }\r\n const str = instance.functions.__objectFromGo(ptr);\r\n return JSON.parse(str);\r\n }\r\n};\r\n","interface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n key?: string | number;\r\n}\r\n\r\nfunction arePropsEqual(oldProps: any, newProps: any): boolean {\r\n const oldKeys = Object.keys(oldProps).filter(k => k !== 'children');\r\n const newKeys = Object.keys(newProps).filter(k => k !== 'children');\r\n \r\n if (oldKeys.length !== newKeys.length) return false;\r\n return oldKeys.every(key => oldProps[key] === newProps[key]);\r\n}\r\n\r\nexport function diff(oldNode: VNode | any, newNode: VNode | any): boolean {\r\n if (oldNode == null || newNode == null) return oldNode !== newNode;\r\n if (typeof oldNode !== typeof newNode) return true;\r\n if (typeof newNode === 'string' || typeof newNode === 'number')\r\n return oldNode !== newNode;\r\n if (newNode.type !== oldNode.type) return true;\r\n return !arePropsEqual(oldNode.props, newNode.props);\r\n}\r\n\r\nexport function shouldComponentUpdate(oldProps: any, newProps: any): boolean {\r\n return !arePropsEqual(oldProps, newProps);\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\n\r\nexport class Component {\r\n state: any = {};\r\n props: any;\r\n element: HTMLElement | null = null;\r\n private _mounted: boolean = false;\r\n\r\n constructor(props: any = {}) {\r\n this.props = props;\r\n }\r\n\r\n componentDidMount() {\r\n // Hook for after component is mounted\r\n }\r\n\r\n async setState(newState: any) {\r\n const prevState = { ...this.state };\r\n this.state = { ...prevState, ...newState };\r\n console.log(`${this.constructor.name} state updated:`, {\r\n prev: prevState,\r\n next: this.state\r\n });\r\n \r\n await Promise.resolve(); // Ensure state is updated before re-render\r\n if (this._mounted) {\r\n await this.update();\r\n } else {\r\n await this.update();\r\n }\r\n }\r\n\r\n private _replayEvents(oldElement: HTMLElement, newElement: HTMLElement) {\r\n const oldEvents = (oldElement as any).__events || {};\r\n Object.entries(oldEvents).forEach(([event, handler]) => {\r\n newElement.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n (newElement as any).__events = oldEvents;\r\n }\r\n\r\n private _deepCloneWithEvents(node: HTMLElement): HTMLElement {\r\n const clone = node.cloneNode(false) as HTMLElement;\r\n \r\n // Copy events from original element\r\n const events = (node as any).__events || {};\r\n (clone as any).__events = events;\r\n Object.entries(events).forEach(([event, handler]) => {\r\n clone.addEventListener(event as keyof HTMLElementEventMap, handler as EventListener);\r\n });\r\n\r\n // Clone children\r\n Array.from(node.childNodes).forEach(child => {\r\n if (child instanceof HTMLElement) {\r\n clone.appendChild(this._deepCloneWithEvents(child));\r\n } else {\r\n clone.appendChild(child.cloneNode(true));\r\n }\r\n });\r\n\r\n return clone;\r\n }\r\n\r\n async update() {\r\n const vdom = this.render();\r\n if (!vdom) return document.createTextNode('');\r\n \r\n const rendered = await createElement(vdom);\r\n if (rendered instanceof HTMLElement) {\r\n return this._updateElement(rendered);\r\n }\r\n \r\n const wrapper = document.createElement('div');\r\n wrapper.appendChild(rendered);\r\n return this._updateElement(wrapper);\r\n }\r\n\r\n private async _updateElement(rendered: HTMLElement) {\r\n const newElement = this._deepCloneWithEvents(rendered);\r\n (newElement as any).__instance = this;\r\n \r\n if (!this.element) {\r\n this.element = newElement;\r\n if (!this._mounted) {\r\n this._mounted = true;\r\n queueMicrotask(() => this.componentDidMount());\r\n }\r\n } else if (this.element.parentNode) {\r\n this.element.parentNode.replaceChild(newElement, this.element);\r\n this.element = newElement;\r\n }\r\n \r\n return this.element;\r\n }\r\n\r\n render(): any {\r\n throw new Error('Component must implement render() method');\r\n }\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks.js';\r\nimport { \r\n loadGoWasm as loadGoWasmImpl, \r\n createTypedWasmFunction as createTypedWasmFunctionImpl,\r\n goValues as goValuesImpl,\r\n type GoWasmInstance,\r\n type GoWasmOptions\r\n} from './wasm.js';\r\n\r\n// Import items needed for the default export\r\nimport { jsx, jsxs, jsxDEV, Fragment } from './jsx-runtime.js';\r\nimport { render, hydrate } from './renderer.js';\r\nimport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary\r\n} from './hooks.js';\r\nimport { createContext } from './context.js';\r\nimport { renderToString } from './server-renderer.js';\r\nimport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\nimport { diff, shouldComponentUpdate } from './vdom.js';\r\nimport { Component } from './component.js';\r\n\r\n// Re-export core modules with explicit names to ensure they appear in bundle\r\nexport { render, hydrate } from './renderer.js';\r\nexport { \r\n jsx, \r\n jsxs, \r\n jsxDEV,\r\n Fragment, \r\n createElement \r\n} from './jsx-runtime.js';\r\n\r\nexport { \r\n useState, \r\n useEffect,\r\n useMemo, \r\n useRef, \r\n useContext,\r\n useErrorBoundary,\r\n prepareRender,\r\n finishRender,\r\n setRenderCallback\r\n} from './hooks.js';\r\n\r\n// Context API\r\nexport { createContext } from './context.js';\r\n\r\n// Server-side rendering\r\nexport { renderToString } from './server-renderer.js';\r\n\r\n// Batch updates utility\r\nexport { batchUpdates, isBatching, getIsBatching } from './batch.js';\r\n\r\n// VDOM utilities\r\nexport { diff, shouldComponentUpdate } from './vdom.js';\r\n\r\n// Export Component class\r\nexport { Component } from './component.js';\r\n\r\n// Server module stub for browser environments\r\nexport const server = {\r\n async getServer() {\r\n throw new Error(\"Server module can only be used in Node.js environment\");\r\n }\r\n};\r\n\r\n// Export WASM functionality explicitly\r\nexport const loadGoWasm = loadGoWasmImpl;\r\nexport const createTypedWasmFunction = createTypedWasmFunctionImpl;\r\nexport const goValues = goValuesImpl;\r\nexport type { GoWasmInstance, GoWasmOptions } from './wasm.js';\r\n\r\n// Add wasm object to ensure compatibility with existing dist/index.js\r\nexport const wasm = {\r\n loadGoWasm: loadGoWasmImpl,\r\n createTypedWasmFunction: createTypedWasmFunctionImpl,\r\n goValues: goValuesImpl\r\n};\r\n\r\n// Re-export types\r\nexport type { Context } from './context.js';\r\nexport type { VNode } from './types.js';\r\n\r\n// Export server types from the safe type-only file\r\nexport type { \r\n Server, \r\n ServerConfig, \r\n User, \r\n DbConfig, \r\n MiddlewareFunction \r\n} from './server-types.js';\r\n\r\n// Export this so it can be properly identified in the bundle\r\nexport let isHydrating = false;\r\n\r\n// Default export for compatibility with some module systems\r\nexport default {\r\n Fragment,\r\n jsx,\r\n jsxs,\r\n createElement,\r\n render, \r\n hydrate,\r\n useState,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useContext,\r\n useErrorBoundary,\r\n createContext,\r\n renderToString,\r\n batchUpdates,\r\n server,\r\n loadGoWasm,\r\n createTypedWasmFunction,\r\n goValues,\r\n wasm,\r\n Component,\r\n diff,\r\n shouldComponentUpdate\r\n // Server functionality is exposed through the server export\r\n};\r\n"],"names":["loadGoWasm","createTypedWasmFunction","goValues","loadGoWasmImpl","createTypedWasmFunctionImpl","goValuesImpl","jsxs"],"mappings":"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"}
|
package/package.json
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
import { useState } from 'frontend-hamroun';
|
2
|
+
export function App() {
|
3
|
+
// Initialize with a default state that works on both server and client
|
4
|
+
const [count, setCount] = useState(0);
|
5
|
+
return (<div>
|
6
|
+
<h1>Server-Side Rendered App</h1>
|
7
|
+
<div>
|
8
|
+
<button onClick={() => setCount(count - 1)} data-action="decrement">-</button>
|
9
|
+
<span style={{ margin: '0 10px' }}>{count}</span>
|
10
|
+
<button onClick={() => setCount(count + 1)} data-action="increment">+</button>
|
11
|
+
</div>
|
12
|
+
<script dangerouslySetInnerHTML={{
|
13
|
+
__html: `window.__INITIAL_STATE__ = ${JSON.stringify({ count: 0 })};`
|
14
|
+
}}/>
|
15
|
+
</div>);
|
16
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { useState, useEffect } from 'frontend-hamroun';
|
2
|
+
export function Counter({ initial = 0 }) {
|
3
|
+
const [count, setCount] = useState(initial);
|
4
|
+
useEffect(() => {
|
5
|
+
document.title = `Count: ${count}`;
|
6
|
+
}, [count]);
|
7
|
+
return (<div>
|
8
|
+
<h2>Counter Component</h2>
|
9
|
+
<button onClick={() => setCount(count - 1)}>-</button>
|
10
|
+
<span style={{ margin: '0 10px' }}>{count}</span>
|
11
|
+
<button onClick={() => setCount(count + 1)}>+</button>
|
12
|
+
</div>);
|
13
|
+
}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import { render, useState, useEffect, useMemo, useRef, useErrorBoundary, createContext, useContext } from 'frontend-hamroun';
|
2
|
+
import './main.css';
|
3
|
+
// Create a theme context
|
4
|
+
const ThemeContext = createContext('light');
|
5
|
+
// Create a component that will throw an error when clicked
|
6
|
+
function BuggyComponent() {
|
7
|
+
const [shouldError, setShouldError] = useState(false);
|
8
|
+
if (shouldError) {
|
9
|
+
throw new Error("Test error from BuggyComponent");
|
10
|
+
}
|
11
|
+
return (<button onClick={() => setShouldError(true)} className="bg-red-600 text-white px-4 py-2 rounded mt-4 hover:bg-red-700">
|
12
|
+
Trigger Error
|
13
|
+
</button>);
|
14
|
+
}
|
15
|
+
function App() {
|
16
|
+
const [count, setCount] = useState(0);
|
17
|
+
const [theme, setTheme] = useState('light');
|
18
|
+
const renderCount = useRef(0);
|
19
|
+
const [error, resetError] = useErrorBoundary();
|
20
|
+
// Demonstrate useEffect
|
21
|
+
useEffect(() => {
|
22
|
+
document.title = `Count: ${count}`;
|
23
|
+
renderCount.current += 1;
|
24
|
+
return () => {
|
25
|
+
console.log('Cleanup effect');
|
26
|
+
};
|
27
|
+
}, [count]);
|
28
|
+
// Demonstrate useMemo
|
29
|
+
const doubled = useMemo(() => count * 2, [count]);
|
30
|
+
if (error) {
|
31
|
+
return (<div className="p-8 max-w-md mx-auto bg-red-50 rounded-lg shadow-lg">
|
32
|
+
<h1 className="text-2xl font-bold text-red-600 mb-4">Something went wrong!</h1>
|
33
|
+
<button onClick={resetError} className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">
|
34
|
+
Try again
|
35
|
+
</button>
|
36
|
+
</div>);
|
37
|
+
}
|
38
|
+
return (<ThemeContext.Provider value={theme}>
|
39
|
+
<div className={`p-8 max-w-4xl mx-auto rounded-lg shadow-lg transition-colors ${theme === 'dark'
|
40
|
+
? 'bg-gray-800 text-white'
|
41
|
+
: 'bg-white text-gray-900'}`}>
|
42
|
+
<h1 className="text-3xl font-bold mb-6">Welcome to Frontend Hamroun</h1>
|
43
|
+
|
44
|
+
<div className="mb-6">
|
45
|
+
<button onClick={() => setCount(count - 1)} className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">-</button>
|
46
|
+
<span className="mx-4 text-xl">{count}</span>
|
47
|
+
<button onClick={() => setCount(count + 1)} className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">+</button>
|
48
|
+
</div>
|
49
|
+
|
50
|
+
<p className="mb-2 text-lg">Doubled value: <span className="font-semibold">{doubled}</span></p>
|
51
|
+
<p className="mb-4 text-lg">Render count: <span className="font-semibold">{renderCount.current}</span></p>
|
52
|
+
|
53
|
+
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')} className={`px-4 py-2 rounded mb-8 ${theme === 'dark'
|
54
|
+
? 'bg-yellow-400 text-gray-900 hover:bg-yellow-300'
|
55
|
+
: 'bg-gray-800 text-white hover:bg-gray-700'}`}>
|
56
|
+
Toggle Theme ({theme})
|
57
|
+
</button>
|
58
|
+
|
59
|
+
<div className="mt-8 border-t pt-6">
|
60
|
+
<h2 className="text-2xl font-bold mb-4">Test Error Boundary</h2>
|
61
|
+
<BuggyComponent />
|
62
|
+
</div>
|
63
|
+
|
64
|
+
<div className="mt-8 border-t pt-6">
|
65
|
+
<h2 className="text-2xl font-bold mb-4">Test Context</h2>
|
66
|
+
<ContextConsumer />
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
</ThemeContext.Provider>);
|
70
|
+
}
|
71
|
+
// Component to test context
|
72
|
+
function ContextConsumer() {
|
73
|
+
// Get the full context object for debugging
|
74
|
+
const themeContext = useContext(ThemeContext);
|
75
|
+
console.log('Theme context object:', themeContext);
|
76
|
+
// Access the current theme from the parent component instead
|
77
|
+
// This is a workaround until context is properly implemented
|
78
|
+
return (<div className={`mt-4 p-4 rounded-md border ${themeContext === 'dark' ? 'border-gray-600' : 'border-gray-300'}`}>
|
79
|
+
<p className="mb-2"><strong>Note:</strong> Context API needs a fix in the framework.</p>
|
80
|
+
<p className="mb-1">Context object type: {typeof themeContext}</p>
|
81
|
+
<p className="mb-4">Context object keys: {Object.keys(themeContext).join(', ') || 'none'}</p>
|
82
|
+
|
83
|
+
<button onClick={() => {
|
84
|
+
// Since we can't get the value directly from context,
|
85
|
+
// Let's add a button to demonstrate we can still use the Provider
|
86
|
+
const newTheme = document.body.style.backgroundColor === 'rgb(51, 51, 51)'
|
87
|
+
? 'light' : 'dark';
|
88
|
+
console.log('Manually changing theme to:', newTheme);
|
89
|
+
// This won't work yet, but demonstrates the intent
|
90
|
+
if (ThemeContext) {
|
91
|
+
console.log('Provider exists, would set value to:', newTheme);
|
92
|
+
}
|
93
|
+
}} className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded">
|
94
|
+
Check Context Implementation
|
95
|
+
</button>
|
96
|
+
</div>);
|
97
|
+
}
|
98
|
+
render(<App />, document.getElementById('root'));
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import express from 'express';
|
2
|
+
import path from 'path';
|
3
|
+
import { fileURLToPath } from 'url';
|
4
|
+
import { renderToString, jsx } from 'frontend-hamroun';
|
5
|
+
import { App } from './App.js';
|
6
|
+
import fs from 'fs';
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
8
|
+
const app = express();
|
9
|
+
const port = 3000;
|
10
|
+
// Find the client entry file
|
11
|
+
function getClientEntry() {
|
12
|
+
const assetsDir = path.join(__dirname, './');
|
13
|
+
const files = fs.readdirSync(assetsDir);
|
14
|
+
const entry = files.find(file => file.startsWith("client") && file.endsWith('.js'));
|
15
|
+
if (!entry) {
|
16
|
+
throw new Error('Client entry file not found');
|
17
|
+
}
|
18
|
+
return entry;
|
19
|
+
}
|
20
|
+
// Static file serving
|
21
|
+
app.use('/assets', express.static(path.join(__dirname, './')));
|
22
|
+
app.use(express.static(path.join(__dirname, 'dist')));
|
23
|
+
// Main route handler
|
24
|
+
app.get('/', async (_req, res) => {
|
25
|
+
try {
|
26
|
+
const clientEntry = getClientEntry();
|
27
|
+
const html = await renderToString({
|
28
|
+
element: jsx(App, null),
|
29
|
+
title: 'SSR App',
|
30
|
+
scripts: [`/assets/${clientEntry}`],
|
31
|
+
initialState: {
|
32
|
+
// Add any initial state here
|
33
|
+
},
|
34
|
+
meta: {
|
35
|
+
'viewport': 'width=device-width, initial-scale=1.0',
|
36
|
+
}
|
37
|
+
});
|
38
|
+
res.send(html);
|
39
|
+
}
|
40
|
+
catch (error) {
|
41
|
+
console.error('Rendering error:', error);
|
42
|
+
res.status(500).send('Server Error');
|
43
|
+
}
|
44
|
+
});
|
45
|
+
app.listen(port, () => {
|
46
|
+
console.log(`Server running at http://localhost:${port}`);
|
47
|
+
});
|
File without changes
|
@@ -0,0 +1,182 @@
|
|
1
|
+
/**
|
2
|
+
* Simple JSX implementation for server-side rendering
|
3
|
+
*/
|
4
|
+
|
5
|
+
// Render a virtual DOM node to HTML string
|
6
|
+
export function renderToString(vnode) {
|
7
|
+
// Handle null or undefined
|
8
|
+
if (vnode == null) return '';
|
9
|
+
|
10
|
+
// Handle primitive values
|
11
|
+
if (typeof vnode === 'string' || typeof vnode === 'number')
|
12
|
+
return escapeHtml(String(vnode));
|
13
|
+
|
14
|
+
// Handle arrays (like fragments)
|
15
|
+
if (Array.isArray(vnode))
|
16
|
+
return vnode.map(renderToString).join('');
|
17
|
+
|
18
|
+
// Handle functional components
|
19
|
+
if (typeof vnode.type === 'function') {
|
20
|
+
try {
|
21
|
+
const result = vnode.type(vnode.props || {});
|
22
|
+
return renderToString(result);
|
23
|
+
} catch (err) {
|
24
|
+
console.error('Error rendering component:', err);
|
25
|
+
return `<div class="error">Error: ${escapeHtml(err.message)}</div>`;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
// Handle Fragment
|
30
|
+
if (vnode.type === Symbol.for('react.fragment')) {
|
31
|
+
return renderToString(vnode.props.children);
|
32
|
+
}
|
33
|
+
|
34
|
+
// Handle regular DOM elements
|
35
|
+
if (typeof vnode.type === 'string') {
|
36
|
+
let props = vnode.props || {};
|
37
|
+
let children = props.children || [];
|
38
|
+
if (!Array.isArray(children)) {
|
39
|
+
children = [children];
|
40
|
+
}
|
41
|
+
|
42
|
+
// Build opening tag with attributes
|
43
|
+
let html = `<${vnode.type}`;
|
44
|
+
|
45
|
+
for (const [key, value] of Object.entries(props)) {
|
46
|
+
if (key === 'children' || key === 'dangerouslySetInnerHTML') continue;
|
47
|
+
|
48
|
+
// Handle event handlers (they should be ignored in SSR)
|
49
|
+
if (key.startsWith('on')) continue;
|
50
|
+
|
51
|
+
// Handle className -> class
|
52
|
+
if (key === 'className') {
|
53
|
+
html += ` class="${escapeHtml(value)}"`;
|
54
|
+
continue;
|
55
|
+
}
|
56
|
+
|
57
|
+
// Handle style objects
|
58
|
+
if (key === 'style' && typeof value === 'object') {
|
59
|
+
const styleStr = Object.entries(value)
|
60
|
+
.map(([k, v]) => `${kebabCase(k)}:${v}`)
|
61
|
+
.join(';');
|
62
|
+
html += ` style="${escapeHtml(styleStr)}"`;
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
|
66
|
+
// Handle boolean attributes
|
67
|
+
if (value === true) {
|
68
|
+
html += ` ${key}`;
|
69
|
+
continue;
|
70
|
+
}
|
71
|
+
|
72
|
+
// Skip false boolean attributes
|
73
|
+
if (value === false) continue;
|
74
|
+
|
75
|
+
// Regular attributes
|
76
|
+
if (value != null) {
|
77
|
+
html += ` ${key}="${escapeHtml(value)}"`;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
// Handle self-closing tags
|
82
|
+
const selfClosing = ['img', 'input', 'br', 'hr', 'meta', 'link', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];
|
83
|
+
if (selfClosing.includes(vnode.type)) {
|
84
|
+
return `${html} />`;
|
85
|
+
}
|
86
|
+
|
87
|
+
// Add closing bracket for opening tag
|
88
|
+
html += '>';
|
89
|
+
|
90
|
+
// Handle dangerouslySetInnerHTML
|
91
|
+
if (props.dangerouslySetInnerHTML) {
|
92
|
+
html += props.dangerouslySetInnerHTML.__html || '';
|
93
|
+
} else {
|
94
|
+
// Add children
|
95
|
+
for (const child of children) {
|
96
|
+
html += renderToString(child);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
// Add closing tag
|
101
|
+
html += `</${vnode.type}>`;
|
102
|
+
|
103
|
+
return html;
|
104
|
+
}
|
105
|
+
|
106
|
+
// Unknown node type
|
107
|
+
console.warn('Unknown vnode type:', vnode.type);
|
108
|
+
return '';
|
109
|
+
}
|
110
|
+
|
111
|
+
// Create a JSX element
|
112
|
+
export function jsx(type, props, ...children) {
|
113
|
+
props = props || {};
|
114
|
+
if (children.length) {
|
115
|
+
props.children = children.length === 1 ? children[0] : children;
|
116
|
+
}
|
117
|
+
return { type, props };
|
118
|
+
}
|
119
|
+
|
120
|
+
// Helper for escaping HTML
|
121
|
+
function escapeHtml(str) {
|
122
|
+
return String(str)
|
123
|
+
.replace(/&/g, '&')
|
124
|
+
.replace(/</g, '<')
|
125
|
+
.replace(/>/g, '>')
|
126
|
+
.replace(/"/g, '"')
|
127
|
+
.replace(/'/g, ''');
|
128
|
+
}
|
129
|
+
|
130
|
+
// Helper to convert camelCase to kebab-case for CSS properties
|
131
|
+
function kebabCase(str) {
|
132
|
+
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
133
|
+
}
|
134
|
+
|
135
|
+
// Create a basic requestLogger middleware
|
136
|
+
export function requestLogger(req, res, next) {
|
137
|
+
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
|
138
|
+
next();
|
139
|
+
}
|
140
|
+
|
141
|
+
// Create a basic error handler middleware
|
142
|
+
export function errorHandler(err, req, res, next) {
|
143
|
+
console.error('Server error:', err);
|
144
|
+
res.status(500).send('Server Error');
|
145
|
+
}
|
146
|
+
|
147
|
+
// Create a basic 404 handler middleware
|
148
|
+
export function notFoundHandler(req, res) {
|
149
|
+
res.status(404).send('Not Found');
|
150
|
+
}
|
151
|
+
|
152
|
+
// Create a basic rate limiter middleware
|
153
|
+
export function rateLimit(options = { windowMs: 60000, max: 100 }) {
|
154
|
+
const requests = new Map();
|
155
|
+
|
156
|
+
return (req, res, next) => {
|
157
|
+
const ip = req.ip || 'unknown';
|
158
|
+
const now = Date.now();
|
159
|
+
|
160
|
+
if (!requests.has(ip)) {
|
161
|
+
requests.set(ip, []);
|
162
|
+
}
|
163
|
+
|
164
|
+
const reqs = requests.get(ip);
|
165
|
+
const validReqs = reqs.filter(time => now - time < options.windowMs);
|
166
|
+
|
167
|
+
validReqs.push(now);
|
168
|
+
requests.set(ip, validReqs);
|
169
|
+
|
170
|
+
if (validReqs.length > options.max) {
|
171
|
+
return res.status(429).send('Too Many Requests');
|
172
|
+
}
|
173
|
+
|
174
|
+
next();
|
175
|
+
};
|
176
|
+
}
|
177
|
+
|
178
|
+
// Export other necessary functions
|
179
|
+
export const Fragment = Symbol.for('react.fragment');
|
180
|
+
export function loadGoWasmFromFile() {
|
181
|
+
throw new Error('WASM not supported in this environment');
|
182
|
+
}
|