{"_id":"@damian88/nestjs","name":"@damian88/nestjs","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@damian88/nestjs","version":"0.0.1","main":"./dist/index.js","types":"./dist/index.ts","exports":{".":{"require":"./dist/index.js","import":"./dist/index.js"}},"repository":{"type":"github","url":"git+https://github.com/Damian-Mostert/nestreact-view.git"},"publishConfig":{"access":"public"},"keywords":["nest","react","engine","nestreact-view","view"],"description":"","author":{"name":"Damian Mostert"},"private":false,"license":"UNLICENSED","scripts":{"build":"tsup src --dts --format esm,cjs --out-dir dist"},"dependencies":{"@nestjs/common":"^11.0.1","@nestjs/config":"^4.0.2","@nestjs/core":"^11.0.1","@nestjs/mongoose":"^11.0.3","@nestjs/platform-express":"^11.0.1","@nestjs/serve-static":"^5.0.3","@nestjs/typeorm":"^11.0.0","@types/react":"^19.1.1","@types/react-dom":"^19.1.2","@vitejs/plugin-react":"^4.3.4","esbuild":"^0.25.2","react":"19.1.0","react-dom":"^19.1.0","tsup":"^8.4.0"},"devDependencies":{"@eslint/eslintrc":"^3.2.0","@eslint/js":"^9.18.0","@nestjs/cli":"^11.0.0","@nestjs/schematics":"^11.0.0","@nestjs/testing":"^11.0.1","@swc/cli":"^0.6.0","@swc/core":"^1.10.7","@types/express":"^5.0.0","@types/jest":"^29.5.14","@types/node":"^22.10.7","@types/supertest":"^6.0.2","autoprefixer":"^10.4.21","eslint":"^9.18.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2","globals":"^16.0.0","jest":"^29.7.0","postcss":"^8.5.3","source-map-support":"^0.5.21","supertest":"^7.0.0","ts-jest":"^29.2.5","ts-loader":"^9.5.2","ts-node":"^10.9.2","tsconfig-paths":"^4.2.0","typescript":"^5.7.3","typescript-eslint":"^8.20.0"},"jest":{"moduleFileExtensions":["js","json","ts"],"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"collectCoverageFrom":["**/*.(t|j)s"],"coverageDirectory":"../coverage","testEnvironment":"node"},"_id":"@damian88/nestjs@0.0.1","gitHead":"0ddf433cdcf0fe8f5d0467a019efad47bcdc8057","bugs":{"url":"https://github.com/Damian-Mostert/nestreact-view/issues"},"homepage":"https://github.com/Damian-Mostert/nestreact-view#readme","_nodeVersion":"20.11.1","_npmVersion":"10.2.4","dist":{"integrity":"sha512-83A9oSeErrRmmIp1Be8A8RAJRX7xtjkESuyolzcDH0euV4i4jcIz0c4fFmApyu/2z7vq+lauOzsOvHYCNkWqmg==","shasum":"3490578d77ce68bd7d2319502d9c0736bac7b0ec","tarball":"https://registry.npmjs.org/@damian88/nestjs/-/nestjs-0.0.1.tgz","fileCount":18,"unpackedSize":45272,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDHWYS9URavPAcQyVpP0TMqjlnNvQtXOFPIUgp8LpFNYAIgYU7SVrdfjtDC5JTmFV31PMElEvasQMm6KV4GYNCmL2o="}]},"_npmUser":{"name":"damian88","email":"damianmostert86@gmail.com"},"directories":{},"maintainers":[{"name":"damian88","email":"damianmostert86@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs_0.0.1_1745090547986_0.13083636834388046"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-19T19:22:27.909Z","0.0.1":"2025-04-19T19:22:28.256Z","modified":"2025-04-19T19:22:28.505Z"},"maintainers":[{"name":"damian88","email":"damianmostert86@gmail.com"}],"homepage":"https://github.com/Damian-Mostert/nestreact-view#readme","keywords":["nest","react","engine","nestreact-view","view"],"repository":{"type":"github","url":"git+https://github.com/Damian-Mostert/nestreact-view.git"},"author":{"name":"Damian Mostert"},"bugs":{"url":"https://github.com/Damian-Mostert/nestreact-view/issues"},"license":"UNLICENSED","readme":"# nestreact-view [![npm version](https://img.shields.io/npm/v/nestreact-view)](https://www.npmjs.com/package/nestreact-view)\n\n\n**Render React views with server-side support and client-side hydration inside your NestJS or Express app.**\n\n`nestreact-view` brings the power of React JSX templates to your NestJS or Express backend. It provides a decorator-based syntax for defining server-side and client-side components, full support for third-party libraries, and seamless SSR-to-hydration transitions — all with zero Webpack config or Babel setup required.\n\n---\n\n## ✨ Features\n\n- ✅ Server-side rendering with React in NestJS / Express\n- 🔁 Seamless hydration of client-side components\n- ⚙️ Use third-party libraries (like `react-parallax-tilt`) directly on the client\n- 🧠 Decorator-based syntax for organizing views\n- 🎯 TypeScript-first design with inferred props and module support\n- 🧩 Works with `res.render()` and native Express/Nest views\n- 💻 No client-side build system required — pure Node runtime\n\n---\n\n## 📦 Installation\n\nInstall via npm or yarn:\n\n```bash\nnpm install nestreact-view\n```\n\n## ⚙️ Setup\nIn your nest server add the following to your main.ts\n```ts\nimport  NestReactEngin from 'nestreact-view';\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n  NestReactEngine(app);\n  await app.listen(process.env.PORT ?? 3000);\n}\nbootstrap();\n\n```\nyou can now use `res.render(\"templateName\",{props})` to render a tsx template as \"src/views/${templateName}\".tsx, or you can use built in nest functions to render a template:\n```tsx\nimport { Controller, Get, Post, Render, Req, Res } from '@nestjs/common';\nimport { Request, Response } from 'express';\n\n@Controller()\nexport class ApiController {\n\t@Get('/')\n\t@Render(\"home\")\n\tHome(@Req() req: Request, @Res() res: Response) {\n\t\treturn { hello: 'who are you?' }\n\t}\n}\n```\n\n## Template Tools\n```tsx\nimport { Use, Server, Render, Client, Component } from 'nestreact-view';\n```\n\n\n#### ⚙️ Server & Render\n\nUsing @Server class defines the server side template, You will get passed The client side components difined in @client\n```tsx\n@Server()\nclass $ {\n\t@Render() async render({ Client }: { Client: ClientSide }) {\n\t\treturn (\n\t\t\t<html>\n\t\t\t\t<head>\n\t\t\t\t\t<title>Test</title>\n\t\t\t\t</head>\n\t\t\t\t<body>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\t\tgap: '4rem',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n                        {/*Render client side components*/}\n\t\t\t\t\t\t<Client.Header test=\"Header Test\" />\n\t\t\t\t\t\t<Client.Home test=\"Home Test\" />\n\t\t\t\t\t\t<Client.Footer test=\"Footer Test\" />\n\t\t\t\t\t</div>\n\t\t\t\t</body>\n\t\t\t</html>\n\t\t);\n\t}\n}\n\n```\n#### 💻 Client\n@Client is used to define client side components, Components defined here will be passed to the server in an Object as seen in the example above.\n```tsx\n@Client()\n@Use({\n\t//...modules\n})\nclass ClientSide {\n\t///...components\n}\n```\n#### 🧩 Component\n@Component is used to difine a client side component, works like `@Component(containerElementType:string) Callback(props:any){return<></>}`\n```tsx\nclass ClientSide {\n\t@Component('footer') Footer(props: { test: string }) {\n\t\treturn <>Footer says: {props.test}</>;\n\t}\n}\n```\n#### 📦 Use\n\nYou can pass third-party React libraries to the client using the @Use() decorator.\n\n```tsx\n//Import modules for type declarations\nimport React from 'react';\nimport * as Tilt from 'react-parallax-tilt';\n\n@Client\n@Use({\n  React: 'react',\n  MyUI: 'my-ui-lib',\n  Tilt: 'react-parallax-tilt',\n})class Callback{}\n```\n\nThen use them in any @Component(containerElementType:string) like this, you might need to use .default:\n```tsx\n@Client\n@Use({\n  React: 'react',\n  MyUI: 'my-ui-lib',\n  Tilt: 'react-parallax-tilt',\n})class ClientSide {\n\t@Component('footer') Footer(props: { test: string }) {\n\t\treturn <>\n\t\t<MyUI.Button>Click Me</MyUI.Button>\n\t\t<Tilt.default>Fancy Tilt Box</Tilt.default>\n\t\t</>\n\t}\n}\n```\n## Example views\n\n```tsx\nimport { Server, Render, Client, Component, Use } from 'nestreact-view';\n\n@Server()\nclass $ {\n  @Render()\n  render({ Client }: { Client: ClientSide }) {\n    return (\n      <html>\n        <head>\n          <title>Welcome</title>\n        </head>\n        <body>\n          <h1>Hello from the server!</h1>\n          <Client.Greeting name=\"Damian\" />\n        </body>\n      </html>\n    );\n  }\n}\n\n@Client()\n@Use({ React: 'react' })\nclass ClientSide {\n  @Component('div') Greeting(props: { name: string }) {\n    return <p>Welcome, {props.name}! 🎉</p>;\n  }\n}\n```\n```tsx\n@Server()\nclass $ {\n  async fetchData() {\n    // Simulate async data fetching\n    return new Promise<string>((res) => setTimeout(() => res('Server Data'), 100));\n  }\n\n  @Render()\n  async render({ Client }: { Client: ClientSide }) {\n    const data = await this.fetchData();\n    return (\n      <html>\n        <head>\n          <title>Dynamic Page</title>\n        </head>\n        <body>\n          <Client.Loader text={data} />\n        </body>\n      </html>\n    );\n  }\n}\n\n@Client()\n@Use({ React: 'react' })\nclass ClientSide {\n  @Component('section') Loader(props: { text: string }) {\n    const [loaded, setLoaded] = React.useState(false);\n\n    React.useEffect(() => {\n      setTimeout(() => setLoaded(true), 1000);\n    }, []);\n\n    return <>{loaded ? <strong>{props.text}</strong> : 'Loading...'}</>;\n  }\n}\n```\n```tsx\n@Server()\nclass $ {\n  @Render()\n  render({ Client }: { Client: ClientSide }) {\n    return (\n      <html>\n        <head>\n          <title>Navigation Example</title>\n        </head>\n        <body>\n          <nav>\n            <a href=\"/\">Home</a> | <a href=\"/about\">About</a>\n          </nav>\n          <Client.Page name=\"Home\" />\n        </body>\n      </html>\n    );\n  }\n}\n\n@Client()\n@Use({ React: 'react' })\nclass ClientSide {\n  @Component('main') Page(props: { name: string }) {\n    return <h2>This is the {props.name} page</h2>;\n  }\n}\n```\n```tsx\n@Server()\nclass $ {\n  @Render()\n  render({ Client }: { Client: ClientSide }) {\n    return (\n      <html>\n        <head>\n          <title>Form Example</title>\n        </head>\n        <body>\n          <h1>Contact Us</h1>\n          <Client.Form />\n        </body>\n      </html>\n    );\n  }\n}\n\n@Client()\n@Use({ React: 'react' })\nclass ClientSide {\n  @Component('form') Form() {\n    const [value, setValue] = React.useState('');\n    const [submitted, setSubmitted] = React.useState(false);\n\n    return (\n      <>\n        <input\n          type=\"text\"\n          value={value}\n          placeholder=\"Your name\"\n          onChange={(e) => setValue(e.target.value)}\n        />\n        <button\n          type=\"button\"\n          onClick={() => {\n            setSubmitted(true);\n          }}\n        >\n          Submit\n        </button>\n        {submitted && <p>Thanks, {value}!</p>}\n      </>\n    );\n  }\n}\n```","readmeFilename":"readme.md","_rev":"1-8faaf002681c1f37322479c96eb5a3f8"}