Skip to content

Commit 46fe02f

Browse files
gwaxpaoloricciuti
andauthored
chore: split out the ssp definitions (#116)
* Split out the ssp definitions I was looking to offer another ssp definition but I was worried the main file was getting a bit too large, so I split the existing definitions out first. * chore: re-export types from `sveltekit-search-params` * Update .changeset/tasty-donkeys-scream.md --------- Co-authored-by: Paolo Ricciuti <[email protected]>
1 parent 73e5347 commit 46fe02f

File tree

10 files changed

+152
-133
lines changed

10 files changed

+152
-133
lines changed

Diff for: .changeset/tasty-donkeys-scream.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'sveltekit-search-params': minor
3+
---
4+
5+
chore: split out the ssp definitions

Diff for: eslint.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export default [
4949
caughtErrorsIgnorePattern: '^(_|\\$\\$)',
5050
},
5151
],
52+
'@typescript-eslint/no-explicit-any': 'off',
5253
},
5354
},
5455
];

Diff for: src/lib/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
// Reexport your entry components here
2-
export { ssp, queryParameters, queryParam } from './sveltekit-search-params.js';
2+
import ssp from './ssp';
3+
4+
export { queryParameters, queryParam } from './sveltekit-search-params';
5+
export { ssp };

Diff for: src/lib/ssp/index.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {
2+
arrayEncodeAndDecodeOptions,
3+
objectEncodeAndDecodeOptions,
4+
} from './json-encode';
5+
import { lzEncodeAndDecodeOptions } from './lz-encode';
6+
import { primitiveEncodeAndDecodeOptions } from './util';
7+
8+
export default {
9+
number: primitiveEncodeAndDecodeOptions({
10+
encode: (value: number) => value.toString(),
11+
decode: (value: string | null) => (value ? parseFloat(value) : null),
12+
}),
13+
boolean: primitiveEncodeAndDecodeOptions({
14+
encode: (value: boolean) => value + '',
15+
decode: (value: string | null) => value !== null && value !== 'false',
16+
}),
17+
string: primitiveEncodeAndDecodeOptions({
18+
encode: (value: string | null) => value ?? '',
19+
decode: (value: string | null) => value,
20+
}),
21+
object: objectEncodeAndDecodeOptions,
22+
array: arrayEncodeAndDecodeOptions,
23+
lz: lzEncodeAndDecodeOptions,
24+
} as const;

Diff for: src/lib/ssp/json-encode.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import type { EncodeAndDecodeOptions } from '$lib/types';
2+
3+
function objectEncodeAndDecodeOptions<T extends object = any>(
4+
defaultValue: T,
5+
): EncodeAndDecodeOptions<T> & { defaultValue: T };
6+
function objectEncodeAndDecodeOptions<
7+
T extends object = any,
8+
>(): EncodeAndDecodeOptions<T> & { defaultValue: undefined };
9+
function objectEncodeAndDecodeOptions<T extends object = any>(
10+
defaultValue?: T,
11+
): EncodeAndDecodeOptions<T> {
12+
return {
13+
encode: (value: T) => JSON.stringify(value),
14+
decode: (value: string | null): T | null => {
15+
if (value === null) return null;
16+
try {
17+
return JSON.parse(value);
18+
} catch {
19+
return null;
20+
}
21+
},
22+
defaultValue,
23+
};
24+
}
25+
26+
function arrayEncodeAndDecodeOptions<T = any>(
27+
defaultValue: T[],
28+
): EncodeAndDecodeOptions<T[]> & { defaultValue: T[] };
29+
function arrayEncodeAndDecodeOptions<T = any>(): EncodeAndDecodeOptions<T[]> & {
30+
defaultValue: undefined;
31+
};
32+
function arrayEncodeAndDecodeOptions<T = any>(
33+
defaultValue?: T[],
34+
): EncodeAndDecodeOptions<T[]> {
35+
return {
36+
encode: (value: T[]) => JSON.stringify(value),
37+
decode: (value: string | null): T[] | null => {
38+
if (value === null) return null;
39+
try {
40+
return JSON.parse(value);
41+
} catch {
42+
return null;
43+
}
44+
},
45+
defaultValue,
46+
};
47+
}
48+
49+
export { objectEncodeAndDecodeOptions, arrayEncodeAndDecodeOptions };

