@kyro-cms/admin 0.1.2 → 0.1.3
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/package.json +17 -6
- package/src/components/Admin.tsx +50 -1
- package/src/components/LoginPage.tsx +223 -0
- package/src/components/layout/Sidebar.tsx +35 -0
- package/src/index.ts +35 -0
- package/src/middleware.ts +2 -0
- package/src/pages/api/auth/register.ts +133 -0
- package/src/styles/main.css +148 -0
- package/.astro/content.d.ts +0 -154
- package/.astro/settings.json +0 -5
- package/.astro/types.d.ts +0 -2
- package/astro.config.mjs +0 -28
- package/bun.lock +0 -1374
- package/dist/client/_astro/AdminLayout.DkDpng53.css +0 -1
- package/dist/client/_astro/AutoForm.3eJCmCJp.js +0 -1
- package/dist/client/_astro/client.DyczpTbx.js +0 -9
- package/dist/client/_astro/index.B02hbnpo.js +0 -1
- package/dist/client/fonts/Serotiva-Black.woff2 +0 -0
- package/dist/client/fonts/Serotiva-Bold.woff2 +0 -0
- package/dist/client/fonts/Serotiva-Medium.woff2 +0 -0
- package/dist/client/fonts/Serotiva-Regular.woff2 +0 -0
- package/dist/client/fonts/Serotiva-SemiBold.woff2 +0 -0
- package/dist/server/chunks/AdminLayout_D-_JeUqC.mjs +0 -26
- package/dist/server/chunks/_id__BzI_o0qT.mjs +0 -50
- package/dist/server/chunks/_id__Cd-jOuY3.mjs +0 -238
- package/dist/server/chunks/_id__DvbD--iR.mjs +0 -992
- package/dist/server/chunks/_id__vpVaEo16.mjs +0 -128
- package/dist/server/chunks/_virtual_astro_server-island-manifest_CQQ1F5PF.mjs +0 -7
- package/dist/server/chunks/_virtual_astro_session-driver_Bk3Q189E.mjs +0 -4
- package/dist/server/chunks/astro-component_Dbx3T2Nh.mjs +0 -37
- package/dist/server/chunks/audit-logs_DrnUMRvY.mjs +0 -74
- package/dist/server/chunks/config_CPXslElD.mjs +0 -4221
- package/dist/server/chunks/dataStore_Dl7cA2Qp.mjs +0 -89
- package/dist/server/chunks/index_CVqOkerS.mjs +0 -2960
- package/dist/server/chunks/index_CX8SQ4BF.mjs +0 -55
- package/dist/server/chunks/index_CYofDU51.mjs +0 -58
- package/dist/server/chunks/index_DdNRhuaM.mjs +0 -55
- package/dist/server/chunks/index_DupPvtIF.mjs +0 -42
- package/dist/server/chunks/index_YTS_M-B9.mjs +0 -263
- package/dist/server/chunks/index_YeCzuVps.mjs +0 -53
- package/dist/server/chunks/login_DLyqMRO8.mjs +0 -93
- package/dist/server/chunks/logout_CSbt5wea.mjs +0 -50
- package/dist/server/chunks/me_C04jlYhH.mjs +0 -41
- package/dist/server/chunks/new_BbQ9b55M.mjs +0 -92
- package/dist/server/chunks/node_9bvTewss.mjs +0 -1014
- package/dist/server/chunks/noop-entrypoint_BOlrdqWF.mjs +0 -3
- package/dist/server/chunks/sequence_9cl7AJy-.mjs +0 -2503
- package/dist/server/chunks/server_peBx9VXG.mjs +0 -8117
- package/dist/server/chunks/sharp_pmJ7nHES.mjs +0 -142
- package/dist/server/chunks/users_Dzddy_YR.mjs +0 -137
- package/dist/server/entry.mjs +0 -5
- package/dist/server/virtual_astro_middleware.mjs +0 -48
- package/public/fonts/Serotiva-Black.woff2 +0 -0
- package/public/fonts/Serotiva-Bold.woff2 +0 -0
- package/public/fonts/Serotiva-Medium.woff2 +0 -0
- package/public/fonts/Serotiva-Regular.woff2 +0 -0
- package/public/fonts/Serotiva-SemiBold.woff2 +0 -0
- package/tsconfig.json +0 -12
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { RedisAuthAdapter } from './index_CVqOkerS.mjs';
|
|
2
|
-
import jwt from 'jsonwebtoken';
|
|
3
|
-
|
|
4
|
-
const JWT_SECRET = process.env.JWT_SECRET || "change-me-in-production";
|
|
5
|
-
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || "24h";
|
|
6
|
-
async function getAuthApi() {
|
|
7
|
-
return new RedisAuthAdapter({
|
|
8
|
-
url: process.env.REDIS_URL || "redis://localhost:6379",
|
|
9
|
-
tls: process.env.REDIS_TLS === "true"
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
const POST = async ({ request }) => {
|
|
13
|
-
try {
|
|
14
|
-
const body = await request.json();
|
|
15
|
-
const { email, password } = body;
|
|
16
|
-
if (!email || !password) {
|
|
17
|
-
return new Response(
|
|
18
|
-
JSON.stringify({ error: "Email and password required" }),
|
|
19
|
-
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
const adapter = await getAuthApi();
|
|
23
|
-
await adapter.connect();
|
|
24
|
-
const user = await adapter.findUserByEmail(email);
|
|
25
|
-
if (!user || !user.passwordHash) {
|
|
26
|
-
await adapter.disconnect();
|
|
27
|
-
return new Response(JSON.stringify({ error: "Invalid credentials" }), {
|
|
28
|
-
status: 401,
|
|
29
|
-
headers: { "Content-Type": "application/json" }
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
if (user.locked) {
|
|
33
|
-
await adapter.disconnect();
|
|
34
|
-
return new Response(JSON.stringify({ error: "Account is locked" }), {
|
|
35
|
-
status: 403,
|
|
36
|
-
headers: { "Content-Type": "application/json" }
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
const valid = await adapter.verifyPassword(password, user.passwordHash);
|
|
40
|
-
if (!valid) {
|
|
41
|
-
await adapter.recordFailedAttempt(user.id);
|
|
42
|
-
await adapter.disconnect();
|
|
43
|
-
return new Response(JSON.stringify({ error: "Invalid credentials" }), {
|
|
44
|
-
status: 401,
|
|
45
|
-
headers: { "Content-Type": "application/json" }
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
await adapter.resetAttempts(user.id);
|
|
49
|
-
const session = await adapter.createSession(user.id, {
|
|
50
|
-
ipAddress: request.headers.get("x-forwarded-for") || "unknown",
|
|
51
|
-
userAgent: request.headers.get("user-agent") || ""
|
|
52
|
-
});
|
|
53
|
-
const token = jwt.sign(
|
|
54
|
-
{
|
|
55
|
-
sub: user.id,
|
|
56
|
-
email: user.email,
|
|
57
|
-
role: user.role,
|
|
58
|
-
tenantId: user.tenantId
|
|
59
|
-
},
|
|
60
|
-
JWT_SECRET,
|
|
61
|
-
{ expiresIn: JWT_EXPIRES_IN }
|
|
62
|
-
);
|
|
63
|
-
await adapter.disconnect();
|
|
64
|
-
const { passwordHash, ...safeUser } = user;
|
|
65
|
-
return new Response(
|
|
66
|
-
JSON.stringify({
|
|
67
|
-
success: true,
|
|
68
|
-
user: safeUser,
|
|
69
|
-
token,
|
|
70
|
-
refreshToken: session.refreshToken
|
|
71
|
-
}),
|
|
72
|
-
{
|
|
73
|
-
status: 200,
|
|
74
|
-
headers: { "Content-Type": "application/json" }
|
|
75
|
-
}
|
|
76
|
-
);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error("Login error:", error);
|
|
79
|
-
return new Response(JSON.stringify({ error: "Login failed" }), {
|
|
80
|
-
status: 500,
|
|
81
|
-
headers: { "Content-Type": "application/json" }
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
87
|
-
__proto__: null,
|
|
88
|
-
POST
|
|
89
|
-
}, Symbol.toStringTag, { value: 'Module' }));
|
|
90
|
-
|
|
91
|
-
const page = () => _page;
|
|
92
|
-
|
|
93
|
-
export { page };
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { RedisAuthAdapter } from './index_CVqOkerS.mjs';
|
|
2
|
-
|
|
3
|
-
async function getAuthApi() {
|
|
4
|
-
return new RedisAuthAdapter({
|
|
5
|
-
url: process.env.REDIS_URL || "redis://localhost:6379",
|
|
6
|
-
tls: process.env.REDIS_TLS === "true"
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
const POST = async ({ request }) => {
|
|
10
|
-
try {
|
|
11
|
-
const body = await request.json();
|
|
12
|
-
const { refreshToken } = body;
|
|
13
|
-
if (!refreshToken) {
|
|
14
|
-
return new Response(JSON.stringify({ error: "Refresh token required" }), {
|
|
15
|
-
status: 400,
|
|
16
|
-
headers: { "Content-Type": "application/json" }
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
const adapter = await getAuthApi();
|
|
20
|
-
await adapter.connect();
|
|
21
|
-
const session = await adapter.findSessionByToken(refreshToken);
|
|
22
|
-
if (!session) {
|
|
23
|
-
await adapter.disconnect();
|
|
24
|
-
return new Response(JSON.stringify({ error: "Invalid refresh token" }), {
|
|
25
|
-
status: 401,
|
|
26
|
-
headers: { "Content-Type": "application/json" }
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
await adapter.disconnect();
|
|
30
|
-
return new Response(JSON.stringify({ success: true, session }), {
|
|
31
|
-
status: 200,
|
|
32
|
-
headers: { "Content-Type": "application/json" }
|
|
33
|
-
});
|
|
34
|
-
} catch (error) {
|
|
35
|
-
console.error("Logout error:", error);
|
|
36
|
-
return new Response(JSON.stringify({ error: "Logout failed" }), {
|
|
37
|
-
status: 500,
|
|
38
|
-
headers: { "Content-Type": "application/json" }
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
44
|
-
__proto__: null,
|
|
45
|
-
POST
|
|
46
|
-
}, Symbol.toStringTag, { value: 'Module' }));
|
|
47
|
-
|
|
48
|
-
const page = () => _page;
|
|
49
|
-
|
|
50
|
-
export { page };
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import jwt from 'jsonwebtoken';
|
|
2
|
-
|
|
3
|
-
const JWT_SECRET = process.env.JWT_SECRET || "change-me-in-production";
|
|
4
|
-
const GET = async ({ request }) => {
|
|
5
|
-
const authHeader = request.headers.get("authorization");
|
|
6
|
-
const token = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
|
|
7
|
-
if (!token) {
|
|
8
|
-
return new Response(JSON.stringify({ error: "Not authenticated" }), {
|
|
9
|
-
status: 401,
|
|
10
|
-
headers: { "Content-Type": "application/json" }
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
try {
|
|
14
|
-
const payload = jwt.verify(token, JWT_SECRET);
|
|
15
|
-
return new Response(
|
|
16
|
-
JSON.stringify({
|
|
17
|
-
user: {
|
|
18
|
-
id: payload.sub,
|
|
19
|
-
email: payload.email,
|
|
20
|
-
role: payload.role,
|
|
21
|
-
tenantId: payload.tenantId
|
|
22
|
-
}
|
|
23
|
-
}),
|
|
24
|
-
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
25
|
-
);
|
|
26
|
-
} catch {
|
|
27
|
-
return new Response(JSON.stringify({ error: "Invalid token" }), {
|
|
28
|
-
status: 401,
|
|
29
|
-
headers: { "Content-Type": "application/json" }
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
35
|
-
__proto__: null,
|
|
36
|
-
GET
|
|
37
|
-
}, Symbol.toStringTag, { value: 'Module' }));
|
|
38
|
-
|
|
39
|
-
const page = () => _page;
|
|
40
|
-
|
|
41
|
-
export { page };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { c as createComponent } from './astro-component_Dbx3T2Nh.mjs';
|
|
2
|
-
import 'piccolore';
|
|
3
|
-
import { Q as renderTemplate, a3 as addAttribute, B as maybeRenderHead } from './sequence_9cl7AJy-.mjs';
|
|
4
|
-
import { r as renderComponent } from './server_peBx9VXG.mjs';
|
|
5
|
-
import { $ as $$AdminLayout } from './AdminLayout_D-_JeUqC.mjs';
|
|
6
|
-
|
|
7
|
-
var __freeze = Object.freeze;
|
|
8
|
-
var __defProp = Object.defineProperty;
|
|
9
|
-
var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(raw || cooked.slice()) }));
|
|
10
|
-
var _a;
|
|
11
|
-
const $$New = createComponent(async ($$result, $$props, $$slots) => {
|
|
12
|
-
const roleOptions = ["super_admin", "admin", "editor", "author", "customer", "guest"];
|
|
13
|
-
return renderTemplate`${renderComponent($$result, "AdminLayout", $$AdminLayout, { "title": "New User" }, { "default": async ($$result2) => renderTemplate(_a || (_a = __template([" ", '<div class="flex-1 overflow-y-auto p-8 pr-12 space-y-8"> <!-- Header --> <div class="surface-tile p-6 flex items-center justify-between"> <div> <h1 class="text-3xl font-black tracking-tighter text-[#0b1222]">Create User</h1> <p class="text-sm text-[#64748b] mt-1 font-medium">Add a new user to the system</p> </div> <a href="/users" class="text-sm font-bold text-[#64748b] hover:text-[#0b1222] transition-colors">\n← Back to users\n</a> </div> <!-- Form --> <div class="surface-tile p-6"> <form id="create-user-form" class="space-y-6 max-w-2xl"> <div> <label for="email" class="block text-sm font-bold text-[#0b1222] mb-2">Email Address</label> <input type="email" id="email" name="email" required class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]" placeholder="user@example.com"> </div> <div> <label for="password" class="block text-sm font-bold text-[#0b1222] mb-2">Password</label> <input type="password" id="password" name="password" required minlength="12" class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]" placeholder="Minimum 12 characters"> <p class="text-xs text-[#64748b] mt-1">Must contain uppercase, lowercase, numbers, and special characters</p> </div> <div> <label for="role" class="block text-sm font-bold text-[#0b1222] mb-2">Role</label> <select id="role" name="role" class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]"> ', ` </select> </div> <div> <label for="tenantId" class="block text-sm font-bold text-[#0b1222] mb-2">Tenant ID (optional)</label> <input type="text" id="tenantId" name="tenantId" class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]" placeholder="Leave empty for global user"> </div> <div class="flex items-center justify-end gap-3 pt-4 border-t border-gray-100"> <a href="/users" class="px-6 py-3 border border-gray-200 rounded-xl text-sm font-bold text-[#64748b] hover:bg-gray-50 transition-colors">
|
|
14
|
-
Cancel
|
|
15
|
-
</a> <button type="submit" class="px-6 py-3 bg-[#0b1222] text-white rounded-xl text-sm font-bold hover:bg-[#1a2332] transition-colors">
|
|
16
|
-
Create User
|
|
17
|
-
</button> </div> </form> <div id="form-message" class="hidden mt-4 p-4 rounded-xl text-sm font-bold"></div> </div> </div> <script>
|
|
18
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
19
|
-
const form = document.getElementById('create-user-form');
|
|
20
|
-
const message = document.getElementById('form-message');
|
|
21
|
-
|
|
22
|
-
form?.addEventListener('submit', async (e) => {
|
|
23
|
-
e.preventDefault();
|
|
24
|
-
const formData = new FormData(form);
|
|
25
|
-
const body = Object.fromEntries(formData.entries());
|
|
26
|
-
|
|
27
|
-
const res = await fetch('/api/users', {
|
|
28
|
-
method: 'POST',
|
|
29
|
-
headers: { 'Content-Type': 'application/json' },
|
|
30
|
-
body: JSON.stringify(body),
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const data = await res.json();
|
|
34
|
-
|
|
35
|
-
if (res.ok) {
|
|
36
|
-
message.textContent = 'User created successfully!';
|
|
37
|
-
message.className = 'mt-4 p-4 rounded-xl text-sm font-bold bg-green-50 text-green-600';
|
|
38
|
-
setTimeout(() => { window.location.href = \`/users/\${data.data.id}\`; }, 1000);
|
|
39
|
-
} else {
|
|
40
|
-
message.textContent = data.error || 'Failed to create user';
|
|
41
|
-
message.className = 'mt-4 p-4 rounded-xl text-sm font-bold bg-red-50 text-red-600';
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
<\/script> `], [" ", '<div class="flex-1 overflow-y-auto p-8 pr-12 space-y-8"> <!-- Header --> <div class="surface-tile p-6 flex items-center justify-between"> <div> <h1 class="text-3xl font-black tracking-tighter text-[#0b1222]">Create User</h1> <p class="text-sm text-[#64748b] mt-1 font-medium">Add a new user to the system</p> </div> <a href="/users" class="text-sm font-bold text-[#64748b] hover:text-[#0b1222] transition-colors">\n← Back to users\n</a> </div> <!-- Form --> <div class="surface-tile p-6"> <form id="create-user-form" class="space-y-6 max-w-2xl"> <div> <label for="email" class="block text-sm font-bold text-[#0b1222] mb-2">Email Address</label> <input type="email" id="email" name="email" required class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]" placeholder="user@example.com"> </div> <div> <label for="password" class="block text-sm font-bold text-[#0b1222] mb-2">Password</label> <input type="password" id="password" name="password" required minlength="12" class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]" placeholder="Minimum 12 characters"> <p class="text-xs text-[#64748b] mt-1">Must contain uppercase, lowercase, numbers, and special characters</p> </div> <div> <label for="role" class="block text-sm font-bold text-[#0b1222] mb-2">Role</label> <select id="role" name="role" class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]"> ', ` </select> </div> <div> <label for="tenantId" class="block text-sm font-bold text-[#0b1222] mb-2">Tenant ID (optional)</label> <input type="text" id="tenantId" name="tenantId" class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#0b1222]/20 focus:border-[#0b1222]" placeholder="Leave empty for global user"> </div> <div class="flex items-center justify-end gap-3 pt-4 border-t border-gray-100"> <a href="/users" class="px-6 py-3 border border-gray-200 rounded-xl text-sm font-bold text-[#64748b] hover:bg-gray-50 transition-colors">
|
|
46
|
-
Cancel
|
|
47
|
-
</a> <button type="submit" class="px-6 py-3 bg-[#0b1222] text-white rounded-xl text-sm font-bold hover:bg-[#1a2332] transition-colors">
|
|
48
|
-
Create User
|
|
49
|
-
</button> </div> </form> <div id="form-message" class="hidden mt-4 p-4 rounded-xl text-sm font-bold"></div> </div> </div> <script>
|
|
50
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
51
|
-
const form = document.getElementById('create-user-form');
|
|
52
|
-
const message = document.getElementById('form-message');
|
|
53
|
-
|
|
54
|
-
form?.addEventListener('submit', async (e) => {
|
|
55
|
-
e.preventDefault();
|
|
56
|
-
const formData = new FormData(form);
|
|
57
|
-
const body = Object.fromEntries(formData.entries());
|
|
58
|
-
|
|
59
|
-
const res = await fetch('/api/users', {
|
|
60
|
-
method: 'POST',
|
|
61
|
-
headers: { 'Content-Type': 'application/json' },
|
|
62
|
-
body: JSON.stringify(body),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const data = await res.json();
|
|
66
|
-
|
|
67
|
-
if (res.ok) {
|
|
68
|
-
message.textContent = 'User created successfully!';
|
|
69
|
-
message.className = 'mt-4 p-4 rounded-xl text-sm font-bold bg-green-50 text-green-600';
|
|
70
|
-
setTimeout(() => { window.location.href = \\\`/users/\\\${data.data.id}\\\`; }, 1000);
|
|
71
|
-
} else {
|
|
72
|
-
message.textContent = data.error || 'Failed to create user';
|
|
73
|
-
message.className = 'mt-4 p-4 rounded-xl text-sm font-bold bg-red-50 text-red-600';
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
<\/script> `])), maybeRenderHead(), roleOptions.map((role) => renderTemplate`<option${addAttribute(role, "value")}>${role}</option>`)) })}`;
|
|
78
|
-
}, "/Users/macbook/Dev/Web/Astro/kyro-cms/admin/src/pages/users/new.astro", void 0);
|
|
79
|
-
|
|
80
|
-
const $$file = "/Users/macbook/Dev/Web/Astro/kyro-cms/admin/src/pages/users/new.astro";
|
|
81
|
-
const $$url = "/users/new";
|
|
82
|
-
|
|
83
|
-
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
84
|
-
__proto__: null,
|
|
85
|
-
default: $$New,
|
|
86
|
-
file: $$file,
|
|
87
|
-
url: $$url
|
|
88
|
-
}, Symbol.toStringTag, { value: 'Module' }));
|
|
89
|
-
|
|
90
|
-
const page = () => _page;
|
|
91
|
-
|
|
92
|
-
export { page };
|