create-tezx-app 2.0.6 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin +590 -52
  2. package/package.json +1 -1
package/bin CHANGED
@@ -1,5 +1,97 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as H}from"node:child_process";import{mkdirSync as z,writeFileSync as X}from"node:fs";import $,{join as Y,resolve as J}from"node:path";import _ from"node:readline";var g=(s,n)=>({version:n,npm:["npm install",s],bun:["bun add",s],yarn:["yarn add",s],pnpm:["pnpm add",s]});var I={content:`
2
+ import{execSync as K}from"node:child_process";import{mkdirSync as j,writeFileSync as Y}from"node:fs";import E,{join as q,resolve as Q}from"node:path";import P from"node:readline";var p=(n,s)=>({version:s,npm:["npm install",n],bun:["bun add",n],yarn:["yarn add",n],pnpm:["pnpm add",n]});var I={readme:`
3
+ # \u{1F510} GitHub OAuth2 Example for TezX
4
+
5
+ This example demonstrates how to implement GitHub OAuth2 login using \`@tezx/github-oauth2\`.
6
+
7
+ ---
8
+
9
+ ## \u{1F680} Features
10
+
11
+ - \u{1F510} Redirects users to GitHub for login
12
+ - \u{1F4E5} Handles GitHub's OAuth2 callback
13
+ - \u{1F9D1} Retrieves user profile and creates session
14
+ - \u2699\uFE0F Easy to integrate with any TezX backend
15
+
16
+ ---
17
+
18
+ ## \u{1F527} Setup
19
+
20
+ ### 1. Install the required package
21
+
22
+ \`\`\`bash
23
+ ${Object.values(p("@tezx/github-oauth2","^1.0.3"))?.filter(n=>typeof n!="string")?.join(`
24
+ #or
25
+ `)}
26
+ \`\`\`
27
+
28
+ ### 2. Add environment variables
29
+
30
+ Create a \`.env\` file:
31
+
32
+ \`\`\`env
33
+ GITHUB_CLIENT_ID=your_client_id
34
+ GITHUB_CLIENT_SECRET=your_client_secret
35
+ \`\`\`
36
+
37
+ Make sure you register your OAuth app at:
38
+ > https://github.com/settings/developers
39
+
40
+ Use callback URL:
41
+ \`http://localhost:3000/github/callback\`
42
+
43
+ ---
44
+
45
+ ## \u{1F9EA} Example Flow
46
+
47
+ ### Step 1: Redirect to GitHub login
48
+
49
+ \`\`\`ts
50
+ app.get('/github', getGithubOAuthURL({
51
+ authClient: client,
52
+ }), (ctx) => {
53
+ return ctx.redirect(ctx.state.get('github_oauth_url'));
54
+ });
55
+ \`\`\`
56
+
57
+ ### Step 2: GitHub redirects back \u2192 create session
58
+
59
+ \`\`\`ts
60
+ app.get('/github/callback', verifyGithubToken({
61
+ authClient: client,
62
+ Callbacks: (ctx) => ({
63
+ session: async (session, user) => {
64
+ console.log("Session:", session);
65
+ console.log("User:", user);
66
+ return session;
67
+ }
68
+ }),
69
+ }), async (ctx) => {
70
+ return ctx.json({ success: true });
71
+ });
72
+ \`\`\`
73
+
74
+ ---
75
+
76
+ ## \u{1F4C1} File Structure
77
+
78
+ \`\`\`
79
+ .
80
+ \u251C\u2500\u2500 .env
81
+ \u251C\u2500\u2500 server.ts
82
+ \`\`\`
83
+
84
+ ---
85
+
86
+ ## \u{1F4DA} References
87
+
88
+ - GitHub OAuth Docs: https://docs.github.com/en/developers/apps/building-oauth-apps
89
+ - TezX GitHub OAuth: https://www.npmjs.com/package/@tezx/github-oauth2
90
+
91
+ ---
92
+
93
+ Login securely and build smarter auth with TezX! \u{1F680}
94
+ `.trim(),content:`
3
95
  // 1. Initialize OAuth2 client
4
96
  const client = GitHubOauthClient({
5
97
  clientId: process.env.GITHUB_CLIENT_ID,
@@ -29,47 +121,87 @@ app.get('/github/callback', verifyGithubToken({
29
121
  }), async (ctx) => {
30
122
  return ctx.json({ success: true });
31
123
  });
32
- `,files:[{content:`GITHUB_CLIENT_ID = 12323
33
- GITHUB_CLIENT_SECRET=234234
34
- `,path:".env"}],import:["import { GitHubOauthClient, getGithubOAuthURL, verifyGithubToken } from '@tezx/github-oauth2'; "],package:[g("@tezx/github-oauth2","^1.0.2")]};var G={content:`
35
- // 1. Initialize OAuth2 client
36
- const client = GoogleOauthClient({
37
- clientId: process.env.GOOGLE_CLIENT_ID,
38
- clientSecret: process.env.GOOGLE_CLIENT_SECRET,
39
- redirectUri: 'http://localhost:3000/auth/callback',
40
- });
124
+ `.trim(),files:[{content:`GITHUB_CLIENT_ID=12323
125
+ GITHUB_CLIENT_SECRET=234234`,path:".env"}],import:["import { GitHubOauthClient, getGithubOAuthURL, verifyGithubToken } from '@tezx/github-oauth2';"],package:[p("@tezx/github-oauth2","^1.0.3")]};var G={readme:`
126
+ # \u{1F510} Google OAuth2 Example for TezX
41
127
 
42
- // 2. Route to start Google login
128
+ This example demonstrates how to use \`@tezx/google-oauth2\` to implement Google OAuth2 login in your TezX app.
129
+
130
+ ---
131
+
132
+ ## \u{1F680} Features
133
+
134
+ - Redirects users to Google Sign-In
135
+ - Verifies ID token and fetches user profile
136
+ - Allows role control via email domain or claims
137
+ - Persists session with custom user structure
138
+
139
+ ---
140
+
141
+ ## \u{1F527} Setup Instructions
142
+
143
+ ### 1. Install Required Packages
144
+
145
+ Choose your package manager and install:
146
+
147
+ \`\`\`bash
148
+ ${Object.values(p("@tezx/google-oauth2","^1.0.9")).filter(n=>typeof n!="string").join(`
149
+ # or
150
+ `)}
151
+
152
+ # Plus Google OAuth SDK
153
+ ${Object.values(p("@googleapis/oauth2","^2.0.1")).filter(n=>typeof n!="string").join(`
154
+ # or
155
+ `)}
156
+ \`\`\`
157
+
158
+ ---
159
+
160
+ ### 2. Setup \`.env\`
161
+
162
+ \`\`\`env
163
+ GOOGLE_CLIENT_ID=your-google-client-id
164
+ GOOGLE_CLIENT_SECRET=your-google-client-secret
165
+ \`\`\`
166
+
167
+ > Register your app here: https://console.cloud.google.com/apis/credentials
168
+ > Redirect URI: \`http://localhost:3000/auth/callback\`
169
+
170
+ ---
171
+
172
+ ## \u{1F9EA} Example Route Flow
173
+
174
+ ### \u{1F517} Step 1: Start Google OAuth
175
+
176
+ \`\`\`ts
43
177
  app.get('/auth/google', getGoogleOAuthURL({
44
178
  authClient: client,
45
- scopes: ['openid','email','profile'],
179
+ scopes: ['openid', 'email', 'profile'],
46
180
  }), (ctx) => {
47
181
  return ctx.redirect(ctx.state.get('google_oauth_url'));
48
182
  });
183
+ \`\`\`
49
184
 
50
- // 3. Callback route, verify token and establish session
185
+ ---
186
+
187
+ ### \u2705 Step 2: Callback \u2014 Verify & Create Session
188
+
189
+ \`\`\`ts
51
190
  app.get('/auth/callback', verifyGoogleToken({
52
191
  authClient: client,
53
192
  onError: (err) => {
54
193
  console.error('OAuth Error:', err);
55
- // handle error or redirect
56
194
  },
57
195
  onSuccess: (tokens) => {
58
196
  console.log('Tokens:', tokens);
59
197
  },
60
- Callbacks: (ctx)=> {
61
- return {
62
- signIn: async (user) => {
63
- // e.g. allow only users from a domain
64
- return user.email.endsWith('@yourcompany.com');
65
- },
198
+ Callbacks: (ctx) => ({
199
+ signIn: async (user) => user.email.endsWith('@yourcompany.com'),
66
200
  jwt: async (token, user) => {
67
- // attach roles or custom claims
68
201
  token.role = user.email_verified ? 'member' : 'guest';
69
202
  return token;
70
203
  },
71
204
  session: async (session, user) => {
72
- // persist user profile in session
73
205
  session.user = {
74
206
  id: user.sub,
75
207
  email: user.email,
@@ -78,15 +210,154 @@ app.get('/auth/callback', verifyGoogleToken({
78
210
  };
79
211
  return session;
80
212
  }
81
- }
213
+ })
214
+ }), async (ctx) => {
215
+ return ctx.json({ success: true });
216
+ });
217
+ \`\`\`
218
+
219
+ ---
220
+
221
+ ## \u{1F4C1} File Structure
222
+
223
+ \`\`\`
224
+ .
225
+ \u251C\u2500\u2500 .env
226
+ \u2514\u2500\u2500 server.ts
227
+ \`\`\`
228
+
229
+ ---
230
+
231
+ > \u{1F4A1} Note: TezX OAuth2 uses stateful sessions or JWTs depending on your setup. It supports advanced callback hooks for full control.
232
+
233
+ Secure your apps with Google the easy way \u{1F512}
234
+ `.trim(),content:`
235
+ // 1. Initialize OAuth2 client
236
+ const client = GoogleOauthClient({
237
+ clientId: process.env.GOOGLE_CLIENT_ID,
238
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
239
+ redirectUri: 'http://localhost:3000/auth/callback',
240
+ });
241
+
242
+ // 2. Route to start Google login
243
+ app.get('/auth/google', getGoogleOAuthURL({
244
+ authClient: client,
245
+ scopes: ['openid','email','profile'],
246
+ }), (ctx) => {
247
+ return ctx.redirect(ctx.state.get('google_oauth_url'));
248
+ });
249
+
250
+ // 3. Callback route, verify token and establish session
251
+ app.get('/auth/callback', verifyGoogleToken({
252
+ authClient: client,
253
+ onError: (err) => {
254
+ console.error('OAuth Error:', err);
255
+ },
256
+ onSuccess: (tokens) => {
257
+ console.log('Tokens:', tokens);
258
+ },
259
+ Callbacks: (ctx)=> {
260
+ return {
261
+ signIn: async (user) => {
262
+ return user.email.endsWith('@yourcompany.com');
263
+ },
264
+ jwt: async (token, user) => {
265
+ token.role = user.email_verified ? 'member' : 'guest';
266
+ return token;
267
+ },
268
+ session: async (session, user) => {
269
+ session.user = {
270
+ id: user.sub,
271
+ email: user.email,
272
+ name: user.name,
273
+ picture: user.picture
274
+ };
275
+ return session;
276
+ }
277
+ }
82
278
  }
83
279
  }), async (ctx) => {
84
- // Now ctx.session is populated
85
280
  return ctx.json({ success: true });
86
281
  });
87
- `,files:[{content:`GOOGLE_CLIENT_ID = 12323
282
+ `.trim(),files:[{content:`GOOGLE_CLIENT_ID=12323
88
283
  GOOGLE_CLIENT_SECRET=234234
89
- `,path:".env"}],import:['import { GoogleOauthClient, getGoogleOAuthURL, verifyGoogleToken } from "@tezx/google-oauth2";'],package:[g("@tezx/google-oauth2","^1.0.8"),g("@googleapis/oauth2","^2.0.1")]};var D=`
284
+ `,path:".env"}],import:['import { GoogleOauthClient, getGoogleOAuthURL, verifyGoogleToken } from "@tezx/google-oauth2";'],package:[p("@tezx/google-oauth2","^1.0.9"),p("@googleapis/oauth2","^2.0.1")]};var R={readme:`
285
+ # TezX View Engine Example
286
+
287
+ This example demonstrates how to use the \`@tezx/view-engine\` package to render server-side views using template engines such as **EJS**, **Pug**, **Handlebars**, **Mustache**, or **Nunjucks**.
288
+
289
+ ---
290
+
291
+ ## \u{1F680} How it works
292
+
293
+ The \`ViewEngine\` class handles:
294
+
295
+ - Compiling templates at runtime
296
+ - Injecting dynamic data into views
297
+ - Supporting multiple template engines with the same API
298
+
299
+ ---
300
+
301
+ ## \u{1F4C1} File structure
302
+
303
+ \`\`\`bash
304
+ .src
305
+ \u251C\u2500\u2500 views/
306
+ \u2502 \u2514\u2500\u2500 home.ejs
307
+ \u2514\u2500\u2500 index.ts
308
+ \`\`\`
309
+
310
+ ---
311
+
312
+ ## \u{1F9EA} Example Usage
313
+
314
+ \`\`\`ts
315
+ import { ViewEngine } from "@tezx/view-engine";
316
+
317
+ const views = new ViewEngine("ejs", "./views");
318
+
319
+ app.get("engine", async (ctx) => {
320
+ const html = await views.render("home", {
321
+ title: "TezX SSR Page",
322
+ user: ctx.user || { name: "Guest" },
323
+ });
324
+ return ctx.html(html);
325
+ });
326
+ \`\`\`
327
+
328
+ ---
329
+
330
+ ## \u{1F4A1} Notes
331
+
332
+ - The \`ViewEngine\` class auto-caches template files unless disabled.
333
+ - You can switch engines by passing a different type like \`"pug"\`, \`"hbs"\`, etc.
334
+ - All rendering is asynchronous.
335
+
336
+ ---
337
+
338
+ Happy TezX templating! \u{1F389}
339
+ `.trim(),content:`
340
+ const views = new ViewEngine("ejs", "./views");
341
+
342
+ app.get("engine", async (ctx) => {
343
+ const html = await views.render("home", {
344
+ title: "TezX SSR Page",
345
+ user: ctx.user || { name: "Guest" },
346
+ });
347
+ return ctx.html(html);
348
+ });
349
+ `.trim(),files:[{content:`
350
+ <html lang="en">
351
+ <head>
352
+ <meta charset="UTF-8">
353
+ <title><%= title %></title>
354
+ </head>
355
+ <body>
356
+ <h1>Welcome to TezX SSR!</h1>
357
+ <p>Hello, <%= user.name %> \u{1F44B}</p>
358
+ </body>
359
+ </html>
360
+ `.trim(),path:"views/home.ejs"}],import:['import { ViewEngine } from "@tezx/view-engine";'],package:[p("@tezx/view-engine","^1.0.3"),p("ejs","^3.1.10")]};var F=`
90
361
  <!DOCTYPE html>
91
362
  <html lang="en">
92
363
  <head>
@@ -254,28 +525,107 @@ GOOGLE_CLIENT_SECRET=234234
254
525
  </script>
255
526
  </body>
256
527
  </html>
257
- `,N={content:`
528
+ `,_={readme:`
529
+ # \u{1F50C} TezX WebSocket Example
530
+
531
+ This example demonstrates how to set up a WebSocket server using \`upgradeWebSocket\` from \`tezx/ws\`.
532
+
533
+ ---
534
+
535
+ ## \u{1F680} Features
536
+
537
+ - Upgrade HTTP requests to WebSocket connections
538
+ - Handle events: \`open\`, \`message\`, and \`close\`
539
+ - Respond to \`ping\` with \`pong\`
540
+ - Echo received messages back to the client
541
+ - Works with Node.js and Bun
542
+
543
+ ---
544
+
545
+ ## \u{1F527} Setup
546
+
547
+ ### 1. Install required package (if needed)
548
+
549
+ TezX WebSocket support is built-in with \`tezx/ws\`. If your setup doesn't include it:
550
+
551
+ \`\`\`bash
552
+ npm install tezx
553
+ # or
554
+ bun add tezx
555
+ \`\`\`
556
+
557
+ ---
558
+
559
+ ### 2. How it works
560
+
561
+ - Connect to \`/ws\` via a browser or WebSocket client
562
+ - On connect: sends a welcome message
563
+ - On message: replies with either \`pong\` or echoes back the message
564
+ - Logs disconnection reason
565
+
566
+ ---
567
+
568
+ ## \u{1F9EA} Client Test File
569
+
570
+ A simple HTML file is included in \`public/ws.html\`:
571
+
572
+ \`\`\`html
573
+ <script>
574
+ const ws = new WebSocket("ws://localhost:3000/ws");
575
+
576
+ ws.onopen = () => {
577
+ console.log("Connected to WebSocket!");
578
+ ws.send("ping");
579
+ };
580
+
581
+ ws.onmessage = (event) => {
582
+ console.log("Message:", event.data);
583
+ };
584
+
585
+ ws.onclose = () => {
586
+ console.log("Disconnected.");
587
+ };
588
+ </script>
589
+ \`\`\`
590
+
591
+ ---
592
+
593
+ ## \u{1F4C1} File Structure
594
+
595
+ \`\`\`
596
+ .
597
+ \u251C\u2500\u2500 public/
598
+ \u2502 \u2514\u2500\u2500 ws.html
599
+ \u2514\u2500\u2500 src
600
+ \u2514\u2500\u2500 index.ts
601
+ \`\`\`
602
+
603
+ ---
604
+
605
+ Enjoy real-time power with TezX! \u26A1\uFE0F
606
+ `.trim(),content:`
258
607
  const socket = [];
608
+
259
609
  app.get(
260
610
  "/ws",
261
611
  upgradeWebSocket(
262
612
  (ctx) => {
263
613
  return {
264
- // make sure it is work with nodejs
614
+ // \u2705 Node.js-compatible WebSocket handler
265
615
  open: (ws) => {
266
- socket.push(ws);
267
- console.log("WebSocket connected");
268
- ws.send("\u{1F44B} Welcome to TezX WebSocket!");
616
+ socket.push(ws);
617
+ console.log("WebSocket connected");
618
+ ws.send("\u{1F44B} Welcome to TezX WebSocket!");
269
619
  },
270
620
  message: (ws, msg) => {
271
- if (typeof msg === "string" && msg === "ping") {
272
- ws.send("pong \u{1F3D3}");
273
- } else if (msg !== undefined) {
274
- ws.send("Echo: " + msg);
275
- }
621
+ if (typeof msg === "string" && msg === "ping") {
622
+ ws.send("pong \u{1F3D3}");
623
+ } else if (msg !== undefined) {
624
+ ws.send("Echo: " + msg);
625
+ }
276
626
  },
277
627
  close: (ws, data) => {
278
- console.log(\`WebSocket closed: \${ data?.reason ?? "No reason provided"}\`);
628
+ console.log(\`WebSocket closed: \${data?.reason ?? "No reason provided"}\`);
279
629
  },
280
630
  };
281
631
  },
@@ -290,12 +640,130 @@ app.get(
290
640
  return ctx.sendFile("public/ws.html");
291
641
  },
292
642
  );
293
- `,files:[{content:D,path:"public/ws.html"}],import:['import { upgradeWebSocket } from "tezx/ws";']};var C={minimal:{content:"",files:[],import:[],package:[]},ws:N,"github-oauth2":I,"google-oauth2":G};import F from"node:readline";async function j(s,n,t){return new Promise(r=>{let o=0;F.emitKeypressEvents(process.stdin,s),process.stdin.isTTY&&process.stdin.setRawMode(!0);let a=()=>{process.stdout.write("\x1B[2J\x1B[0f"),console.log(n+` (Use \u2191 \u2193 arrows, Enter to confirm)
294
- `),t.forEach((l,i)=>{console.log(`${i===o?"\u{1F449}":" "} ${i===o?"\x1B[36m":"\x1B[0m"}${l}\x1B[0m`)})},c=(l,i)=>{if(i.name==="up")o=(o-1+t.length)%t.length,a();else if(i.name==="down")o=(o+1)%t.length,a();else if(i.name==="return")return r(t[o])};a(),process.stdin.on("keypress",c)})}var L={reset:"\x1B[0m",bold:"\x1B[1m",underline:"\x1B[4m",gray:"\x1B[90m",white:"\x1B[97m",black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",bgYellow:"\x1B[43m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m",bgCyan:"\x1B[46m",bgWhite:"\x1B[47m",orange:"\x1B[38;2;255;88;30m",bgOrange:"\x1B[48;2;255;88;30m"};function e(s,n){return`${L[n]}${s}${L.reset}`}import{mkdirSync as B,writeFileSync as O}from"node:fs";import{join as k}from"node:path";var T="2.0.6";var M=({ts:s,template:n,root:t,env:r,useStatic:o=!1,staticFolder:a})=>{let c=k(t,s?"src/index.ts":"src/index.js");B(k(t,"src"),{recursive:!0});let l=`
643
+ `.trim(),files:[{content:F,path:"public/ws.html"}],import:['import { upgradeWebSocket } from "tezx/ws";']};var C={minimal:{readme:"",content:"",files:[],import:[],package:[]},ws:_,"github-oauth2":I,"google-oauth2":G,"view-engine":R};import B from"node:readline";async function z(n,s,t){return new Promise(r=>{let o=0;B.emitKeypressEvents(process.stdin,n),process.stdin.isTTY&&process.stdin.setRawMode(!0);let a=()=>{process.stdout.write("\x1B[2J\x1B[0f"),console.log(s+` (Use \u2191 \u2193 arrows, Enter to confirm)
644
+ `),t.forEach((l,i)=>{console.log(`${i===o?"\u{1F449}":" "} ${i===o?"\x1B[36m":"\x1B[0m"}${l}\x1B[0m`)})},c=(l,i)=>{if(i.name==="up")o=(o-1+t.length)%t.length,a();else if(i.name==="down")o=(o+1)%t.length,a();else if(i.name==="return")return r(t[o])};a(),process.stdin.on("keypress",c)})}var A={reset:"\x1B[0m",bold:"\x1B[1m",underline:"\x1B[4m",gray:"\x1B[90m",white:"\x1B[97m",black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",bgYellow:"\x1B[43m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m",bgCyan:"\x1B[46m",bgWhite:"\x1B[47m",orange:"\x1B[38;2;255;88;30m",bgOrange:"\x1B[48;2;255;88;30m"};function e(n,s){return`${A[s]}${n}${A.reset}`}import{mkdirSync as V,writeFileSync as b}from"node:fs";import{join as g}from"node:path";var S="2.0.8";var J=`
645
+ # \u{1F680} TezX Starter Template
646
+
647
+ Welcome to the **TezX Starter Template** \u2014 a blazing-fast, full-featured backend template built on [TezX](https://github.com/tezxjs/tezx), the lightweight web framework inspired by the best of Express, Hono, and Bun.
648
+
649
+ This starter is designed to help you spin up production-ready APIs or SSR apps in seconds.
650
+
651
+ ---
652
+
653
+ ## \u2728 Features
654
+
655
+ - \u26A1\uFE0F Ultra-fast routing & middleware
656
+ - \u{1F512} Built-in WebSocket & OAuth2-ready
657
+ - \u{1F527} Plug-and-play \`ViewEngine\` for SSR
658
+ - \u{1F331} Environment-based config support
659
+ - \u{1F9EA} Minimal, testable, and extendable codebase
660
+
661
+ ---
662
+
663
+ ## \u{1F4E6} Tech Stack
664
+
665
+ - **Framework:** [TezX](https://github.com/tezxjs/tezx)
666
+ - **Language:** TypeScript / JavaScript
667
+ - **Template Engine (optional):** \`ejs\`, \`pug\`, \`hbs\`, \`mustache\`, or \`nunjucks\`
668
+ - **Runtime Support:** Node.js, Bun, Deno (via compatibility)
669
+
670
+ ---
671
+
672
+ ## \u{1F6E0}\uFE0F Getting Started
673
+
674
+ ### 1. Install Dependencies
675
+
676
+ \`\`\`bash
677
+ npm install
678
+ # or
679
+ bun install
680
+ \`\`\`\`
681
+
682
+ ### 2. Start Development Server
683
+
684
+ \`\`\`bash
685
+ npm run dev
686
+ # or
687
+ bun run dev
688
+ \`\`\`
689
+
690
+ ### 3. Open in Browser
691
+
692
+ \`\`\`bash
693
+ http://localhost:3000
694
+ \`\`\`
695
+
696
+ ---
697
+
698
+ ## \u{1F510} Environment Variables
699
+
700
+ Create a \`.env\` file at the project root:
701
+
702
+ \`\`\`bash
703
+ PORT=3000
704
+ NODE_ENV=development
705
+
706
+ # For OAuth2 templates
707
+ GOOGLE_CLIENT_ID=your-client-id
708
+ GOOGLE_CLIENT_SECRET=your-secret
709
+ \`\`\`
710
+
711
+ ---
712
+
713
+ ## \u{1F4C1} Project Structure
714
+
715
+ \`\`\`
716
+ .
717
+ \u251C\u2500\u2500 public/ # Static files (images, js, css)
718
+ \u251C\u2500\u2500 views/ # SSR templates (optional)
719
+ \u251C\u2500\u2500 src/
720
+ \u2502 \u251C\u2500\u2500 index.ts # Entry point
721
+ \u2502 \u2514\u2500\u2500 routes/ # Route modules
722
+ \u251C\u2500\u2500 .env
723
+ \u251C\u2500\u2500 .gitignore
724
+ \u2514\u2500\u2500 package.json
725
+ \`\`\`
726
+
727
+ ---
728
+
729
+ ## \u{1F9EA} Example Commands
730
+
731
+ \`\`\`bash
732
+ # Build the app
733
+ bun run build
734
+
735
+ # Start the server in production
736
+ bun start
737
+
738
+ # Run a TezX test (if added)
739
+ bun test
740
+ \`\`\`
741
+
742
+ ---
743
+
744
+ ## \u{1F91D} Contributing
745
+
746
+ Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
747
+
748
+ ---
749
+
750
+ ## \u{1F4C4} License
751
+
752
+ MIT \xA9 [SRAKIB17](https://github.com/SRAKIB17)
753
+
754
+ ---
755
+
756
+ ## \u{1F49A} Powered by
757
+
758
+ [TezX Framework](https://github.com/tezxjs/TezX) \xB7 Made with performance in mind
759
+
760
+ ---
761
+
762
+ `,L=({ts:n,template:s,root:t,env:r,useStatic:o=!1,staticFolder:a})=>{let c=g(t,n?"src/index.ts":"src/index.js");V(g(t,"src"),{recursive:!0});let l=`
295
763
  import { TezX } from "tezx";
296
764
  import { ${r}Adapter ,loadEnv} from "tezx/${r}";
297
765
  import { logger } from "tezx/middleware";
298
- ${n?.import?.join(`
766
+ ${s?.import?.join(`
299
767
  `)}
300
768
  const app = new TezX({
301
769
  env: loadEnv(),
@@ -307,13 +775,13 @@ app.use([logger()]);
307
775
  app.get("/", (ctx) => ctx.text("Hello from TezX (${r})"));
308
776
 
309
777
  ${o?`app.static("${a||"public"}");`:""}
310
- ${n?.content?`
311
- ${n?.content?.trim()}
778
+ ${s?.content?`
779
+ ${s?.content?.trim()}
312
780
  `:""}
313
781
  ${r}Adapter(app).listen(3000, () => {
314
782
  console.log("\u{1F680} TezX running on http://localhost:3000");
315
783
  });
316
- `;if(s){let i=`
784
+ `;if(n){let i=`
317
785
  {
318
786
  "compilerOptions": {
319
787
  "outDir": "./dist",
@@ -335,7 +803,7 @@ ${r}Adapter(app).listen(3000, () => {
335
803
  "tests"
336
804
  ]
337
805
  }
338
- `.trim();O(k(t,"tsconfig.json"),i)}O(c,l.trim())},R=({template:s,root:n,projectName:t,env:r,ts:o,useWS:a,choiceStep:c})=>{let l=[];Array.isArray(s?.package)&&s?.package?.forEach(d=>{let{version:x,npm:h}=d||{};l.push(`"${h?.[1]}": "${x}"`)});let i={bun:{start:"bun dist/index.js",dev:"bun run --hot --watch src/index.ts"},deno:{start:"deno run --allow-all dist/index.js",dev:"deno run --watch --allow-all --unstable-sloppy-imports src/index.ts"},node:{start:"node dist/index.js",dev:"tsx watch src/index.ts"}},p=`
806
+ `.trim();b(g(t,"tsconfig.json"),i)}b(c,l.trim())},N=({template:n,root:s,projectName:t,env:r,ts:o,useWS:a,choiceStep:c})=>{let l=[];Array.isArray(n?.package)&&n?.package?.forEach(m=>{let{version:w,npm:v}=m||{};l.push(`"${v?.[1]}": "${w}"`)});let i={bun:{start:"bun dist/index.js",dev:"bun run --hot --watch src/index.ts"},deno:{start:"deno run --allow-all dist/index.js",dev:"deno run --watch --allow-all --unstable-sloppy-imports src/index.ts"},node:{start:"node dist/index.js",dev:"tsx watch src/index.ts"}},u=`
339
807
  {
340
808
  "name": "${t||"tezx-app-example"}",
341
809
  "version": "1.0.0",
@@ -361,7 +829,7 @@ ${r}Adapter(app).listen(3000, () => {
361
829
  "homepage": "https://github.com/tezxjs/tezx-app-example",
362
830
  "dependencies": {
363
831
  ${o?'"typescript": "^5.8.2",':""}
364
- "tezx": "^${T}"${r=="node"?`,
832
+ "tezx": "^${S}"${r=="node"?`,
365
833
  "tsx": "^4.19.2"`:""}${a&&r=="node"?`,
366
834
  "ws": "^8.18.1"`:""}${l.length?`,
367
835
  ${l?.join(`,
@@ -370,15 +838,85 @@ ${r}Adapter(app).listen(3000, () => {
370
838
  "devDependencies": {
371
839
  "@types/node": "^22.13.14"
372
840
  }
373
- }`.trim();O(k(n,"package.json"),p)};var y=["npm","bun","yarn","pnpm"],f=["node","bun","deno"];function K(s){let n=0,t=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],r=setInterval(()=>{process.stdout.write(`\r${t[n=++n%t.length]} ${s}`)},80);return()=>{clearInterval(r),process.stdout.write(`\r\u2705 Done!
374
- `)}}var S=_.createInterface({input:process.stdin,output:process.stdout});_.emitKeypressEvents(process.stdin);process.stdin.isTTY&&process.stdin.setRawMode(!0);var b=(s,n="")=>new Promise(t=>{S.question(n?`${s} (${n}): `:s,r=>{t(r.trim()||n)})});async function A(s){let n=s?.directory,t=s?.options;console.log(e(`
841
+ }`.trim();b(g(s,"package.json"),u)},D=({root:n})=>{let s=`
842
+ # Node dependencies
843
+ node_modules/
844
+ .env
845
+ .env.local
846
+ .env.*.local
847
+
848
+ # Diagnostic reports (https://nodejs.org/api/report.html)
849
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
850
+
851
+ # Logs
852
+ logs
853
+ *.log
854
+ npm-debug.log*
855
+ yarn-debug.log*
856
+ yarn-error.log*
857
+ lerna-debug.log*
858
+ .pnpm-debug.log*
859
+
860
+
861
+ # Runtime data
862
+ pids
863
+ *.pid
864
+ *.seed
865
+ *.pid.lock
866
+
867
+ # Directory for instrumented libs generated by jscoverage/JSCover
868
+ lib-cov
869
+
870
+ # Dependency directories
871
+ node_modules/
872
+ package/example-ts/node_modules/
873
+ package/example-commonjs/node_modules/
874
+ package/example-js-module/node_modules/
875
+ package-lock.json
876
+ bun.lock
877
+
878
+ # Stores VSCode versions used for testing VSCode extensions
879
+ .vscode-test
880
+
881
+ # yarn v2
882
+ .yarn/cache
883
+ .yarn/unplugged
884
+ .yarn/build-state.yml
885
+ .yarn/install-state.gz
886
+ .pnp.*
887
+
888
+
889
+ # Build outputs
890
+ dist/
891
+ build/
892
+ .cache/
893
+ .tezx/
894
+ out/
895
+
896
+ # System files
897
+ .DS_Store
898
+ Thumbs.db
899
+
900
+
901
+ # Output of 'npm pack'
902
+ *.tgz
903
+
904
+ # Yarn Integrity file
905
+ .yarn-integrity
906
+
907
+ # Editor settings
908
+ .vscode/
909
+ .idea/
910
+ *.swp
911
+ `.trim();b(g(n,".gitignore"),s,{encoding:"utf8"})},M=({root:n,readme:s})=>{let t=typeof s=="string"?s?.trim():J.trim();b(g(n,"README.md"),t,{encoding:"utf8"})};var f=["npm","bun","yarn","pnpm"],x=["node","bun","deno"];function Z(n){let s=0,t=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],r=setInterval(()=>{process.stdout.write(`\r${t[s=++s%t.length]} ${n}`)},80);return()=>{clearInterval(r),process.stdout.write(`\r\u2705 Done!
912
+ `)}}var $=P.createInterface({input:process.stdin,output:process.stdout});P.emitKeypressEvents(process.stdin);process.stdin.isTTY&&process.stdin.setRawMode(!0);var y=(n,s="")=>new Promise(t=>{$.question(s?`${n} (${s}): `:n,r=>{t(r.trim()||s)})});async function W(n){let s=n?.directory,t=n?.options;console.log(e(`
375
913
  \u26A1 TezX App Creator (no dependencies CLI)
376
- `,"orange")),n||(n=await b(e("\u{1F4E6} Project name: ","magenta")),n||(console.log(e("\u274C Project name required.","red")),process.exit(0)));let r=$.basename(n),o=J(process.cwd(),n),a=!!t?.ts,c=t?.env||t?.runtime,l=f?.includes(c)?c:await j(S,"\u{1F4BB} Runtime?",f),i=t?.staticFolder||"public",p=!0,d={content:"",import:[],files:[]};if(t?.t||t?.template){let m=t.t||t.template,v=C?.[m];v||(console.error(`\u274C Unknown template: "${m}"`),console.error(`\u2139\uFE0F Available templates: ${Object.keys(C).join(", ")}`),process.exit(0)),d=v}else a=!!(t?.ts||(await b("\u{1F7E6} Use TypeScript? (y/N): ")).toLowerCase()==="y"),p=!!t?.useStatic||(await b("\u{1F4C1} Use static folder? (y/N): ")).toLowerCase()==="y",i=p?t?.staticFolder||await b("\u{1F4C2} Static folder name? (default: public): "):"";let x=t?.pm||t?.p,h=y?.includes(x)?x:await j(S,"\u{1F4E6} Choose your package manager",y),w=t?.i==="true"||t?.install==="true"||(await b("\u{1F4E5} Install dependencies now? (y/N): ")).toLowerCase()==="y";console.log(`
914
+ `,"orange")),s||(s=await y(e("\u{1F4E6} Project name: ","magenta")),s||(console.log(e("\u274C Project name required.","red")),process.exit(0)));let r=E.basename(s),o=Q(process.cwd(),s),a=!!t?.ts,c=t?.env||t?.runtime,l=x?.includes(c)?c:await z($,"\u{1F4BB} Runtime?",x),i=t?.staticFolder||"public",u=!0,m={content:"",import:[],readme:"",files:[]};if(t?.t||t?.template){let d=t.t||t.template,k=C?.[d];k||(console.error(`\u274C Unknown template: "${d}"`),console.error(`\u2139\uFE0F Available templates: ${Object.keys(C).join(", ")}`),process.exit(0)),m=k}else a=!!(t?.ts||(await y("\u{1F7E6} Use TypeScript? (y/N): ")).toLowerCase()==="y"),u=!!t?.useStatic||(await y("\u{1F4C1} Use static folder? (y/N): ")).toLowerCase()==="y",i=u?t?.staticFolder||await y("\u{1F4C2} Static folder name? (default: public): "):"";let w=t?.pm||t?.p,v=f?.includes(w)?w:await z($,"\u{1F4E6} Choose your package manager",f),T=t?.i==="true"||t?.install==="true"||(await y("\u{1F4E5} Install dependencies now? (y/N): ")).toLowerCase()==="y";console.log(`
377
915
  \u{1F4C1} Creating project: ${r}...
378
- `);let U=K("Creating Project");if(z(o,{recursive:!0}),p){let m=Y(o,i||"public");z(m,{recursive:!0})}let u={bun:{cd:"cd "+n,install:"bun install",dev:"bun dev",build:"bun build:cjs && bun build:esm && bun build:dts"},npm:{cd:"cd "+n,install:"npm install",dev:"npm run dev",build:"npm run build:cjs && npm run build:esm && npm run build:dts"},yarn:{cd:"cd "+n,install:"yarn",dev:"yarn dev",build:"yarn build:cjs && yarn build:esm && yarn build:dts"},pnpm:{cd:"cd "+n,install:"pnpm install",dev:"pnpm run dev",build:"pnpm run build:cjs && pnpm run build:esm && pnpm run build:dts"}}[h];M({template:d,root:o,ts:!!a,env:l,staticFolder:i,useStatic:p}),R({projectName:r,env:l,root:o,ts:!!a,template:d,choiceStep:u}),S.close(),d?.files?.forEach(m=>{let v=$.join(o,$.dirname(m?.path));z(v,{recursive:!0}),X($.join(o,m?.path),m?.content)}),w&&H(u?.install,{cwd:o,stdio:"inherit"}),console.log(e(`
916
+ `);let U=Z("Creating Project");if(j(o,{recursive:!0}),u){let d=q(o,i||"public");j(d,{recursive:!0})}let h={bun:{cd:"cd "+s,install:"bun install",dev:"bun dev",build:"bun build:esm && bun build:dts"},npm:{cd:"cd "+s,install:"npm install",dev:"npm run dev",build:"npm run build:esm && npm run build:dts"},yarn:{cd:"cd "+s,install:"yarn",dev:"yarn dev",build:"yarn build:esm && yarn build:dts"},pnpm:{cd:"cd "+s,install:"pnpm install",dev:"pnpm run dev",build:"pnpm run build:esm && pnpm run build:dts"}}[v];L({template:m,root:o,ts:!!a,env:l,staticFolder:i,useStatic:u}),N({projectName:r,env:l,root:o,ts:!!a,template:m,choiceStep:h}),D({root:o}),M({root:o,readme:m?.readme}),$.close(),m?.files?.forEach(d=>{let k=E.join(o,E.dirname(d?.path));j(k,{recursive:!0}),Y(E.join(o,d?.path),d?.content)}),T&&K(h?.install,{cwd:o,stdio:"inherit"}),console.log(e(`
379
917
  \u2705 TezX project "${r}" is ready!
380
- `,"green")),console.log(e("\u{1F9F0} Summary of your configuration:","cyan")),console.log(`\u{1F4C1} Project Name: ${e(r,"yellow")}`);let E=t?.t||t?.template;E&&console.log(`\u{1F4C1} Template Name: ${e(E,"orange")}`),console.log(`\u{1F7E6} TypeScript: ${e(a?"Yes":"No",a?"green":"gray")}`),console.log(`\u{1F4BB} Runtime: ${e(l,"blue")}`),console.log(`\u{1F4C1} Static Folder: ${e(p?i||"public":"Not Used",p?"green":"gray")}`),console.log(`\u{1F4E6} Package Manager: ${e(h,"magenta")}`),console.log(`\u{1F4E5} Dependencies Installed: ${e(w?"Yes":"No",w?"green":"red")}
381
- `),console.log(e("\u{1F449} Next Steps:","cyan")),console.log(e(` ${u?.cd}`,"white")),w||console.log(e(` ${u?.install}`,"white")),console.log(e(` ${u?.dev}`,"white")),console.log(""),U(),process.exit(0)}function P(){console.log(`
918
+ `,"green")),console.log(e("\u{1F9F0} Summary of your configuration:","cyan")),console.log(`\u{1F4C1} Project Name: ${e(r,"yellow")}`);let O=t?.t||t?.template;O&&console.log(`\u{1F4C1} Template Name: ${e(O,"orange")}`),console.log(`\u{1F7E6} TypeScript: ${e(a?"Yes":"No",a?"green":"gray")}`),console.log(`\u{1F4BB} Runtime: ${e(l,"blue")}`),console.log(`\u{1F4C1} Static Folder: ${e(u?i||"public":"Not Used",u?"green":"gray")}`),console.log(`\u{1F4E6} Package Manager: ${e(v,"magenta")}`),console.log(`\u{1F4E5} Dependencies Installed: ${e(T?"Yes":"No",T?"green":"red")}
919
+ `),console.log(e("\u{1F449} Next Steps:","cyan")),console.log(e(` ${h?.cd}`,"white")),T||console.log(e(` ${h?.install}`,"white")),console.log(e(` ${h?.dev}`,"white")),console.log(""),U(),process.exit(0)}function X(){console.log(`
382
920
  ${e("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E","gray")}
383
921
  ${e("\u2502","gray")} ${e("\u26A1 Create TezX","yellow")} - Scaffold your next backend app ${e("\u2502","gray")}
384
922
  ${e("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F","gray")}
@@ -418,4 +956,4 @@ ${r}Adapter(app).listen(3000, () => {
418
956
  ${e("https://github.com/tezxjs/tezx","underline")}
419
957
 
420
958
  ${e("\u{1F9D1}\u200D\u{1F4BB} Author:","cyan")}
421
- Rakibul Islam ${e("<https://github.com/srakib17>","blue")}`),process.exit(0)}function W(){console.log(`TezX CLI v${T}`),process.exit(0)}(async()=>{let s=(a,c)=>{c.name==="c"&&c.ctrl&&(process.stdin.off("keypress",s),process.stdin.isTTY&&process.stdin.setRawMode(!1),process.exit(0))};process.stdin.on("keypress",s);let n=process.argv.slice(2),t={},r;for(let a=0;a<n.length;a++){let c=n[a];if(c.startsWith("--")){let l=c.slice(2),i=n[a+1];i&&!i.startsWith("-")?(t[l]=i,a++):t[l]="true"}else if(c.startsWith("-")){let l=c.slice(1),i=n[a+1];i&&!i.startsWith("-")?(t[l]=i,a++):t[l]="true"}else r||(r=c)}let o={directory:r,options:t};if((t.y==="true"||t.yes==="true")&&(o.options.ts="true",o.options.useStatic="true",o.options.staticFolder="public",o.options.pm=y?.includes(o.options?.p||o?.options?.pm)?o.options?.p||o?.options?.pm:"npm",o.options.p=y?.includes(o.options?.p||o?.options?.pm)?o.options?.p||o?.options?.pm:"npm",o.options.env=f?.includes(o.options?.env||o?.options?.runtime)?o.options?.env||o?.options?.runtime:"node",o.options.runtime=f?.includes(o.options?.env||o?.options?.runtime)?o.options?.env||o?.options?.runtime:"node",o.options.install="true"),t.help||t.h){P();return}if(t.v||t.version){W();return}A(o)})();
959
+ Rakibul Islam ${e("<https://github.com/srakib17>","blue")}`),process.exit(0)}function H(){console.log(`TezX CLI v${S}`),process.exit(0)}(async()=>{let n=(a,c)=>{c.name==="c"&&c.ctrl&&(process.stdin.off("keypress",n),process.stdin.isTTY&&process.stdin.setRawMode(!1),process.exit(0))};process.stdin.on("keypress",n);let s=process.argv.slice(2),t={},r;for(let a=0;a<s.length;a++){let c=s[a];if(c.startsWith("--")){let l=c.slice(2),i=s[a+1];i&&!i.startsWith("-")?(t[l]=i,a++):t[l]="true"}else if(c.startsWith("-")){let l=c.slice(1),i=s[a+1];i&&!i.startsWith("-")?(t[l]=i,a++):t[l]="true"}else r||(r=c)}let o={directory:r,options:t};if((t.y==="true"||t.yes==="true")&&(o.options.ts="true",o.options.useStatic="true",o.options.staticFolder="public",o.options.pm=f?.includes(o.options?.p||o?.options?.pm)?o.options?.p||o?.options?.pm:"npm",o.options.p=f?.includes(o.options?.p||o?.options?.pm)?o.options?.p||o?.options?.pm:"npm",o.options.env=x?.includes(o.options?.env||o?.options?.runtime)?o.options?.env||o?.options?.runtime:"node",o.options.runtime=x?.includes(o.options?.env||o?.options?.runtime)?o.options?.env||o?.options?.runtime:"node",o.options.install="true"),t.help||t.h){X();return}if(t.v||t.version){H();return}W(o)})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tezx-app",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "type": "module",
5
5
  "description": "TezX is a high-performance, lightweight JavaScript framework designed for speed, scalability, and flexibility. It enables efficient routing, middleware management, and static file serving with minimal configuration. Fully compatible with Node.js, Deno, and Bun.",
6
6
  "bin": "./bin",