Skip to content

Commit b649c8a

Browse files
minor improvements
1 parent c77dc58 commit b649c8a

File tree

12 files changed

+242
-251
lines changed

12 files changed

+242
-251
lines changed

__tests__/storage/index.test.ts

Lines changed: 0 additions & 120 deletions
This file was deleted.

__tests__/strings.test.ts

Lines changed: 138 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { toCamelCase, toKebabCase, ucFirst } from '@/strings'
1+
import { parseValue, stringifyValue, toCamelCase, toKebabCase, ucFirst } from '@/strings'
22

33
describe( 'ucFirst', () => {
44

@@ -26,27 +26,27 @@ describe( 'ucFirst', () => {
2626

2727
// @ts-expect-error negative testing
2828
expect( () => ucFirst( false ) )
29-
.toThrow( 'string.charAt is not a function' )
29+
.toThrow( 'input.charAt is not a function' )
3030

3131
// @ts-expect-error negative testing
3232
expect( () => ucFirst( true ) )
33-
.toThrow( 'string.charAt is not a function' )
33+
.toThrow( 'input.charAt is not a function' )
3434

3535
// @ts-expect-error negative testing
3636
expect( () => ucFirst( 1 ) )
37-
.toThrow( 'string.charAt is not a function' )
37+
.toThrow( 'input.charAt is not a function' )
3838

3939
// @ts-expect-error negative testing
4040
expect( () => ucFirst( {} ) )
41-
.toThrow( 'string.charAt is not a function' )
41+
.toThrow( 'input.charAt is not a function' )
4242

4343
// @ts-expect-error negative testing
4444
expect( () => ucFirst( () => {} ) )
45-
.toThrow( 'string.charAt is not a function' )
45+
.toThrow( 'input.charAt is not a function' )
4646

4747
// @ts-expect-error negative testing
4848
expect( () => ucFirst( [] ) )
49-
.toThrow( 'string.charAt is not a function' )
49+
.toThrow( 'input.charAt is not a function' )
5050

5151
} )
5252

@@ -72,6 +72,12 @@ describe( 'toCamelCase', () => {
7272
expect( toCamelCase( 'some_value' ) )
7373
.toBe( 'someValue' )
7474

75+
expect( toCamelCase( 'some value_with mixed_Cases' ) )
76+
.toBe( 'someValueWithMixedCases' )
77+
78+
expect( toCamelCase( '-string@with#special$characters' ) )
79+
.toBe( 'StringWithSpecialCharacters' )
80+
7581
} )
7682

7783
} )
@@ -87,9 +93,134 @@ describe( 'toKebabCase', () => {
8793
expect( toKebabCase( 'backgroundColor' ) )
8894
.toBe( 'background-color' )
8995

96+
expect( toKebabCase( 'string with spaces' ) )
97+
.toBe( 'string-with-spaces' )
98+
99+
expect( toKebabCase( 'string_with_underscores' ) )
100+
.toBe( 'string-with-underscores' )
101+
90102
expect( toKebabCase( 'WebkitAlignContent' ) )
91103
.toBe( '-webkit-align-content' )
92104

105+
expect( toKebabCase( 'some value_with mixed_Cases' ) )
106+
.toBe( 'some-value-with-mixed-cases' )
107+
108+
expect( toKebabCase( '-string@with#special$characters' ) )
109+
.toBe( '-string-with-special-characters' )
110+
111+
} )
112+
113+
} )
114+
115+
116+
describe( 'stringifyValue', () => {
117+
118+
it( 'stringifies Date objects', () => {
119+
120+
expect( stringifyValue( new Date( 'Sat, 20 Apr 2025 16:20:00 GMT' ) ) )
121+
.toBe( '2025-04-20T16:20:00.000Z' )
122+
123+
} )
124+
125+
126+
it( 'stringifies objects with `JSON.stringify()`', () => {
127+
128+
expect( stringifyValue( null ) )
129+
.toBe( 'null' )
130+
131+
expect( stringifyValue( { prop: 'value', prop2: true } ) )
132+
.toBe( '{"prop":"value","prop2":true}' )
133+
134+
expect( stringifyValue( [ 1, 2, true, null, () => {} ] ) )
135+
.toBe( '[1,2,true,null,null]' )
136+
137+
expect( stringifyValue( new Map( [
138+
[ 'key', 'value' ],
139+
[ 'key2', 'value' ],
140+
] ) ) ).toBe( '[["key","value"],["key2","value"]]' )
141+
142+
expect( stringifyValue( new Headers( {
143+
key : 'value',
144+
key2 : 'value',
145+
} ) ) ).toBe( '[["key","value"],["key2","value"]]' )
146+
147+
} )
148+
149+
150+
it( 'stringifies other value types', () => {
151+
152+
expect( stringifyValue( true ) )
153+
.toBe( 'true' )
154+
expect( stringifyValue( false ) )
155+
.toBe( 'false' )
156+
157+
expect( stringifyValue( 0 ) )
158+
.toBe( '0' )
159+
expect( stringifyValue( 420 ) )
160+
.toBe( '420' )
161+
162+
} )
163+
164+
165+
it( 'returns empty string with un-serializable valuee', () => {
166+
expect( stringifyValue( undefined ) )
167+
.toBe( '' )
168+
169+
expect( stringifyValue( () => {} ) )
170+
.toBe( '' )
171+
172+
expect( stringifyValue( new Promise<void>( resolve => resolve() ) ) )
173+
.toBe( '' )
174+
} )
175+
176+
} )
177+
178+
179+
describe( 'parseValue', () => {
180+
181+
it( 'parses Date strings to Date objects', () => {
182+
expect( parseValue<Date>(
183+
stringifyValue( new Date() )
184+
) ).toBeInstanceOf( Date )
185+
} )
186+
187+
188+
it( 'parses numeric strings to `number`', () => {
189+
expect( parseValue<number>( '12345' ) ).toBe( 12345 )
190+
} )
191+
192+
193+
it( 'returns `undefined` if no value has been given', () => {
194+
expect( parseValue() ).toBeUndefined()
195+
} )
196+
197+
198+
it( 'returns `undefined` if empty `string` has been given', () => {
199+
expect( parseValue( ' ' ) ).toBeUndefined()
200+
} )
201+
202+
203+
it( 'returns parsed value using JSON.parse() for valid JSON strings', () => {
204+
205+
expect( parseValue<true>(
206+
stringifyValue( true )
207+
) ).toBe( true )
208+
209+
expect( parseValue(
210+
stringifyValue( { key: 'value' } )
211+
) ).toEqual( { key: 'value' } )
212+
213+
expect( parseValue(
214+
stringifyValue( [ 1, 2, 3, 4, 5 ] )
215+
) ).toEqual( [ 1, 2, 3, 4, 5 ] )
216+
217+
} )
218+
219+
220+
it( 'returns value as is if JSON.parse() fails', () => {
221+
222+
expect( parseValue( 'String value' ) ).toBe( 'String value' )
223+
93224
} )
94225

95226
} )

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@
6363
"require": "./dist/validation.js"
6464
},
6565
"./storage": {
66-
"types": "./dist/storage/Storage.d.ts",
67-
"import": "./dist/storage/Storage.mjs",
68-
"require": "./dist/storage/Storage.js"
66+
"types": "./dist/storage/index.d.ts",
67+
"import": "./dist/storage/index.mjs",
68+
"require": "./dist/storage/index.js"
6969
},
7070
"./storage/Cookie": {
7171
"types": "./dist/storage/Cookie.d.ts",

src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
export * from './storage'
12
export * from './blob'
23
export * from './generators'
34
export * from './map'
4-
export * from './strings'
5+
export * from './strings'
6+
export * from './types'
7+
export * from './validation'

src/map.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export interface TypedMap<
3737
*
3838
* @template T The object type defining the key-value relationships.
3939
* @template P Defines whether the `Map.get()` method should return a possibily undefined value.
40+
*
41+
* @param iterable Initial `Map` constructor iterable object.
42+
*
4043
* @returns A new instance of a type-safe Map.
4144
*/
4245
export const getTypedMap = <

src/storage/Cookie.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { isValidDate } from '@alessiofrittoli/date-utils'
2-
import { toCamelCase, ucFirst } from '@/strings'
2+
import { parseValue, stringifyValue, toCamelCase, ucFirst } from '@/strings'
33

44
import { getTypedMap, type TypedMap } from '@/map'
5-
import { Storage } from './Storage'
65

76

87
/** The Cookie Priority. */
@@ -251,7 +250,7 @@ export class Cookie
251250
}
252251
if ( key === 'MaxAge' ) key = 'Max-Age' as K
253252

