@e7w/easy-routes 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -21,6 +21,8 @@ export function Layout() {
21
21
  src/\*\*/pages/\*\*/meta.ts配置如下
22
22
 
23
23
  ```ts
24
- export const permission: number = 0b0; // 默认是0b0代表需要登录,只有最右边的一位代表登录,其他位可以自己定enum代表权限
24
+ export const permission: number = 0b0; // 默认是0b0代表不需要登录,只有最右边的一位代表登录,其他位可以自己定enum代表权限
25
25
  export const loader: Loader = async (ctx, meta) => {}; // 可以动态修改ctx,ctx.data是返回给页面组件的值,ctx.title是页面的title,signed代表是否登录成功,noPermission代表是否没有权限
26
+ export const displayInMenu: string = "首页"; // 空字符串或者没有代表不展示在menu里
27
+ export const menuIcon: string = "xxx.svg"; // menu的icon
26
28
  ```
@@ -0,0 +1,26 @@
1
+ import z from "zod";
2
+ import { Params, RouteObject } from "react-router";
3
+
4
+ //#region src/types/index.d.ts
5
+ interface Ctx {
6
+ title: string;
7
+ signed: boolean;
8
+ noPermission: boolean;
9
+ req: {
10
+ params: Params;
11
+ query: Params;
12
+ pathname: string;
13
+ };
14
+ data?: any;
15
+ }
16
+ declare abstract class Permission {
17
+ permission: number;
18
+ abstract defaultTitle: string;
19
+ abstract init(req: Ctx["req"]): Promise<void> | void;
20
+ }
21
+ declare const PermissionSchema: z.ZodType<Permission, Permission>;
22
+ //#endregion
23
+ //#region src/router.d.ts
24
+ declare const routes: RouteObject[];
25
+ //#endregion
26
+ export { type Ctx, Permission, PermissionSchema, routes };
package/dist/index.mjs ADDED
@@ -0,0 +1,470 @@
1
+ import z from "zod";
2
+ import { Navigate, Outlet, isRouteErrorResponse, redirect, useNavigation, useRouteError } from "react-router";
3
+ import { c } from "react/compiler-runtime";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { useEffect, useRef, useState } from "react";
6
+ import nProgress from "nprogress";
7
+ import "nprogress/nprogress.css";
8
+ import { inject, loader, provide, useLoader } from "@e7w/easy-model";
9
+ import './style.css';
10
+ //#region src/types/index.ts
11
+ var Permission = class {
12
+ permission = 0;
13
+ };
14
+ const PermissionSchema = z.object({
15
+ init: z.function({ output: z.union([z.promise(z.void()), z.void()]) }),
16
+ permission: z.number(),
17
+ defaultTitle: z.string()
18
+ });
19
+ //#endregion
20
+ //#region src/components/DefaultOutlet.tsx
21
+ const DefaultOutlet = () => {
22
+ const $ = c(2);
23
+ if ($[0] !== "86245ef798e2727374ee553b08ad2562f91d79b38190dfff1bf2e15388787321") {
24
+ for (let $i = 0; $i < 2; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
25
+ $[0] = "86245ef798e2727374ee553b08ad2562f91d79b38190dfff1bf2e15388787321";
26
+ }
27
+ let t0;
28
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29
+ t0 = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Outlet, {}) });
30
+ $[1] = t0;
31
+ } else t0 = $[1];
32
+ return t0;
33
+ };
34
+ //#endregion
35
+ //#region src/components/ErrorBoundary.tsx
36
+ const ErrorBoundary = () => {
37
+ const $ = c(10);
38
+ if ($[0] !== "c0519d7cbaee7b0126a2e952b78b40bd9558a23ee78ea987eb3dcf5c9585862b") {
39
+ for (let $i = 0; $i < 10; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
40
+ $[0] = "c0519d7cbaee7b0126a2e952b78b40bd9558a23ee78ea987eb3dcf5c9585862b";
41
+ }
42
+ const error = useRouteError();
43
+ let t0;
44
+ let t1;
45
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
46
+ t0 = /* @__PURE__ */ jsx("h1", {
47
+ className: "text-2xl font-bold mb-4",
48
+ children: "Error"
49
+ });
50
+ t1 = /* @__PURE__ */ jsx("p", { children: "Something went wrong." });
51
+ $[1] = t0;
52
+ $[2] = t1;
53
+ } else {
54
+ t0 = $[1];
55
+ t1 = $[2];
56
+ }
57
+ let t2;
58
+ if ($[3] !== error) {
59
+ t2 = isRouteErrorResponse(error) && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("p", {
60
+ className: "text-red-300",
61
+ children: [
62
+ error.status,
63
+ " ",
64
+ error.statusText
65
+ ]
66
+ }), /* @__PURE__ */ jsx("p", {
67
+ className: "text-red-300",
68
+ children: JSON.stringify(error.data)
69
+ })] });
70
+ $[3] = error;
71
+ $[4] = t2;
72
+ } else t2 = $[4];
73
+ let t3;
74
+ if ($[5] !== error) {
75
+ t3 = error instanceof Error && /* @__PURE__ */ jsx("p", {
76
+ className: "text-red-300",
77
+ children: error.message
78
+ });
79
+ $[5] = error;
80
+ $[6] = t3;
81
+ } else t3 = $[6];
82
+ let t4;
83
+ if ($[7] !== t2 || $[8] !== t3) {
84
+ t4 = /* @__PURE__ */ jsx("div", {
85
+ className: "flex h-screen w-full items-center justify-center",
86
+ children: /* @__PURE__ */ jsxs("div", {
87
+ className: "flex flex-col items-center justify-center",
88
+ children: [
89
+ t0,
90
+ t1,
91
+ t2,
92
+ t3
93
+ ]
94
+ })
95
+ });
96
+ $[7] = t2;
97
+ $[8] = t3;
98
+ $[9] = t4;
99
+ } else t4 = $[9];
100
+ return t4;
101
+ };
102
+ //#endregion
103
+ //#region src/utils/hooks.ts
104
+ function useDebouncedValue(value) {
105
+ const $ = c(6);
106
+ if ($[0] !== "cafc571037d3460a1577637e6ed6134f48e275412c9fbdd1e3259d6b7886985f") {
107
+ for (let $i = 0; $i < 6; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
108
+ $[0] = "cafc571037d3460a1577637e6ed6134f48e275412c9fbdd1e3259d6b7886985f";
109
+ }
110
+ const [result, setResult] = useState(value);
111
+ const timer = useRef(void 0);
112
+ let t0;
113
+ if ($[1] !== value) {
114
+ t0 = () => {
115
+ clearTimeout(timer.current);
116
+ timer.current = window.setTimeout(() => {
117
+ setResult(value);
118
+ }, 700);
119
+ return () => {
120
+ window.clearTimeout(timer.current);
121
+ };
122
+ };
123
+ $[1] = value;
124
+ $[2] = t0;
125
+ } else t0 = $[2];
126
+ let t1;
127
+ if ($[3] !== result || $[4] !== value) {
128
+ t1 = [result, value];
129
+ $[3] = result;
130
+ $[4] = value;
131
+ $[5] = t1;
132
+ } else t1 = $[5];
133
+ useEffect(t0, t1);
134
+ return result;
135
+ }
136
+ //#endregion
137
+ //#region src/components/Loading.tsx
138
+ const Loading = () => {
139
+ const $ = c(2);
140
+ if ($[0] !== "9ba59b6b2e9bf36d0d2119a54dc7f29c23de32230207b1503967b02ba51f79d2") {
141
+ for (let $i = 0; $i < 2; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
142
+ $[0] = "9ba59b6b2e9bf36d0d2119a54dc7f29c23de32230207b1503967b02ba51f79d2";
143
+ }
144
+ const { isGlobalLoading } = useLoader();
145
+ if (!useDebouncedValue(isGlobalLoading)) return;
146
+ let t0;
147
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
148
+ t0 = /* @__PURE__ */ jsxs("div", {
149
+ className: "spinner-box",
150
+ children: [
151
+ /* @__PURE__ */ jsx("div", { className: "blue-orbit leo" }),
152
+ /* @__PURE__ */ jsx("div", { className: "green-orbit leo" }),
153
+ /* @__PURE__ */ jsx("div", { className: "red-orbit leo" }),
154
+ /* @__PURE__ */ jsx("div", { className: "white-orbit w1 leo" }),
155
+ /* @__PURE__ */ jsx("div", { className: "white-orbit w2 leo" }),
156
+ /* @__PURE__ */ jsx("div", { className: "white-orbit w3 leo" })
157
+ ]
158
+ });
159
+ $[1] = t0;
160
+ } else t0 = $[1];
161
+ return t0;
162
+ };
163
+ //#endregion
164
+ //#region src/components/ProgressLayout.tsx
165
+ nProgress.configure({
166
+ showSpinner: false,
167
+ speed: 500,
168
+ minimum: .1,
169
+ easing: "ease",
170
+ trickleSpeed: 200
171
+ });
172
+ const ProgressLayout = () => {
173
+ const $ = c(5);
174
+ if ($[0] !== "de22e6cf6e3aceb20c6d7925d182a0e90b0719d98cf1e99dbf79a6686dd7cae1") {
175
+ for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
176
+ $[0] = "de22e6cf6e3aceb20c6d7925d182a0e90b0719d98cf1e99dbf79a6686dd7cae1";
177
+ }
178
+ const { state } = useNavigation();
179
+ let t0;
180
+ let t1;
181
+ if ($[1] !== state) {
182
+ t0 = () => {
183
+ if (state === "loading") nProgress.start();
184
+ else nProgress.done();
185
+ };
186
+ t1 = [state];
187
+ $[1] = state;
188
+ $[2] = t0;
189
+ $[3] = t1;
190
+ } else {
191
+ t0 = $[2];
192
+ t1 = $[3];
193
+ }
194
+ useEffect(t0, t1);
195
+ let t2;
196
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
197
+ t2 = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Outlet, {}), /* @__PURE__ */ jsx(Loading, {})] });
198
+ $[4] = t2;
199
+ } else t2 = $[4];
200
+ return t2;
201
+ };
202
+ //#endregion
203
+ //#region src/models/system.ts
204
+ let _initProto, _init_router, _init_extra_router;
205
+ function _applyDecs(e, t, n, r, o, i) {
206
+ var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length;
207
+ function g(t, n, r) {
208
+ return function(o, i) {
209
+ n && (i = o, o = e);
210
+ for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []);
211
+ return r ? i : o;
212
+ };
213
+ }
214
+ function b(e, t, n, r) {
215
+ if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined"));
216
+ return e;
217
+ }
218
+ function applyDec(e, t, n, r, o, i, u, s, f, l, p) {
219
+ function d(e) {
220
+ if (!p(e)) throw new TypeError("Attempted to access private element on non-instance");
221
+ }
222
+ var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o;
223
+ function I(t, n, r) {
224
+ return function(o, i) {
225
+ return n && (i = o, o = e), r && r(o), P[t].call(o, i);
226
+ };
227
+ }
228
+ if (!w) {
229
+ var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value";
230
+ if (f ? (l || D ? P = {
231
+ get: _setFunctionName(function() {
232
+ return v(this);
233
+ }, r, "get"),
234
+ set: function(e) {
235
+ t[4](this, e);
236
+ }
237
+ } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) {
238
+ if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet");
239
+ y[+s][r] = o < 3 ? 1 : o;
240
+ }
241
+ }
242
+ for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) {
243
+ var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = {
244
+ kind: [
245
+ "field",
246
+ "accessor",
247
+ "method",
248
+ "getter",
249
+ "setter",
250
+ "class"
251
+ ][o],
252
+ name: r,
253
+ metadata: a,
254
+ addInitializer: function(e, t) {
255
+ if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished");
256
+ b(t, "An initializer", "be", !0), i.push(t);
257
+ }.bind(null, A)
258
+ };
259
+ if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);
260
+ else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function(e) {
261
+ return r in e;
262
+ } }, j || (c.get = f ? E ? function(e) {
263
+ return d(e), P.value;
264
+ } : I("get", 0, d) : function(e) {
265
+ return e[r];
266
+ }), E || S || (c.set = f ? I("set", 0, d) : function(e, t) {
267
+ e[r] = t;
268
+ }), N = T.call(z, D ? {
269
+ get: P.get,
270
+ set: P.set
271
+ } : P[F], H), A.v = 1, D) {
272
+ if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);
273
+ else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined");
274
+ } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N);
275
+ }
276
+ return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N;
277
+ }
278
+ function w(e) {
279
+ return m(e, d, {
280
+ configurable: !0,
281
+ enumerable: !0,
282
+ value: a
283
+ });
284
+ }
285
+ return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function(e) {
286
+ e && f.push(g(e));
287
+ }, p = function(t, r) {
288
+ for (var i = 0; i < n.length; i++) {
289
+ var a = n[i], c = a[1], l = 7 & c;
290
+ if ((8 & c) == t && !l == r) {
291
+ var p = a[2], d = !!a[3], m = 16 & c;
292
+ applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function(t) {
293
+ return _checkInRHS(t) === e;
294
+ } : o);
295
+ }
296
+ }
297
+ }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), {
298
+ e: c,
299
+ get c() {
300
+ var n = [];
301
+ return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)];
302
+ }
303
+ };
304
+ }
305
+ function _toPropertyKey(t) {
306
+ var i = _toPrimitive(t, "string");
307
+ return "symbol" == typeof i ? i : i + "";
308
+ }
309
+ function _toPrimitive(t, r) {
310
+ if ("object" != typeof t || !t) return t;
311
+ var e = t[Symbol.toPrimitive];
312
+ if (void 0 !== e) {
313
+ var i = e.call(t, r || "default");
314
+ if ("object" != typeof i) return i;
315
+ throw new TypeError("@@toPrimitive must return a primitive value.");
316
+ }
317
+ return ("string" === r ? String : Number)(t);
318
+ }
319
+ function _setFunctionName(e, t, n) {
320
+ "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : "");
321
+ try {
322
+ Object.defineProperty(e, "name", {
323
+ configurable: !0,
324
+ value: n ? n + " " + t : t
325
+ });
326
+ } catch (e) {}
327
+ return e;
328
+ }
329
+ function _checkInRHS(e) {
330
+ if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null"));
331
+ return e;
332
+ }
333
+ const system = provide(class System {
334
+ static {
335
+ [_init_router, _init_extra_router, _initProto] = _applyDecs(this, [], [[
336
+ inject(PermissionSchema),
337
+ 0,
338
+ "router"
339
+ ], [
340
+ [
341
+ loader,
342
+ loader.once,
343
+ void 0,
344
+ loader.load(true)
345
+ ],
346
+ 18,
347
+ "init"
348
+ ]]).e;
349
+ }
350
+ constructor() {
351
+ _init_extra_router(this);
352
+ }
353
+ router = (_initProto(this), _init_router(this));
354
+ async init(req) {
355
+ await this.router?.init(req);
356
+ }
357
+ hasPermission(permission = 0) {
358
+ return ((this.router?.permission || 0) & permission) === permission;
359
+ }
360
+ getCtx(req, permission = 1) {
361
+ return {
362
+ title: this.router?.defaultTitle ?? document.title,
363
+ signed: (permission & 1) === 0 || this.hasPermission(1),
364
+ noPermission: !this.hasPermission(permission),
365
+ req
366
+ };
367
+ }
368
+ })();
369
+ //#endregion
370
+ //#region src/router.tsx
371
+ const pages = import.meta.glob("/src/**/pages/**/index.tsx", {
372
+ eager: true,
373
+ import: "Page"
374
+ });
375
+ const layouts = import.meta.glob("/src/**/pages/**/layout.tsx", {
376
+ eager: true,
377
+ import: "Layout"
378
+ });
379
+ const metas = import.meta.glob("/src/**/pages/**/meta.ts", { eager: true });
380
+ const menuObj = { "/": {
381
+ name: "首页",
382
+ path: "/"
383
+ } };
384
+ const routes = [];
385
+ const obj = {};
386
+ const filePaths = new Set(Object.keys({
387
+ ...pages,
388
+ ...layouts
389
+ }).map((p) => p.replace(/\/(index|layout)\.tsx$/, "")));
390
+ filePaths.forEach((filePath) => {
391
+ const Page = pages[filePath + "/index.tsx"];
392
+ const Layout = layouts[filePath + "/layout.tsx"] || DefaultOutlet;
393
+ const meta = metas[filePath + "/meta.ts"] || {};
394
+ const path = filePath.replace(/.*\/pages/, "").replace(/\[([^\]]+)\]/, ":$1") || "/";
395
+ const hasPage = Boolean(Page);
396
+ obj[path] = {
397
+ path,
398
+ element: /* @__PURE__ */ jsx(Layout, {}),
399
+ children: [{
400
+ element: hasPage ? /* @__PURE__ */ jsx(Page, {}) : /* @__PURE__ */ jsx(Navigate, {
401
+ to: "/",
402
+ replace: true
403
+ }),
404
+ index: true,
405
+ loader: hasPage ? async ({ params, request }) => {
406
+ const url = new URL(request.url);
407
+ const req = {
408
+ params,
409
+ query: Object.fromEntries(url.searchParams),
410
+ pathname: url.pathname.replace(/\/?$/, "/")
411
+ };
412
+ await system.init(req)?.catch?.(() => {});
413
+ const ctx = system.getCtx(req, meta.permission);
414
+ await meta.loader?.(ctx)?.catch?.(() => {});
415
+ if (!ctx.signed) return redirect(`/login?from=${encodeURIComponent(request.url)}`);
416
+ if (ctx.noPermission) return redirect("/403");
417
+ document.title = ctx.title;
418
+ return ctx.data;
419
+ } : void 0
420
+ }]
421
+ };
422
+ if (meta.displayInMenu) menuObj[path] = {
423
+ name: meta.displayInMenu,
424
+ path,
425
+ icon: meta.menuIcon
426
+ };
427
+ });
428
+ filePaths.forEach((filePath) => {
429
+ const path = filePath.replace(/.*\/pages/, "").replace(/\[([^\]]+)\]/, ":$1") || "/";
430
+ if (path === "/") return;
431
+ const currentObj = obj[path];
432
+ const currentMenu = menuObj[path];
433
+ const segments = path.split("/").filter(Boolean);
434
+ const paths = ["/"];
435
+ let finished1 = false;
436
+ let finished2 = !currentMenu;
437
+ segments.reduce((acc, curr) => {
438
+ const newPath = acc + "/" + curr;
439
+ if (newPath !== path) paths.unshift(newPath);
440
+ return newPath;
441
+ }, "");
442
+ for (const p of paths) {
443
+ if (!finished1 && obj[p]) {
444
+ obj[p].children.push(currentObj);
445
+ finished1 = true;
446
+ }
447
+ if (!finished2 && menuObj[p]) {
448
+ menuObj[p].children ??= [];
449
+ menuObj[p].children.push(currentMenu);
450
+ finished2 = true;
451
+ }
452
+ if (finished1 && finished2) break;
453
+ }
454
+ });
455
+ obj["/"].errorElement = /* @__PURE__ */ jsx(ErrorBoundary, {});
456
+ routes.push({
457
+ path: "/",
458
+ element: /* @__PURE__ */ jsx(ProgressLayout, {}),
459
+ children: [obj["/"]]
460
+ });
461
+ routes.push({
462
+ path: "*",
463
+ element: /* @__PURE__ */ jsx(Navigate, {
464
+ to: obj["/404"] ? "/404" : "/",
465
+ replace: true
466
+ })
467
+ });
468
+ menuObj["/"];
469
+ //#endregion
470
+ export { Permission, PermissionSchema, routes };