tina4-nodejs 3.10.64 → 3.10.65
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/package.json +1 -1
- package/packages/core/src/metrics.ts +65 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tina4-nodejs",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.65",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Tina4 for Node.js/TypeScript — 54 built-in features, zero dependencies",
|
|
6
6
|
"keywords": ["tina4", "framework", "web", "api", "orm", "graphql", "websocket", "typescript"],
|
|
@@ -50,22 +50,71 @@ function readFileSafe(filePath: string): string | null {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
function relativePath(filePath: string): string {
|
|
54
|
-
return path.relative(
|
|
53
|
+
function relativePath(filePath: string, root: string = "."): string {
|
|
54
|
+
return path.relative(root, filePath);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// ── Test file detection ─────────────────────────────────────
|
|
58
58
|
|
|
59
59
|
function hasMatchingTest(relPath: string): boolean {
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
];
|
|
68
|
-
|
|
60
|
+
const parts = relPath.split('/');
|
|
61
|
+
const basename = parts[parts.length - 1] || '';
|
|
62
|
+
const name = basename.replace(/\.(ts|js)$/, '');
|
|
63
|
+
// Parent directory name (e.g. "adapters" from "adapters/sqlite.ts")
|
|
64
|
+
const parentModule = parts.length > 1 ? parts[parts.length - 2] : '';
|
|
65
|
+
|
|
66
|
+
// Stage 1: Filename matching — name.test, name.spec, test_name patterns
|
|
67
|
+
const testDirs = ['test', 'tests', 'spec'];
|
|
68
|
+
for (const td of testDirs) {
|
|
69
|
+
const patterns = [
|
|
70
|
+
`${td}/${name}.test.ts`,
|
|
71
|
+
`${td}/${name}.test.js`,
|
|
72
|
+
`${td}/${name}.spec.ts`,
|
|
73
|
+
`${td}/${name}.spec.js`,
|
|
74
|
+
// Also check parent-named tests (test/database.test.ts covers adapters/sqlite.ts)
|
|
75
|
+
...(parentModule && parentModule !== name ? [
|
|
76
|
+
`${td}/${parentModule}.test.ts`,
|
|
77
|
+
`${td}/${parentModule}.test.js`,
|
|
78
|
+
`${td}/${parentModule}.spec.ts`,
|
|
79
|
+
] : []),
|
|
80
|
+
];
|
|
81
|
+
if (patterns.some(p => fs.existsSync(p))) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Build the module import path for content matching
|
|
87
|
+
// e.g. "packages/core/src/metrics.ts" → "metrics" or "src/metrics"
|
|
88
|
+
const pathWithoutExt = relPath.replace(/\.(ts|js)$/, '');
|
|
89
|
+
// Build CamelCase class name from camelCase/kebab module name
|
|
90
|
+
// e.g. "sqlTranslation" → "SqlTranslation", "sql-translation" → "SqlTranslation"
|
|
91
|
+
const className = name
|
|
92
|
+
.replace(/[-_](.)/g, (_, c: string) => c.toUpperCase())
|
|
93
|
+
.replace(/^(.)/, (_, c: string) => c.toUpperCase());
|
|
94
|
+
|
|
95
|
+
// Stage 2+3: Content scan — check if any test file imports or references this module
|
|
96
|
+
for (const td of testDirs) {
|
|
97
|
+
if (!fs.existsSync(td)) continue;
|
|
98
|
+
const testFiles = walkFiles(td, ['.ts', '.js']);
|
|
99
|
+
for (const testFile of testFiles) {
|
|
100
|
+
const content = readFileSafe(testFile);
|
|
101
|
+
if (content === null) continue;
|
|
102
|
+
// Stage 2: import path matching
|
|
103
|
+
if (content.includes(name) && (
|
|
104
|
+
content.includes(`"${name}"`) || content.includes(`'${name}'`) ||
|
|
105
|
+
content.includes(`/${name}"`) || content.includes(`/${name}'`) ||
|
|
106
|
+
content.includes(pathWithoutExt)
|
|
107
|
+
)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
// Stage 3: class name mention
|
|
111
|
+
if (className !== name && new RegExp(`\\b${className.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(content)) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return false;
|
|
69
118
|
}
|
|
70
119
|
|
|
71
120
|
// ── Line counting ────────────────────────────────────────────
|
|
@@ -192,7 +241,7 @@ interface FunctionInfo {
|
|
|
192
241
|
file?: string;
|
|
193
242
|
}
|
|
194
243
|
|
|
195
|
-
function extractFunctions(source: string, filePath: string): FunctionInfo[] {
|
|
244
|
+
function extractFunctions(source: string, filePath: string, root: string = "."): FunctionInfo[] {
|
|
196
245
|
const functions: FunctionInfo[] = [];
|
|
197
246
|
const lines = source.split("\n");
|
|
198
247
|
|
|
@@ -268,7 +317,7 @@ function extractFunctions(source: string, filePath: string): FunctionInfo[] {
|
|
|
268
317
|
complexity,
|
|
269
318
|
loc: funcLoc,
|
|
270
319
|
args,
|
|
271
|
-
file: relativePath(filePath),
|
|
320
|
+
file: relativePath(filePath, root),
|
|
272
321
|
});
|
|
273
322
|
|
|
274
323
|
break; // Only match first pattern per line
|
|
@@ -590,7 +639,7 @@ export function quickMetrics(root: string = "src"): Record<string, any> {
|
|
|
590
639
|
totalFunctions += functions;
|
|
591
640
|
|
|
592
641
|
fileDetails.push({
|
|
593
|
-
path: relativePath(f),
|
|
642
|
+
path: relativePath(f, rootPath),
|
|
594
643
|
loc: counts.loc,
|
|
595
644
|
blank: counts.blank,
|
|
596
645
|
comment: counts.comment,
|
|
@@ -704,7 +753,7 @@ export function fullAnalysis(root: string = "src"): Record<string, any> {
|
|
|
704
753
|
const source = readFileSafe(f);
|
|
705
754
|
if (source === null) continue;
|
|
706
755
|
|
|
707
|
-
const relPath = relativePath(f);
|
|
756
|
+
const relPath = relativePath(f, rootPath);
|
|
708
757
|
const lines = source.split("\n");
|
|
709
758
|
const loc = lines.filter(
|
|
710
759
|
(l) => l.trim() && !l.trim().startsWith("//")
|
|
@@ -722,7 +771,7 @@ export function fullAnalysis(root: string = "src"): Record<string, any> {
|
|
|
722
771
|
}
|
|
723
772
|
|
|
724
773
|
// Analyze functions/methods
|
|
725
|
-
const fileFunctions = extractFunctions(source, f);
|
|
774
|
+
const fileFunctions = extractFunctions(source, f, rootPath);
|
|
726
775
|
let fileComplexity = 0;
|
|
727
776
|
|
|
728
777
|
for (const func of fileFunctions) {
|