254-
return [ key, Storage.stringifyValue( value ) ].join( '=' )
253+
return [ key, stringifyValue( value ) ].join( '=' )
255254
} )
256255
.join( ';' )
257256
)
@@ -338,6 +337,6 @@ export class Cookie
338337
return ( value !== 'false' ) as T
339338
}
340339

341-
return Storage.parseValue<T>( value )
340+
return parseValue<T>( value )
342341
}
343342
}

src/storage/LocalStorage.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { Storage } from './Storage'
2-
1+
import { parseValue, stringifyValue } from '@/strings'
32

43
/**
54
* A browser-compatible implementation of [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). Data is stored
@@ -33,7 +32,7 @@ export class LocalStorage
3332
static get<T>( name: string )
3433
{
3534
return (
36-
Storage.parseValue<T>( localStorage.getItem( name ) || undefined )
35+
parseValue<T>( localStorage.getItem( name ) || undefined )
3736
)
3837
}
3938

@@ -49,7 +48,7 @@ export class LocalStorage
4948
*/
5049
static set<T>( name: string, value: T )
5150
{
52-
return localStorage.setItem( name, Storage.stringifyValue( value ) )
51+
return localStorage.setItem( name, stringifyValue( value ) )
5352
}
5453

5554

0 commit comments

Comments
 (0)