feat(frontend): add API client, layout, and routing

- Create Axios-based API client with sources, jobs, and dashboard endpoints
- Add responsive Layout component with navigation sidebar
- Set up React Router with Dashboard, Backups, and Settings routes
- Configure TanStack Query provider with default options
- Use lucide-react for navigation icons
This commit is contained in:
2026-05-11 21:47:20 +02:00
parent 7676438466
commit d3b92593d5
14073 changed files with 2182272 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Tinylibs
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.
+12
View File
@@ -0,0 +1,12 @@
# tinyspy
> minimal fork of nanospy, with more features 🕵🏻‍♂️
A `10KB` package for minimal and easy testing with no dependencies.
This package was created for having a tiny spy library to use in `vitest`, but it can also be used in `jest` and other test environments.
_In case you need more tiny libraries like tinypool or tinyspy, please consider submitting an [RFC](https://github.com/tinylibs/rfcs)_
## Docs
Read **[full docs](https://github.com/tinylibs/tinyspy#readme)** on GitHub.
+156
View File
@@ -0,0 +1,156 @@
"use strict";
var w = Object.defineProperty;
var M = Object.getOwnPropertyDescriptor;
var E = Object.getOwnPropertyNames;
var G = Object.prototype.hasOwnProperty;
var j = (e, t) => {
for (var n in t)
w(e, n, { get: t[n], enumerable: !0 });
}, D = (e, t, n, s) => {
if (t && typeof t == "object" || typeof t == "function")
for (let r of E(t))
!G.call(e, r) && r !== n && w(e, r, { get: () => t[r], enumerable: !(s = M(t, r)) || s.enumerable });
return e;
};
var F = (e) => D(w({}, "__esModule", { value: !0 }), e);
// src/index.ts
var B = {};
j(B, {
createInternalSpy: () => g,
getInternalState: () => I,
internalSpyOn: () => K,
restoreAll: () => z,
spies: () => d,
spy: () => _,
spyOn: () => $
});
module.exports = F(B);
// src/utils.ts
function R(e, t) {
if (!e)
throw new Error(t);
}
function u(e, t) {
return typeof t === e;
}
function b(e) {
return e instanceof Promise;
}
function f(e, t, n) {
Object.defineProperty(e, t, n);
}
function i(e, t, n) {
Object.defineProperty(e, t, { value: n });
}
// src/constants.ts
var c = Symbol.for("tinyspy:spy");
// src/internal.ts
var d = /* @__PURE__ */ new Set(), q = (e) => {
e.called = !1, e.callCount = 0, e.calls = [], e.results = [], e.next = [];
}, V = (e) => (f(e, c, { value: { reset: () => q(e[c]) } }), e[c]), I = (e) => e[c] || V(e);
function g(e) {
R(u("function", e) || u("undefined", e), "cannot spy on a non-function value");
let t = function(...s) {
let r = I(t);
r.called = !0, r.callCount++, r.calls.push(s);
let m = r.next.shift();
if (m) {
r.results.push(m);
let [l, o] = m;
if (l === "ok")
return o;
throw o;
}
let p, x = "ok";
if (r.impl)
try {
new.target ? p = Reflect.construct(r.impl, s, new.target) : p = r.impl.apply(this, s), x = "ok";
} catch (l) {
throw p = l, x = "error", r.results.push([x, l]), l;
}
let a = [x, p];
if (b(p)) {
let l = p.then((o) => a[1] = o).catch((o) => {
throw a[0] = "error", a[1] = o, o;
});
Object.assign(l, p), p = l;
}
return r.results.push(a), p;
};
i(t, "_isMockFunction", !0), i(t, "length", e ? e.length : 0), i(t, "name", e && e.name || "spy");
let n = I(t);
return n.reset(), n.impl = e, t;
}
function A(e) {
let t = I(e);
f(e, "returns", {
get: () => t.results.map(([, n]) => n)
}), ["called", "callCount", "results", "calls", "reset", "impl"].forEach((n) => f(e, n, { get: () => t[n], set: (s) => t[n] = s })), i(e, "nextError", (n) => (t.next.push(["error", n]), t)), i(e, "nextResult", (n) => (t.next.push(["ok", n]), t));
}
// src/spy.ts
function _(e) {
let t = g(e);
return A(t), t;
}
// src/spyOn.ts
var k = (e, t) => Object.getOwnPropertyDescriptor(e, t), P = (e, t) => {
t != null && typeof t == "function" && t.prototype != null && Object.setPrototypeOf(e.prototype, t.prototype);
};
function K(e, t, n) {
R(!u("undefined", e), "spyOn could not find an object to spy upon"), R(u("object", e) || u("function", e), "cannot spyOn on a primitive value");
let [s, r] = (() => {
if (!u("object", t))
return [t, "value"];
if ("getter" in t && "setter" in t)
throw new Error("cannot spy on both getter and setter");
if ("getter" in t)
return [t.getter, "get"];
if ("setter" in t)
return [t.setter, "set"];
throw new Error("specify getter or setter to spy on");
})(), m = k(e, s), p = Object.getPrototypeOf(e), x = p && k(p, s), a = m || x;
R(a || s in e, `${String(s)} does not exist`);
let l = !1;
r === "value" && a && !a.value && a.get && (r = "get", l = !0, n = a.get());
let o;
a ? o = a[r] : r !== "value" ? o = () => e[s] : o = e[s], n || (n = o);
let y = g(n);
r === "value" && P(y, o);
let O = (v) => {
let { value: H, ...h } = a || {
configurable: !0,
writable: !0
};
r !== "value" && delete h.writable, h[r] = v, f(e, s, h);
}, C = () => a ? f(e, s, a) : O(o), T = y[c];
return i(T, "restore", C), i(T, "getOriginal", () => l ? o() : o), i(T, "willCall", (v) => (T.impl = v, y)), O(l ? () => (P(y, n), y) : y), d.add(y), y;
}
function $(e, t, n) {
let s = K(e, t, n);
return A(s), ["restore", "getOriginal", "willCall"].forEach((r) => {
i(s, r, s[c][r]);
}), s;
}
// src/restoreAll.ts
function z() {
for (let e of d)
e.restore();
d.clear();
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createInternalSpy,
getInternalState,
internalSpyOn,
restoreAll,
spies,
spy,
spyOn
});
+82
View File
@@ -0,0 +1,82 @@
declare const S: unique symbol;
interface GetState {
<A extends any[], R>(spy: SpyInternalImpl<A, R>): SpyInternalImplState<A, R>;
<A extends any[], R>(spy: SpyInternal<A, R>): SpyInternalState<A, R>;
}
declare let spies: Set<SpyImpl<any[], any>>;
declare let getInternalState: GetState;
declare type ReturnError = ['error', any];
declare type ReturnOk<R> = ['ok', R];
declare type ResultFn<R> = ReturnError | ReturnOk<R>;
interface SpyInternal<A extends any[] = any[], R = any> {
(this: any, ...args: A): R;
[S]: SpyInternalState<A, R>;
}
interface SpyInternalImpl<A extends any[] = any[], R = any> extends SpyInternal<A, R> {
[S]: SpyInternalImplState<A, R>;
}
interface SpyInternalState<A extends any[] = any[], R = any> {
called: boolean;
callCount: number;
calls: A[];
results: ResultFn<R>[];
reset(): void;
impl: ((...args: A) => R) | undefined;
next: ResultFn<R>[];
}
interface SpyInternalImplState<A extends any[] = any[], R = any> extends SpyInternalState<A, R> {
getOriginal(): (...args: A) => R;
willCall(cb: (...args: A) => R): this;
restore(): void;
}
interface Spy<A extends any[] = any[], R = any> extends SpyInternalState<A, R> {
returns: R[];
length: number;
nextError(error: any): this;
nextResult(result: R): this;
}
interface SpyImpl<A extends any[] = any[], R = any> extends Spy<A, R> {
getOriginal(): (...args: A) => R;
willCall(cb: (...args: A) => R): this;
restore(): void;
}
declare function createInternalSpy<A extends any[], R>(cb?: ((...args: A) => R) | {
new (...args: A): R;
}): SpyInternal<A, R>;
interface SpyFn<A extends any[] = any[], R = any> extends Spy<A, R> {
new (...args: A): R extends void ? any : R;
(...args: A): R;
}
declare function spy<A extends any[], R>(cb?: ((...args: A) => R) | {
new (...args: A): R;
}): SpyFn<A, R>;
declare type Procedure = (...args: any[]) => any;
declare type Methods<T> = {
[K in keyof T]: T[K] extends Procedure ? K : never;
}[keyof T];
declare type Getters<T> = {
[K in keyof T]: T[K] extends Procedure ? never : K;
}[keyof T];
declare type Constructors<T> = {
[K in keyof T]: T[K] extends new (...args: any[]) => any ? K : never;
}[keyof T];
declare function internalSpyOn<T, K extends string & keyof T>(obj: T, methodName: K | {
getter: K;
} | {
setter: K;
}, mock?: Procedure): SpyInternalImpl<any[], any>;
declare function spyOn<T, S extends Getters<Required<T>>>(obj: T, methodName: {
setter: S;
}, mock?: (arg: T[S]) => void): SpyImpl<[T[S]], void>;
declare function spyOn<T, G extends Getters<Required<T>>>(obj: T, methodName: {
getter: G;
}, mock?: () => T[G]): SpyImpl<[], T[G]>;
declare function spyOn<T, M extends Constructors<Required<T>>>(object: T, method: M): Required<T>[M] extends new (...args: infer A) => infer R ? SpyImpl<A, R> : never;
declare function spyOn<T, M extends Methods<Required<T>>>(obj: T, methodName: M, mock?: T[M]): Required<T>[M] extends (...args: infer A) => infer R ? SpyImpl<A, R> : never;
declare function restoreAll(): void;
export { Spy, SpyFn, SpyImpl, SpyInternal, SpyInternalImpl, createInternalSpy, getInternalState, internalSpyOn, restoreAll, spies, spy, spyOn };
+126
View File
@@ -0,0 +1,126 @@
// src/utils.ts
function R(e, t) {
if (!e)
throw new Error(t);
}
function u(e, t) {
return typeof t === e;
}
function b(e) {
return e instanceof Promise;
}
function f(e, t, n) {
Object.defineProperty(e, t, n);
}
function i(e, t, n) {
Object.defineProperty(e, t, { value: n });
}
// src/constants.ts
var c = Symbol.for("tinyspy:spy");
// src/internal.ts
var g = /* @__PURE__ */ new Set(), C = (e) => {
e.called = !1, e.callCount = 0, e.calls = [], e.results = [], e.next = [];
}, M = (e) => (f(e, c, { value: { reset: () => C(e[c]) } }), e[c]), A = (e) => e[c] || M(e);
function I(e) {
R(u("function", e) || u("undefined", e), "cannot spy on a non-function value");
let t = function(...s) {
let r = A(t);
r.called = !0, r.callCount++, r.calls.push(s);
let m = r.next.shift();
if (m) {
r.results.push(m);
let [l, o] = m;
if (l === "ok")
return o;
throw o;
}
let p, d = "ok";
if (r.impl)
try {
new.target ? p = Reflect.construct(r.impl, s, new.target) : p = r.impl.apply(this, s), d = "ok";
} catch (l) {
throw p = l, d = "error", r.results.push([d, l]), l;
}
let a = [d, p];
if (b(p)) {
let l = p.then((o) => a[1] = o).catch((o) => {
throw a[0] = "error", a[1] = o, o;
});
Object.assign(l, p), p = l;
}
return r.results.push(a), p;
};
i(t, "_isMockFunction", !0), i(t, "length", e ? e.length : 0), i(t, "name", e && e.name || "spy");
let n = A(t);
return n.reset(), n.impl = e, t;
}
function v(e) {
let t = A(e);
f(e, "returns", {
get: () => t.results.map(([, n]) => n)
}), ["called", "callCount", "results", "calls", "reset", "impl"].forEach((n) => f(e, n, { get: () => t[n], set: (s) => t[n] = s })), i(e, "nextError", (n) => (t.next.push(["error", n]), t)), i(e, "nextResult", (n) => (t.next.push(["ok", n]), t));
}
// src/spy.ts
function z(e) {
let t = I(e);
return v(t), t;
}
// src/spyOn.ts
var k = (e, t) => Object.getOwnPropertyDescriptor(e, t), P = (e, t) => {
t != null && typeof t == "function" && t.prototype != null && Object.setPrototypeOf(e.prototype, t.prototype);
};
function E(e, t, n) {
R(!u("undefined", e), "spyOn could not find an object to spy upon"), R(u("object", e) || u("function", e), "cannot spyOn on a primitive value");
let [s, r] = (() => {
if (!u("object", t))
return [t, "value"];
if ("getter" in t && "setter" in t)
throw new Error("cannot spy on both getter and setter");
if ("getter" in t)
return [t.getter, "get"];
if ("setter" in t)
return [t.setter, "set"];
throw new Error("specify getter or setter to spy on");
})(), m = k(e, s), p = Object.getPrototypeOf(e), d = p && k(p, s), a = m || d;
R(a || s in e, `${String(s)} does not exist`);
let l = !1;
r === "value" && a && !a.value && a.get && (r = "get", l = !0, n = a.get());
let o;
a ? o = a[r] : r !== "value" ? o = () => e[s] : o = e[s], n || (n = o);
let y = I(n);
r === "value" && P(y, o);
let O = (h) => {
let { value: G, ...w } = a || {
configurable: !0,
writable: !0
};
r !== "value" && delete w.writable, w[r] = h, f(e, s, w);
}, K = () => a ? f(e, s, a) : O(o), T = y[c];
return i(T, "restore", K), i(T, "getOriginal", () => l ? o() : o), i(T, "willCall", (h) => (T.impl = h, y)), O(l ? () => (P(y, n), y) : y), g.add(y), y;
}
function W(e, t, n) {
let s = E(e, t, n);
return v(s), ["restore", "getOriginal", "willCall"].forEach((r) => {
i(s, r, s[c][r]);
}), s;
}
// src/restoreAll.ts
function Z() {
for (let e of g)
e.restore();
g.clear();
}
export {
I as createInternalSpy,
A as getInternalState,
E as internalSpyOn,
Z as restoreAll,
g as spies,
z as spy,
W as spyOn
};
+36
View File
@@ -0,0 +1,36 @@
{
"name": "tinyspy",
"version": "2.2.1",
"type": "module",
"packageManager": "pnpm@8.4.0",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.cjs"
},
"files": [
"dist/**"
],
"repository": {
"type": "git",
"url": "git+https://github.com/tinylibs/tinyspy.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/tinylibs/tinyspy/issues"
},
"homepage": "https://github.com/tinylibs/tinyspy#readme",
"keywords": [
"spy",
"mock",
"typescript",
"method"
],
"engines": {
"node": ">=14.0.0"
}
}