Refactor routing in App component to enhance navigation and improve error handling by integrating dynamic routes and updating the NotFound route.

This commit is contained in:
becarta
2025-05-23 12:43:00 +02:00
parent f40db0f5c9
commit a544759a3b
11127 changed files with 1647032 additions and 0 deletions

21
node_modules/deterministic-object-hash/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Zane Bauman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

120
node_modules/deterministic-object-hash/README.md generated vendored Normal file
View File

@@ -0,0 +1,120 @@
# Deterministic-Object-Hash
A deterministic object hashing algorithm for Node.js and web platform.
## The Problem
Using `JSON.stringify` on two objects that are deeply equal does not lead to the same output string. Instead the keys are ordered in the same order that they were added. This leads to two objects that are deeply equal being hashed to different values.
```typescript
import { createHash } from "crypto";
import { isEqual } from "lodash";
const obj1: Record<string, string> = {};
obj1['a'] = 'x';
obj1['b'] = 'y';
obj1['c'] = 'z';
const obj2: Record<string, string> = {};
obj2['c'] = 'z';
obj2['b'] = 'y';
obj2['a'] = 'x';
isEqual(obj1, obj2);
// -> true
const string1 = JSON.stringify(obj1);
// -> {"a":"x","b":"y","c":"z"}
const string2 = JSON.stringify(obj2);
// -> {"c":"z","b":"y","a":"x"}
createHash('sha1').update(string1).digest('hex');
// -> ff75fe071d236ce309c15d5636ecaa86c0519ebc
createHash('sha1').update(string2).digest('hex');
// -> 2e53bac865f7be77c8e10cd86d737fbbf259ed37
```
## Usage
Pass a value and receive a deterministic hash of the value.
```typescript
import deterministicHash from 'deterministic-object-hash';
const objA = { a: 'x', arr: [1,2,3,4], b: 'y' };
const objB = { b: 'y', a: 'x', arr: [1,2,3,4] };
await deterministicHash({
c: [ objA, objB ],
b: objA,
e: objB,
f: ()=>{ Math.random(); },
g: Symbol('Unique identity'),
h: new Error('AHHH')
});
// -> 4c57bcb76498dca7b98ef9747c8f1e7f10c30388
await deterministicHash({
h: new Error('AHHH'),
e: objB,
g: Symbol('Unique identity'),
b: objA,
f: ()=>{ Math.random(); },
c: [ objA, objB ]
});
// -> 4c57bcb76498dca7b98ef9747c8f1e7f10c30388
```
## Settings
A hash algorithm can be passed as the second argument. This takes any value that is valid for `webcrypto.subtle.digest`. The default is `SHA-1`. \
A digest format can be passed as the third argument. This takes any value that is valid for `Hash.digest`. The default is `hex`.
```typescript
await deterministicHash('value', 'SHA-1');
// -> efede6000ad4e1ff258a38866c71aa351d3c01f6
await deterministicHash('value', 'SHA-256', 'hex');
// -> a0b7821a11db531982044ca5ca2e788e2d749d6b696cd3aa4172342f584f2ee1
await deterministicHash('value', 'SHA-512', 'base64');
// -> 514CuHw/31qqUH2waqaqhKSMvLYH/YdZeRI4QqDBwhKbUk0/3mxhv4NUubXIl5Dm2k0VpU6ZZkmunEb10RngfQ==
```
## Supported Values
| | |
| ------------------- | ----------------- |
| String | Number |
| Boolean | Function |
| Plain Objects | Symbol |
| undefined | null |
| Infinity | NaN |
| BigInt | Array |
| Classes/Inheritance | Errors |
| Date | RegExp |
| Map | Set |
| Int8Array | Uint8Array |
| Int16Array | Uint16Array |
| Int32Array | Uint32Array |
| Float32Array | Float64Array |
| BigInt64Array | BigUint64Array |
| Uint8ClampedArray | globalThis |
| ArrayBuffer | SharedArrayBuffer |
## Unsupported Values
| | |
| -------- | -------- |
| WeakMap | WeakSet |
| Atomics | DataView |
| Promises | Reflect |
| Proxy | |
Due to their nature, [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet#description) and [WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap#why_weakmap) are not enumerable. As a result there is no way to know what is in a WeakSet/WeakMap unless we are told.
## Support
Currently this has only been tested on Node.js `18.x.x`. More tests are to come and this section will be updated as I test them.
## Contributors
Contributions are welcome. Feel free to create a PR and tag [zbauman3](https://github.com/zbauman3).
### Past contributors:
- [zbauman3](https://github.com/zbauman3)
- [RodrigoTomeES](https://github.com/RodrigoTomeES)

View File

@@ -0,0 +1,6 @@
export declare const encoders: {
base64: (input: ArrayBuffer) => string;
base64url: (input: ArrayBuffer) => string;
hex: (input: ArrayBuffer) => string;
binary: (input: ArrayBuffer) => string;
};

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encoders = void 0;
const base_64_1 = require("base-64");
const binary = (input) => {
let binary = "";
const bytes = new Uint8Array(input);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
const buffer = bytes[i];
if (buffer)
binary += String.fromCharCode(buffer);
}
return binary;
};
const hex = (input) => [...new Uint8Array(input)]
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
// @see https://stackoverflow.com/questions/35155089/node-sha-256-base64-digest
// @see https://stackoverflow.com/questions/9267899/arraybuffer-to-base64-encoded-string
const base64 = (input) => (0, base_64_1.encode)(binary(input));
const base64url = (input) => base64(input).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
exports.encoders = {
base64,
base64url,
hex,
binary,
};

View File

@@ -0,0 +1,5 @@
/// <reference types="node" />
import { BinaryToTextEncoding, webcrypto } from "node:crypto";
/** Creates a deterministic hash for all inputs. */
export default function deterministicHash(input: unknown, algorithm?: Parameters<typeof webcrypto.subtle.digest>[0], output?: BinaryToTextEncoding): Promise<string>;
export declare function deterministicString(input: unknown): string;

166
node_modules/deterministic-object-hash/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,166 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deterministicString = void 0;
const node_crypto_1 = require("node:crypto");
const isPlainObject_1 = __importDefault(require("./isPlainObject"));
const encoders_1 = require("./encoders");
/** Creates a deterministic hash for all inputs. */
async function deterministicHash(input, algorithm = "SHA-1", output = "hex") {
const encoder = new TextEncoder();
const data = encoder.encode(deterministicString(input));
const hash = await node_crypto_1.webcrypto.subtle.digest(algorithm, data);
return encoders_1.encoders[output](hash);
}
exports.default = deterministicHash;
function deterministicString(input) {
if (typeof input === 'string') {
//wrap in quotes (and escape queotes) to differentiate from stringified primitives
return JSON.stringify(input);
}
else if (typeof input === 'symbol' || typeof input === 'function') {
//use `toString` for an accurate representation of these
return input.toString();
}
else if (typeof input === 'bigint') {
//bigint turns into a string int, so I need to differentiate it from a normal int
return `${input}n`;
}
else if (input === globalThis || input === undefined || input === null || typeof input === 'boolean' || typeof input === 'number' || typeof input !== 'object') {
//cast to string for any of these
return `${input}`;
}
else if (input instanceof Date) {
//using timestamp for dates
return `(${input.constructor.name}:${input.getTime()})`;
}
else if (input instanceof RegExp || input instanceof Error || input instanceof WeakMap || input instanceof WeakSet) {
//use simple `toString`. `WeakMap` and `WeakSet` are non-iterable, so this is the best I can do
return `(${input.constructor.name}:${input.toString()})`;
}
else if (input instanceof Set) {
//add the constructor as a key
let ret = `(${input.constructor.name}:[`;
//add all unique values
for (const val of input.values()) {
ret += `${deterministicString(val)},`;
}
ret += '])';
return ret;
}
else if (Array.isArray(input) ||
input instanceof Int8Array ||
input instanceof Uint8Array ||
input instanceof Uint8ClampedArray ||
input instanceof Int16Array ||
input instanceof Uint16Array ||
input instanceof Int32Array ||
input instanceof Uint32Array ||
input instanceof Float32Array ||
input instanceof Float64Array ||
input instanceof BigInt64Array ||
input instanceof BigUint64Array) {
//add the constructor as a key
let ret = `(${input.constructor.name}:[`;
//add all key/value pairs
for (const [k, v] of input.entries()) {
ret += `(${k}:${deterministicString(v)}),`;
}
ret += '])';
return ret;
}
else if (input instanceof ArrayBuffer || input instanceof SharedArrayBuffer) {
//each typed array must be in multiples of their byte size.
//see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects
if (input.byteLength % 8 === 0) {
return deterministicString(new BigUint64Array(input));
}
else if (input.byteLength % 4 === 0) {
return deterministicString(new Uint32Array(input));
}
else if (input.byteLength % 2 === 0) {
return deterministicString(new Uint16Array(input));
}
else {
/** @todo - Change this to a system that breaks it down into parts. E.g. byteLength of 17 = BigUint64Array*2 and Uint8Array */
let ret = '(';
for (let i = 0; i < input.byteLength; i++) {
ret += `${deterministicString(new Uint8Array(input.slice(i, i + 1)))},`;
}
ret += ')';
return ret;
}
}
else if (input instanceof Map || (0, isPlainObject_1.default)(input)) {
//all key/values will be put here for sorting by key
const sortable = [];
//get key/value pairs
const entries = (input instanceof Map
? input.entries()
: Object.entries(input));
//add all key value pairs
for (const [k, v] of entries) {
sortable.push([deterministicString(k), deterministicString(v)]);
}
//if not a map, get Symbol keys and add them
if (!(input instanceof Map)) {
const symbolKeys = Object.getOwnPropertySymbols(input);
//convert each symbol key to a key/value pair
for (let i = 0; i < symbolKeys.length; i++) {
sortable.push([
deterministicString(symbolKeys[i]),
deterministicString(
//have to ignore because `noImplicitAny` is `true` but this is implicitly `any`
//@ts-ignore
input[symbolKeys[i]])
]);
}
}
//sort alphabetically by keys
sortable.sort(([a], [b]) => a.localeCompare(b));
//add the constructor as a key
let ret = `(${input.constructor.name}:[`;
//add all of the key/value pairs
for (const [k, v] of sortable) {
ret += `(${k}:${v}),`;
}
ret += '])';
return ret;
}
//a class/non-plain object
const allEntries = [];
for (const k in input) {
allEntries.push([
deterministicString(k),
deterministicString(
//have to ignore because `noImplicitAny` is `true` but this is implicitly `any`
//@ts-ignore
input[k])
]);
}
//get all own property symbols
const symbolKeys = Object.getOwnPropertySymbols(input);
//convert each symbol key to a key/value pair
for (let i = 0; i < symbolKeys.length; i++) {
allEntries.push([
deterministicString(symbolKeys[i]),
deterministicString(
//have to ignore because `noImplicitAny` is `true` but this is implicitly `any`
//@ts-ignore
input[symbolKeys[i]])
]);
}
//sort alphabetically by keys
allEntries.sort(([a], [b]) => a.localeCompare(b));
//add the constructor as a key
let ret = `(${input.constructor.name}:[`;
//add all of the key/value pairs
for (const [k, v] of allEntries) {
ret += `(${k}:${v}),`;
}
ret += '])';
return ret;
}
exports.deterministicString = deterministicString;

View File

@@ -0,0 +1 @@
export default function isPlainObject(value: unknown): boolean;

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const objConstructorString = Function.prototype.toString.call(Object);
function isPlainObject(value) {
//base object
if (typeof value !== 'object' ||
value === null ||
Object.prototype.toString.call(value) !== '[object Object]') {
return false;
}
//get the prototype
const proto = Object.getPrototypeOf(value);
//no prototype === all good
if (proto === null) {
return true;
}
//has own prop 'constructor'
if (!Object.prototype.hasOwnProperty.call(proto, 'constructor')) {
return false;
}
// validate that the constructor is `Object`
return (typeof proto.constructor === 'function' &&
proto.constructor instanceof proto.constructor &&
Function.prototype.toString.call(proto.constructor) === objConstructorString);
}
exports.default = isPlainObject;
;

42
node_modules/deterministic-object-hash/package.json generated vendored Normal file
View File

@@ -0,0 +1,42 @@
{
"name": "deterministic-object-hash",
"version": "2.0.2",
"description": "A deterministic object hashing algorithm for Node.js.",
"main": "dist/index.js",
"scripts": {
"test": "npx jest",
"build": "npx tsc -b ./",
"ts-watch": "npx tsc -b --watch ./"
},
"repository": {
"type": "git",
"url": "git+https://github.com/zbauman3/Deterministic-Object-Hash.git"
},
"keywords": [
"deterministic",
"object",
"hash",
"algorithm"
],
"author": "Zane Bauman",
"license": "MIT",
"bugs": {
"url": "https://github.com/zbauman3/Deterministic-Object-Hash/issues"
},
"homepage": "https://github.com/zbauman3/Deterministic-Object-Hash#readme",
"devDependencies": {
"@types/base-64": "^1.0.2",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.178",
"@types/node": "18.18.9",
"jest": "^27.4.7",
"lodash": "^4.17.21",
"typescript": "^4.5.5"
},
"engines": {
"node": ">=18"
},
"dependencies": {
"base-64": "^1.0.0"
}
}