Diff for: src/lib/ssp/lz-encode.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { EncodeAndDecodeOptions } from '$lib/types';
2+
import {
3+
compressToEncodedURIComponent,
4+
decompressFromEncodedURIComponent,
5+
} from './lz-string';
6+
7+
export function lzEncodeAndDecodeOptions<T = any>(
8+
defaultValue: T,
9+
): EncodeAndDecodeOptions<T> & { defaultValue: T };
10+
export function lzEncodeAndDecodeOptions<
11+
T = any,
12+
>(): EncodeAndDecodeOptions<T> & {
13+
defaultValue: undefined;
14+
};
15+
export function lzEncodeAndDecodeOptions<T = any>(
16+
defaultValue?: T,
17+
): EncodeAndDecodeOptions<T> {
18+
return {
19+
encode: (value: T) =>
20+
compressToEncodedURIComponent(JSON.stringify(value)),
21+
decode: (value: string | null): T | null => {
22+
if (!value) return null;
23+
try {
24+
return JSON.parse(
25+
decompressFromEncodedURIComponent(value) ?? '',
26+
);
27+
} catch {
28+
return null;
29+
}
30+
},
31+
defaultValue,
32+
};
33+
}
File renamed without changes.

Diff for: src/lib/ssp/util.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { EncodeAndDecodeOptions } from '$lib/types';
2+
3+
export function primitiveEncodeAndDecodeOptions<T>({
4+
encode,
5+
decode,
6+
}: {
7+
encode: (value: T) => string | undefined;
8+
decode: (value: string | null) => T | null;
9+
}) {
10+
function ssp(
11+
defaultValue: T,
12+
): EncodeAndDecodeOptions<T> & { defaultValue: T };
13+
function ssp(): EncodeAndDecodeOptions<T> & { defaultValue: undefined };
14+
function ssp(defaultValue?: T): EncodeAndDecodeOptions<T> {
15+
return { encode, decode, defaultValue };
16+
}
17+
return ssp;
18+
}

Diff for: src/lib/sveltekit-search-params.ts

+3-132
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
21
import { browser, building } from '$app/environment';
32
import { goto } from '$app/navigation';
43
import { page as page_store } from '$app/stores';
@@ -12,10 +11,8 @@ import {
1211
type Readable,
1312
readable,
1413
} from 'svelte/store';
15-
import {
16-
compressToEncodedURIComponent,
17-
decompressFromEncodedURIComponent,
18-
} from './lz-string/index.js';
14+
import type { EncodeAndDecodeOptions, StoreOptions } from './types';
15+
export type { EncodeAndDecodeOptions, StoreOptions };
1916

2017
// during building we fake the page store with an URL with no search params
2118
// as it should be during prerendering. This allow the application to still build
@@ -43,22 +40,6 @@ const GOTO_OPTIONS_PUSH = {
4340
replaceState: false,
4441
};
4542

46-
export type EncodeAndDecodeOptions<T = any> = {
47-
encode: (value: T) => string | undefined;
48-
decode: (value: string | null) => T | null;
49-
defaultValue?: T;
50-
};
51-
52-
export type StoreOptions<T> = {
53-
debounceHistory?: number;
54-
pushHistory?: boolean;
55-
sort?: boolean;
56-
showDefaults?: boolean;
57-
equalityFn?: T extends object
58-
? (current: T | null, next: T | null) => boolean
59-
: never;
60-
};
61-
6243
type LooseAutocomplete<T> = {
6344
[K in keyof T]: T[K];
6445
} & {
@@ -142,121 +123,11 @@ function isComplexEqual<T>(
142123
);
143124
}
144125

