@wtasnorg/node-lib 0.0.6 → 0.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.
- package/changelog.txt +14 -0
- package/dev_checklist.txt +56 -0
- package/docs/README.md +8 -34
- package/docs/docs.json +1538 -0
- package/docs/functions/createFindDirectories.md +2 -2
- package/docs/functions/hello.md +2 -2
- package/docs/functions/parseUserAgent.md +42 -0
- package/docs/functions/pojo.md +4 -4
- package/docs/interfaces/FileSystemDependencies.md +9 -9
- package/docs/interfaces/FindDirectoriesOptions.md +8 -8
- package/docs/interfaces/UserAgentInfo.md +61 -0
- package/eslint.config.js +52 -0
- package/gen-docs/001_commands.txt +44 -0
- package/gen-docs/001_coverage.txt +43 -0
- package/gen-docs/001_env.txt +33 -0
- package/gen-docs/001_lint.txt +40 -0
- package/gen-docs/001_state.txt +58 -0
- package/gen-docs/002_api.txt +34 -0
- package/gen-docs/002_deps.txt +46 -0
- package/gen-docs/002_errors.txt +34 -0
- package/gen-docs/002_naming.txt +36 -0
- package/gen-docs/002_notes.txt +20 -0
- package/gen-docs/002_purity.txt +36 -0
- package/gen-docs/002_scope.txt +28 -0
- package/gen-docs/002_srp.txt +34 -0
- package/gen-sec/001_commands.txt +65 -0
- package/gen-sec/001_env.txt +28 -0
- package/gen-sec/001_findings.txt +63 -0
- package/gen-sec/001_inventory.txt +41 -0
- package/gen-sec/001_owasp.txt +78 -0
- package/gen-sec/001_scope.txt +44 -0
- package/package.json +10 -3
- package/{README.md → readme.txt} +3 -1
- package/src/find.d.ts +4 -4
- package/src/find.js +13 -7
- package/src/find.test.js +2 -6
- package/src/find.test.ts +3 -11
- package/src/find.ts +13 -13
- package/src/index.d.ts +4 -2
- package/src/index.js +2 -1
- package/src/index.ts +6 -2
- package/src/pojo.d.ts +2 -2
- package/src/pojo.js +2 -2
- package/src/pojo.test.js +1 -3
- package/src/pojo.test.ts +2 -1
- package/src/pojo.ts +3 -3
- package/src/user-agent.d.ts +48 -0
- package/src/user-agent.js +189 -0
- package/src/user-agent.test.d.ts +2 -0
- package/src/user-agent.test.js +54 -0
- package/src/user-agent.test.ts +60 -0
- package/src/user-agent.ts +199 -0
- package/test_report +26 -0
- package/typedoc.json +6 -2
- package/DEV_CHECKLIST.md +0 -15
- package/docs/_media/LICENSE +0 -21
- package/docs/globals.md +0 -16
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 002 Refinement Notes
|
|
2
|
+
Generated: 2026-01-19T20:43:05+05:30
|
|
3
|
+
|
|
4
|
+
## Action Items
|
|
5
|
+
|
|
6
|
+
1. **[API]** Export parseUserAgent and UserAgentInfo from index.ts
|
|
7
|
+
2. **[BUG]** Fix detectEngine logic - "Blink" never returned due to ordering
|
|
8
|
+
3. **[CLEANUP]** Consider removing unused `stat` from FileSystemDependencies
|
|
9
|
+
|
|
10
|
+
## Deferred
|
|
11
|
+
|
|
12
|
+
- Coverage improvements (find.js 64.71%) - separate iteration
|
|
13
|
+
|
|
14
|
+
## Summary
|
|
15
|
+
|
|
16
|
+
Code quality is high. Two issues found:
|
|
17
|
+
1. Missing public export (API gap)
|
|
18
|
+
2. Logic bug in detectEngine (Blink detection)
|
|
19
|
+
|
|
20
|
+
Both are low-effort fixes.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 002 Purity & Side-Effect Findings
|
|
2
|
+
Generated: 2026-01-19T20:43:05+05:30
|
|
3
|
+
|
|
4
|
+
## Summary
|
|
5
|
+
|
|
6
|
+
Excellent purity. Side effects isolated and intentional.
|
|
7
|
+
|
|
8
|
+
## Per-Module Analysis
|
|
9
|
+
|
|
10
|
+
### find.ts ✅
|
|
11
|
+
- I/O injected, not hardcoded
|
|
12
|
+
- Pure computation inside walk()
|
|
13
|
+
- Side effects (readdir) at boundary via dependency injection
|
|
14
|
+
|
|
15
|
+
### hello.ts ⚠️
|
|
16
|
+
- console.log is a side effect
|
|
17
|
+
- Mitigated: guarded with `if (console?.log)`
|
|
18
|
+
- Acceptable: function purpose is verification output
|
|
19
|
+
|
|
20
|
+
### pojo.ts ✅
|
|
21
|
+
- Pure function
|
|
22
|
+
- No side effects
|
|
23
|
+
- Deterministic output
|
|
24
|
+
|
|
25
|
+
### user-agent.ts ✅
|
|
26
|
+
- All functions pure
|
|
27
|
+
- String parsing only
|
|
28
|
+
- No I/O, no mutation
|
|
29
|
+
|
|
30
|
+
## Issues Found
|
|
31
|
+
|
|
32
|
+
None requiring action.
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
PASS - Side effects appropriately isolated.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 002 Scope - Refinement Iteration
|
|
2
|
+
Generated: 2026-01-19T20:43:05+05:30
|
|
3
|
+
|
|
4
|
+
## In Scope
|
|
5
|
+
|
|
6
|
+
Modules:
|
|
7
|
+
- find.ts - Directory traversal factory
|
|
8
|
+
- hello.ts - Library health check
|
|
9
|
+
- pojo.ts - Object conversion utility
|
|
10
|
+
- user-agent.ts - UA string parser
|
|
11
|
+
- index.ts - Public exports
|
|
12
|
+
|
|
13
|
+
## Out of Scope
|
|
14
|
+
|
|
15
|
+
- Test files (*.test.ts)
|
|
16
|
+
- Generated files (*.js, *.d.ts)
|
|
17
|
+
- Build/tooling configuration
|
|
18
|
+
|
|
19
|
+
## Assumptions
|
|
20
|
+
|
|
21
|
+
- Library is functional; tests pass
|
|
22
|
+
- No breaking API changes desired
|
|
23
|
+
- Focus: code quality, not features
|
|
24
|
+
|
|
25
|
+
## Constraints
|
|
26
|
+
|
|
27
|
+
- Must maintain backward compatibility
|
|
28
|
+
- All changes require passing tests
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 002 SRP Findings
|
|
2
|
+
Generated: 2026-01-19T20:43:05+05:30
|
|
3
|
+
|
|
4
|
+
## Summary
|
|
5
|
+
|
|
6
|
+
All modules have good single responsibility. No major violations.
|
|
7
|
+
|
|
8
|
+
## Per-Module Analysis
|
|
9
|
+
|
|
10
|
+
### find.ts ✅
|
|
11
|
+
- Single concern: directory traversal with filtering
|
|
12
|
+
- Pure factory pattern isolates FS dependencies
|
|
13
|
+
- Helper functions (isAllowed, isBlocked) are cohesive
|
|
14
|
+
|
|
15
|
+
### hello.ts ✅
|
|
16
|
+
- Single concern: library health check
|
|
17
|
+
- Minor: console.log side effect is appropriate for purpose
|
|
18
|
+
|
|
19
|
+
### pojo.ts ✅
|
|
20
|
+
- Single concern: class-to-POJO conversion
|
|
21
|
+
- Pure function, no side effects
|
|
22
|
+
|
|
23
|
+
### user-agent.ts ✅
|
|
24
|
+
- Single concern: UA string parsing
|
|
25
|
+
- Well-decomposed: detectBrowser, detectOS, detectDeviceType, detectEngine
|
|
26
|
+
- Each sub-function has single responsibility
|
|
27
|
+
|
|
28
|
+
## Issues Found
|
|
29
|
+
|
|
30
|
+
None requiring action.
|
|
31
|
+
|
|
32
|
+
## Status
|
|
33
|
+
|
|
34
|
+
PASS - All modules satisfy SRP.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# 001 Commands Executed
|
|
2
|
+
Generated: 2026-01-19T20:46:44+05:30
|
|
3
|
+
|
|
4
|
+
## Environment Verification
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
which npm node semgrep
|
|
8
|
+
# /home/anubhav/.nvm/versions/node/v24.5.0/bin/npm
|
|
9
|
+
# /home/anubhav/.nvm/versions/node/v24.5.0/bin/node
|
|
10
|
+
# semgrep not found
|
|
11
|
+
|
|
12
|
+
npm --version
|
|
13
|
+
# 11.7.0
|
|
14
|
+
|
|
15
|
+
node --version
|
|
16
|
+
# v24.5.0
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Dependency Audit
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm audit --json
|
|
23
|
+
# 0 vulnerabilities
|
|
24
|
+
# 131 dependencies (1 prod, 130 dev)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Static Pattern Analysis
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Command injection patterns
|
|
31
|
+
grep -rE 'eval|Function\(|exec|spawn|child_process' src/*.ts
|
|
32
|
+
# No results
|
|
33
|
+
|
|
34
|
+
# Secret patterns
|
|
35
|
+
grep -riE 'password|secret|api.?key|token|credential' src/*.ts
|
|
36
|
+
# Found: pojo.test.ts (test data only)
|
|
37
|
+
|
|
38
|
+
# XSS patterns
|
|
39
|
+
grep -rE 'innerHTML|outerHTML|document\.write' src/*.ts
|
|
40
|
+
# No results
|
|
41
|
+
|
|
42
|
+
# File operation patterns
|
|
43
|
+
grep -rE 'fs\.|readFile|writeFile|unlink|rmdir' src/*.ts
|
|
44
|
+
# No results
|
|
45
|
+
|
|
46
|
+
# Network patterns
|
|
47
|
+
grep -riE 'http|fetch|axios|request' src/*.ts
|
|
48
|
+
# No results
|
|
49
|
+
|
|
50
|
+
# Crypto patterns
|
|
51
|
+
grep -riE 'crypto|hash|md5|sha1|sha256' src/*.ts
|
|
52
|
+
# No results
|
|
53
|
+
|
|
54
|
+
# SQL patterns
|
|
55
|
+
grep -riE 'sql|query|database|db\.' src/*.ts
|
|
56
|
+
# No results
|
|
57
|
+
|
|
58
|
+
# Deserialization patterns
|
|
59
|
+
grep -rE 'JSON\.parse|deserialize|pickle' src/*.ts
|
|
60
|
+
# No results
|
|
61
|
+
|
|
62
|
+
# Prototype pollution patterns
|
|
63
|
+
grep -rE 'prototype|__proto__|constructor\[' src/*.ts
|
|
64
|
+
# Found: pojo.ts, pojo.test.ts (documentation/test only)
|
|
65
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 001 Environment Verification
|
|
2
|
+
Generated: 2026-01-19T20:46:44+05:30
|
|
3
|
+
|
|
4
|
+
## Tooling Status
|
|
5
|
+
|
|
6
|
+
| Tool | Status | Version | Path |
|
|
7
|
+
|----------|-----------|-----------|----------------------------------------|
|
|
8
|
+
| node | ✅ OK | v24.5.0 | /home/anubhav/.nvm/versions/node/... |
|
|
9
|
+
| npm | ✅ OK | 11.7.0 | /home/anubhav/.nvm/versions/node/... |
|
|
10
|
+
| semgrep | ❌ MISSING| - | - |
|
|
11
|
+
|
|
12
|
+
## npm audit
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Vulnerabilities: 0
|
|
16
|
+
- Critical: 0
|
|
17
|
+
- High: 0
|
|
18
|
+
- Moderate: 0
|
|
19
|
+
- Low: 0
|
|
20
|
+
- Info: 0
|
|
21
|
+
|
|
22
|
+
Dependencies: 131 (1 prod, 130 dev)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Notes
|
|
26
|
+
|
|
27
|
+
- Semgrep not installed; manual pattern analysis performed
|
|
28
|
+
- All dev dependencies, minimal prod footprint
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 001 Security Findings
|
|
2
|
+
Generated: 2026-01-19T20:46:44+05:30
|
|
3
|
+
|
|
4
|
+
## Summary
|
|
5
|
+
|
|
6
|
+
| Severity | Count |
|
|
7
|
+
|----------|-------|
|
|
8
|
+
| Critical | 0 |
|
|
9
|
+
| High | 0 |
|
|
10
|
+
| Medium | 0 |
|
|
11
|
+
| Low | 1 |
|
|
12
|
+
| Info | 1 |
|
|
13
|
+
|
|
14
|
+
## Findings
|
|
15
|
+
|
|
16
|
+
### [LOW] F001 - Path Traversal Potential in find.ts
|
|
17
|
+
|
|
18
|
+
**Location:** find.ts:23-26, createFindDirectories()
|
|
19
|
+
|
|
20
|
+
**Description:**
|
|
21
|
+
The `root` parameter is passed to `resolve()` without validation.
|
|
22
|
+
If a consumer passes user-controlled input, path traversal is possible.
|
|
23
|
+
|
|
24
|
+
**Impact:** Directory enumeration outside intended scope.
|
|
25
|
+
|
|
26
|
+
**Exploitability:** LOW - Requires consumer misuse.
|
|
27
|
+
|
|
28
|
+
**CWE:** CWE-22 (Path Traversal)
|
|
29
|
+
|
|
30
|
+
**OWASP:** A01 (Broken Access Control)
|
|
31
|
+
|
|
32
|
+
**Confidence:** LOW - Library design expects trusted input.
|
|
33
|
+
|
|
34
|
+
**Recommendation:**
|
|
35
|
+
- Document that `root` must be trusted input
|
|
36
|
+
- Optionally add: validate root is within allowed base path
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
### [INFO] F002 - "secret" String in Test File
|
|
41
|
+
|
|
42
|
+
**Location:** pojo.test.ts:54-65
|
|
43
|
+
|
|
44
|
+
**Description:**
|
|
45
|
+
String "secret" appears in test data (SecretBox class).
|
|
46
|
+
|
|
47
|
+
**Impact:** None - test data only.
|
|
48
|
+
|
|
49
|
+
**Confidence:** HIGH - Verified as test fixture.
|
|
50
|
+
|
|
51
|
+
**Recommendation:** No action needed.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Residual Risk
|
|
56
|
+
|
|
57
|
+
**MINIMAL** - This is a stateless utility library with:
|
|
58
|
+
- No network exposure
|
|
59
|
+
- No database access
|
|
60
|
+
- No authentication
|
|
61
|
+
- No user input handling
|
|
62
|
+
|
|
63
|
+
Security posture depends on consumer implementation.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 001 Attack Surface Inventory
|
|
2
|
+
Generated: 2026-01-19T20:46:44+05:30
|
|
3
|
+
|
|
4
|
+
## Overview
|
|
5
|
+
|
|
6
|
+
This is a pure utility library with NO:
|
|
7
|
+
- HTTP endpoints
|
|
8
|
+
- CLI interfaces
|
|
9
|
+
- Database access
|
|
10
|
+
- Authentication
|
|
11
|
+
- Network I/O
|
|
12
|
+
|
|
13
|
+
## Entry Points
|
|
14
|
+
|
|
15
|
+
### find.ts - createFindDirectories()
|
|
16
|
+
|
|
17
|
+
- Input: FileSystemDependencies (injected), root path, options
|
|
18
|
+
- Operations: Directory traversal via injected readdir
|
|
19
|
+
- Trust boundary: Consumer provides FS functions
|
|
20
|
+
|
|
21
|
+
### hello.ts - hello()
|
|
22
|
+
|
|
23
|
+
- Input: None
|
|
24
|
+
- Operations: Returns static string, logs to console
|
|
25
|
+
- Trust boundary: None
|
|
26
|
+
|
|
27
|
+
### pojo.ts - pojo()
|
|
28
|
+
|
|
29
|
+
- Input: Object instance
|
|
30
|
+
- Operations: Object.entries, Object.fromEntries
|
|
31
|
+
- Trust boundary: Consumer provides object
|
|
32
|
+
|
|
33
|
+
### user-agent.ts - parseUserAgent()
|
|
34
|
+
|
|
35
|
+
- Input: String (user-agent)
|
|
36
|
+
- Operations: String parsing (split, includes)
|
|
37
|
+
- Trust boundary: Consumer provides UA string
|
|
38
|
+
|
|
39
|
+
## Attack Surface Rating
|
|
40
|
+
|
|
41
|
+
**MINIMAL** - Pure functions, no I/O, no state, no network.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# 001 OWASP Top 10 Assessment
|
|
2
|
+
Generated: 2026-01-19T20:46:44+05:30
|
|
3
|
+
|
|
4
|
+
## A01 - Broken Access Control
|
|
5
|
+
|
|
6
|
+
**N/A** - No authentication, authorization, or access control.
|
|
7
|
+
|
|
8
|
+
## A02 - Cryptographic Failures
|
|
9
|
+
|
|
10
|
+
**N/A** - No cryptographic operations.
|
|
11
|
+
- No passwords, tokens, or secrets
|
|
12
|
+
- No hashing or encryption
|
|
13
|
+
|
|
14
|
+
## A03 - Injection
|
|
15
|
+
|
|
16
|
+
**LOW RISK** - Pattern analysis performed:
|
|
17
|
+
|
|
18
|
+
| Pattern | Found | Files |
|
|
19
|
+
|---------------------|-------|-------|
|
|
20
|
+
| eval() | ❌ No | - |
|
|
21
|
+
| Function() | ❌ No | - |
|
|
22
|
+
| exec/spawn | ❌ No | - |
|
|
23
|
+
| child_process | ❌ No | - |
|
|
24
|
+
| SQL | ❌ No | - |
|
|
25
|
+
| innerHTML | ❌ No | - |
|
|
26
|
+
|
|
27
|
+
## A04 - Insecure Design
|
|
28
|
+
|
|
29
|
+
**N/A** - Simple utility library.
|
|
30
|
+
- No business logic
|
|
31
|
+
- No rate limiting needed
|
|
32
|
+
- No trust assumptions
|
|
33
|
+
|
|
34
|
+
## A05 - Security Misconfiguration
|
|
35
|
+
|
|
36
|
+
**N/A** - No configuration surface.
|
|
37
|
+
- No debug modes
|
|
38
|
+
- No CORS
|
|
39
|
+
- No credentials
|
|
40
|
+
|
|
41
|
+
## A06 - Vulnerable Components
|
|
42
|
+
|
|
43
|
+
**PASS** - npm audit: 0 vulnerabilities
|
|
44
|
+
- 131 dependencies scanned
|
|
45
|
+
- No known CVEs
|
|
46
|
+
|
|
47
|
+
## A07 - Identification & Authentication Failures
|
|
48
|
+
|
|
49
|
+
**N/A** - No authentication.
|
|
50
|
+
|
|
51
|
+
## A08 - Software & Data Integrity Failures
|
|
52
|
+
|
|
53
|
+
**LOW RISK** - Analyzed for deserialization:
|
|
54
|
+
|
|
55
|
+
| Pattern | Found | Notes |
|
|
56
|
+
|---------------------|-------|--------------------------|
|
|
57
|
+
| JSON.parse | ❌ No | - |
|
|
58
|
+
| Prototype pollution | ❌ No | pojo() uses safe methods |
|
|
59
|
+
|
|
60
|
+
pojo() uses Object.entries/fromEntries which are safe.
|
|
61
|
+
|
|
62
|
+
## A09 - Logging & Monitoring Failures
|
|
63
|
+
|
|
64
|
+
**N/A** - Library code, not service.
|
|
65
|
+
- console.log in hello() is benign
|
|
66
|
+
|
|
67
|
+
## A10 - SSRF
|
|
68
|
+
|
|
69
|
+
**N/A** - No network I/O.
|
|
70
|
+
- No fetch, axios, http
|
|
71
|
+
- No URL handling
|
|
72
|
+
|
|
73
|
+
## Summary
|
|
74
|
+
|
|
75
|
+
| Category | Status |
|
|
76
|
+
|----------|--------|
|
|
77
|
+
| A01-A10 | N/A or PASS |
|
|
78
|
+
| Overall | **LOW RISK** |
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# 001 Scope - Security Assessment
|
|
2
|
+
Generated: 2026-01-19T20:46:44+05:30
|
|
3
|
+
|
|
4
|
+
## Target
|
|
5
|
+
|
|
6
|
+
- Package: @wtasnorg/node-lib@0.0.8
|
|
7
|
+
- Type: TypeScript utility library
|
|
8
|
+
- Platform: Node.js
|
|
9
|
+
|
|
10
|
+
## In Scope
|
|
11
|
+
|
|
12
|
+
- src/*.ts (source files)
|
|
13
|
+
- Dependencies (package.json)
|
|
14
|
+
- Build artifacts
|
|
15
|
+
|
|
16
|
+
## Out of Scope
|
|
17
|
+
|
|
18
|
+
- Test files (contain mock data only)
|
|
19
|
+
- Documentation
|
|
20
|
+
- CI/CD configuration
|
|
21
|
+
|
|
22
|
+
## Sensitive Data Classes
|
|
23
|
+
|
|
24
|
+
None identified. Library is stateless and handles:
|
|
25
|
+
- File paths (find.ts)
|
|
26
|
+
- String parsing (user-agent.ts, pojo.ts)
|
|
27
|
+
- No PII, credentials, or financial data
|
|
28
|
+
|
|
29
|
+
## Allowed Techniques
|
|
30
|
+
|
|
31
|
+
- Static code analysis
|
|
32
|
+
- Dependency auditing
|
|
33
|
+
- Pattern matching for dangerous APIs
|
|
34
|
+
|
|
35
|
+
## Forbidden Techniques
|
|
36
|
+
|
|
37
|
+
- Network scanning (N/A - no network exposure)
|
|
38
|
+
- Dynamic exploitation (N/A - library code)
|
|
39
|
+
|
|
40
|
+
## Assumptions
|
|
41
|
+
|
|
42
|
+
- Library runs in trusted Node.js environment
|
|
43
|
+
- Consumers provide trusted inputs
|
|
44
|
+
- No direct user input handling
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wtasnorg/node-lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "node library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"docs": "./node_modules/.bin/typedoc",
|
|
9
9
|
"docs:json": "./node_modules/.bin/typedoc --json docs/docs.json",
|
|
10
10
|
"docs:watch": "./node_modules/.bin/typedoc --watch",
|
|
11
|
-
"test": "bash -c 'node --test src/**/*.test.js'"
|
|
11
|
+
"test": "bash -c 'node --test src/**/*.test.js'",
|
|
12
|
+
"lint": "npx eslint src/*.ts --no-warn-ignored"
|
|
12
13
|
},
|
|
13
14
|
"keywords": [
|
|
14
15
|
"library"
|
|
@@ -27,9 +28,15 @@
|
|
|
27
28
|
"url": "git+https://github.com/wtasg/node-lib.git"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
31
|
+
"@eslint/js": "^9.39.1",
|
|
32
|
+
"@stylistic/eslint-plugin": "^5.6.1",
|
|
30
33
|
"@types/node": "^24.10.1",
|
|
34
|
+
"eslint": "^9.39.1",
|
|
35
|
+
"eslint-config-prettier": "^10.1.8",
|
|
36
|
+
"globals": "^16.5.0",
|
|
31
37
|
"typedoc": "^0.28.15",
|
|
32
38
|
"typedoc-plugin-markdown": "^4.9.0",
|
|
33
|
-
"typescript": "^5.9.3"
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
|
+
"typescript-eslint": "^8.48.1"
|
|
34
41
|
}
|
|
35
42
|
}
|
package/{README.md → readme.txt}
RENAMED
|
@@ -9,6 +9,8 @@ A library project for nodejs. #nodejs #typescript #library
|
|
|
9
9
|
|
|
10
10
|
1. hello (for debugging)
|
|
11
11
|
2. `pojo` for converting class objects to Plain Old Javascript Objects.
|
|
12
|
+
3. `createFindDirectories` as a factory for finding directories; think `find path -type d`.
|
|
13
|
+
4. `parseUserAgent` for extracting information from user-agent strings.
|
|
12
14
|
|
|
13
15
|
## Develop
|
|
14
16
|
|
|
@@ -31,7 +33,7 @@ npm install @wtasnorg/node-lib
|
|
|
31
33
|
# check if you can run code
|
|
32
34
|
import {hello} from "@wtasnorg/node-lib";
|
|
33
35
|
|
|
34
|
-
await hello();
|
|
36
|
+
await hello();
|
|
35
37
|
// "hello from @wtasnorg/node-lib"
|
|
36
38
|
```
|
|
37
39
|
|
package/src/find.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
interface FileSystemDependencies {
|
|
2
|
-
readdir: (
|
|
2
|
+
readdir: (_path: string, _opts: {
|
|
3
3
|
withFileTypes: true;
|
|
4
4
|
}) => Promise<{
|
|
5
5
|
name: string;
|
|
6
6
|
isDirectory(): boolean;
|
|
7
7
|
}[]>;
|
|
8
|
-
stat: (
|
|
8
|
+
stat: (_path: string) => Promise<{
|
|
9
9
|
isDirectory(): boolean;
|
|
10
10
|
}>;
|
|
11
11
|
}
|
|
12
12
|
interface FindDirectoriesOptions {
|
|
13
13
|
maxDepth?: number;
|
|
14
14
|
followSymlinks?: boolean;
|
|
15
|
-
allowlist?: string[] | ((
|
|
16
|
-
blocklist?: string[] | ((
|
|
15
|
+
allowlist?: string[] | ((_absPath: string, _name: string) => boolean);
|
|
16
|
+
blocklist?: string[] | ((_absPath: string, _name: string) => boolean);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Factory that produces an async findDirectories function with
|
package/src/find.js
CHANGED
|
@@ -12,8 +12,9 @@ function createFindDirectories(deps) {
|
|
|
12
12
|
function isAllowed(absPath, name) {
|
|
13
13
|
if (allowlist) {
|
|
14
14
|
if (Array.isArray(allowlist)) {
|
|
15
|
-
if (!allowlist.includes(name))
|
|
15
|
+
if (!allowlist.includes(name)) {
|
|
16
16
|
return false;
|
|
17
|
+
}
|
|
17
18
|
}
|
|
18
19
|
else if (!allowlist(absPath, name)) {
|
|
19
20
|
return false;
|
|
@@ -24,8 +25,9 @@ function createFindDirectories(deps) {
|
|
|
24
25
|
function isBlocked(absPath, name) {
|
|
25
26
|
if (blocklist) {
|
|
26
27
|
if (Array.isArray(blocklist)) {
|
|
27
|
-
if (blocklist.includes(name))
|
|
28
|
+
if (blocklist.includes(name)) {
|
|
28
29
|
return true;
|
|
30
|
+
}
|
|
29
31
|
}
|
|
30
32
|
else if (blocklist(absPath, name)) {
|
|
31
33
|
return true;
|
|
@@ -34,18 +36,22 @@ function createFindDirectories(deps) {
|
|
|
34
36
|
return false;
|
|
35
37
|
}
|
|
36
38
|
async function walk(currentPath, depth) {
|
|
37
|
-
if (depth > maxDepth)
|
|
39
|
+
if (depth > maxDepth) {
|
|
38
40
|
return;
|
|
41
|
+
}
|
|
39
42
|
const entries = await readdir(currentPath, { withFileTypes: true });
|
|
40
43
|
for (const entry of entries) {
|
|
41
44
|
const childPath = resolve(join(currentPath, entry.name));
|
|
42
|
-
|
|
43
|
-
if (!isDirectory)
|
|
45
|
+
const isDirectory = entry.isDirectory();
|
|
46
|
+
if (!isDirectory) {
|
|
44
47
|
continue;
|
|
45
|
-
|
|
48
|
+
}
|
|
49
|
+
if (isBlocked(childPath, entry.name)) {
|
|
46
50
|
continue;
|
|
47
|
-
|
|
51
|
+
}
|
|
52
|
+
if (!isAllowed(childPath, entry.name)) {
|
|
48
53
|
continue;
|
|
54
|
+
}
|
|
49
55
|
results.push(childPath);
|
|
50
56
|
if (depth < maxDepth) {
|
|
51
57
|
await walk(childPath, depth + 1);
|
package/src/find.test.js
CHANGED
|
@@ -58,10 +58,8 @@ test("find: findDirectories symlink is NOT treated as a directory", async () =>
|
|
|
58
58
|
]);
|
|
59
59
|
});
|
|
60
60
|
test("find: findDirectories at depth=2", async () => {
|
|
61
|
-
const calls = [];
|
|
62
61
|
const deps = {
|
|
63
62
|
readdir: async (path) => {
|
|
64
|
-
calls.push(path);
|
|
65
63
|
switch (path) {
|
|
66
64
|
case "/root":
|
|
67
65
|
return [dir("a"), dir("b"), file("ignore.txt")];
|
|
@@ -73,7 +71,7 @@ test("find: findDirectories at depth=2", async () => {
|
|
|
73
71
|
return [];
|
|
74
72
|
}
|
|
75
73
|
},
|
|
76
|
-
stat: async (
|
|
74
|
+
stat: async () => ({
|
|
77
75
|
isDirectory: () => false
|
|
78
76
|
})
|
|
79
77
|
};
|
|
@@ -88,10 +86,8 @@ test("find: findDirectories at depth=2", async () => {
|
|
|
88
86
|
].sort());
|
|
89
87
|
});
|
|
90
88
|
test("find: findDirectories at depth=3", async () => {
|
|
91
|
-
const calls = [];
|
|
92
89
|
const deps = {
|
|
93
90
|
readdir: async (path) => {
|
|
94
|
-
calls.push(path);
|
|
95
91
|
switch (path) {
|
|
96
92
|
case "/root":
|
|
97
93
|
return [dir("a"), dir("b")];
|
|
@@ -108,7 +104,7 @@ test("find: findDirectories at depth=3", async () => {
|
|
|
108
104
|
return [];
|
|
109
105
|
}
|
|
110
106
|
},
|
|
111
|
-
stat: async (
|
|
107
|
+
stat: async () => ({
|
|
112
108
|
isDirectory: () => false
|
|
113
109
|
})
|
|
114
110
|
};
|
package/src/find.test.ts
CHANGED
|
@@ -77,12 +77,8 @@ test("find: findDirectories symlink is NOT treated as a directory", async () =>
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
test("find: findDirectories at depth=2", async () => {
|
|
80
|
-
const calls: string[] = [];
|
|
81
|
-
|
|
82
80
|
const deps: FileSystemDependencies = {
|
|
83
81
|
readdir: async (path: string): Promise<{ name: string; isDirectory(): boolean }[]> => {
|
|
84
|
-
calls.push(path);
|
|
85
|
-
|
|
86
82
|
switch (path) {
|
|
87
83
|
case "/root":
|
|
88
84
|
return [dir("a"), dir("b"), file("ignore.txt")];
|
|
@@ -94,7 +90,7 @@ test("find: findDirectories at depth=2", async () => {
|
|
|
94
90
|
return [];
|
|
95
91
|
}
|
|
96
92
|
},
|
|
97
|
-
stat: async (
|
|
93
|
+
stat: async () => ({
|
|
98
94
|
isDirectory: () => false
|
|
99
95
|
})
|
|
100
96
|
};
|
|
@@ -113,12 +109,8 @@ test("find: findDirectories at depth=2", async () => {
|
|
|
113
109
|
});
|
|
114
110
|
|
|
115
111
|
test("find: findDirectories at depth=3", async () => {
|
|
116
|
-
const calls: string[] = [];
|
|
117
|
-
|
|
118
112
|
const deps: FileSystemDependencies = {
|
|
119
113
|
readdir: async (path: string): Promise<{ name: string; isDirectory(): boolean }[]> => {
|
|
120
|
-
calls.push(path);
|
|
121
|
-
|
|
122
114
|
switch (path) {
|
|
123
115
|
case "/root":
|
|
124
116
|
return [dir("a"), dir("b")];
|
|
@@ -130,12 +122,12 @@ test("find: findDirectories at depth=3", async () => {
|
|
|
130
122
|
case "/root/b/b1":
|
|
131
123
|
return [dir("c")];
|
|
132
124
|
case "/root/b/b1/c":
|
|
133
|
-
return [dir("d"), file("fd")]
|
|
125
|
+
return [dir("d"), file("fd")];
|
|
134
126
|
default:
|
|
135
127
|
return [];
|
|
136
128
|
}
|
|
137
129
|
},
|
|
138
|
-
stat: async (
|
|
130
|
+
stat: async () => ({
|
|
139
131
|
isDirectory: () => false
|
|
140
132
|
})
|
|
141
133
|
};
|