@buildinams/core 0.1.0 → 0.2.0
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.
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines the schema for parsing and stringifying states to and from hrefs.
|
|
3
|
+
*
|
|
4
|
+
* The `HrefSchema` type is a generic that takes a state shape and declares three methods:
|
|
5
|
+
*
|
|
6
|
+
* - `parse`: A function that takes an href string and returns the corresponding state object.
|
|
7
|
+
* - `stringify`: A function that takes a state object and the current href, and returns a new href string that represents the given state.
|
|
8
|
+
* - `parseStringify`: A function that takes a current href and a mutation function, and returns a new href string that represents the mutated state.
|
|
9
|
+
*
|
|
10
|
+
* This schema is used to map application state to URL hrefs and vice versa.
|
|
11
|
+
*/
|
|
12
|
+
type HrefSchema<State = any> = {
|
|
13
|
+
/** Parse a href string into the state shape */
|
|
14
|
+
parse: (href: string) => State & {
|
|
15
|
+
href: string;
|
|
16
|
+
};
|
|
17
|
+
/** Stringify a state shape and current href into a new href string */
|
|
18
|
+
stringify: (state: State & {
|
|
19
|
+
href: string;
|
|
20
|
+
}) => string;
|
|
21
|
+
/** Compute a new href string based on a given href and a mutation of the current state. */
|
|
22
|
+
parseStringify: (href: string, mutate: (state: State) => State) => string;
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
_template: HrefSchemaTemplate<State>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A utility type to extract the state shape from a given `HrefSchema`. It infers the state type from the `HrefSchema` and adds the `href` property to it.
|
|
30
|
+
*/
|
|
31
|
+
type HrefSchemaState<T extends HrefSchema> = T extends HrefSchema<infer U> ? U & {
|
|
32
|
+
href: string;
|
|
33
|
+
} : never;
|
|
34
|
+
/**
|
|
35
|
+
* Helper function to create a `HrefSchema` from a simpler template that only requires the logic for converting between URLs and state objects. The `createSchema` function takes care of implementing the `parse`, `stringify`, and `parseStringify` methods based on the provided template functions.
|
|
36
|
+
*
|
|
37
|
+
* The template requires two functions:
|
|
38
|
+
* - `urlToState`: A function that takes a URL object and returns the corresponding state object.
|
|
39
|
+
* - `stateToUrl`: A function that takes a state object and the current URL, and returns a new URL object that represents the given state.
|
|
40
|
+
*
|
|
41
|
+
* This allows you to focus on the logic for how your application's state maps to the URL structure without having to manually handle the parsing and stringifying of hrefs.
|
|
42
|
+
*/
|
|
43
|
+
declare const createHrefSchema: <T>(template: HrefSchemaTemplate<T>) => HrefSchema<T>;
|
|
44
|
+
type HrefSchemaTemplate<State = never> = {
|
|
45
|
+
/** Parse a href string into the state shape */
|
|
46
|
+
urlToState: (url: URL) => State;
|
|
47
|
+
/** Stringify a state shape and current href into a new href string */
|
|
48
|
+
stateToUrl: (state: State, url: URL) => URL;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { type HrefSchema, type HrefSchemaState, createHrefSchema };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/navigation/href-schema.ts
|
|
2
|
+
var hrefToUrl = (href) => new URL(href, "http://localhost");
|
|
3
|
+
var createHrefSchema = (template) => ({
|
|
4
|
+
_template: template,
|
|
5
|
+
stringify: (state) => {
|
|
6
|
+
const current = hrefToUrl(state.href);
|
|
7
|
+
const next = template.stateToUrl(state, current);
|
|
8
|
+
return next.pathname + next.search;
|
|
9
|
+
},
|
|
10
|
+
parse: (href) => {
|
|
11
|
+
const current = hrefToUrl(href);
|
|
12
|
+
return {
|
|
13
|
+
...template.urlToState(current),
|
|
14
|
+
href: current.pathname + current.search
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
parseStringify: (href, mutate) => {
|
|
18
|
+
const current = hrefToUrl(href);
|
|
19
|
+
const next = template.stateToUrl(
|
|
20
|
+
mutate(template.urlToState(current)),
|
|
21
|
+
current
|
|
22
|
+
);
|
|
23
|
+
return next.pathname + next.search;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export { createHrefSchema };
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/navigation/href-schema.ts"],"names":[],"mappings":";AAmCA,IAAM,YAAY,CAAC,IAAA,KAAiB,IAAI,GAAA,CAAI,MAAM,kBAAkB,CAAA;AAW7D,IAAM,gBAAA,GAAmB,CAC/B,QAAA,MACoB;AAAA,EACpB,SAAA,EAAW,QAAA;AAAA,EACX,SAAA,EAAW,CAAC,KAAA,KAAU;AACrB,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,KAAA,CAAM,IAAI,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,UAAA,CAAW,KAAA,EAAO,OAAO,CAAA;AAC/C,IAAA,OAAO,IAAA,CAAK,WAAW,IAAA,CAAK,MAAA;AAAA,EAC7B,CAAA;AAAA,EAEA,KAAA,EAAO,CAAC,IAAA,KAAS;AAChB,IAAA,MAAM,OAAA,GAAU,UAAU,IAAI,CAAA;AAC9B,IAAA,OAAO;AAAA,MACN,GAAG,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA;AAAA,MAC9B,IAAA,EAAM,OAAA,CAAQ,QAAA,GAAW,OAAA,CAAQ;AAAA,KAClC;AAAA,EACD,CAAA;AAAA,EAEA,cAAA,EAAgB,CAAC,IAAA,EAAM,MAAA,KAAW;AACjC,IAAA,MAAM,OAAA,GAAU,UAAU,IAAI,CAAA;AAC9B,IAAA,MAAM,OAAO,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,CAAO,QAAA,CAAS,UAAA,CAAW,OAAO,CAAC,CAAA;AAAA,MACnC;AAAA,KACD;AACA,IAAA,OAAO,IAAA,CAAK,WAAW,IAAA,CAAK,MAAA;AAAA,EAC7B;AACD,CAAA","file":"index.js","sourcesContent":["/**\n * Defines the schema for parsing and stringifying states to and from hrefs.\n *\n * The `HrefSchema` type is a generic that takes a state shape and declares three methods:\n *\n * - `parse`: A function that takes an href string and returns the corresponding state object.\n * - `stringify`: A function that takes a state object and the current href, and returns a new href string that represents the given state.\n * - `parseStringify`: A function that takes a current href and a mutation function, and returns a new href string that represents the mutated state.\n *\n * This schema is used to map application state to URL hrefs and vice versa.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type HrefSchema<State = any> = {\n\t/** Parse a href string into the state shape */\n\tparse: (href: string) => State & { href: string };\n\t/** Stringify a state shape and current href into a new href string */\n\tstringify: (state: State & { href: string }) => string;\n\n\t/** Compute a new href string based on a given href and a mutation of the current state. */\n\tparseStringify: (href: string, mutate: (state: State) => State) => string;\n\n\t/**\n\t * @internal\n\t */\n\t_template: HrefSchemaTemplate<State>;\n};\n\n/**\n * A utility type to extract the state shape from a given `HrefSchema`. It infers the state type from the `HrefSchema` and adds the `href` property to it.\n */\nexport type HrefSchemaState<T extends HrefSchema> =\n\tT extends HrefSchema<infer U> ? U & { href: string } : never;\n\n// This is fine as we only use the `pathname` an `search` properties from the URL object,\n// which do not contain the \"https://localhost\" origin.\nconst hrefToUrl = (href: string) => new URL(href, \"http://localhost\");\n\n/**\n * Helper function to create a `HrefSchema` from a simpler template that only requires the logic for converting between URLs and state objects. The `createSchema` function takes care of implementing the `parse`, `stringify`, and `parseStringify` methods based on the provided template functions.\n *\n * The template requires two functions:\n * - `urlToState`: A function that takes a URL object and returns the corresponding state object.\n * - `stateToUrl`: A function that takes a state object and the current URL, and returns a new URL object that represents the given state.\n *\n * This allows you to focus on the logic for how your application's state maps to the URL structure without having to manually handle the parsing and stringifying of hrefs.\n */\nexport const createHrefSchema = <T>(\n\ttemplate: HrefSchemaTemplate<T>,\n): HrefSchema<T> => ({\n\t_template: template,\n\tstringify: (state) => {\n\t\tconst current = hrefToUrl(state.href);\n\t\tconst next = template.stateToUrl(state, current);\n\t\treturn next.pathname + next.search;\n\t},\n\n\tparse: (href) => {\n\t\tconst current = hrefToUrl(href);\n\t\treturn {\n\t\t\t...template.urlToState(current),\n\t\t\thref: current.pathname + current.search,\n\t\t};\n\t},\n\n\tparseStringify: (href, mutate) => {\n\t\tconst current = hrefToUrl(href);\n\t\tconst next = template.stateToUrl(\n\t\t\tmutate(template.urlToState(current)),\n\t\t\tcurrent,\n\t\t);\n\t\treturn next.pathname + next.search;\n\t},\n});\n\ntype HrefSchemaTemplate<State = never> = {\n\t/** Parse a href string into the state shape */\n\turlToState: (url: URL) => State;\n\t/** Stringify a state shape and current href into a new href string */\n\tstateToUrl: (state: State, url: URL) => URL;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buildinams/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Build in Amsterdam <development@buildinamsterdam.com> (https://www.buildinamsterdam.com/)",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"types": "./dist/index.d.ts",
|
|
26
26
|
"default": "./dist/index.js"
|
|
27
27
|
},
|
|
28
|
+
"./navigation": {
|
|
29
|
+
"types": "./dist/navigation/index.d.ts",
|
|
30
|
+
"default": "./dist/navigation/index.js"
|
|
31
|
+
},
|
|
28
32
|
"./store": {
|
|
29
33
|
"types": "./dist/store/index.d.ts",
|
|
30
34
|
"default": "./dist/store/index.js"
|
|
@@ -35,6 +39,9 @@
|
|
|
35
39
|
"*": [
|
|
36
40
|
"./dist/index.d.ts"
|
|
37
41
|
],
|
|
42
|
+
"./navigation": [
|
|
43
|
+
"./dist/navigation/index.d.ts"
|
|
44
|
+
],
|
|
38
45
|
"./store": [
|
|
39
46
|
"./dist/store/index.d.ts"
|
|
40
47
|
]
|