tina4-nodejs 3.7.1 → 3.8.1

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/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
- # CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.0.0)
1
+ # CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.8.0)
2
2
 
3
3
  > This file helps AI assistants (Claude, Copilot, Cursor, etc.) understand and work on this codebase effectively.
4
4
 
5
5
  ## What This Project Is
6
6
 
7
- Tina4 for Node.js/TypeScript v3.0.0 — a convention-over-configuration structural paradigm. **Not a framework.** The developer writes TypeScript; Tina4 is invisible infrastructure.
7
+ Tina4 for Node.js/TypeScript v3.8.0 — a convention-over-configuration structural paradigm. **Not a framework.** The developer writes TypeScript; Tina4 is invisible infrastructure.
8
8
 
9
9
  The philosophy: zero ceremony, batteries included, file system as source of truth.
10
10
 
@@ -582,7 +582,7 @@ When adding new features, add a corresponding `test/<feature>.test.ts` file.
582
582
  ## v3 Features Summary
583
583
 
584
584
  - **38 built-in features**, zero third-party dependencies
585
- - **1,669 tests** passing across all modules
585
+ - **1,812 tests** passing across all modules
586
586
  - **Production server auto-detect**: `npx tina4nodejs serve --production` auto-uses cluster mode
587
587
  - **`npx tina4nodejs generate`**: model, route, migration, middleware scaffolding
588
588
  - **Database**: 5 engines (SQLite, PostgreSQL, MySQL, MSSQL, Firebird), query caching (`TINA4_DB_CACHE=true`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tina4-nodejs",
3
- "version": "3.7.1",
3
+ "version": "3.8.1",
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"],
@@ -359,11 +359,26 @@ export class Router {
359
359
  paramNames.push(name);
360
360
  return "(.+)";
361
361
  }
362
- // Dynamic param: {id} (primary syntax, matching Python)
362
+ // Dynamic param: {id}, {id:int}, {id:float}, {id:path} (matching Python/Ruby)
363
363
  if (segment.startsWith("{") && segment.endsWith("}")) {
364
- const name = segment.slice(1, -1);
364
+ const inner = segment.slice(1, -1);
365
+ const colonIdx = inner.indexOf(":");
366
+ const name = colonIdx >= 0 ? inner.slice(0, colonIdx) : inner;
367
+ const type = colonIdx >= 0 ? inner.slice(colonIdx + 1) : "string";
365
368
  paramNames.push(name);
366
- return "([^/]+)";
369
+ switch (type) {
370
+ case "int":
371
+ case "integer":
372
+ return "(\\d+)";
373
+ case "float":
374
+ case "number":
375
+ return "([\\d.]+)";
376
+ case "path":
377
+ case ".*":
378
+ return "(.+)";
379
+ default:
380
+ return "([^/]+)";
381
+ }
367
382
  }
368
383
  // Dynamic param: [id] (file-based routing internal syntax)
369
384
  if (segment.startsWith("[") && segment.endsWith("]")) {
@@ -758,7 +758,9 @@ const BUILTIN_FILTERS: Record<string, FilterFn> = {
758
758
  md5: (v) => createHash("md5").update(String(v)).digest("hex"),
759
759
  sha256: (v) => createHash("sha256").update(String(v)).digest("hex"),
760
760
  base64_encode: (v) => Buffer.isBuffer(v) ? v.toString("base64") : Buffer.from(String(v)).toString("base64"),
761
+ base64encode: (v) => Buffer.isBuffer(v) ? v.toString("base64") : Buffer.from(String(v)).toString("base64"),
761
762
  base64_decode: (v) => Buffer.from(String(v), "base64").toString("utf-8"),
763
+ base64decode: (v) => Buffer.from(String(v), "base64").toString("utf-8"),
762
764
  data_uri: (v) => {
763
765
  if (v && typeof v === "object" && "content" in v) {
764
766
  const ct = (v as any).type ?? "application/octet-stream";
Binary file
Binary file
Binary file