@tiny-server/core 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/apiResults.d.ts +48 -0
- package/dist/api/entity.d.ts +27 -0
- package/dist/api/index.d.ts +8 -0
- package/dist/api/paginationOptions.d.ts +13 -0
- package/dist/api/permissions.d.ts +55 -0
- package/dist/api/problemDetails.d.ts +16 -0
- package/dist/api/session.d.ts +38 -0
- package/dist/api/sortOptions.d.ts +17 -0
- package/dist/api/status.d.ts +27 -0
- package/dist/app/App.d.ts +12 -0
- package/dist/app/context.d.ts +6 -0
- package/dist/app/create.d.ts +12 -0
- package/dist/app/features/extensions/Extension.d.ts +32 -0
- package/dist/app/features/extensions/index.d.ts +2 -0
- package/dist/app/features/extensions/types.d.ts +43 -0
- package/dist/app/features/index.d.ts +6 -0
- package/dist/app/features/layout/Error.d.ts +15 -0
- package/dist/app/features/layout/Layout.d.ts +4 -0
- package/dist/app/features/layout/Loading.d.ts +14 -0
- package/dist/app/features/layout/Page.d.ts +6 -0
- package/dist/app/features/layout/index.d.ts +6 -0
- package/dist/app/features/layout/initializer.d.ts +2 -0
- package/dist/app/features/layout/types.d.ts +13 -0
- package/dist/app/features/menu/Menu.d.ts +7 -0
- package/dist/app/features/menu/MenuContainer.d.ts +4 -0
- package/dist/app/features/menu/MenuItem.d.ts +11 -0
- package/dist/app/features/menu/index.d.ts +5 -0
- package/dist/app/features/menu/initializer.d.ts +2 -0
- package/dist/app/features/menu/types.d.ts +71 -0
- package/dist/app/features/modals/Modal.d.ts +5 -0
- package/dist/app/features/modals/ModalBody.d.ts +4 -0
- package/dist/app/features/modals/ModalContent.d.ts +7 -0
- package/dist/app/features/modals/ModalFooter.d.ts +5 -0
- package/dist/app/features/modals/ModalHeader.d.ts +5 -0
- package/dist/app/features/modals/Modals.d.ts +4 -0
- package/dist/app/features/modals/index.d.ts +8 -0
- package/dist/app/features/modals/initializer.d.ts +2 -0
- package/dist/app/features/modals/store.d.ts +14 -0
- package/dist/app/features/modals/types.d.ts +84 -0
- package/dist/app/features/query/AppQueryClientProvider.d.ts +2 -0
- package/dist/app/features/query/client.d.ts +2 -0
- package/dist/app/features/query/index.d.ts +3 -0
- package/dist/app/features/query/initializer.d.ts +2 -0
- package/dist/app/features/query/types.d.ts +9 -0
- package/dist/app/features/router/AppLayout.d.ts +1 -0
- package/dist/app/features/router/AppRouteLayout.d.ts +5 -0
- package/dist/app/features/router/AppRouter.d.ts +4 -0
- package/dist/app/features/router/RouterErrorBoundary.d.ts +1 -0
- package/dist/app/features/router/context.d.ts +5 -0
- package/dist/app/features/router/index.d.ts +3 -0
- package/dist/app/features/router/middlewares.d.ts +42 -0
- package/dist/app/index.d.ts +5 -0
- package/dist/app/types.d.ts +78 -0
- package/dist/components/ErrorBoundary.d.ts +19 -0
- package/dist/components/WithPermissions.d.ts +30 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/fetch.d.ts +84 -0
- package/dist/i18n/InitI18n.d.ts +6 -0
- package/dist/i18n/defineLocales.d.ts +10 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/useGlobalT.d.ts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +557 -0
- package/dist/module.d.ts +7 -0
- package/dist/utils/dates.d.ts +3 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/usePagination.d.ts +31 -0
- package/dist/utils/useSearch.d.ts +19 -0
- package/dist/utils/useSession.d.ts +22 -0
- package/package.json +52 -0
- package/src/api/apiResults.ts +50 -0
- package/src/api/entity.ts +29 -0
- package/src/api/index.ts +8 -0
- package/src/api/paginationOptions.ts +13 -0
- package/src/api/permissions.ts +63 -0
- package/src/api/problemDetails.ts +19 -0
- package/src/api/session.ts +51 -0
- package/src/api/sortOptions.ts +18 -0
- package/src/api/status.ts +34 -0
- package/src/app/App.tsx +33 -0
- package/src/app/context.ts +17 -0
- package/src/app/create.ts +34 -0
- package/src/app/features/extensions/Extension.tsx +69 -0
- package/src/app/features/extensions/index.ts +2 -0
- package/src/app/features/extensions/types.tsx +52 -0
- package/src/app/features/index.ts +6 -0
- package/src/app/features/layout/Error.tsx +20 -0
- package/src/app/features/layout/Layout.tsx +7 -0
- package/src/app/features/layout/Loading.tsx +21 -0
- package/src/app/features/layout/Page.tsx +42 -0
- package/src/app/features/layout/index.ts +6 -0
- package/src/app/features/layout/initializer.ts +12 -0
- package/src/app/features/layout/types.ts +14 -0
- package/src/app/features/menu/Menu.tsx +66 -0
- package/src/app/features/menu/MenuContainer.tsx +9 -0
- package/src/app/features/menu/MenuItem.tsx +46 -0
- package/src/app/features/menu/index.ts +5 -0
- package/src/app/features/menu/initializer.ts +8 -0
- package/src/app/features/menu/types.ts +84 -0
- package/src/app/features/modals/Modal.tsx +20 -0
- package/src/app/features/modals/ModalBody.tsx +8 -0
- package/src/app/features/modals/ModalContent.tsx +35 -0
- package/src/app/features/modals/ModalFooter.tsx +19 -0
- package/src/app/features/modals/ModalHeader.tsx +15 -0
- package/src/app/features/modals/Modals.tsx +33 -0
- package/src/app/features/modals/index.ts +8 -0
- package/src/app/features/modals/initializer.ts +17 -0
- package/src/app/features/modals/store.ts +35 -0
- package/src/app/features/modals/types.ts +94 -0
- package/src/app/features/query/AppQueryClientProvider.tsx +7 -0
- package/src/app/features/query/client.ts +3 -0
- package/src/app/features/query/index.ts +3 -0
- package/src/app/features/query/initializer.ts +6 -0
- package/src/app/features/query/types.ts +10 -0
- package/src/app/features/router/AppLayout.tsx +18 -0
- package/src/app/features/router/AppRouteLayout.tsx +31 -0
- package/src/app/features/router/AppRouter.tsx +45 -0
- package/src/app/features/router/RouterErrorBoundary.tsx +20 -0
- package/src/app/features/router/context.ts +7 -0
- package/src/app/features/router/index.ts +3 -0
- package/src/app/features/router/middlewares.ts +76 -0
- package/src/app/index.ts +6 -0
- package/src/app/types.ts +82 -0
- package/src/components/ErrorBoundary.tsx +34 -0
- package/src/components/WithPermissions.tsx +59 -0
- package/src/components/index.ts +2 -0
- package/src/fetch.ts +185 -0
- package/src/i18n/InitI18n.tsx +24 -0
- package/src/i18n/defineLocales.ts +59 -0
- package/src/i18n/index.ts +3 -0
- package/src/i18n/useGlobalT.ts +13 -0
- package/src/index.ts +8 -0
- package/src/module.tsx +27 -0
- package/src/utils/dates.ts +34 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/usePagination.ts +64 -0
- package/src/utils/useSearch.ts +40 -0
- package/src/utils/useSession.ts +42 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
import { useTranslation as K, initReactI18next as V } from "react-i18next";
|
|
2
|
+
import C from "i18next";
|
|
3
|
+
import { jsx as o, Fragment as h, jsxs as y } from "react/jsx-runtime";
|
|
4
|
+
import { LoadingOverlay as U, Box as W, Container as _, Stack as G, Grid as X, GridCol as A, Title as Y, Group as j, NavLink as T, Modal as p, MantineProvider as Z } from "@mantine/core";
|
|
5
|
+
import { Component as ee, useCallback as x, useContext as ne, createContext as te, useMemo as v, Suspense as w, useEffect as oe } from "react";
|
|
6
|
+
import { useSearchParams as z, NavLink as re, useRouteError as se, isRouteErrorResponse as ie, Outlet as B, useNavigation as ae, useLocation as ue, createContext as ce, createBrowserRouter as le, RouterContextProvider as de, redirect as O, data as pe } from "react-router";
|
|
7
|
+
import { useDisclosure as fe } from "@mantine/hooks";
|
|
8
|
+
import { createStore as me } from "zustand/vanilla";
|
|
9
|
+
import { queryOptions as E, useSuspenseQuery as he, QueryClient as ye, QueryClientProvider as ge } from "@tanstack/react-query";
|
|
10
|
+
import { RouterProvider as ve } from "react-router/dom";
|
|
11
|
+
import { useStore as we } from "zustand";
|
|
12
|
+
const ke = {
|
|
13
|
+
json: async (e) => {
|
|
14
|
+
const n = e.headers.get("content-type");
|
|
15
|
+
if (n && !/application\/(.+\+)?json/.test(n))
|
|
16
|
+
throw new Error(`JSON response handler received invalid content type "${n}".`);
|
|
17
|
+
const t = await e.text();
|
|
18
|
+
try {
|
|
19
|
+
return t.length ? JSON.parse(t) : null;
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error("JSON response handler failed to parse JSON response.");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}, Ce = {
|
|
25
|
+
statusOk: async (e, n) => {
|
|
26
|
+
if (!e.ok)
|
|
27
|
+
throw Ee(n) ? new Me(e, n) : new I(e, `Request failed with status code ${e.status}.`);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
async function b(e) {
|
|
31
|
+
e = typeof e == "string" ? { url: e } : e;
|
|
32
|
+
const {
|
|
33
|
+
baseUrl: n = window.location.origin,
|
|
34
|
+
url: t,
|
|
35
|
+
body: r,
|
|
36
|
+
params: i = {},
|
|
37
|
+
responseHandler: s = "json",
|
|
38
|
+
responseValidators: u = ["statusOk"],
|
|
39
|
+
...a
|
|
40
|
+
} = e, l = typeof s == "string" ? ke[s] : s, c = async (F, J) => {
|
|
41
|
+
for (const S of u)
|
|
42
|
+
await (typeof S == "string" ? Ce[S] : S)(F, J);
|
|
43
|
+
}, k = xe(t, n, i), g = new Headers(a.headers);
|
|
44
|
+
let f;
|
|
45
|
+
!(r instanceof FormData) && (!g.has("Content-Type") || g.get("Content-Type")?.includes("application/json")) ? (g.set("Content-Type", "application/json"), f = JSON.stringify(r)) : f = r;
|
|
46
|
+
const m = {
|
|
47
|
+
...a,
|
|
48
|
+
headers: g,
|
|
49
|
+
body: f
|
|
50
|
+
}, q = await fetch(k, m), D = await l(q);
|
|
51
|
+
return await c(q, D), D;
|
|
52
|
+
}
|
|
53
|
+
function xe(e, n, t) {
|
|
54
|
+
const r = new URL(e, n), i = r.searchParams;
|
|
55
|
+
for (const [s, u] of Object.entries(t)) {
|
|
56
|
+
const a = Array.isArray(u) ? u : [u];
|
|
57
|
+
for (const l of a)
|
|
58
|
+
l != null && i.append(s, String(l));
|
|
59
|
+
}
|
|
60
|
+
return r;
|
|
61
|
+
}
|
|
62
|
+
class I extends Error {
|
|
63
|
+
/**
|
|
64
|
+
* The received fetch response.
|
|
65
|
+
*/
|
|
66
|
+
response;
|
|
67
|
+
constructor(n, t) {
|
|
68
|
+
super(t ?? "An error occurred during a fetch request."), this.response = n;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
class Me extends I {
|
|
72
|
+
problem;
|
|
73
|
+
constructor(n, t) {
|
|
74
|
+
super(n, t.title), this.problem = t;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function Se() {
|
|
78
|
+
return b("/api/v1/permissions");
|
|
79
|
+
}
|
|
80
|
+
function hn() {
|
|
81
|
+
return E({
|
|
82
|
+
queryKey: ["permissions"],
|
|
83
|
+
queryFn: () => Se(),
|
|
84
|
+
staleTime: 1 / 0
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function Ee(e) {
|
|
88
|
+
return !!e && typeof e == "object";
|
|
89
|
+
}
|
|
90
|
+
async function be() {
|
|
91
|
+
try {
|
|
92
|
+
const { data: e } = await b("/api/v1/auth/session");
|
|
93
|
+
return { hasSession: !0, session: e };
|
|
94
|
+
} catch (e) {
|
|
95
|
+
if (e instanceof I && e.response.status === 401)
|
|
96
|
+
return { hasSession: !1, session: void 0 };
|
|
97
|
+
throw e;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function P() {
|
|
101
|
+
return E({
|
|
102
|
+
queryKey: ["session"],
|
|
103
|
+
queryFn: () => be(),
|
|
104
|
+
staleTime: 1 / 0,
|
|
105
|
+
gcTime: 1 / 0
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function Ie() {
|
|
109
|
+
return b("/api/v1/status");
|
|
110
|
+
}
|
|
111
|
+
function yn() {
|
|
112
|
+
return E({
|
|
113
|
+
queryKey: ["status"],
|
|
114
|
+
queryFn: () => Ie(),
|
|
115
|
+
staleTime: 1 / 0
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
class M extends ee {
|
|
119
|
+
constructor(n) {
|
|
120
|
+
super(n), this.state = { hasError: !1 };
|
|
121
|
+
}
|
|
122
|
+
static getDerivedStateFromError() {
|
|
123
|
+
return { hasError: !0 };
|
|
124
|
+
}
|
|
125
|
+
render() {
|
|
126
|
+
return this.state.hasError ? this.props.fallback : this.props.children;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function gn(e) {
|
|
130
|
+
return L(e, {
|
|
131
|
+
year: "numeric",
|
|
132
|
+
month: "2-digit",
|
|
133
|
+
day: "2-digit"
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function vn(e) {
|
|
137
|
+
return L(e, {
|
|
138
|
+
hour: "2-digit",
|
|
139
|
+
minute: "2-digit",
|
|
140
|
+
second: "2-digit"
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function wn(e) {
|
|
144
|
+
return L(e, {
|
|
145
|
+
year: "numeric",
|
|
146
|
+
month: "2-digit",
|
|
147
|
+
day: "2-digit",
|
|
148
|
+
hour: "2-digit",
|
|
149
|
+
minute: "2-digit",
|
|
150
|
+
second: "2-digit"
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function L(e, n) {
|
|
154
|
+
if (e != null)
|
|
155
|
+
return new Date(e).toLocaleString(void 0, n);
|
|
156
|
+
}
|
|
157
|
+
function kn({
|
|
158
|
+
pageParamName: e = "page",
|
|
159
|
+
pageSizeParamName: n = "pageSize",
|
|
160
|
+
defaultPage: t = 1,
|
|
161
|
+
defaultPageSize: r = 20
|
|
162
|
+
} = {}) {
|
|
163
|
+
const [i, s] = z(), u = +(i.get(e) || t), a = +(i.get(n) || r), l = isNaN(u) ? t : u, c = isNaN(a) ? r : a, k = x(
|
|
164
|
+
(f) => {
|
|
165
|
+
s((m) => (m.set(e, f.toString()), m));
|
|
166
|
+
},
|
|
167
|
+
[e, s]
|
|
168
|
+
), g = x(
|
|
169
|
+
(f) => {
|
|
170
|
+
s((m) => (m.set(n, f.toString()), m));
|
|
171
|
+
},
|
|
172
|
+
[n, s]
|
|
173
|
+
);
|
|
174
|
+
return { page: l, pageSize: c, setPage: k, setPageSize: g };
|
|
175
|
+
}
|
|
176
|
+
function Cn({ searchParamName: e = "search", defaultSearch: n = "" } = {}) {
|
|
177
|
+
const [t, r] = z(), i = t.get(e) || n, s = x(
|
|
178
|
+
(u) => {
|
|
179
|
+
r((a) => (u && u !== n ? a.set(e, u) : a.delete(e), a));
|
|
180
|
+
},
|
|
181
|
+
[n, e, r]
|
|
182
|
+
);
|
|
183
|
+
return { search: i, setSearch: s };
|
|
184
|
+
}
|
|
185
|
+
function Pe() {
|
|
186
|
+
const { data: e } = he(P());
|
|
187
|
+
return e;
|
|
188
|
+
}
|
|
189
|
+
function Le() {
|
|
190
|
+
const e = Pe();
|
|
191
|
+
if (!e.hasSession)
|
|
192
|
+
throw new Error(
|
|
193
|
+
"useSession was called, but no active user session exists. This hook should only be called in components which are guaranteed to be rendered in an active session context."
|
|
194
|
+
);
|
|
195
|
+
return e.session;
|
|
196
|
+
}
|
|
197
|
+
function Re() {
|
|
198
|
+
return Le().permissions;
|
|
199
|
+
}
|
|
200
|
+
function qe({ permissions: e = [], operator: n = "and", children: t, fallback: r }) {
|
|
201
|
+
const i = Re();
|
|
202
|
+
return (n === "and" ? e.every((u) => i.includes(u)) : e.some((u) => i.includes(u))) ? /* @__PURE__ */ o(h, { children: t }) : /* @__PURE__ */ o(h, { children: r });
|
|
203
|
+
}
|
|
204
|
+
function xn(e, n) {
|
|
205
|
+
return function(i) {
|
|
206
|
+
return /* @__PURE__ */ o(qe, { ...e, children: /* @__PURE__ */ o(n, { ...i }) });
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
const $ = te(null);
|
|
210
|
+
function d() {
|
|
211
|
+
const e = ne($);
|
|
212
|
+
if (!e)
|
|
213
|
+
throw new Error("App context had no configured value. Was the hook called outside of an <App> component?");
|
|
214
|
+
return e;
|
|
215
|
+
}
|
|
216
|
+
function Mn({
|
|
217
|
+
name: e,
|
|
218
|
+
params: n,
|
|
219
|
+
fallback: t,
|
|
220
|
+
loadingFallback: r,
|
|
221
|
+
errorFallback: i
|
|
222
|
+
}) {
|
|
223
|
+
const s = d(), { Loading: u, Error: a } = s.components;
|
|
224
|
+
r ??= /* @__PURE__ */ o(u, { kind: "extension" }), i ??= /* @__PURE__ */ o(a, { kind: "extension" });
|
|
225
|
+
const l = v(() => s.modules.flatMap((c) => c.extensions).filter((c) => c.name === e).map((c) => c.component), [e, s.modules]);
|
|
226
|
+
return l.length === 0 ? t : /* @__PURE__ */ o(M, { fallback: i ?? t, children: /* @__PURE__ */ o(w, { fallback: r ?? t, children: l.map((c, k) => /* @__PURE__ */ o(c, { params: n }, k)) }) });
|
|
227
|
+
}
|
|
228
|
+
function De({ kind: e }) {
|
|
229
|
+
return /* @__PURE__ */ y(h, { children: [
|
|
230
|
+
"Error: ",
|
|
231
|
+
e
|
|
232
|
+
] });
|
|
233
|
+
}
|
|
234
|
+
function Ae({ children: e }) {
|
|
235
|
+
return /* @__PURE__ */ o(h, { children: e });
|
|
236
|
+
}
|
|
237
|
+
function Te() {
|
|
238
|
+
return /* @__PURE__ */ o(U, { visible: !0 });
|
|
239
|
+
}
|
|
240
|
+
function je({ header: e, actions: n, children: t }) {
|
|
241
|
+
const { Loading: r } = d().components;
|
|
242
|
+
return /* @__PURE__ */ o(W, { h: "100%", p: "xl", children: /* @__PURE__ */ o(_, { h: "100%", children: /* @__PURE__ */ y(G, { gap: "xl", children: [
|
|
243
|
+
/* @__PURE__ */ y(X, { gap: "md", align: "center", children: [
|
|
244
|
+
/* @__PURE__ */ o(A, { span: { base: 12, md: "auto" }, children: /* @__PURE__ */ o(
|
|
245
|
+
Y,
|
|
246
|
+
{
|
|
247
|
+
order: 1,
|
|
248
|
+
textWrap: "nowrap",
|
|
249
|
+
miw: 0,
|
|
250
|
+
style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
251
|
+
children: e
|
|
252
|
+
}
|
|
253
|
+
) }),
|
|
254
|
+
/* @__PURE__ */ o(A, { span: { base: 12, md: "content" }, children: /* @__PURE__ */ o(j, { gap: "md", wrap: "wrap", children: n }) })
|
|
255
|
+
] }),
|
|
256
|
+
/* @__PURE__ */ o(w, { fallback: /* @__PURE__ */ o(r, { kind: "page" }), children: /* @__PURE__ */ o("div", { children: t }) })
|
|
257
|
+
] }) }) });
|
|
258
|
+
}
|
|
259
|
+
const ze = (e) => {
|
|
260
|
+
e.components.Error ??= De, e.components.Layout ??= Ae, e.components.Loading ??= Te, e.components.Page ??= je;
|
|
261
|
+
};
|
|
262
|
+
function Be({
|
|
263
|
+
children: e
|
|
264
|
+
}) {
|
|
265
|
+
return /* @__PURE__ */ o(h, { children: e });
|
|
266
|
+
}
|
|
267
|
+
function Oe({
|
|
268
|
+
id: e,
|
|
269
|
+
label: n,
|
|
270
|
+
description: t,
|
|
271
|
+
leftSection: r,
|
|
272
|
+
rightSection: i,
|
|
273
|
+
to: s,
|
|
274
|
+
onClick: u,
|
|
275
|
+
children: a
|
|
276
|
+
}) {
|
|
277
|
+
const l = {
|
|
278
|
+
label: n,
|
|
279
|
+
description: t,
|
|
280
|
+
leftSection: r,
|
|
281
|
+
rightSection: i,
|
|
282
|
+
onClick: u
|
|
283
|
+
};
|
|
284
|
+
return s ? /* @__PURE__ */ o(T, { component: re, to: s, ...l, children: a }) : /* @__PURE__ */ o(T, { href: `#${e}`, ...l, children: a });
|
|
285
|
+
}
|
|
286
|
+
const $e = (e) => {
|
|
287
|
+
e.components.MenuContainer ??= Be, e.components.MenuItem ??= Oe;
|
|
288
|
+
};
|
|
289
|
+
function Sn({ type: e, params: n }) {
|
|
290
|
+
const {
|
|
291
|
+
components: { MenuContainer: t, Loading: r, Error: i },
|
|
292
|
+
modules: s
|
|
293
|
+
} = d(), u = v(() => {
|
|
294
|
+
const a = s.flatMap((c) => c.menuItems).filter((c) => c.menu === e);
|
|
295
|
+
return a.filter((c) => !c.parentId).map((c) => /* @__PURE__ */ o(Q, { type: e, params: n, thisItem: c, allItems: a }, c.id));
|
|
296
|
+
}, [e, n, s]);
|
|
297
|
+
return /* @__PURE__ */ o(M, { fallback: /* @__PURE__ */ o(i, { kind: "menu" }), children: /* @__PURE__ */ o(w, { fallback: /* @__PURE__ */ o(r, { kind: "menu" }), children: /* @__PURE__ */ o(t, { type: e, params: n, children: u }) }) });
|
|
298
|
+
}
|
|
299
|
+
function Q({ type: e, params: n, thisItem: t, allItems: r }) {
|
|
300
|
+
const i = t.component, s = v(() => {
|
|
301
|
+
const u = r.filter((a) => a.parentId === t.id).map((a) => /* @__PURE__ */ o(Q, { type: e, params: n, thisItem: a, allItems: r }, a.id));
|
|
302
|
+
return u.length > 0 ? u : void 0;
|
|
303
|
+
}, [e, n, t, r]);
|
|
304
|
+
return /* @__PURE__ */ o(i, { id: t.id, type: e, params: n, children: s });
|
|
305
|
+
}
|
|
306
|
+
function Qe({ name: e, params: n, options: t, onClose: r }) {
|
|
307
|
+
const [i, { close: s }] = fe(!0);
|
|
308
|
+
return /* @__PURE__ */ y(p.Root, { ...t, opened: i, onClose: s, onExitTransitionEnd: r, children: [
|
|
309
|
+
/* @__PURE__ */ o(p.Overlay, {}),
|
|
310
|
+
/* @__PURE__ */ o(p.Content, { children: /* @__PURE__ */ o(Ke, { name: e, params: n, onClose: s }) })
|
|
311
|
+
] });
|
|
312
|
+
}
|
|
313
|
+
function He({ children: e }) {
|
|
314
|
+
return /* @__PURE__ */ o(p.Body, { children: e });
|
|
315
|
+
}
|
|
316
|
+
function Ne({ children: e, actions: n }) {
|
|
317
|
+
return /* @__PURE__ */ y(p.Body, { component: "footer", children: [
|
|
318
|
+
e,
|
|
319
|
+
n && /* @__PURE__ */ o(j, { gap: "sm", justify: "flex-end", children: n })
|
|
320
|
+
] });
|
|
321
|
+
}
|
|
322
|
+
function Fe({ title: e }) {
|
|
323
|
+
return /* @__PURE__ */ y(p.Header, { children: [
|
|
324
|
+
/* @__PURE__ */ o(p.Title, { children: e }),
|
|
325
|
+
/* @__PURE__ */ o(p.CloseButton, {})
|
|
326
|
+
] });
|
|
327
|
+
}
|
|
328
|
+
const H = me((e) => ({
|
|
329
|
+
_lastId: 0,
|
|
330
|
+
modals: [],
|
|
331
|
+
openModal(n, t) {
|
|
332
|
+
const r = `modal-${this._lastId + 1}`;
|
|
333
|
+
return e((i) => ({
|
|
334
|
+
_lastId: i._lastId + 1,
|
|
335
|
+
modals: [...i.modals, { id: r, name: n, params: t }]
|
|
336
|
+
})), r;
|
|
337
|
+
},
|
|
338
|
+
closeModal(n) {
|
|
339
|
+
e((t) => ({
|
|
340
|
+
modals: t.modals.filter((r) => r.id !== n)
|
|
341
|
+
}));
|
|
342
|
+
}
|
|
343
|
+
})), Je = (e) => {
|
|
344
|
+
e.components.Modal ??= Qe, e.components.ModalBody ??= He, e.components.ModalHeader ??= Fe, e.components.ModalFooter ??= Ne, e.showModal ??= (n, t) => {
|
|
345
|
+
H.getState().openModal(n, t);
|
|
346
|
+
};
|
|
347
|
+
};
|
|
348
|
+
function Ke({ name: e, params: n, onClose: t }) {
|
|
349
|
+
const {
|
|
350
|
+
components: { Loading: r, Error: i },
|
|
351
|
+
modules: s
|
|
352
|
+
} = d(), u = v(() => s.flatMap((a) => a.modals).filter((a) => a.name === e).map((a) => a.component), [s, e]);
|
|
353
|
+
return /* @__PURE__ */ o(h, { children: u.map((a, l) => /* @__PURE__ */ o(M, { fallback: /* @__PURE__ */ o(i, { kind: "modal" }), children: /* @__PURE__ */ o(w, { fallback: /* @__PURE__ */ o(r, { kind: "modal" }), children: /* @__PURE__ */ o(a, { name: e, params: n, onClose: t }) }) }, l)) });
|
|
354
|
+
}
|
|
355
|
+
function En() {
|
|
356
|
+
const { Modal: e } = d().components, { modals: n, closeModal: t } = we(H), r = v(
|
|
357
|
+
() => n.reduce(
|
|
358
|
+
(i, { id: s }) => (i[s] = () => t(s), i),
|
|
359
|
+
{}
|
|
360
|
+
),
|
|
361
|
+
[n, t]
|
|
362
|
+
);
|
|
363
|
+
return /* @__PURE__ */ o(h, { children: n.map(({ id: i, name: s, params: u }) => /* @__PURE__ */ o(e, { name: s, params: u, onClose: r[i] }, i)) });
|
|
364
|
+
}
|
|
365
|
+
const N = new ye();
|
|
366
|
+
function Ve({ children: e }) {
|
|
367
|
+
return /* @__PURE__ */ o(ge, { client: N, children: e });
|
|
368
|
+
}
|
|
369
|
+
const Ue = (e) => {
|
|
370
|
+
e.queryClient ??= N;
|
|
371
|
+
};
|
|
372
|
+
function We() {
|
|
373
|
+
const e = d(), { Error: n } = e.components, t = se();
|
|
374
|
+
if (ie(t)) {
|
|
375
|
+
if (t.status === 403)
|
|
376
|
+
return /* @__PURE__ */ o(n, { kind: "route-forbidden" });
|
|
377
|
+
if (t.status === 404)
|
|
378
|
+
return /* @__PURE__ */ o(n, { kind: "route-not-found" });
|
|
379
|
+
}
|
|
380
|
+
return /* @__PURE__ */ o(n, { kind: "route" });
|
|
381
|
+
}
|
|
382
|
+
function _e() {
|
|
383
|
+
const e = d(), { Loading: n, Layout: t } = e.components;
|
|
384
|
+
return (
|
|
385
|
+
// Error boundary/fallback is defined in the route as errorElement so that it also catches
|
|
386
|
+
// and handles router errors.
|
|
387
|
+
/* @__PURE__ */ o(w, { fallback: /* @__PURE__ */ o(n, { kind: "app" }), children: /* @__PURE__ */ o(t, { children: /* @__PURE__ */ o(B, {}) }) })
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
function Ge() {
|
|
391
|
+
const e = d(), { Loading: n, Error: t } = e.components, r = ae().state === "loading", i = ue().key;
|
|
392
|
+
return /* @__PURE__ */ o(M, { fallback: /* @__PURE__ */ o(t, { kind: "route" }), children: /* @__PURE__ */ o(w, { fallback: /* @__PURE__ */ o(n, { kind: "route" }), children: r ? /* @__PURE__ */ o(n, { kind: "route" }) : /* @__PURE__ */ o(B, {}) }, i) });
|
|
393
|
+
}
|
|
394
|
+
const R = ce();
|
|
395
|
+
function Xe() {
|
|
396
|
+
const e = d(), n = v(() => {
|
|
397
|
+
const { Loading: t, Error: r } = e.components, i = e.modules.flatMap((a) => a.routes);
|
|
398
|
+
return le([
|
|
399
|
+
{
|
|
400
|
+
Component: _e,
|
|
401
|
+
hydrateFallbackElement: /* @__PURE__ */ o(t, { kind: "app" }),
|
|
402
|
+
errorElement: /* @__PURE__ */ o(r, { kind: "app" }),
|
|
403
|
+
children: [
|
|
404
|
+
{
|
|
405
|
+
Component: Ge,
|
|
406
|
+
hydrateFallbackElement: /* @__PURE__ */ o(t, { kind: "route" }),
|
|
407
|
+
errorElement: /* @__PURE__ */ o(We, {}),
|
|
408
|
+
children: i
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
], { getContext: () => {
|
|
413
|
+
const a = new de();
|
|
414
|
+
return a.set(R, e), a;
|
|
415
|
+
} });
|
|
416
|
+
}, [e]);
|
|
417
|
+
return /* @__PURE__ */ o(ve, { router: n });
|
|
418
|
+
}
|
|
419
|
+
function bn({
|
|
420
|
+
redirectUrl: e = "/",
|
|
421
|
+
permissions: n = [],
|
|
422
|
+
onUnauthorized: t,
|
|
423
|
+
onForbidden: r
|
|
424
|
+
} = {}) {
|
|
425
|
+
return async ({ context: i }) => {
|
|
426
|
+
const { queryClient: s } = i.get(R), { session: u } = await s.ensureQueryData(P());
|
|
427
|
+
if (!u)
|
|
428
|
+
throw await t?.(), O(e);
|
|
429
|
+
if (!n.every((a) => u.permissions.includes(a)))
|
|
430
|
+
throw await r?.(), pe({ message: `Permission(s) '${n.join(", ")}' required` }, 403);
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function In({ redirectUrl: e = "/" } = {}) {
|
|
434
|
+
return async ({ context: n }) => {
|
|
435
|
+
const { queryClient: t } = n.get(R), { hasSession: r } = await t.ensureQueryData(P());
|
|
436
|
+
if (r)
|
|
437
|
+
throw O(e);
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
function Pn({ app: e, children: n }) {
|
|
441
|
+
const t = x(
|
|
442
|
+
({ children: r }) => e.modules.flatMap((s) => s.providers).reduceRight((s, u) => /* @__PURE__ */ o(u, { children: s }), r),
|
|
443
|
+
[e.modules]
|
|
444
|
+
);
|
|
445
|
+
return /* @__PURE__ */ o($.Provider, { value: e, children: /* @__PURE__ */ y(t, { children: [
|
|
446
|
+
/* @__PURE__ */ o(Xe, {}),
|
|
447
|
+
n
|
|
448
|
+
] }) });
|
|
449
|
+
}
|
|
450
|
+
function Ln(e) {
|
|
451
|
+
let n = {
|
|
452
|
+
modules: e,
|
|
453
|
+
components: {}
|
|
454
|
+
};
|
|
455
|
+
for (const t of e.flatMap((r) => r.appInitializers))
|
|
456
|
+
n = t(n) ?? n;
|
|
457
|
+
return n;
|
|
458
|
+
}
|
|
459
|
+
function Ye(e) {
|
|
460
|
+
return {
|
|
461
|
+
appInitializers: e.appInitializers ?? [],
|
|
462
|
+
routes: e.routes ?? [],
|
|
463
|
+
extensions: e.extensions ?? [],
|
|
464
|
+
menuItems: e.menuItems ?? [],
|
|
465
|
+
modals: e.modals ?? [],
|
|
466
|
+
providers: e.providers ?? []
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
function Ze(e) {
|
|
470
|
+
const n = (t) => typeof t == "string" ? t : t.name;
|
|
471
|
+
return Array.isArray(e) ? e.map((t, r) => n(t) + `-${r}`).join(".") : n(e);
|
|
472
|
+
}
|
|
473
|
+
function Rn(e, n) {
|
|
474
|
+
const t = Ze(e), r = () => {
|
|
475
|
+
for (const [i, s] of Object.entries(n))
|
|
476
|
+
C?.addResourceBundle(i, "translation", { [t]: s }, !0, !0);
|
|
477
|
+
console.info(`Registered translations for key "${t}".`);
|
|
478
|
+
};
|
|
479
|
+
return C.isInitialized ? r() : C.on("initialized", r), function() {
|
|
480
|
+
const { t: s } = K(void 0, { keyPrefix: t });
|
|
481
|
+
return s;
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
const en = {
|
|
485
|
+
lng: "en",
|
|
486
|
+
fallbackLng: "en",
|
|
487
|
+
interpolation: {
|
|
488
|
+
escapeValue: !1
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
function nn({ options: e = en, children: n }) {
|
|
492
|
+
return oe(() => {
|
|
493
|
+
C.use(V).init(e);
|
|
494
|
+
}, [e]), n;
|
|
495
|
+
}
|
|
496
|
+
function qn(e = {}) {
|
|
497
|
+
return Ye({
|
|
498
|
+
appInitializers: [ze, $e, Je, Ue],
|
|
499
|
+
providers: [
|
|
500
|
+
(n) => /* @__PURE__ */ o(Ve, { ...n }),
|
|
501
|
+
(n) => /* @__PURE__ */ o(Z, { ...e.mantineProviderProps, ...n }),
|
|
502
|
+
(n) => /* @__PURE__ */ o(nn, { options: e.i18n, ...n })
|
|
503
|
+
]
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
export {
|
|
507
|
+
Pn as App,
|
|
508
|
+
I as AppFetchError,
|
|
509
|
+
Ve as AppQueryClientProvider,
|
|
510
|
+
Xe as AppRouter,
|
|
511
|
+
De as DefaultError,
|
|
512
|
+
Ae as DefaultLayout,
|
|
513
|
+
Te as DefaultLoading,
|
|
514
|
+
Be as DefaultMenuContainer,
|
|
515
|
+
Oe as DefaultMenuItem,
|
|
516
|
+
Qe as DefaultModal,
|
|
517
|
+
He as DefaultModalBody,
|
|
518
|
+
Ne as DefaultModalFooter,
|
|
519
|
+
Fe as DefaultModalHeader,
|
|
520
|
+
je as DefaultPage,
|
|
521
|
+
M as ErrorBoundary,
|
|
522
|
+
Mn as Extension,
|
|
523
|
+
Sn as Menu,
|
|
524
|
+
Ke as ModalContent,
|
|
525
|
+
En as Modals,
|
|
526
|
+
Me as ProblemDetailsError,
|
|
527
|
+
qe as WithPermissions,
|
|
528
|
+
R as appContext,
|
|
529
|
+
b as appFetch,
|
|
530
|
+
Ln as createApp,
|
|
531
|
+
qn as createCoreModule,
|
|
532
|
+
Ye as createModule,
|
|
533
|
+
Rn as defineLocales,
|
|
534
|
+
gn as formatDate,
|
|
535
|
+
wn as formatDateTime,
|
|
536
|
+
vn as formatTime,
|
|
537
|
+
Ee as isProblemDetails,
|
|
538
|
+
ze as layoutInitializer,
|
|
539
|
+
$e as menuInitializer,
|
|
540
|
+
Je as modalsInitializer,
|
|
541
|
+
Ue as queryInitializer,
|
|
542
|
+
Se as readPermissions,
|
|
543
|
+
hn as readPermissionsQuery,
|
|
544
|
+
be as readSessionState,
|
|
545
|
+
P as readSessionStateQuery,
|
|
546
|
+
Ie as readStatus,
|
|
547
|
+
yn as readStatusQuery,
|
|
548
|
+
In as requireAnonymous,
|
|
549
|
+
bn as requireSession,
|
|
550
|
+
d as useApp,
|
|
551
|
+
kn as usePagination,
|
|
552
|
+
Re as usePermissions,
|
|
553
|
+
Cn as useSearch,
|
|
554
|
+
Le as useSession,
|
|
555
|
+
Pe as useSessionState,
|
|
556
|
+
xn as withPermissions
|
|
557
|
+
};
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { InitOptions } from 'i18next';
|
|
2
|
+
import { MantineProviderProps } from '@mantine/core';
|
|
3
|
+
export interface CoreModuleOptions {
|
|
4
|
+
i18n?: InitOptions<unknown>;
|
|
5
|
+
mantineProviderProps?: MantineProviderProps;
|
|
6
|
+
}
|
|
7
|
+
export declare function createCoreModule(options?: CoreModuleOptions): import('./app').Module;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function formatDate(date?: null | string | number | Date): string | undefined;
|
|
2
|
+
export declare function formatTime(date?: null | string | number | Date): string | undefined;
|
|
3
|
+
export declare function formatDateTime(date?: null | string | number | Date): string | undefined;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface UsePaginationOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The default name of the page query parameter in the URL.
|
|
4
|
+
* @default 'page'
|
|
5
|
+
*/
|
|
6
|
+
pageParamName?: string;
|
|
7
|
+
/**
|
|
8
|
+
* The default name of the page size query parameter in the URL.
|
|
9
|
+
* @default 'pageSize'
|
|
10
|
+
*/
|
|
11
|
+
pageSizeParamName?: string;
|
|
12
|
+
/**
|
|
13
|
+
* The default page value to be used as a fallback for missing values.
|
|
14
|
+
* @default 1
|
|
15
|
+
*/
|
|
16
|
+
defaultPage?: number;
|
|
17
|
+
/**
|
|
18
|
+
* The default page size value to be used as a fallback for missing values.
|
|
19
|
+
* @default 20
|
|
20
|
+
*/
|
|
21
|
+
defaultPageSize?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Manages pagination query parameters for handling page and page size values in the URL.
|
|
25
|
+
*/
|
|
26
|
+
export declare function usePagination({ pageParamName, pageSizeParamName, defaultPage, defaultPageSize, }?: UsePaginationOptions): {
|
|
27
|
+
page: number;
|
|
28
|
+
pageSize: number;
|
|
29
|
+
setPage: (newPage: number) => void;
|
|
30
|
+
setPageSize: (newPageSize: number) => void;
|
|
31
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface UseSearchOptions {
|
|
2
|
+
/**
|
|
3
|
+
* The default name of the search query parameter in the URL.
|
|
4
|
+
* @default 'search'
|
|
5
|
+
*/
|
|
6
|
+
searchParamName?: string;
|
|
7
|
+
/**
|
|
8
|
+
* The default search value to be used as a fallback for missing values.
|
|
9
|
+
* @default ''
|
|
10
|
+
*/
|
|
11
|
+
defaultSearch?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Manages a "search" query parameter used for filtering and searching page content.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useSearch({ searchParamName, defaultSearch }?: UseSearchOptions): {
|
|
17
|
+
search: string;
|
|
18
|
+
setSearch: (newSearch: string) => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Permission, SessionRead, SessionState } from '../api';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the app's current {@link SessionState}.
|
|
4
|
+
* This is a convenience hook which returns the data of the current {@link readSessionStateQuery}.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useSessionState(): SessionState;
|
|
7
|
+
/**
|
|
8
|
+
* Returns the app's active {@link SessionRead} session data.
|
|
9
|
+
*
|
|
10
|
+
* **⚠️ Important**:
|
|
11
|
+
* This hook should only be used in components which are guaranteed to be rendered in an active session context.
|
|
12
|
+
* If no active session exists, this hook will throw an error.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useSession(): SessionRead;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the app's active session's permissions.
|
|
17
|
+
*
|
|
18
|
+
* **⚠️ Important**:
|
|
19
|
+
* This hook should only be used in components which are guaranteed to be rendered in an active session context.
|
|
20
|
+
* If no active session exists, this hook will throw an error.
|
|
21
|
+
*/
|
|
22
|
+
export declare function usePermissions(): Array<Permission>;
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tiny-server/core",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "The Tiny Server core frontend package.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"tiny-server",
|
|
7
|
+
"module",
|
|
8
|
+
"core"
|
|
9
|
+
],
|
|
10
|
+
"author": "Manuel Römer",
|
|
11
|
+
"license": "AGPL-3.0-only",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/manuelroemer/tiny-server.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/manuelroemer/tiny-server/issues"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"module": "dist/index.js",
|
|
22
|
+
"types": "dist/index.d.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"start": "vite build --watch",
|
|
35
|
+
"build": "vite build",
|
|
36
|
+
"test": "",
|
|
37
|
+
"lint": "eslint src"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@mantine/core": "^9",
|
|
41
|
+
"@mantine/form": "^9",
|
|
42
|
+
"@mantine/hooks": "^9",
|
|
43
|
+
"@mantine/notifications": "^9",
|
|
44
|
+
"@tanstack/react-query": "^5",
|
|
45
|
+
"i18next": "^26",
|
|
46
|
+
"react": "^19",
|
|
47
|
+
"react-dom": "^19",
|
|
48
|
+
"react-i18next": "^17",
|
|
49
|
+
"react-router": "^7",
|
|
50
|
+
"zustand": "^5"
|
|
51
|
+
}
|
|
52
|
+
}
|