Skip to content

Commit 4f4cd0c

Browse files
authored
Phase 5 performance (#6)
1 parent a4508e4 commit 4f4cd0c

File tree

4 files changed

+354
-7
lines changed

4 files changed

+354
-7
lines changed

.github/workflows/ci.yml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,23 +117,55 @@ jobs:
117117
name: build-artifacts
118118
path: dist/
119119

120+
validate:
121+
name: Validate Package
122+
runs-on: ubuntu-latest
123+
needs: [build]
124+
125+
steps:
126+
- name: Checkout code
127+
uses: actions/checkout@v5
128+
129+
- name: Setup Node.js
130+
uses: actions/setup-node@v4
131+
with:
132+
node-version: 20
133+
cache: 'npm'
134+
135+
- name: Install dependencies
136+
run: npm ci
137+
138+
- name: Build the library
139+
run: npm run build
140+
141+
- name: Check bundle size
142+
run: npm run size
143+
144+
- name: Validate package with publint
145+
run: npx publint
146+
147+
- name: Check TypeScript types
148+
run: npx @arethetypeswrong/cli --pack .
149+
120150
# Summary job to ensure all checks pass
121151
ci-success:
122152
name: CI Success
123153
runs-on: ubuntu-latest
124-
needs: [typecheck, test, build]
154+
needs: [typecheck, test, build, validate]
125155
if: always()
126156

127157
steps:
128158
- name: Check all jobs status
129159
run: |
130160
if [[ "${{ needs.typecheck.result }}" != "success" || \
131161
"${{ needs.test.result }}" != "success" || \
132-
"${{ needs.build.result }}" != "success" ]]; then
162+
"${{ needs.build.result }}" != "success" || \
163+
"${{ needs.validate.result }}" != "success" ]]; then
133164
echo "❌ One or more CI checks failed"
134165
echo "TypeCheck: ${{ needs.typecheck.result }}"
135166
echo "Test: ${{ needs.test.result }}"
136167
echo "Build: ${{ needs.build.result }}"
168+
echo "Validate: ${{ needs.validate.result }}"
137169
exit 1
138170
fi
139171
echo "✅ All CI checks passed successfully!"

benchmarks/string-utils.bench.ts

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { describe, bench } from 'vitest';
2+
import { Bench } from 'tinybench';
3+
import {
4+
slugify,
5+
camelCase,
6+
snakeCase,
7+
kebabCase,
8+
pascalCase,
9+
capitalize,
10+
truncate,
11+
escapeHtml,
12+
stripHtml,
13+
randomString,
14+
hashString,
15+
reverse,
16+
isEmail,
17+
isUrl,
18+
wordCount
19+
} from '../src/index.js';
20+
21+
describe('String Transformation Benchmarks', () => {
22+
bench('slugify - simple string', () => {
23+
slugify('Hello World');
24+
});
25+
26+
bench('slugify - complex string with special chars', () => {
27+
slugify('Hello World! @#$%^&*() This is a Test-String_123');
28+
});
29+
30+
bench('camelCase - simple', () => {
31+
camelCase('hello world');
32+
});
33+
34+
bench('camelCase - kebab-case input', () => {
35+
camelCase('hello-world-test-string');
36+
});
37+
38+
bench('snakeCase - simple', () => {
39+
snakeCase('hello world');
40+
});
41+
42+
bench('snakeCase - camelCase input', () => {
43+
snakeCase('helloWorldTestString');
44+
});
45+
46+
bench('kebabCase - simple', () => {
47+
kebabCase('hello world');
48+
});
49+
50+
bench('pascalCase - simple', () => {
51+
pascalCase('hello world test');
52+
});
53+
54+
bench('capitalize - simple', () => {
55+
capitalize('hello world');
56+
});
57+
58+
bench('reverse - short string', () => {
59+
reverse('hello');
60+
});
61+
62+
bench('reverse - long string', () => {
63+
reverse('The quick brown fox jumps over the lazy dog');
64+
});
65+
});
66+
67+
describe('String Manipulation Benchmarks', () => {
68+
bench('truncate - short string', () => {
69+
truncate('Hello World', 5);
70+
});
71+
72+
bench('truncate - long string', () => {
73+
truncate('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', 50);
74+
});
75+
76+
bench('escapeHtml - simple', () => {
77+
escapeHtml('<div>Hello & "world"</div>');
78+
});
79+
80+
bench('escapeHtml - complex HTML', () => {
81+
escapeHtml('<script>alert("XSS")</script><div class="test" data-value=\'test\'>&lt;Hello&gt;</div>');
82+
});
83+
84+
bench('stripHtml - simple', () => {
85+
stripHtml('<p>Hello World</p>');
86+
});
87+
88+
bench('stripHtml - complex HTML', () => {
89+
stripHtml('<div class="container"><h1>Title</h1><p>Paragraph with <strong>bold</strong> and <em>italic</em></p></div>');
90+
});
91+
92+
bench('wordCount - short text', () => {
93+
wordCount('Hello world test');
94+
});
95+
96+
bench('wordCount - long text', () => {
97+
wordCount('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.');
98+
});
99+
});
100+
101+
describe('String Generation Benchmarks', () => {
102+
bench('randomString - length 10', () => {
103+
randomString(10);
104+
});
105+
106+
bench('randomString - length 50', () => {
107+
randomString(50);
108+
});
109+
110+
bench('randomString - custom charset', () => {
111+
randomString(20, '0123456789ABCDEF');
112+
});
113+
114+
bench('hashString - short', () => {
115+
hashString('hello');
116+
});
117+
118+
bench('hashString - long', () => {
119+
hashString('The quick brown fox jumps over the lazy dog. This is a longer string to hash.');
120+
});
121+
});
122+
123+
describe('String Validation Benchmarks', () => {
124+
bench('isEmail - valid email', () => {
125+
isEmail('[email protected]');
126+
});
127+
128+
bench('isEmail - invalid email', () => {
129+
isEmail('not.an.email');
130+
});
131+
132+
bench('isUrl - valid URL', () => {
133+
isUrl('https://example.com/path?query=value');
134+
});
135+
136+
bench('isUrl - invalid URL', () => {
137+
isUrl('not a url');
138+
});
139+
});
140+
141+
// Standalone benchmark suite for detailed performance analysis
142+
export async function runDetailedBenchmarks() {
143+
const bench = new Bench({ time: 100 });
144+
145+
bench
146+
.add('slugify', () => {
147+
slugify('Hello World! This is a Test String-123_456');
148+
})
149+
.add('camelCase', () => {
150+
camelCase('hello-world-test-string');
151+
})
152+
.add('snakeCase', () => {
153+
snakeCase('helloWorldTestString');
154+
})
155+
.add('truncate', () => {
156+
truncate('Lorem ipsum dolor sit amet, consectetur adipiscing elit', 30);
157+
})
158+
.add('escapeHtml', () => {
159+
escapeHtml('<div>Hello & "world" <script>alert("test")</script></div>');
160+
})
161+
.add('randomString', () => {
162+
randomString(20);
163+
});
164+
165+
await bench.warmup();
166+
await bench.run();
167+
168+
console.table(bench.table());
169+
170+
return bench;
171+
}

0 commit comments

Comments
 (0)