Add sync error logging, extend error flash, fix unload saves

- Log workforce sync errors to backend stdout so they appear in docker logs
- Extend error flash from 5s to 15s so errors are readable
- Replace sendBeacon (POST-only) with keepalive fetch (PUT) on unload —
  sendBeacon was hitting 404s on all three unload saves

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-22 14:19:38 +00:00
parent c7066521ff
commit 18e24efbeb
14485 changed files with 1836116 additions and 33 deletions

21
frontend/node_modules/smob/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-2022 Peter Placzek
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.

162
frontend/node_modules/smob/README.MD generated vendored Normal file
View file

@ -0,0 +1,162 @@
# SMOB 🧪
[![npm version](https://badge.fury.io/js/smob.svg)](https://badge.fury.io/js/smob)
[![main](https://github.com/tada5hi/smob/actions/workflows/main.yml/badge.svg)](https://github.com/tada5hi/smob/actions/workflows/main.yml)
[![codecov](https://codecov.io/gh/tada5hi/smob/branch/master/graph/badge.svg?token=0VL41WO0CG)](https://codecov.io/gh/tada5hi/smob)
[![Known Vulnerabilities](https://snyk.io/test/github/Tada5hi/smob/badge.svg?targetFile=package.json)](https://snyk.io/test/github/Tada5hi/smob?targetFile=package.json)
[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
A zero dependency library to **s**afe **m**erge **ob**jects and arrays with customizable behavior.
**Table of Contents**
- [Installation](#installation)
- [Usage](#usage)
- [Merger](#merger)
- [Utils](#utils)
- [License](#license)
## Installation
```bash
npm install smob --save
```
## Usage
```typescript
import { merge } from "smob";
const output = merge(...sources);
```
The following merge options are set by default:
- **array**: `true` Merge object array properties.
- **arrayDistinct**: `false` Remove duplicates, when merging array elements.
- **arrayPriority**: `left` (options.priority) The source aka leftmost array has by **default** the highest priority.
- **clone**: `false` Deep clone input sources.
- **inPlace**: `false` Merge sources in place.
- **priority**: `left` The source aka leftmost object has by **default** the highest priority.
The merge behaviour can be changed by creating a custom [merger](#merger).
**Arguments**
- sources `(any[] | Record<string, any>)[]`: The source arrays/objects.
```typescript
import { merge } from 'smob';
merge({ a: 1 }, { b: 2 }, { c: 3 });
// { a: 1, b: 2, c: 3 }
merge(['foo'], ['bar']);
// ['foo', 'bar']
```
### Merger
A custom merger can simply be created by using the `createMerger` method.
**Array**
```typescript
import { createMerger } from 'smob';
const merge = createMerger({ array: false });
merge({ a: [1,2,3] }, { a: [4,5,6] });
// { a: [1,2,3] }
```
**ArrayDistinct**
```typescript
import { createMerger } from 'smob';
const merge = createMerger({ arrayDistinct: true });
merge({ a: [1,2,3] }, { a: [3,4,5] });
// { a: [1,2,3,4,5] }
```
**Priority**
```typescript
import { createMerger } from 'smob';
const merge = createMerger({ priority: 'right' });
merge({ a: 1 }, { a: 2 }, { a: 3 })
// { a: 3 }
```
**Strategy**
```typescript
import { createMerger } from 'smob';
const merge = createMerger({
strategy: (target, key, value) => {
if (
typeof target[key] === 'number' &&
typeof value === 'number'
) {
target[key] += value;
return target;
}
}
});
merge({ a: 1 }, { a: 2 }, { a: 3 });
// { a: 6 }
```
A returned value indicates that the strategy has been applied.
## Utils
### distinctArray
```typescript
import { distinctArray } from 'smob';
distnctArray(['foo', 'bar', 'foo']);
// ['foo', 'bar']
```
The function also removes non-primitive
elements that are identical by value or reference.
**Objects**
```typescript
import { distinctArray } from 'smob';
distinctArray([{ foo: 'bar' }, { foo: 'bar' }]);
// [{ foo: 'bar' }]
```
**Arrays**
```typescript
import { distinctArray } from 'smob';
distinctArray([['foo', 'bar'], ['foo', 'bar']]);
// [['foo', 'bar']]
```
### isEqual
Checks if two (non-primitive) elements
are identical by value or reference.
````typescript
import { isEqual } from 'smob';
isEqual({foo: 'bar'}, {foo: 'bar'});
// true
isEqual(['foo', 'bar'], ['foo', 'bar']);
// true
````
## License
Made with 💚
Published under [MIT License](./LICENSE).

215
frontend/node_modules/smob/dist/index.cjs generated vendored Normal file
View file

@ -0,0 +1,215 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/constants.ts
let PriorityName = /* @__PURE__ */ function(PriorityName) {
PriorityName["LEFT"] = "left";
PriorityName["RIGHT"] = "right";
return PriorityName;
}({});
//#endregion
//#region src/utils/check.ts
function isObject(item) {
return !!item && typeof item === "object" && !Array.isArray(item);
}
function isSafeKey(key) {
return key !== "__proto__" && key !== "prototype" && key !== "constructor";
}
function isEqual(x, y) {
if (Object.is(x, y)) return true;
if (x instanceof Date && y instanceof Date) return x.getTime() === y.getTime();
if (x instanceof RegExp && y instanceof RegExp) return x.toString() === y.toString();
if (isObject(x) && isObject(y)) {
const keysX = Reflect.ownKeys(x);
const keysY = Reflect.ownKeys(y);
if (keysX.length !== keysY.length) return false;
for (let i = 0; i < keysX.length; i++) {
const key = keysX[i];
if (!Reflect.has(y, key) || !isEqual(x[key], y[key])) return false;
}
return true;
}
if (Array.isArray(x) && Array.isArray(y)) {
if (x.length !== y.length) return false;
for (let i = 0; i < x.length; i++) if (!isEqual(x[i], y[i])) return false;
return true;
}
return false;
}
//#endregion
//#region src/utils/array.ts
function distinctArray(arr) {
for (let i = 0; i < arr.length; i++) for (let j = arr.length - 1; j > i; j--) if (isEqual(arr[i], arr[j])) arr.splice(j, 1);
return arr;
}
//#endregion
//#region src/utils/clone.ts
/* istanbul ignore next */
const gT = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw new Error("unable to locate global object");
})();
function polyfillClone(input) {
const map = /* @__PURE__ */ new WeakMap();
const fn = (value) => {
if (Array.isArray(value)) {
if (map.has(value)) return map.get(value);
const cloned = [];
map.set(value, cloned);
value.map((el) => cloned.push(fn(el)));
return cloned;
}
if (isObject(value)) {
if (map.has(value)) return map.get(value);
const output = {};
const keys = Object.keys(value);
map.set(value, output);
for (let i = 0; i < keys.length; i++) output[keys[i]] = fn(value[keys[i]]);
return output;
}
return value;
};
return fn(input);
}
/* istanbul ignore next */
function clone(value) {
if (gT.structuredClone) return gT.structuredClone(value);
/* istanbul ignore next */
return polyfillClone(value);
}
//#endregion
//#region src/utils/object.ts
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
//#endregion
//#region src/utils/options.ts
function buildOptions(options = {}) {
options.array = options.array ?? true;
options.arrayDistinct = options.arrayDistinct ?? false;
options.clone = options.clone ?? false;
options.inPlace = options.inPlace ?? false;
options.priority = options.priority || "left";
options.arrayPriority = options.arrayPriority || options.priority;
return options;
}
function togglePriority(priority) {
return priority === "left" ? `right` : `left`;
}
//#endregion
//#region src/module.ts
function baseMerger(context, ...sources) {
let target;
let source;
let { priority } = context.options;
if (sources.length >= 2) {
if (Array.isArray(sources.at(0)) && Array.isArray(sources.at(-1))) priority = context.options.arrayPriority;
}
if (priority === "right") {
target = sources.pop();
source = sources.pop();
} else {
target = sources.shift();
source = sources.shift();
}
if (!source) {
if (Array.isArray(target) && context.options.arrayDistinct) return distinctArray(target);
return target;
}
if (Array.isArray(target) && Array.isArray(source)) {
target.push(...source);
if (context.options.arrayPriority === "right") return baseMerger(context, ...sources, target);
return baseMerger(context, target, ...sources);
}
context.map.set(source, true);
if (isObject(target) && isObject(source)) {
const keys = Object.keys(source);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (!isSafeKey(key)) continue;
if (hasOwnProperty(target, key)) {
if (context.options.strategy) {
if (typeof context.options.strategy(target, key, source[key]) !== "undefined") continue;
}
if (isObject(target[key]) && isObject(source[key])) {
if (context.map.has(source[key])) {
const sourceKeys = Object.keys(source[key]);
for (let j = 0; j < sourceKeys.length; j++) if (isSafeKey(sourceKeys[j]) && !hasOwnProperty(target[key], sourceKeys[j])) target[key][sourceKeys[j]] = source[key][sourceKeys[j]];
continue;
}
if (context.options.priority === "right") target[key] = baseMerger(context, source[key], target[key]);
else target[key] = baseMerger(context, target[key], source[key]);
continue;
}
if (context.options.array && Array.isArray(target[key]) && Array.isArray(source[key])) switch (context.options.priority !== context.options.arrayPriority ? togglePriority(context.options.arrayPriority) : context.options.arrayPriority) {
case "left":
Object.assign(target, { [key]: baseMerger(context, target[key], source[key]) });
break;
case "right":
Object.assign(target, { [key]: baseMerger(context, source[key], target[key]) });
break;
}
} else Object.assign(target, { [key]: source[key] });
}
}
context.map = /* @__PURE__ */ new WeakMap();
if (context.options.priority === "right") return baseMerger(context, ...sources, target);
return baseMerger(context, target, ...sources);
}
function createMerger(input) {
const options = buildOptions(input);
return (...sources) => {
if (!sources.length) throw new SyntaxError("At least one input element is required.");
const ctx = {
options,
map: /* @__PURE__ */ new WeakMap()
};
if (options.clone) return baseMerger(ctx, ...clone(sources));
if (!options.inPlace) {
if (Array.isArray(sources.at(0)) && options.arrayPriority === "left") {
sources.unshift([]);
return baseMerger(ctx, ...sources);
}
if (Array.isArray(sources.at(-1)) && options.arrayPriority === "right") {
sources.push([]);
return baseMerger(ctx, ...sources);
}
if (options.priority === "left") sources.unshift({});
else sources.push({});
}
return baseMerger(ctx, ...sources);
};
}
const merge = createMerger();
//#endregion
//#region src/presets.ts
/**
* Assign source attributes to a target object.
*
* @param target
* @param sources
*/
function assign(target, ...sources) {
return createMerger({
inPlace: true,
priority: "left",
array: false
})(target, ...sources);
}
//#endregion
exports.PriorityName = PriorityName;
exports.assign = assign;
exports.buildOptions = buildOptions;
exports.clone = clone;
exports.createMerger = createMerger;
exports.distinctArray = distinctArray;
exports.hasOwnProperty = hasOwnProperty;
exports.isEqual = isEqual;
exports.isObject = isObject;
exports.isSafeKey = isSafeKey;
exports.merge = merge;
exports.polyfillClone = polyfillClone;
exports.togglePriority = togglePriority;
//# sourceMappingURL=index.cjs.map

1
frontend/node_modules/smob/dist/index.cjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

100
frontend/node_modules/smob/dist/index.d.cts generated vendored Normal file
View file

@ -0,0 +1,100 @@
//#region src/constants.d.ts
declare enum PriorityName {
LEFT = "left",
RIGHT = "right"
}
//#endregion
//#region src/type.d.ts
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type Options = {
/**
* Merge object array properties.
*
* default: true
*/
array: boolean;
/**
* Remove duplicates, when merging array elements.
*
* default: false
*/
arrayDistinct: boolean;
/**
* Merge sources from left-to-right or right-to-left.
* From v2 upwards default to left independent of the option priority.
*
* default: left (aka. options.priority)
*/
arrayPriority: `${PriorityName}`;
/**
* Strategy to merge different object keys.
*
* @param target
* @param key
* @param value
*/
strategy?: (target: Record<string, any>, key: string, value: unknown) => Record<string, any> | undefined;
/**
* Merge sources in place.
*
* default: false
*/
inPlace?: boolean;
/**
* Deep clone input sources.
*
* default: false
*/
clone?: boolean;
/**
* Merge sources from left-to-right or right-to-left.
* From v2 upwards default to right.
*
* default: left
*/
priority: `${PriorityName}`;
};
type OptionsInput = Partial<Options>;
type MergerSource = any[] | Record<string, any>;
type MergerSourceUnwrap<T extends MergerSource> = T extends Array<infer Return> ? Return : T;
type MergerResult<B extends MergerSource> = UnionToIntersection<MergerSourceUnwrap<B>>;
type MergerContext = {
options: Options;
map: WeakMap<any, any>;
};
type Merger = <B extends MergerSource[]>(...sources: B) => MergerResult<B>;
//#endregion
//#region src/module.d.ts
declare function createMerger(input?: OptionsInput): Merger;
declare const merge: Merger;
//#endregion
//#region src/utils/array.d.ts
declare function distinctArray<T = any>(arr: T[]): T[];
//#endregion
//#region src/utils/check.d.ts
declare function isObject(item: unknown): item is Record<string, any>;
declare function isSafeKey(key: string): boolean;
declare function isEqual(x: any, y: any): boolean;
//#endregion
//#region src/utils/clone.d.ts
declare function polyfillClone<T>(input: T): T;
declare function clone<T>(value: T): T;
//#endregion
//#region src/utils/object.d.ts
declare function hasOwnProperty<X extends {}, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown>;
//#endregion
//#region src/utils/options.d.ts
declare function buildOptions(options?: OptionsInput): Options;
declare function togglePriority(priority: `${PriorityName}`): "right" | "left";
//#endregion
//#region src/presets.d.ts
/**
* Assign source attributes to a target object.
*
* @param target
* @param sources
*/
declare function assign<A extends Record<string, any>, B extends Record<string, any>[]>(target: A, ...sources: B): A & MergerResult<B>;
//#endregion
export { Merger, MergerContext, MergerResult, MergerSource, MergerSourceUnwrap, Options, OptionsInput, PriorityName, assign, buildOptions, clone, createMerger, distinctArray, hasOwnProperty, isEqual, isObject, isSafeKey, merge, polyfillClone, togglePriority };
//# sourceMappingURL=index.d.cts.map

100
frontend/node_modules/smob/dist/index.d.mts generated vendored Normal file
View file

@ -0,0 +1,100 @@
//#region src/constants.d.ts
declare enum PriorityName {
LEFT = "left",
RIGHT = "right"
}
//#endregion
//#region src/type.d.ts
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type Options = {
/**
* Merge object array properties.
*
* default: true
*/
array: boolean;
/**
* Remove duplicates, when merging array elements.
*
* default: false
*/
arrayDistinct: boolean;
/**
* Merge sources from left-to-right or right-to-left.
* From v2 upwards default to left independent of the option priority.
*
* default: left (aka. options.priority)
*/
arrayPriority: `${PriorityName}`;
/**
* Strategy to merge different object keys.
*
* @param target
* @param key
* @param value
*/
strategy?: (target: Record<string, any>, key: string, value: unknown) => Record<string, any> | undefined;
/**
* Merge sources in place.
*
* default: false
*/
inPlace?: boolean;
/**
* Deep clone input sources.
*
* default: false
*/
clone?: boolean;
/**
* Merge sources from left-to-right or right-to-left.
* From v2 upwards default to right.
*
* default: left
*/
priority: `${PriorityName}`;
};
type OptionsInput = Partial<Options>;
type MergerSource = any[] | Record<string, any>;
type MergerSourceUnwrap<T extends MergerSource> = T extends Array<infer Return> ? Return : T;
type MergerResult<B extends MergerSource> = UnionToIntersection<MergerSourceUnwrap<B>>;
type MergerContext = {
options: Options;
map: WeakMap<any, any>;
};
type Merger = <B extends MergerSource[]>(...sources: B) => MergerResult<B>;
//#endregion
//#region src/module.d.ts
declare function createMerger(input?: OptionsInput): Merger;
declare const merge: Merger;
//#endregion
//#region src/utils/array.d.ts
declare function distinctArray<T = any>(arr: T[]): T[];
//#endregion
//#region src/utils/check.d.ts
declare function isObject(item: unknown): item is Record<string, any>;
declare function isSafeKey(key: string): boolean;
declare function isEqual(x: any, y: any): boolean;
//#endregion
//#region src/utils/clone.d.ts
declare function polyfillClone<T>(input: T): T;
declare function clone<T>(value: T): T;
//#endregion
//#region src/utils/object.d.ts
declare function hasOwnProperty<X extends {}, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown>;
//#endregion
//#region src/utils/options.d.ts
declare function buildOptions(options?: OptionsInput): Options;
declare function togglePriority(priority: `${PriorityName}`): "right" | "left";
//#endregion
//#region src/presets.d.ts
/**
* Assign source attributes to a target object.
*
* @param target
* @param sources
*/
declare function assign<A extends Record<string, any>, B extends Record<string, any>[]>(target: A, ...sources: B): A & MergerResult<B>;
//#endregion
export { Merger, MergerContext, MergerResult, MergerSource, MergerSourceUnwrap, Options, OptionsInput, PriorityName, assign, buildOptions, clone, createMerger, distinctArray, hasOwnProperty, isEqual, isObject, isSafeKey, merge, polyfillClone, togglePriority };
//# sourceMappingURL=index.d.mts.map

202
frontend/node_modules/smob/dist/index.mjs generated vendored Normal file
View file

@ -0,0 +1,202 @@
//#region src/constants.ts
let PriorityName = /* @__PURE__ */ function(PriorityName) {
PriorityName["LEFT"] = "left";
PriorityName["RIGHT"] = "right";
return PriorityName;
}({});
//#endregion
//#region src/utils/check.ts
function isObject(item) {
return !!item && typeof item === "object" && !Array.isArray(item);
}
function isSafeKey(key) {
return key !== "__proto__" && key !== "prototype" && key !== "constructor";
}
function isEqual(x, y) {
if (Object.is(x, y)) return true;
if (x instanceof Date && y instanceof Date) return x.getTime() === y.getTime();
if (x instanceof RegExp && y instanceof RegExp) return x.toString() === y.toString();
if (isObject(x) && isObject(y)) {
const keysX = Reflect.ownKeys(x);
const keysY = Reflect.ownKeys(y);
if (keysX.length !== keysY.length) return false;
for (let i = 0; i < keysX.length; i++) {
const key = keysX[i];
if (!Reflect.has(y, key) || !isEqual(x[key], y[key])) return false;
}
return true;
}
if (Array.isArray(x) && Array.isArray(y)) {
if (x.length !== y.length) return false;
for (let i = 0; i < x.length; i++) if (!isEqual(x[i], y[i])) return false;
return true;
}
return false;
}
//#endregion
//#region src/utils/array.ts
function distinctArray(arr) {
for (let i = 0; i < arr.length; i++) for (let j = arr.length - 1; j > i; j--) if (isEqual(arr[i], arr[j])) arr.splice(j, 1);
return arr;
}
//#endregion
//#region src/utils/clone.ts
/* istanbul ignore next */
const gT = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw new Error("unable to locate global object");
})();
function polyfillClone(input) {
const map = /* @__PURE__ */ new WeakMap();
const fn = (value) => {
if (Array.isArray(value)) {
if (map.has(value)) return map.get(value);
const cloned = [];
map.set(value, cloned);
value.map((el) => cloned.push(fn(el)));
return cloned;
}
if (isObject(value)) {
if (map.has(value)) return map.get(value);
const output = {};
const keys = Object.keys(value);
map.set(value, output);
for (let i = 0; i < keys.length; i++) output[keys[i]] = fn(value[keys[i]]);
return output;
}
return value;
};
return fn(input);
}
/* istanbul ignore next */
function clone(value) {
if (gT.structuredClone) return gT.structuredClone(value);
/* istanbul ignore next */
return polyfillClone(value);
}
//#endregion
//#region src/utils/object.ts
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
//#endregion
//#region src/utils/options.ts
function buildOptions(options = {}) {
options.array = options.array ?? true;
options.arrayDistinct = options.arrayDistinct ?? false;
options.clone = options.clone ?? false;
options.inPlace = options.inPlace ?? false;
options.priority = options.priority || "left";
options.arrayPriority = options.arrayPriority || options.priority;
return options;
}
function togglePriority(priority) {
return priority === "left" ? `right` : `left`;
}
//#endregion
//#region src/module.ts
function baseMerger(context, ...sources) {
let target;
let source;
let { priority } = context.options;
if (sources.length >= 2) {
if (Array.isArray(sources.at(0)) && Array.isArray(sources.at(-1))) priority = context.options.arrayPriority;
}
if (priority === "right") {
target = sources.pop();
source = sources.pop();
} else {
target = sources.shift();
source = sources.shift();
}
if (!source) {
if (Array.isArray(target) && context.options.arrayDistinct) return distinctArray(target);
return target;
}
if (Array.isArray(target) && Array.isArray(source)) {
target.push(...source);
if (context.options.arrayPriority === "right") return baseMerger(context, ...sources, target);
return baseMerger(context, target, ...sources);
}
context.map.set(source, true);
if (isObject(target) && isObject(source)) {
const keys = Object.keys(source);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (!isSafeKey(key)) continue;
if (hasOwnProperty(target, key)) {
if (context.options.strategy) {
if (typeof context.options.strategy(target, key, source[key]) !== "undefined") continue;
}
if (isObject(target[key]) && isObject(source[key])) {
if (context.map.has(source[key])) {
const sourceKeys = Object.keys(source[key]);
for (let j = 0; j < sourceKeys.length; j++) if (isSafeKey(sourceKeys[j]) && !hasOwnProperty(target[key], sourceKeys[j])) target[key][sourceKeys[j]] = source[key][sourceKeys[j]];
continue;
}
if (context.options.priority === "right") target[key] = baseMerger(context, source[key], target[key]);
else target[key] = baseMerger(context, target[key], source[key]);
continue;
}
if (context.options.array && Array.isArray(target[key]) && Array.isArray(source[key])) switch (context.options.priority !== context.options.arrayPriority ? togglePriority(context.options.arrayPriority) : context.options.arrayPriority) {
case "left":
Object.assign(target, { [key]: baseMerger(context, target[key], source[key]) });
break;
case "right":
Object.assign(target, { [key]: baseMerger(context, source[key], target[key]) });
break;
}
} else Object.assign(target, { [key]: source[key] });
}
}
context.map = /* @__PURE__ */ new WeakMap();
if (context.options.priority === "right") return baseMerger(context, ...sources, target);
return baseMerger(context, target, ...sources);
}
function createMerger(input) {
const options = buildOptions(input);
return (...sources) => {
if (!sources.length) throw new SyntaxError("At least one input element is required.");
const ctx = {
options,
map: /* @__PURE__ */ new WeakMap()
};
if (options.clone) return baseMerger(ctx, ...clone(sources));
if (!options.inPlace) {
if (Array.isArray(sources.at(0)) && options.arrayPriority === "left") {
sources.unshift([]);
return baseMerger(ctx, ...sources);
}
if (Array.isArray(sources.at(-1)) && options.arrayPriority === "right") {
sources.push([]);
return baseMerger(ctx, ...sources);
}
if (options.priority === "left") sources.unshift({});
else sources.push({});
}
return baseMerger(ctx, ...sources);
};
}
const merge = createMerger();
//#endregion
//#region src/presets.ts
/**
* Assign source attributes to a target object.
*
* @param target
* @param sources
*/
function assign(target, ...sources) {
return createMerger({
inPlace: true,
priority: "left",
array: false
})(target, ...sources);
}
//#endregion
export { PriorityName, assign, buildOptions, clone, createMerger, distinctArray, hasOwnProperty, isEqual, isObject, isSafeKey, merge, polyfillClone, togglePriority };
//# sourceMappingURL=index.mjs.map

1
frontend/node_modules/smob/dist/index.mjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

75
frontend/node_modules/smob/package.json generated vendored Normal file
View file

@ -0,0 +1,75 @@
{
"name": "smob",
"version": "1.6.2",
"description": "Zero dependency library to safe merge objects.",
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"types": "dist/index.d.mts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": [
"dist"
],
"engines": {
"node": ">=20.0.0"
},
"scripts": {
"build:types": "tsc",
"build:js": "tsdown",
"build": "npm run build:types && npm run build:js",
"lint": "eslint",
"lint:fix": "npm run lint -- --fix",
"test": "vitest --config test/vitest.config.ts --run",
"test:coverage": "vitest --config test/vitest.config.ts --run --coverage",
"prepare": "husky"
},
"author": {
"name": "Peter Placzek",
"email": "contact@tada5hi.net",
"url": "https://github.com/tada5hi"
},
"license": "MIT",
"keywords": [
"object",
"object-merge",
"merge",
"safe",
"deep-merge",
"merge-deep"
],
"repository": {
"type": "git",
"url": "git+https://github.com/Tada5hi/smob.git"
},
"bugs": {
"url": "https://github.com/Tada5hi/smob/issues"
},
"homepage": "https://github.com/Tada5hi/smob#readme",
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@tada5hi/commitlint-config": "^1.3.1",
"@tada5hi/eslint-config": "^2.3.0",
"@tada5hi/tsconfig": "^0.7.2",
"@vitest/coverage-v8": "^4.1.5",
"eslint": "^10.3.0",
"husky": "^9.1.7",
"tsdown": "^0.22.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.59.2",
"vitest": "^4.1.5"
}
}