tina4-nodejs 3.5.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -371,7 +371,7 @@ export default class User {
371
371
  };
372
372
  }
373
373
 
374
- // Auto-generates: GET/POST /api/users, GET/PUT/DELETE /api/users/:id
374
+ // Auto-generates: GET/POST /api/users, GET/PUT/DELETE /api/users/{id}
375
375
  // With filtering, sorting, pagination, and validation built in
376
376
  ```
377
377
 
@@ -409,10 +409,10 @@ get("/protected", async (request, response) => {
409
409
  ### JWT Authentication
410
410
 
411
411
  ```typescript
412
- import { createToken, validateToken } from "tina4-nodejs";
412
+ import { getToken, validToken } from "tina4-nodejs";
413
413
 
414
- const token = createToken({userId: 42}, "your-secret");
415
- const payload = validateToken(token, "your-secret");
414
+ const token = getToken({userId: 42}, "your-secret");
415
+ const payload = validToken(token, "your-secret");
416
416
  ```
417
417
 
418
418
  POST/PUT/PATCH/DELETE routes require `Authorization: Bearer <token>` by default. Use `noauth()` to make public, `secured()` to protect GET routes.
@@ -643,7 +643,7 @@ DATABASE_USERNAME=admin # Separate credentials for networked databa
643
643
  DATABASE_PASSWORD=secret
644
644
  TINA4_DEBUG=true # Enable dev toolbar, error overlay
645
645
  TINA4_LOG_LEVEL=ALL # ALL, DEBUG, INFO, WARNING, ERROR
646
- TINA4_LANGUAGE=en # en, fr, af, zh, ja, es
646
+ TINA4_LOCALE=en # en, fr, af, zh, ja, es
647
647
  TINA4_SESSION_HANDLER=SessionFileHandler
648
648
  SWAGGER_TITLE=My API
649
649
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "type": "module",
5
5
  "description": "This is not a framework. Tina4 for Node.js/TypeScript — zero deps, 38 built-in features.",
6
6
  "keywords": ["tina4", "framework", "web", "api", "orm", "graphql", "websocket", "typescript"],
@@ -10,11 +10,12 @@ export async function serveProject(options: ServeOptions): Promise<void> {
10
10
  const cwd = process.cwd();
11
11
 
12
12
  const routesDir = resolve(cwd, "src/routes");
13
+ const ormDir = resolve(cwd, "src/orm");
13
14
  const modelsDir = resolve(cwd, "src/models");
14
15
  const templatesDir = resolve(cwd, "src/templates");
15
16
  const staticDir = resolve(cwd, "public");
16
17
 
17
- if (!existsSync(routesDir) && !existsSync(modelsDir)) {
18
+ if (!existsSync(routesDir) && !existsSync(modelsDir) && !existsSync(ormDir)) {
18
19
  console.error(" Error: Not a Tina4 project. Run this from a project created with 'tina4 init'.");
19
20
  process.exit(1);
20
21
  }
@@ -31,7 +32,8 @@ export async function serveProject(options: ServeOptions): Promise<void> {
31
32
  });
32
33
 
33
34
  // Watch for file changes and reload routes
34
- const watcher = watchForChanges([routesDir, modelsDir, templatesDir], async () => {
35
+ const watchDirs = [routesDir, ormDir, modelsDir, templatesDir].filter((d) => existsSync(d));
36
+ const watcher = watchForChanges(watchDirs, async () => {
35
37
  try {
36
38
  const { discoverRoutes } = await import("@tina4/core");
37
39
  const routes = await discoverRoutes(routesDir);
@@ -383,6 +383,7 @@ ${reset}
383
383
  const base = config?.basePath ? resolve(config.basePath) : process.cwd();
384
384
  const routesDir = resolve(base, config?.routesDir ?? "src/routes");
385
385
  const modelsDir = resolve(base, config?.modelsDir ?? "src/models");
386
+ const ormDir = resolve(base, "src/orm");
386
387
  const staticDir = resolve(base, config?.staticDir ?? "public");
387
388
  const templatesDir = resolve(base, config?.templatesDir ?? "src/templates");
388
389
 
@@ -429,8 +430,10 @@ ${reset}
429
430
  console.log(`\n No routes directory found at ${routesDir}`);
430
431
  }
431
432
 
432
- // Initialize ORM if models directory exists
433
- if (existsSync(modelsDir)) {
433
+ // Initialize ORM if models directory exists (check src/orm/ first, then src/models/)
434
+ const hasOrmDir = existsSync(ormDir);
435
+ const hasModelsDir = existsSync(modelsDir);
436
+ if (hasOrmDir || hasModelsDir) {
434
437
  try {
435
438
  const orm = await import("@tina4/orm");
436
439
  const dbConfig = config?.database ?? {};
@@ -439,7 +442,18 @@ ${reset}
439
442
  path: dbConfig.path ?? "./data/tina4.db",
440
443
  });
441
444
 
442
- const models = await orm.discoverModels(modelsDir);
445
+ // Discover from src/orm/ (primary) and src/models/ (fallback), merge results
446
+ let models = hasOrmDir ? await orm.discoverModels(ormDir) : [];
447
+ if (hasModelsDir) {
448
+ const extraModels = await orm.discoverModels(modelsDir);
449
+ // Only add models not already discovered (src/orm/ takes priority)
450
+ const existingTables = new Set(models.map((m: any) => m.definition.tableName));
451
+ for (const m of extraModels) {
452
+ if (!existingTables.has(m.definition.tableName)) {
453
+ models.push(m);
454
+ }
455
+ }
456
+ }
443
457
  if (models.length > 0) {
444
458
  console.log(`\n Models discovered:`);
445
459
  orm.syncModels(models);
@@ -476,9 +490,16 @@ ${reset}
476
490
  let modelDefs: Array<{ tableName: string; fields: Record<string, unknown> }> = [];
477
491
  try {
478
492
  const orm = await import("@tina4/orm");
479
- if (existsSync(modelsDir)) {
480
- const models = await orm.discoverModels(modelsDir);
481
- modelDefs = models.map((m) => m.definition);
493
+ const allModelDirs = [ormDir, modelsDir].filter((d) => existsSync(d));
494
+ const seenTables = new Set<string>();
495
+ for (const dir of allModelDirs) {
496
+ const discovered = await orm.discoverModels(dir);
497
+ for (const m of discovered) {
498
+ if (!seenTables.has(m.definition.tableName)) {
499
+ modelDefs.push(m.definition);
500
+ seenTables.add(m.definition.tableName);
501
+ }
502
+ }
482
503
  }
483
504
  } catch {
484
505
  // ORM not available, swagger will work without model schemas