Conversion from svelte params to pagination query to search params
This commit is contained in:
parent
5f1c7e9804
commit
9846fab54c
301
package-lock.json
generated
301
package-lock.json
generated
@ -8,6 +8,7 @@
|
|||||||
"name": "michalvankodev",
|
"name": "michalvankodev",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mobily/ts-belt": "^3.10.0",
|
||||||
"@vanilla-extract/css": "^1.6.8",
|
"@vanilla-extract/css": "^1.6.8",
|
||||||
"@vanilla-extract/sprinkles": "^1.4.0",
|
"@vanilla-extract/sprinkles": "^1.4.0",
|
||||||
"@vanilla-extract/vite-plugin": "^3.1.4",
|
"@vanilla-extract/vite-plugin": "^3.1.4",
|
||||||
@ -40,7 +41,8 @@
|
|||||||
"svgstore-cli": "^2.0.1",
|
"svgstore-cli": "^2.0.1",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.3.1",
|
||||||
"typescript": "^4.6.2",
|
"typescript": "^4.6.2",
|
||||||
"vite": "^2.8.6"
|
"vite": "^2.8.6",
|
||||||
|
"vitest": "^0.7.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
@ -445,6 +447,14 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@mobily/ts-belt": {
|
||||||
|
"version": "3.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mobily/ts-belt/-/ts-belt-3.10.0.tgz",
|
||||||
|
"integrity": "sha512-F3XLU3zMDzJOf9KlKgnNOz5rdAtMG/UBxEDU4UNA4ewKFRd5DsbIIJmeAifLudNwcXmoIgtZ39KwVjPaL/CjgA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@ -566,6 +576,21 @@
|
|||||||
"integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==",
|
"integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/chai": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/chai-subset": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/chai": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/classnames": {
|
"node_modules/@types/classnames": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.3.1.tgz",
|
||||||
@ -1035,6 +1060,15 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/assertion-error": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
@ -1120,6 +1154,24 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/chai": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"assertion-error": "^1.1.0",
|
||||||
|
"check-error": "^1.0.2",
|
||||||
|
"deep-eql": "^3.0.1",
|
||||||
|
"get-func-name": "^2.0.0",
|
||||||
|
"loupe": "^2.3.1",
|
||||||
|
"pathval": "^1.1.1",
|
||||||
|
"type-detect": "^4.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
@ -1136,6 +1188,15 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/check-error": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cheerio": {
|
"node_modules/cheerio": {
|
||||||
"version": "1.0.0-rc.10",
|
"version": "1.0.0-rc.10",
|
||||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
|
||||||
@ -1304,6 +1365,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/deep-eql": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"type-detect": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||||
@ -2377,6 +2450,15 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-func-name": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||||
@ -2787,6 +2869,18 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/local-pkg": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
@ -2812,6 +2906,15 @@
|
|||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/loupe": {
|
||||||
|
"version": "2.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
|
||||||
|
"integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"get-func-name": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
@ -3119,6 +3222,15 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pathval": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
@ -3707,6 +3819,24 @@
|
|||||||
"globrex": "^0.1.2"
|
"globrex": "^0.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tinypool": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-fvtYGXoui2RpeMILfkvGIgOVkzJEGediv8UJt7TxdAOY8pnvUkFg/fkvqTfXG9Acc9S17Cnn1S4osDc2164guA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tinyspy": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-c5uFHqtUp74R2DJE3/Efg0mH5xicmgziaQXMm/LvuuZn3RdpADH32aEGDRyCzObXT1DNfwDMqRQ/Drh1MlO12g==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/to-fast-properties": {
|
"node_modules/to-fast-properties": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
@ -3775,6 +3905,15 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/type-detect": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-fest": {
|
"node_modules/type-fest": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
@ -3885,6 +4024,50 @@
|
|||||||
"esbuild-windows-arm64": "0.14.27"
|
"esbuild-windows-arm64": "0.14.27"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vitest": {
|
||||||
|
"version": "0.7.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-0.7.10.tgz",
|
||||||
|
"integrity": "sha512-We5a7cnY2aUpX4tAO+w2KRhJiJ4FznfWjYKkqWoAqs4x4pKgyRsMJNZ7OSY/lFHOoRz3yv0mgwfVlZiRc0/mmA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/chai": "^4.3.0",
|
||||||
|
"@types/chai-subset": "^1.3.3",
|
||||||
|
"chai": "^4.3.6",
|
||||||
|
"local-pkg": "^0.4.1",
|
||||||
|
"tinypool": "^0.1.2",
|
||||||
|
"tinyspy": "^0.3.0",
|
||||||
|
"vite": "^2.8.6"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"vitest": "vitest.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.16.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vitest/ui": "*",
|
||||||
|
"c8": "*",
|
||||||
|
"happy-dom": "*",
|
||||||
|
"jsdom": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vitest/ui": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"c8": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"happy-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"jsdom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||||
@ -4315,6 +4498,11 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@mobily/ts-belt": {
|
||||||
|
"version": "3.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mobily/ts-belt/-/ts-belt-3.10.0.tgz",
|
||||||
|
"integrity": "sha512-F3XLU3zMDzJOf9KlKgnNOz5rdAtMG/UBxEDU4UNA4ewKFRd5DsbIIJmeAifLudNwcXmoIgtZ39KwVjPaL/CjgA=="
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@ -4401,6 +4589,21 @@
|
|||||||
"integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==",
|
"integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/chai": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/chai-subset": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/chai": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/classnames": {
|
"@types/classnames": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.3.1.tgz",
|
||||||
@ -4721,6 +4924,12 @@
|
|||||||
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"assertion-error": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
@ -4787,6 +4996,21 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"chai": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"assertion-error": "^1.1.0",
|
||||||
|
"check-error": "^1.0.2",
|
||||||
|
"deep-eql": "^3.0.1",
|
||||||
|
"get-func-name": "^2.0.0",
|
||||||
|
"loupe": "^2.3.1",
|
||||||
|
"pathval": "^1.1.1",
|
||||||
|
"type-detect": "^4.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
@ -4800,6 +5024,12 @@
|
|||||||
"supports-color": "^5.3.0"
|
"supports-color": "^5.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"check-error": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"cheerio": {
|
"cheerio": {
|
||||||
"version": "1.0.0-rc.10",
|
"version": "1.0.0-rc.10",
|
||||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
|
||||||
@ -4929,6 +5159,15 @@
|
|||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"deep-eql": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"type-detect": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"deep-is": {
|
"deep-is": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||||
@ -5623,6 +5862,12 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"get-func-name": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||||
@ -5932,6 +6177,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz",
|
||||||
"integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA=="
|
"integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA=="
|
||||||
},
|
},
|
||||||
|
"local-pkg": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"locate-path": {
|
"locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
@ -5951,6 +6202,15 @@
|
|||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"loupe": {
|
||||||
|
"version": "2.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
|
||||||
|
"integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"get-func-name": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
@ -6180,6 +6440,12 @@
|
|||||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pathval": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"picocolors": {
|
"picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
@ -6535,6 +6801,18 @@
|
|||||||
"globrex": "^0.1.2"
|
"globrex": "^0.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tinypool": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-fvtYGXoui2RpeMILfkvGIgOVkzJEGediv8UJt7TxdAOY8pnvUkFg/fkvqTfXG9Acc9S17Cnn1S4osDc2164guA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"tinyspy": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-c5uFHqtUp74R2DJE3/Efg0mH5xicmgziaQXMm/LvuuZn3RdpADH32aEGDRyCzObXT1DNfwDMqRQ/Drh1MlO12g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"to-fast-properties": {
|
"to-fast-properties": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
@ -6590,6 +6868,12 @@
|
|||||||
"prelude-ls": "^1.2.1"
|
"prelude-ls": "^1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"type-detect": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"type-fest": {
|
"type-fest": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
@ -6658,6 +6942,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"vitest": {
|
||||||
|
"version": "0.7.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-0.7.10.tgz",
|
||||||
|
"integrity": "sha512-We5a7cnY2aUpX4tAO+w2KRhJiJ4FznfWjYKkqWoAqs4x4pKgyRsMJNZ7OSY/lFHOoRz3yv0mgwfVlZiRc0/mmA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/chai": "^4.3.0",
|
||||||
|
"@types/chai-subset": "^1.3.3",
|
||||||
|
"chai": "^4.3.6",
|
||||||
|
"local-pkg": "^0.4.1",
|
||||||
|
"tinypool": "^0.1.2",
|
||||||
|
"tinyspy": "^0.3.0",
|
||||||
|
"vite": "^2.8.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"word-wrap": {
|
"word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
"build": "svelte-kit build --verbose",
|
"build": "svelte-kit build --verbose",
|
||||||
"preview": "svelte-kit preview",
|
"preview": "svelte-kit preview",
|
||||||
"start": "svelte-kit start",
|
"start": "svelte-kit start",
|
||||||
"test": "run-p --race dev cy:run",
|
"test": "vitest",
|
||||||
"lint": "prettier --check . && eslint --ignore-path .gitignore .",
|
"lint": "prettier --check . && eslint --ignore-path .gitignore .",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"svgstore": "svgstore -o static/build/icons-sprite.svg src/svg/**.svg"
|
"svgstore": "svgstore -o static/build/icons-sprite.svg src/svg/**.svg"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mobily/ts-belt": "^3.10.0",
|
||||||
"@vanilla-extract/css": "^1.6.8",
|
"@vanilla-extract/css": "^1.6.8",
|
||||||
"@vanilla-extract/sprinkles": "^1.4.0",
|
"@vanilla-extract/sprinkles": "^1.4.0",
|
||||||
"@vanilla-extract/vite-plugin": "^3.1.4",
|
"@vanilla-extract/vite-plugin": "^3.1.4",
|
||||||
@ -48,6 +49,7 @@
|
|||||||
"svgstore-cli": "^2.0.1",
|
"svgstore-cli": "^2.0.1",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.3.1",
|
||||||
"typescript": "^4.6.2",
|
"typescript": "^4.6.2",
|
||||||
"vite": "^2.8.6"
|
"vite": "^2.8.6",
|
||||||
|
"vitest": "^0.7.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
98
src/lib/pagination/pagination.test.ts
Normal file
98
src/lib/pagination/pagination.test.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { range } from 'ramda'
|
||||||
|
import { describe, expect, test } from 'vitest'
|
||||||
|
import { filterByPropContains, dropAndTake, filterAndCount } from './pagination'
|
||||||
|
|
||||||
|
describe('pagination', () => {
|
||||||
|
test('does not drop any items by default', () => {
|
||||||
|
const items = range(0, 100)
|
||||||
|
expect(dropAndTake({})(items)).toHaveLength(100)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('limits out exact number of items', () => {
|
||||||
|
const items = range(0, 100)
|
||||||
|
expect(dropAndTake({ limit: 10 })(items)).toHaveLength(10)
|
||||||
|
expect(dropAndTake({ limit: 10 })(items)[0]).toBe(0)
|
||||||
|
expect(dropAndTake({ limit: 10 })(items)[9]).toBe(9)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('offset is skipping a number of items from the front', () => {
|
||||||
|
const items = range(0, 100)
|
||||||
|
expect(dropAndTake({ offset: 10 })(items)).toHaveLength(90)
|
||||||
|
expect(dropAndTake({ offset: 10 })(items)[0]).toBe(10)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is able to combine limit and offset', () => {
|
||||||
|
const items = range(0, 100)
|
||||||
|
expect(dropAndTake({ offset: 10, limit: 10 })(items)).toHaveLength(10)
|
||||||
|
expect(dropAndTake({ offset: 10, limit: 10 })(items)[0]).toBe(10)
|
||||||
|
expect(dropAndTake({ offset: 10, limit: 10 })(items)[9]).toBe(19)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is able to filter by a field', () => {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
prop: ['yes'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
prop: ['yes', 'no'],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(filterByPropContains({ prop: 'no' })(items)).toHaveLength(1)
|
||||||
|
expect(filterByPropContains({ prop: 'no' })(items)[0].id).toBe(2)
|
||||||
|
|
||||||
|
expect(filterByPropContains({ prop: 'yes' })(items)[0].id).toBe(1)
|
||||||
|
expect(filterByPropContains({ prop: 'yes' })(items)).toHaveLength(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('is able to combine limit and offset while filtering by field', () => {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
prop: ['yes'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
prop: ['yes', 'no'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
prop: ['yes', 'no'],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
test('combine all parameters', () => {
|
||||||
|
const result = filterAndCount({
|
||||||
|
offset: 1,
|
||||||
|
limit: 1,
|
||||||
|
filters: { prop: 'no' },
|
||||||
|
})(items)
|
||||||
|
expect(result.totalCount).toBe(2)
|
||||||
|
expect(result.items[0].id).toBe(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('with 0 offset', () => {
|
||||||
|
const result = filterAndCount({
|
||||||
|
offset: 0,
|
||||||
|
limit: 1,
|
||||||
|
filters: { prop: 'no' },
|
||||||
|
})(items)
|
||||||
|
expect(result.totalCount).toBe(2)
|
||||||
|
expect(result.items[0].id).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('without filter', () => {
|
||||||
|
const result = filterAndCount({ offset: 1, limit: 1 })(items)
|
||||||
|
expect(result.totalCount).toBe(3)
|
||||||
|
expect(result.items[0].id).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('without any params', () => {
|
||||||
|
const result = filterAndCount({})(items)
|
||||||
|
expect(result.totalCount).toBe(3)
|
||||||
|
expect(result.items.length).toEqual(result.totalCount)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
44
src/lib/pagination/pagination.ts
Normal file
44
src/lib/pagination/pagination.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { identity } from 'ramda'
|
||||||
|
import { flow, A } from '@mobily/ts-belt'
|
||||||
|
const { drop, take } = A
|
||||||
|
|
||||||
|
export interface PaginationQuery {
|
||||||
|
offset?: number
|
||||||
|
limit?: number
|
||||||
|
filters?: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PaginationResult<ItemType> {
|
||||||
|
items: ItemType[]
|
||||||
|
totalCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dropAndTake<Item>({ offset = 0, limit = Infinity }) {
|
||||||
|
return flow(drop<Item>(offset), take<Item>(limit))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function filterByPropContains<Item>(filters: Record<string, string>) {
|
||||||
|
return function (items: Item[]) {
|
||||||
|
return items.filter((item) => {
|
||||||
|
return Object.entries(filters).every(([fieldName, value]) =>
|
||||||
|
item[fieldName].includes(value)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function filterAndCount<Item>({
|
||||||
|
filters,
|
||||||
|
...dropTakeParams
|
||||||
|
}: PaginationQuery) {
|
||||||
|
return function (items: Item[]) {
|
||||||
|
const filterFunction = filters
|
||||||
|
? filterByPropContains<Item>(filters)
|
||||||
|
: identity
|
||||||
|
const filteredItems = filterFunction(items)
|
||||||
|
return {
|
||||||
|
items: dropAndTake<Item>(dropTakeParams)(filteredItems),
|
||||||
|
totalCount: filteredItems.length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
src/lib/pagination/searchParams.test.ts
Normal file
64
src/lib/pagination/searchParams.test.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { describe, test, expect } from 'vitest'
|
||||||
|
import {
|
||||||
|
getPaginationQueryFromSearchParams,
|
||||||
|
getPaginationSearchParams,
|
||||||
|
parseParams,
|
||||||
|
} from './searchParams'
|
||||||
|
|
||||||
|
describe('convert search params', () => {
|
||||||
|
test('drop take params are not taken as filters', () => {
|
||||||
|
expect(
|
||||||
|
getPaginationQueryFromSearchParams(
|
||||||
|
new URLSearchParams('offset=2&limit=5')
|
||||||
|
)
|
||||||
|
).toEqual({ offset: 2, limit: 5 })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('return empty paginationQuery if ', () => {
|
||||||
|
expect(getPaginationQueryFromSearchParams(new URLSearchParams(''))).toEqual(
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('other than drop take params are moved to filters ', () => {
|
||||||
|
expect(
|
||||||
|
getPaginationQueryFromSearchParams(new URLSearchParams('tag=news'))
|
||||||
|
).toEqual({ filters: { tag: 'news' } })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('offset and filter combined', () => {
|
||||||
|
expect(
|
||||||
|
getPaginationQueryFromSearchParams(
|
||||||
|
new URLSearchParams('offset=3&tag=news')
|
||||||
|
)
|
||||||
|
).toEqual({ offset: 3, filters: { tag: 'news' } })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('get search params', () => {
|
||||||
|
test('parse params', () => {
|
||||||
|
const params = 'tags/News/page/1'
|
||||||
|
expect(parseParams(params)).toEqual({ tags: 'News', page: '1' })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should parse values into searchParams for first page', () => {
|
||||||
|
const params = 'tags/News/page/1'
|
||||||
|
expect(getPaginationSearchParams(7, params).toString()).toEqual(
|
||||||
|
'limit=7&offset=0&tags=News'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should parse values into searchParams for third page', () => {
|
||||||
|
const params = 'tags/News/page/3'
|
||||||
|
expect(getPaginationSearchParams(7, params).toString()).toEqual(
|
||||||
|
'limit=7&offset=14&tags=News'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should return first page without any params specified', () => {
|
||||||
|
const params = ''
|
||||||
|
expect(getPaginationSearchParams(7, params).toString()).toEqual(
|
||||||
|
'limit=7&offset=0'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
46
src/lib/pagination/searchParams.ts
Normal file
46
src/lib/pagination/searchParams.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { splitEvery } from 'ramda'
|
||||||
|
import type { PaginationQuery } from './pagination'
|
||||||
|
|
||||||
|
export function getPaginationQueryFromSearchParams(
|
||||||
|
searchParams: URLSearchParams
|
||||||
|
) {
|
||||||
|
return Array.from(searchParams).reduce<PaginationQuery>(
|
||||||
|
(acc, [key, value]) => {
|
||||||
|
const isDropTake = ['offset', 'limit'].includes(key)
|
||||||
|
if (isDropTake) {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[key]: Number(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
filters: {
|
||||||
|
...acc.filters,
|
||||||
|
[key]: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseParams(params: string) {
|
||||||
|
const splittedParams = params.split('/')
|
||||||
|
if (splittedParams.length % 2 !== 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const splits = splitEvery(2, splittedParams)
|
||||||
|
return Object.fromEntries(splits)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert svelte `load` params into a `URLSearchParams` so they can be used to fetch endpoints with pagination queries
|
||||||
|
*/
|
||||||
|
export function getPaginationSearchParams(pageSize: number, params: string) {
|
||||||
|
const { page = 1, ...filters } = parseParams(params)
|
||||||
|
|
||||||
|
const offset = pageSize * (page - 1)
|
||||||
|
const limit = pageSize
|
||||||
|
return new URLSearchParams({ limit, offset, ...filters })
|
||||||
|
}
|
@ -3,11 +3,11 @@
|
|||||||
import type { LoadInput, LoadOutput } from '@sveltejs/kit/types/page'
|
import type { LoadInput, LoadOutput } from '@sveltejs/kit/types/page'
|
||||||
|
|
||||||
export async function load({ fetch, url }: LoadInput): Promise<LoadOutput> {
|
export async function load({ fetch, url }: LoadInput): Promise<LoadOutput> {
|
||||||
const blogPostsResponse = await fetch(`/blog/articles`)
|
const blogPostsResponse = await fetch(`/blog/articles?limit=5`)
|
||||||
const blogPostsContent = await blogPostsResponse.json()
|
const blogPostsContent = await blogPostsResponse.json()
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
latestPosts: take(5, blogPostsContent.posts),
|
latestPosts: blogPostsContent.posts.items,
|
||||||
// TODO Check if not bugged FIXME
|
// TODO Check if not bugged FIXME
|
||||||
segment: '',
|
segment: '',
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
|
import { getPaginationSearchParams } from '$lib/pagination/searchParams'
|
||||||
/**
|
/**
|
||||||
* @type {import('@sveltejs/kit').Load}
|
* @type {import('@sveltejs/kit').Load}
|
||||||
*/
|
*/
|
||||||
export async function load({ fetch }) {
|
export async function load({ fetch, params }) {
|
||||||
const articleResponse = await fetch(`/blog/articles`)
|
console.log('params', params)
|
||||||
.then((r) => r.json())
|
const searchParams = getPaginationSearchParams(7, params.params)
|
||||||
|
console.log('searchpprsm', searchParams)
|
||||||
|
const articleResponse = await fetch(
|
||||||
|
`/blog/articles?${searchParams.toString()}`
|
||||||
|
).then((r) => r.json())
|
||||||
|
|
||||||
return { props: { posts: articleResponse.posts } }
|
return { props: { posts: articleResponse.posts } }
|
||||||
}
|
}
|
||||||
@ -14,8 +19,9 @@
|
|||||||
import ArticleFooter from '../../components/blog/ArticleFooter.svelte'
|
import ArticleFooter from '../../components/blog/ArticleFooter.svelte'
|
||||||
import { postListClass, seeAllClass } from './index.css'
|
import { postListClass, seeAllClass } from './index.css'
|
||||||
import type { PostContent } from './_content'
|
import type { PostContent } from './_content'
|
||||||
|
import type { PaginationResult } from '$lib/pagination/pagination'
|
||||||
|
|
||||||
export let posts: PostContent[]
|
export let posts: PaginationResult<PostContent>
|
||||||
export let tagQuery: string
|
export let tagQuery: string
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -23,7 +29,7 @@
|
|||||||
<title>My blog @michalvankodev</title>
|
<title>My blog @michalvankodev</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
{#if posts.length === 0}
|
{#if posts.items.length === 0}
|
||||||
<p class="no-posts">You've found void in the space.</p>
|
<p class="no-posts">You've found void in the space.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<h1>
|
<h1>
|
||||||
@ -40,7 +46,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<ul class="post-list {postListClass}">
|
<ul class="post-list {postListClass}">
|
||||||
{#each posts as post}
|
{#each posts.items as post}
|
||||||
<li>
|
<li>
|
||||||
<article>
|
<article>
|
||||||
<header>
|
<header>
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
import { readdir, readFile } from 'fs'
|
import { readdir, readFile } from 'fs'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
import { basename } from 'path'
|
import { basename } from 'path'
|
||||||
import { pipe, partial, prop, sortBy, reverse, filter } from 'ramda'
|
import { pipe, prop, sortBy, reverse, filter } from 'ramda'
|
||||||
import fm from 'front-matter'
|
import fm from 'front-matter'
|
||||||
import marked from 'marked'
|
import marked from 'marked'
|
||||||
|
import {
|
||||||
|
filterAndCount,
|
||||||
|
type PaginationQuery,
|
||||||
|
} from '$lib/pagination/pagination'
|
||||||
|
|
||||||
const { NODE_ENV } = process.env
|
const { NODE_ENV } = process.env
|
||||||
|
// TODO remove ramda and migrate to ts-belt
|
||||||
|
// TODO Pagination component for routing
|
||||||
|
// TODO Tag filtering visualization
|
||||||
|
|
||||||
export interface PostAttributes {
|
export interface PostAttributes {
|
||||||
layout: string
|
layout: string
|
||||||
@ -22,7 +29,7 @@ export interface PostContent extends PostAttributes {
|
|||||||
published: boolean
|
published: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getBlogListing(tag?: string) {
|
export async function getBlogListing(paginationQuery: PaginationQuery) {
|
||||||
const files = await promisify(readdir)(`_posts/blog/`, 'utf-8')
|
const files = await promisify(readdir)(`_posts/blog/`, 'utf-8')
|
||||||
const filteredFiles = filterDevelopmentFiles(files)
|
const filteredFiles = filterDevelopmentFiles(files)
|
||||||
|
|
||||||
@ -48,17 +55,11 @@ export async function getBlogListing(tag?: string) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
const filteredContents = pipe<
|
const filteredContents = pipe(
|
||||||
PostContent[],
|
sortBy<PostContent>(prop('date')),
|
||||||
PostContent[],
|
(items) => reverse(items),
|
||||||
PostContent[],
|
|
||||||
PostContent[],
|
|
||||||
PostContent[]
|
|
||||||
>(
|
|
||||||
sortBy(prop('date')),
|
|
||||||
reverse,
|
|
||||||
filter<typeof contents[0]>((article) => article.published),
|
filter<typeof contents[0]>((article) => article.published),
|
||||||
partial(filterByTag, [tag])
|
filterAndCount(paginationQuery)
|
||||||
)(contents)
|
)(contents)
|
||||||
|
|
||||||
return filteredContents
|
return filteredContents
|
||||||
@ -69,9 +70,3 @@ function filterDevelopmentFiles(files: string[]) {
|
|||||||
? files
|
? files
|
||||||
: files.filter((file) => !file.startsWith('dev-'))
|
: files.filter((file) => !file.startsWith('dev-'))
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterByTag(tag: string | undefined, contents: PostContent[]) {
|
|
||||||
return tag
|
|
||||||
? contents.filter((content) => content.tags.includes(tag))
|
|
||||||
: contents
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
|
import { getPaginationQueryFromSearchParams } from '$lib/pagination/searchParams'
|
||||||
import { getBlogListing } from './_content'
|
import { getBlogListing } from './_content'
|
||||||
|
|
||||||
export async function get({ url: { searchParams } }) {
|
export async function get({ url: { searchParams } }) {
|
||||||
console.log('bloglistingparams', searchParams)
|
const paginationQuery = getPaginationQueryFromSearchParams(searchParams)
|
||||||
|
const filteredContents = await getBlogListing(paginationQuery)
|
||||||
|
|
||||||
//Regexp for getting an optional tag and a page from the params
|
|
||||||
const tag = undefined
|
|
||||||
const filteredContents = await getBlogListing(tag)
|
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
body: {
|
body: {
|
||||||
|
Loading…
Reference in New Issue
Block a user