145-
function primitiveEncodeAndDecodeOptions<T>({
146-
encode,
147-
decode,
148-
}: {
149-
encode: (value: T) => string | undefined;
150-
decode: (value: string | null) => T | null;
151-
}) {
152-
function ssp(
153-
defaultValue: T,
154-
): EncodeAndDecodeOptions<T> & { defaultValue: T };
155-
function ssp(): EncodeAndDecodeOptions<T> & { defaultValue: undefined };
156-
function ssp(defaultValue?: T): EncodeAndDecodeOptions<T> {
157-
return { encode, decode, defaultValue };
158-
}
159-
return ssp;
160-
}
161-
162-
function objectEncodeAndDecodeOptions<T extends object = any>(
163-
defaultValue: T,
164-
): EncodeAndDecodeOptions<T> & { defaultValue: T };
165-
function objectEncodeAndDecodeOptions<
166-
T extends object = any,
167-
>(): EncodeAndDecodeOptions<T> & { defaultValue: undefined };
168-
function objectEncodeAndDecodeOptions<T extends object = any>(
169-
defaultValue?: T,
170-
): EncodeAndDecodeOptions<T> {
171-
return {
172-
encode: (value: T) => JSON.stringify(value),
173-
decode: (value: string | null): T | null => {
174-
if (value === null) return null;
175-
try {
176-
return JSON.parse(value);
177-
} catch {
178-
return null;
179-
}
180-
},
181-
defaultValue,
182-
};
183-
}
184-
185-
function arrayEncodeAndDecodeOptions<T = any>(
186-
defaultValue: T[],
187-
): EncodeAndDecodeOptions<T[]> & { defaultValue: T[] };
188-
function arrayEncodeAndDecodeOptions<T = any>(): EncodeAndDecodeOptions<T[]> & {
189-
defaultValue: undefined;
190-
};
191-
function arrayEncodeAndDecodeOptions<T = any>(
192-
defaultValue?: T[],
193-
): EncodeAndDecodeOptions<T[]> {
194-
return {
195-
encode: (value: T[]) => JSON.stringify(value),
196-
decode: (value: string | null): T[] | null => {
197-
if (value === null) return null;
198-
try {
199-
return JSON.parse(value);
200-
} catch {
201-
return null;
202-
}
203-
},
204-
defaultValue,
205-
};
206-
}
207-
208-
function lzEncodeAndDecodeOptions<T = any>(
209-
defaultValue: T,
210-
): EncodeAndDecodeOptions<T> & { defaultValue: T };
211-
function lzEncodeAndDecodeOptions<T = any>(): EncodeAndDecodeOptions<T> & {
212-
defaultValue: undefined;
213-
};
214-
function lzEncodeAndDecodeOptions<T = any>(
215-
defaultValue?: T,
216-
): EncodeAndDecodeOptions<T> {
217-
return {
218-
encode: (value: T) =>
219-
compressToEncodedURIComponent(JSON.stringify(value)),
220-
decode: (value: string | null): T | null => {
221-
if (!value) return null;
222-
try {
223-
return JSON.parse(
224-
decompressFromEncodedURIComponent(value) ?? '',
225-
);
226-
} catch {
227-
return null;
228-
}
229-
},
230-
defaultValue,
231-
};
232-
}
233-
234-
export const ssp = {
235-
number: primitiveEncodeAndDecodeOptions({
236-
encode: (value: number) => value.toString(),
237-
decode: (value: string | null) => (value ? parseFloat(value) : null),
238-
}),
239-
boolean: primitiveEncodeAndDecodeOptions({
240-
encode: (value: boolean) => value + '',
241-
decode: (value: string | null) => value !== null && value !== 'false',
242-
}),
243-
string: primitiveEncodeAndDecodeOptions({
244-
encode: (value: string | null) => value ?? '',
245-
decode: (value: string | null) => value,
246-
}),
247-
object: objectEncodeAndDecodeOptions,
248-
array: arrayEncodeAndDecodeOptions,
249-
lz: lzEncodeAndDecodeOptions,
250-
} satisfies Record<
251-
string,
252-
<T = any>(defaultValue?: T) => EncodeAndDecodeOptions<T>
253-
>;
254-
255126
type SetTimeout = ReturnType<typeof setTimeout>;
256127

257128
const batchedUpdates = new Set<(query: URLSearchParams) => void>();
258129

259-
let batchTimeout: number;
130+
let batchTimeout: ReturnType<typeof setTimeout>;
260131

261132
const debouncedTimeouts = new Map<string, SetTimeout>();
262133

Diff for: src/lib/types.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export type EncodeAndDecodeOptions<T = any> = {
2+
encode: (value: T) => string | undefined;
3+
decode: (value: string | null) => T | null;
4+
defaultValue?: T;
5+
};
6+
7+
export type StoreOptions<T> = {
8+
debounceHistory?: number;
9+
pushHistory?: boolean;
10+
sort?: boolean;
11+
showDefaults?: boolean;
12+
equalityFn?: T extends object
13+
? (current: T | null, next: T | null) => boolean
14+
: never;
15+
};

0 commit comments

Comments
 (0)