@vilio/setup-module 0.0.3 → 0.0.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/dist/actions.d.ts +15 -1
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +141 -0
- package/dist/actions.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/routes.d.ts +1 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +9 -0
- package/dist/routes.js.map +1 -0
- package/dist/ui/pages/setup-wizard.d.ts +2 -2
- package/dist/ui/pages/setup-wizard.d.ts.map +1 -0
- package/dist/ui/pages/setup-wizard.js +52 -0
- package/dist/ui/pages/setup-wizard.js.map +1 -0
- package/package.json +14 -23
- package/dist/actions.cjs +0 -125
- package/dist/actions.mjs +0 -112
- package/dist/index.cjs +0 -38
- package/dist/index.mjs +0 -19
- package/dist/intl.d.ts +0 -13
- package/dist/routes.cjs +0 -12
- package/dist/routes.mjs +0 -8
- package/dist/ui/pages/setup-wizard.cjs +0 -166
- package/dist/ui/pages/setup-wizard.mjs +0 -108
package/dist/actions.d.ts
CHANGED
|
@@ -5,7 +5,20 @@ export declare function syncDatabase(): Promise<{
|
|
|
5
5
|
success: boolean;
|
|
6
6
|
error: any;
|
|
7
7
|
}>;
|
|
8
|
-
export declare function getAvailableModules(): Promise<
|
|
8
|
+
export declare function getAvailableModules(): Promise<{
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
installed: boolean;
|
|
11
|
+
lastStep: string | null | undefined;
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
dependencies: string[];
|
|
16
|
+
extends: string[];
|
|
17
|
+
system: boolean;
|
|
18
|
+
description?: string | undefined;
|
|
19
|
+
npmDependencies?: string[] | undefined;
|
|
20
|
+
npmDevDependencies?: string[] | undefined;
|
|
21
|
+
}[]>;
|
|
9
22
|
export declare function finishSetup(formData: FormData, selectedModuleIds: string[]): Promise<void>;
|
|
10
23
|
export declare function checkDbConnection(): Promise<{
|
|
11
24
|
success: boolean;
|
|
@@ -14,3 +27,4 @@ export declare function checkDbConnection(): Promise<{
|
|
|
14
27
|
success: boolean;
|
|
15
28
|
error: string;
|
|
16
29
|
}>;
|
|
30
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAqBA,wBAAsB,YAAY;;;;;;GAmCjC;AAED,wBAAsB,mBAAmB;;;;;;;;;;;;;KAGxC;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,EAAE,MAAM,EAAE,iBAoG5B;AAED,wBAAsB,iBAAiB;;;;;;GAOtC"}
|
package/dist/actions.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { exec } from "node:child_process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { createUser, db, permissionsTable, rolesTable, rolesToPermissionsTable, systemModulesTable, usersToRolesTable, userTable, } from "@vilio/core/server";
|
|
6
|
+
import { getModules, getVilioPathPrefix } from "@vilio/modules/server";
|
|
7
|
+
import { eq, sql } from "drizzle-orm";
|
|
8
|
+
import { redirect } from "next/navigation";
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
export async function syncDatabase() {
|
|
11
|
+
try {
|
|
12
|
+
// console.log("[Setup:Actions] Starting database synchronization...");
|
|
13
|
+
const root = process.cwd();
|
|
14
|
+
// Force non-interactive push.
|
|
15
|
+
// We use 'npx drizzle-kit push' to ensure it's available.
|
|
16
|
+
// We explicitly point to the config file in the app directory.
|
|
17
|
+
const configPath = path.join(root, "drizzle.config.ts");
|
|
18
|
+
console.log(`[Setup:Actions] Using config: ${configPath}`);
|
|
19
|
+
// Drizzle-kit push --force ensures it doesn't wait for user input
|
|
20
|
+
const { stdout, stderr } = await execAsync(`npx drizzle-kit push --config=${configPath}`, {
|
|
21
|
+
cwd: root,
|
|
22
|
+
env: {
|
|
23
|
+
...process.env,
|
|
24
|
+
// Ensure we are in non-interactive mode if the tool supports it
|
|
25
|
+
CI: "true",
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
console.log("[Setup:Actions] Sync stdout:", stdout);
|
|
29
|
+
if (stderr)
|
|
30
|
+
console.warn("[Setup:Actions] Sync stderr:", stderr);
|
|
31
|
+
return { success: true };
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
console.error("[Setup:Actions] Sync failed:", e);
|
|
35
|
+
// Even if it failed, sometimes it's because of minor warnings.
|
|
36
|
+
// But usually, it's a real error.
|
|
37
|
+
return { success: false, error: e.message };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function getAvailableModules() {
|
|
41
|
+
const modules = await getModules();
|
|
42
|
+
return modules.filter((m) => m.id !== "setup");
|
|
43
|
+
}
|
|
44
|
+
export async function finishSetup(formData, selectedModuleIds) {
|
|
45
|
+
const email = formData.get("email");
|
|
46
|
+
const username = formData.get("username");
|
|
47
|
+
const password = formData.get("password");
|
|
48
|
+
if (!email || !username || !password) {
|
|
49
|
+
throw new Error("Missing required fields");
|
|
50
|
+
}
|
|
51
|
+
// 1. Create the user
|
|
52
|
+
const user = await createUser(email, username, password);
|
|
53
|
+
// 2. Ensure 'admin' role exists and assign it
|
|
54
|
+
await db.transaction(async (tx) => {
|
|
55
|
+
// Must have email verified admin user
|
|
56
|
+
await tx
|
|
57
|
+
.update(userTable)
|
|
58
|
+
.set({
|
|
59
|
+
emailVerifiedAt: new Date(),
|
|
60
|
+
})
|
|
61
|
+
.where(eq(userTable.id, user.id));
|
|
62
|
+
let [adminRole] = await tx
|
|
63
|
+
.select()
|
|
64
|
+
.from(rolesTable)
|
|
65
|
+
.where(eq(rolesTable.name, "admin"));
|
|
66
|
+
if (!adminRole) {
|
|
67
|
+
const [newRole] = await tx
|
|
68
|
+
.insert(rolesTable)
|
|
69
|
+
.values({
|
|
70
|
+
name: "admin",
|
|
71
|
+
description: "System Administrator with full access",
|
|
72
|
+
})
|
|
73
|
+
.returning();
|
|
74
|
+
adminRole = newRole;
|
|
75
|
+
}
|
|
76
|
+
// Ensure system permissions exist
|
|
77
|
+
const systemPermissions = [
|
|
78
|
+
{ name: "system:modules", description: "Manage system modules" },
|
|
79
|
+
{ name: "system:rbac", description: "Manage roles and permissions" },
|
|
80
|
+
{
|
|
81
|
+
name: "system:activity-logs",
|
|
82
|
+
description: "View system activity logs",
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
console.log("Ensuring system permissions exist...");
|
|
86
|
+
for (const perm of systemPermissions) {
|
|
87
|
+
const [existing] = await tx
|
|
88
|
+
.select()
|
|
89
|
+
.from(permissionsTable)
|
|
90
|
+
.where(eq(permissionsTable.name, perm.name));
|
|
91
|
+
let permId = existing?.id;
|
|
92
|
+
if (!existing) {
|
|
93
|
+
const [inserted] = await tx
|
|
94
|
+
.insert(permissionsTable)
|
|
95
|
+
.values(perm)
|
|
96
|
+
.returning();
|
|
97
|
+
permId = inserted.id;
|
|
98
|
+
}
|
|
99
|
+
// Assign permission to admin role
|
|
100
|
+
await tx
|
|
101
|
+
.insert(rolesToPermissionsTable)
|
|
102
|
+
.values({
|
|
103
|
+
roleId: adminRole.id,
|
|
104
|
+
permissionId: permId,
|
|
105
|
+
})
|
|
106
|
+
.onConflictDoNothing();
|
|
107
|
+
}
|
|
108
|
+
await tx.insert(usersToRolesTable).values({
|
|
109
|
+
userId: user.id,
|
|
110
|
+
roleId: adminRole.id,
|
|
111
|
+
});
|
|
112
|
+
// 3. Enable selected modules
|
|
113
|
+
if (selectedModuleIds.length > 0) {
|
|
114
|
+
for (const modId of selectedModuleIds) {
|
|
115
|
+
await tx
|
|
116
|
+
.insert(systemModulesTable)
|
|
117
|
+
.values({
|
|
118
|
+
id: modId,
|
|
119
|
+
enabled: true,
|
|
120
|
+
system: true,
|
|
121
|
+
installed: true,
|
|
122
|
+
})
|
|
123
|
+
.onConflictDoUpdate({
|
|
124
|
+
target: systemModulesTable.id,
|
|
125
|
+
set: { enabled: true },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
redirect(await getVilioPathPrefix());
|
|
131
|
+
}
|
|
132
|
+
export async function checkDbConnection() {
|
|
133
|
+
try {
|
|
134
|
+
await db.execute(sql `SELECT 1`);
|
|
135
|
+
return { success: true };
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
return { success: false, error: String(e) };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAI9C,cAAc,WAAW,CAAC;AAK1B,QAAA,MAAM,WAAW,EAAE,OAclB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import manifest from "../manifest.json";
|
|
2
|
+
import { publicRoutes } from "./routes";
|
|
3
|
+
export * from "./actions";
|
|
4
|
+
import localesEn from "../locales/en/global.json" with { type: "json" };
|
|
5
|
+
import localesPl from "../locales/pl/global.json" with { type: "json" };
|
|
6
|
+
const setupModule = {
|
|
7
|
+
manifest: manifest,
|
|
8
|
+
translations: {
|
|
9
|
+
en: localesEn,
|
|
10
|
+
pl: localesPl,
|
|
11
|
+
},
|
|
12
|
+
init: async () => {
|
|
13
|
+
console.log("[SetupModule] initialized.");
|
|
14
|
+
},
|
|
15
|
+
routes: {
|
|
16
|
+
public: publicRoutes,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
export default setupModule;
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,cAAc,WAAW,CAAC;AAE1B,OAAO,SAAS,MAAM,2BAA2B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxE,OAAO,SAAS,MAAM,2BAA2B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAExE,MAAM,WAAW,GAAY;IAC3B,QAAQ,EAAE,QAAe;IAEzB,YAAY,EAAE;QACZ,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,SAAS;KACd;IACD,IAAI,EAAE,KAAK,IAAI,EAAE;QACf,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,EAAE;QACN,MAAM,EAAE,YAAY;KACrB;CACF,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
package/dist/routes.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG5D,eAAO,MAAM,YAAY,EAAE,qBAAqB,EAM/C,CAAC"}
|
package/dist/routes.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,YAAY,GAA4B;IACnD;QACE,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,WAAW;QACtB,IAAI,EAAE,KAAK;KACZ;CACF,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export declare function SetupWizard(): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
//# sourceMappingURL=setup-wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../../../src/ui/pages/setup-wizard.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,WAAW,4CAsO1B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** biome-ignore-all lint/a11y/noLabelWithoutControl: <all> */
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
4
|
+
import { useTranslation } from "@vilio/intl";
|
|
5
|
+
import { Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Input, } from "@vilio/ui";
|
|
6
|
+
import { Logo } from "@vilio/ui/brand/logo";
|
|
7
|
+
import { Loader } from "@vilio/ui/shared/loader";
|
|
8
|
+
import { CheckCircle2, Database, LayoutGrid, Rocket, UserPlus, } from "lucide-react";
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import { finishSetup, getAvailableModules, syncDatabase } from "../../actions";
|
|
11
|
+
export function SetupWizard() {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const [step, setStep] = React.useState(1);
|
|
14
|
+
const [loading, setLoading] = React.useState(false);
|
|
15
|
+
const [syncStatus, setSyncStatus] = React.useState("idle");
|
|
16
|
+
const [availableModules, setAvailableModules] = React.useState([]);
|
|
17
|
+
const [selectedModules, setSelectedModules] = React.useState([]);
|
|
18
|
+
const nextStep = () => setStep((s) => s + 1);
|
|
19
|
+
const handleSync = async () => {
|
|
20
|
+
setSyncStatus("syncing");
|
|
21
|
+
const result = await syncDatabase();
|
|
22
|
+
if (result.success) {
|
|
23
|
+
setSyncStatus("success");
|
|
24
|
+
// Fetch modules after successful sync
|
|
25
|
+
const modules = await getAvailableModules();
|
|
26
|
+
setAvailableModules(modules.filter((m) => !m.system));
|
|
27
|
+
// Pre-select system modules
|
|
28
|
+
setSelectedModules(modules.filter((m) => m.system).map((m) => m.id));
|
|
29
|
+
setTimeout(nextStep, 1500);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
setSyncStatus("error");
|
|
33
|
+
alert(`Database sync failed: ${result.error}`);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const toggleModule = (id) => {
|
|
37
|
+
setSelectedModules((prev) => prev.includes(id) ? prev.filter((m) => m !== id) : [...prev, id]);
|
|
38
|
+
};
|
|
39
|
+
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-muted/30 p-4", children: _jsxs("div", { className: "w-full max-w-md space-y-8", children: [_jsxs("div", { className: "flex flex-col gap-4 items-center justify-center text-center", children: [_jsx(Logo, { className: "mx-auto" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: t("setup_description") })] }), _jsxs(Card, { className: "border-2 shadow-xl", children: [step === 1 && (_jsxs(_Fragment, { children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { className: "flex items-center gap-2", children: [_jsx(Rocket, { className: "h-5 w-5 text-primary" }), t("welcome")] }), _jsx(CardDescription, { children: t("thank_you") })] }), _jsx(CardContent, { children: _jsx("div", { className: "space-y-4", children: _jsx("p", { className: "text-sm", children: t("step_1_desc") }) }) }), _jsx(CardFooter, { children: _jsx(Button, { onClick: nextStep, className: "w-full", children: t("get_started") }) })] })), step === 2 && (_jsxs(_Fragment, { children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { className: "flex items-center gap-2", children: [_jsx(Database, { className: "h-5 w-5 text-primary" }), t("db_prep")] }), _jsx(CardDescription, { children: t("db_desc") })] }), _jsxs(CardContent, { className: "flex flex-col items-center justify-center py-6", children: [syncStatus === "idle" && (_jsx(Database, { className: "h-12 w-12 text-muted-foreground mb-4" })), syncStatus === "syncing" && (_jsx(Loader, { className: "h-12 w-12 text-primary animate-spin mb-4" })), syncStatus === "success" && (_jsx(CheckCircle2, { className: "h-12 w-12 text-green-500 mb-4" })), _jsxs("p", { className: "text-center text-sm font-medium", children: [syncStatus === "idle" && t("db_ready_to_sync"), syncStatus === "syncing" && t("db_creating_tables"), syncStatus === "success" && t("db_ready"), syncStatus === "error" && t("db_sync_failed")] })] }), _jsx(CardFooter, { children: _jsx(Button, { onClick: handleSync, className: "w-full", disabled: syncStatus === "syncing" || syncStatus === "success", children: syncStatus === "syncing"
|
|
40
|
+
? t("db_syncing_btn")
|
|
41
|
+
: t("db_init_btn") }) })] })), step === 3 && (_jsxs(_Fragment, { children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { className: "flex items-center gap-2", children: [_jsx(LayoutGrid, { className: "h-5 w-5 text-primary" }), t("select_modules")] }), _jsx(CardDescription, { children: t("select_modules_desc") })] }), _jsx(CardContent, { className: "space-y-4 max-h-[300px] overflow-y-auto", children: availableModules.map((mod) => (_jsxs("label", { htmlFor: mod.id, className: "cursor-pointer flex items-start space-x-3 space-y-0 rounded-md border p-3", children: [_jsx(Checkbox, { id: mod.id, checked: selectedModules.includes(mod.id), onCheckedChange: () => toggleModule(mod.id), disabled: mod.system }), _jsxs("div", { className: "grid gap-1.5 leading-none", children: [_jsxs("div", { className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 flex items-center gap-2", children: [mod.name, mod.system && (_jsx(Badge, { variant: "outline", className: "text-[10px] h-4", children: "System" }))] }), _jsx("p", { className: "text-xs text-muted-foreground", children: mod.description || "No description available." })] })] }, mod.id))) }), _jsx(CardFooter, { children: _jsx(Button, { onClick: nextStep, className: "w-full", children: t("continue_to_admin") }) })] })), step === 4 && (_jsxs("form", { action: async (formData) => {
|
|
42
|
+
setLoading(true);
|
|
43
|
+
try {
|
|
44
|
+
await finishSetup(formData, selectedModules);
|
|
45
|
+
}
|
|
46
|
+
catch (_e) {
|
|
47
|
+
// alert(String(e));
|
|
48
|
+
setLoading(false);
|
|
49
|
+
}
|
|
50
|
+
}, children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { className: "flex items-center gap-2", children: [_jsx(UserPlus, { className: "h-5 w-5 text-primary" }), t("admin_account")] }), _jsx(CardDescription, { children: t("admin_description") })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-sm font-medium", children: t("username") }), _jsx(Input, { name: "username", placeholder: "admin", required: true })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-sm font-medium", children: t("email") }), _jsx(Input, { name: "email", type: "email", placeholder: "admin@vilio.io", required: true })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-sm font-medium", children: t("password") }), _jsx(Input, { name: "password", type: "password", required: true })] })] }), _jsx(CardFooter, { className: "mt-4", children: _jsx(Button, { type: "submit", className: "w-full", disabled: loading, children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader, { className: "mr-2 h-4 w-4 animate-spin" }), t("setting_up")] })) : (t("complete")) }) })] }))] }), _jsx("div", { className: "flex justify-center gap-2", children: [1, 2, 3, 4].map((s) => (_jsx("div", { className: `h-1.5 w-8 rounded-full transition-colors ${step >= s ? "bg-primary" : "bg-primary/10"}` }, s))) })] }) }));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=setup-wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-wizard.js","sourceRoot":"","sources":["../../../src/ui/pages/setup-wizard.tsx"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,YAAY,CAAC;;AAEb,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,KAAK,EACL,MAAM,EACN,IAAI,EACJ,WAAW,EACX,eAAe,EACf,UAAU,EACV,UAAU,EACV,SAAS,EACT,QAAQ,EACR,KAAK,GAEN,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,UAAU,EAEV,MAAM,EACN,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE/E,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,CAAC,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,QAAQ,CAEhD,MAAM,CAAC,CAAC;IACV,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAQ,EAAE,CAAC,CAAC;IAC1E,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAW,EAAE,CAAC,CAAC;IAE3E,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7C,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,aAAa,CAAC,SAAS,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QACpC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,aAAa,CAAC,SAAS,CAAC,CAAC;YACzB,sCAAsC;YACtC,MAAM,OAAO,GAAG,MAAM,mBAAmB,EAAE,CAAC;YAE5C,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YACtD,4BAA4B;YAC5B,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrE,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,OAAO,CAAC,CAAC;YACvB,KAAK,CAAC,yBAAyB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,EAAU,EAAE,EAAE;QAClC,kBAAkB,CAAC,CAAC,IAAI,EAAE,EAAE,CAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CACjE,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,cAAK,SAAS,EAAC,+DAA+D,YAC5E,eAAK,SAAS,EAAC,2BAA2B,aACxC,eAAK,SAAS,EAAC,6DAA6D,aAK1E,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,EAE5B,YAAG,SAAS,EAAC,oCAAoC,YAC9C,CAAC,CAAC,mBAAmB,CAAC,GACrB,IACA,EAEN,MAAC,IAAI,IAAC,SAAS,EAAC,oBAAoB,aACjC,IAAI,KAAK,CAAC,IAAI,CACb,8BACE,MAAC,UAAU,eACT,MAAC,SAAS,IAAC,SAAS,EAAC,yBAAyB,aAC5C,KAAC,MAAM,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAC1C,CAAC,CAAC,SAAS,CAAC,IACH,EACZ,KAAC,eAAe,cAAE,CAAC,CAAC,WAAW,CAAC,GAAmB,IACxC,EACb,KAAC,WAAW,cACV,cAAK,SAAS,EAAC,WAAW,YACxB,YAAG,SAAS,EAAC,SAAS,YAAE,CAAC,CAAC,aAAa,CAAC,GAAK,GACzC,GACM,EACd,KAAC,UAAU,cACT,KAAC,MAAM,IAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAC,QAAQ,YAC1C,CAAC,CAAC,aAAa,CAAC,GACV,GACE,IACZ,CACJ,EAEA,IAAI,KAAK,CAAC,IAAI,CACb,8BACE,MAAC,UAAU,eACT,MAAC,SAAS,IAAC,SAAS,EAAC,yBAAyB,aAC5C,KAAC,QAAQ,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAC5C,CAAC,CAAC,SAAS,CAAC,IACH,EACZ,KAAC,eAAe,cAAE,CAAC,CAAC,SAAS,CAAC,GAAmB,IACtC,EACb,MAAC,WAAW,IAAC,SAAS,EAAC,gDAAgD,aACpE,UAAU,KAAK,MAAM,IAAI,CACxB,KAAC,QAAQ,IAAC,SAAS,EAAC,sCAAsC,GAAG,CAC9D,EACA,UAAU,KAAK,SAAS,IAAI,CAC3B,KAAC,MAAM,IAAC,SAAS,EAAC,0CAA0C,GAAG,CAChE,EACA,UAAU,KAAK,SAAS,IAAI,CAC3B,KAAC,YAAY,IAAC,SAAS,EAAC,+BAA+B,GAAG,CAC3D,EACD,aAAG,SAAS,EAAC,iCAAiC,aAC3C,UAAU,KAAK,MAAM,IAAI,CAAC,CAAC,kBAAkB,CAAC,EAC9C,UAAU,KAAK,SAAS,IAAI,CAAC,CAAC,oBAAoB,CAAC,EACnD,UAAU,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,EACzC,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC,gBAAgB,CAAC,IAC5C,IACQ,EACd,KAAC,UAAU,cACT,KAAC,MAAM,IACL,OAAO,EAAE,UAAU,EACnB,SAAS,EAAC,QAAQ,EAClB,QAAQ,EACN,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,YAGrD,UAAU,KAAK,SAAS;4CACvB,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;4CACrB,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GACb,GACE,IACZ,CACJ,EAEA,IAAI,KAAK,CAAC,IAAI,CACb,8BACE,MAAC,UAAU,eACT,MAAC,SAAS,IAAC,SAAS,EAAC,yBAAyB,aAC5C,KAAC,UAAU,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAC9C,CAAC,CAAC,gBAAgB,CAAC,IACV,EACZ,KAAC,eAAe,cAAE,CAAC,CAAC,qBAAqB,CAAC,GAAmB,IAClD,EACb,KAAC,WAAW,IAAC,SAAS,EAAC,yCAAyC,YAC7D,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC7B,iBACE,OAAO,EAAE,GAAG,CAAC,EAAE,EAEf,SAAS,EAAC,2EAA2E,aAErF,KAAC,QAAQ,IACP,EAAE,EAAE,GAAG,CAAC,EAAE,EACV,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EACzC,eAAe,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,GACpB,EACF,eAAK,SAAS,EAAC,2BAA2B,aACxC,eAAK,SAAS,EAAC,oHAAoH,aAChI,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,IAAI,CACb,KAAC,KAAK,IAAC,OAAO,EAAC,SAAS,EAAC,SAAS,EAAC,iBAAiB,uBAE5C,CACT,IACG,EACN,YAAG,SAAS,EAAC,+BAA+B,YACzC,GAAG,CAAC,WAAW,IAAI,2BAA2B,GAC7C,IACA,KArBD,GAAG,CAAC,EAAE,CAsBL,CACT,CAAC,GACU,EACd,KAAC,UAAU,cACT,KAAC,MAAM,IAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAC,QAAQ,YAC1C,CAAC,CAAC,mBAAmB,CAAC,GAChB,GACE,IACZ,CACJ,EAEA,IAAI,KAAK,CAAC,IAAI,CACb,gBACE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gCACzB,UAAU,CAAC,IAAI,CAAC,CAAC;gCACjB,IAAI,CAAC;oCACH,MAAM,WAAW,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;gCAC/C,CAAC;gCAAC,OAAO,EAAE,EAAE,CAAC;oCACZ,oBAAoB;oCACpB,UAAU,CAAC,KAAK,CAAC,CAAC;gCACpB,CAAC;4BACH,CAAC,aAED,MAAC,UAAU,eACT,MAAC,SAAS,IAAC,SAAS,EAAC,yBAAyB,aAC5C,KAAC,QAAQ,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAC5C,CAAC,CAAC,eAAe,CAAC,IACT,EACZ,KAAC,eAAe,cAAE,CAAC,CAAC,mBAAmB,CAAC,GAAmB,IAChD,EACb,MAAC,WAAW,IAAC,SAAS,EAAC,WAAW,aAChC,eAAK,SAAS,EAAC,WAAW,aACxB,gBAAO,SAAS,EAAC,qBAAqB,YAAE,CAAC,CAAC,UAAU,CAAC,GAAS,EAC9D,KAAC,KAAK,IAAC,IAAI,EAAC,UAAU,EAAC,WAAW,EAAC,OAAO,EAAC,QAAQ,SAAG,IAClD,EACN,eAAK,SAAS,EAAC,WAAW,aACxB,gBAAO,SAAS,EAAC,qBAAqB,YAAE,CAAC,CAAC,OAAO,CAAC,GAAS,EAC3D,KAAC,KAAK,IACJ,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,OAAO,EACZ,WAAW,EAAC,gBAAgB,EAC5B,QAAQ,SACR,IACE,EACN,eAAK,SAAS,EAAC,WAAW,aACxB,gBAAO,SAAS,EAAC,qBAAqB,YAAE,CAAC,CAAC,UAAU,CAAC,GAAS,EAC9D,KAAC,KAAK,IAAC,IAAI,EAAC,UAAU,EAAC,IAAI,EAAC,UAAU,EAAC,QAAQ,SAAG,IAC9C,IACM,EACd,KAAC,UAAU,IAAC,SAAS,EAAC,MAAM,YAC1B,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,QAAQ,EAAC,QAAQ,EAAE,OAAO,YACvD,OAAO,CAAC,CAAC,CAAC,CACT,8BACE,KAAC,MAAM,IAAC,SAAS,EAAC,2BAA2B,GAAG,EAC/C,CAAC,CAAC,YAAY,CAAC,IACf,CACJ,CAAC,CAAC,CAAC,CACF,CAAC,CAAC,UAAU,CAAC,CACd,GACM,GACE,IACR,CACR,IACI,EAGP,cAAK,SAAS,EAAC,2BAA2B,YACvC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACvB,cAEE,SAAS,EAAE,4CACT,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAC7B,EAAE,IAHG,CAAC,CAIN,CACH,CAAC,GACE,IACF,GACF,CACP,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vilio/setup-module",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "0.0.4",
|
|
5
4
|
"description": "Installation and setup module for Vilio",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./package.json": "./package.json",
|
|
8
|
-
".":
|
|
9
|
-
"types": "./dist/index.d.ts",
|
|
10
|
-
"import": "./dist/index.mjs",
|
|
11
|
-
"require": "./dist/index.cjs"
|
|
12
|
-
}
|
|
8
|
+
".": "./dist/index.js"
|
|
13
9
|
},
|
|
14
10
|
"files": [
|
|
15
11
|
"dist",
|
|
@@ -19,33 +15,28 @@
|
|
|
19
15
|
"scripts": {
|
|
20
16
|
"release": "npm publish --access public --no-git-checks",
|
|
21
17
|
"clean": "rm -rf ./dist",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"build": "unbuild",
|
|
25
|
-
"dev": "unbuild --stub",
|
|
26
|
-
"lint": "biome check --write"
|
|
18
|
+
"dev": "tsc --watch",
|
|
19
|
+
"build": "tsc"
|
|
27
20
|
},
|
|
28
21
|
"dependencies": {
|
|
29
|
-
"@vilio/modules": "^0.0.
|
|
30
|
-
"@vilio/ui": "^0.0.
|
|
22
|
+
"@vilio/modules": "^0.0.6",
|
|
23
|
+
"@vilio/ui": "^0.0.6",
|
|
31
24
|
"drizzle-orm": "1.0.0-beta.6-4414a19",
|
|
32
25
|
"lucide-react": "^0.475.0"
|
|
33
26
|
},
|
|
34
27
|
"devDependencies": {
|
|
35
|
-
"@vilio/core": "^0.0.
|
|
28
|
+
"@vilio/core": "^0.0.9",
|
|
36
29
|
"@types/node": "^20.19.9",
|
|
37
30
|
"@types/react": "^19",
|
|
38
31
|
"@types/react-dom": "^19",
|
|
39
|
-
"next": "16.1.
|
|
40
|
-
"typescript": "
|
|
41
|
-
"unbuild": "^3.6.1"
|
|
32
|
+
"next": "16.1.6",
|
|
33
|
+
"typescript": "5.9.2"
|
|
42
34
|
},
|
|
43
35
|
"peerDependencies": {
|
|
44
|
-
"@vilio/core": "^0.0.
|
|
45
|
-
"@vilio/intl": "^0.0.
|
|
46
|
-
"next": "
|
|
36
|
+
"@vilio/core": "^0.0.9",
|
|
37
|
+
"@vilio/intl": "^0.0.7",
|
|
38
|
+
"next": "16.1.6",
|
|
47
39
|
"react": "^19.0.0",
|
|
48
40
|
"react-dom": "^19.0.0"
|
|
49
|
-
}
|
|
50
|
-
"main": "./dist/index.mjs"
|
|
41
|
+
}
|
|
51
42
|
}
|
package/dist/actions.cjs
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
"use server";
|
|
3
|
-
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.checkDbConnection = checkDbConnection;
|
|
8
|
-
exports.finishSetup = finishSetup;
|
|
9
|
-
exports.getAvailableModules = getAvailableModules;
|
|
10
|
-
exports.syncDatabase = syncDatabase;
|
|
11
|
-
var _nodeChild_process = require("node:child_process");
|
|
12
|
-
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
13
|
-
var _nodeUtil = require("node:util");
|
|
14
|
-
var _server = require("@vilio/core/server");
|
|
15
|
-
var _server2 = require("@vilio/modules/server");
|
|
16
|
-
var _drizzleOrm = require("drizzle-orm");
|
|
17
|
-
var _navigation = require("next/navigation");
|
|
18
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
-
const execAsync = (0, _nodeUtil.promisify)(_nodeChild_process.exec);
|
|
20
|
-
async function syncDatabase() {
|
|
21
|
-
try {
|
|
22
|
-
const root = process.cwd();
|
|
23
|
-
const configPath = _nodePath.default.join(root, "drizzle.config.ts");
|
|
24
|
-
console.log(`[Setup:Actions] Using config: ${configPath}`);
|
|
25
|
-
const {
|
|
26
|
-
stdout,
|
|
27
|
-
stderr
|
|
28
|
-
} = await execAsync(`npx drizzle-kit push --config=${configPath}`, {
|
|
29
|
-
cwd: root,
|
|
30
|
-
env: {
|
|
31
|
-
...process.env,
|
|
32
|
-
// Ensure we are in non-interactive mode if the tool supports it
|
|
33
|
-
CI: "true"
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
console.log("[Setup:Actions] Sync stdout:", stdout);
|
|
37
|
-
if (stderr) console.warn("[Setup:Actions] Sync stderr:", stderr);
|
|
38
|
-
return {
|
|
39
|
-
success: true
|
|
40
|
-
};
|
|
41
|
-
} catch (e) {
|
|
42
|
-
console.error("[Setup:Actions] Sync failed:", e);
|
|
43
|
-
return {
|
|
44
|
-
success: false,
|
|
45
|
-
error: e.message
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async function getAvailableModules() {
|
|
50
|
-
const modules = await (0, _server2.getModules)();
|
|
51
|
-
return modules.filter(m => m.id !== "setup");
|
|
52
|
-
}
|
|
53
|
-
async function finishSetup(formData, selectedModuleIds) {
|
|
54
|
-
const email = formData.get("email");
|
|
55
|
-
const username = formData.get("username");
|
|
56
|
-
const password = formData.get("password");
|
|
57
|
-
if (!email || !username || !password) {
|
|
58
|
-
throw new Error("Missing required fields");
|
|
59
|
-
}
|
|
60
|
-
const user = await (0, _server.createUser)(email, username, password);
|
|
61
|
-
await _server.db.transaction(async tx => {
|
|
62
|
-
await tx.update(_server.userTable).set({
|
|
63
|
-
emailVerifiedAt: /* @__PURE__ */new Date()
|
|
64
|
-
}).where((0, _drizzleOrm.eq)(_server.userTable.id, user.id));
|
|
65
|
-
let [adminRole] = await tx.select().from(_server.rolesTable).where((0, _drizzleOrm.eq)(_server.rolesTable.name, "admin"));
|
|
66
|
-
if (!adminRole) {
|
|
67
|
-
const [newRole] = await tx.insert(_server.rolesTable).values({
|
|
68
|
-
name: "admin",
|
|
69
|
-
description: "System Administrator with full access"
|
|
70
|
-
}).returning();
|
|
71
|
-
adminRole = newRole;
|
|
72
|
-
}
|
|
73
|
-
const systemPermissions = [{
|
|
74
|
-
name: "system:modules",
|
|
75
|
-
description: "Manage system modules"
|
|
76
|
-
}, {
|
|
77
|
-
name: "system:rbac",
|
|
78
|
-
description: "Manage roles and permissions"
|
|
79
|
-
}, {
|
|
80
|
-
name: "system:activity-logs",
|
|
81
|
-
description: "View system activity logs"
|
|
82
|
-
}];
|
|
83
|
-
console.log("Ensuring system permissions exist...");
|
|
84
|
-
for (const perm of systemPermissions) {
|
|
85
|
-
const [existing] = await tx.select().from(_server.permissionsTable).where((0, _drizzleOrm.eq)(_server.permissionsTable.name, perm.name));
|
|
86
|
-
let permId = existing?.id;
|
|
87
|
-
if (!existing) {
|
|
88
|
-
const [inserted] = await tx.insert(_server.permissionsTable).values(perm).returning();
|
|
89
|
-
permId = inserted.id;
|
|
90
|
-
}
|
|
91
|
-
await tx.insert(_server.rolesToPermissionsTable).values({
|
|
92
|
-
roleId: adminRole.id,
|
|
93
|
-
permissionId: permId
|
|
94
|
-
}).onConflictDoNothing();
|
|
95
|
-
}
|
|
96
|
-
await tx.insert(_server.usersToRolesTable).values({
|
|
97
|
-
userId: user.id,
|
|
98
|
-
roleId: adminRole.id
|
|
99
|
-
});
|
|
100
|
-
if (selectedModuleIds.length > 0) {
|
|
101
|
-
for (const modId of selectedModuleIds) {
|
|
102
|
-
await tx.insert(_server.systemModulesTable).values({
|
|
103
|
-
id: modId,
|
|
104
|
-
enabled: true,
|
|
105
|
-
system: true,
|
|
106
|
-
installed: true
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
(0, _navigation.redirect)(await (0, _server2.getVilioPathPrefix)());
|
|
112
|
-
}
|
|
113
|
-
async function checkDbConnection() {
|
|
114
|
-
try {
|
|
115
|
-
await _server.db.execute((0, _drizzleOrm.sql)`SELECT 1`);
|
|
116
|
-
return {
|
|
117
|
-
success: true
|
|
118
|
-
};
|
|
119
|
-
} catch (e) {
|
|
120
|
-
return {
|
|
121
|
-
success: false,
|
|
122
|
-
error: String(e)
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
}
|
package/dist/actions.mjs
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
"use server";
|
|
2
|
-
import { exec } from "node:child_process";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { promisify } from "node:util";
|
|
5
|
-
import {
|
|
6
|
-
createUser,
|
|
7
|
-
db,
|
|
8
|
-
permissionsTable,
|
|
9
|
-
rolesTable,
|
|
10
|
-
rolesToPermissionsTable,
|
|
11
|
-
systemModulesTable,
|
|
12
|
-
usersToRolesTable,
|
|
13
|
-
userTable
|
|
14
|
-
} from "@vilio/core/server";
|
|
15
|
-
import { getModules, getVilioPathPrefix } from "@vilio/modules/server";
|
|
16
|
-
import { eq, sql } from "drizzle-orm";
|
|
17
|
-
import { redirect } from "next/navigation";
|
|
18
|
-
const execAsync = promisify(exec);
|
|
19
|
-
export async function syncDatabase() {
|
|
20
|
-
try {
|
|
21
|
-
const root = process.cwd();
|
|
22
|
-
const configPath = path.join(root, "drizzle.config.ts");
|
|
23
|
-
console.log(`[Setup:Actions] Using config: ${configPath}`);
|
|
24
|
-
const { stdout, stderr } = await execAsync(
|
|
25
|
-
`npx drizzle-kit push --config=${configPath}`,
|
|
26
|
-
{
|
|
27
|
-
cwd: root,
|
|
28
|
-
env: {
|
|
29
|
-
...process.env,
|
|
30
|
-
// Ensure we are in non-interactive mode if the tool supports it
|
|
31
|
-
CI: "true"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
);
|
|
35
|
-
console.log("[Setup:Actions] Sync stdout:", stdout);
|
|
36
|
-
if (stderr) console.warn("[Setup:Actions] Sync stderr:", stderr);
|
|
37
|
-
return { success: true };
|
|
38
|
-
} catch (e) {
|
|
39
|
-
console.error("[Setup:Actions] Sync failed:", e);
|
|
40
|
-
return { success: false, error: e.message };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export async function getAvailableModules() {
|
|
44
|
-
const modules = await getModules();
|
|
45
|
-
return modules.filter((m) => m.id !== "setup");
|
|
46
|
-
}
|
|
47
|
-
export async function finishSetup(formData, selectedModuleIds) {
|
|
48
|
-
const email = formData.get("email");
|
|
49
|
-
const username = formData.get("username");
|
|
50
|
-
const password = formData.get("password");
|
|
51
|
-
if (!email || !username || !password) {
|
|
52
|
-
throw new Error("Missing required fields");
|
|
53
|
-
}
|
|
54
|
-
const user = await createUser(email, username, password);
|
|
55
|
-
await db.transaction(async (tx) => {
|
|
56
|
-
await tx.update(userTable).set({
|
|
57
|
-
emailVerifiedAt: /* @__PURE__ */ new Date()
|
|
58
|
-
}).where(eq(userTable.id, user.id));
|
|
59
|
-
let [adminRole] = await tx.select().from(rolesTable).where(eq(rolesTable.name, "admin"));
|
|
60
|
-
if (!adminRole) {
|
|
61
|
-
const [newRole] = await tx.insert(rolesTable).values({
|
|
62
|
-
name: "admin",
|
|
63
|
-
description: "System Administrator with full access"
|
|
64
|
-
}).returning();
|
|
65
|
-
adminRole = newRole;
|
|
66
|
-
}
|
|
67
|
-
const systemPermissions = [
|
|
68
|
-
{ name: "system:modules", description: "Manage system modules" },
|
|
69
|
-
{ name: "system:rbac", description: "Manage roles and permissions" },
|
|
70
|
-
{
|
|
71
|
-
name: "system:activity-logs",
|
|
72
|
-
description: "View system activity logs"
|
|
73
|
-
}
|
|
74
|
-
];
|
|
75
|
-
console.log("Ensuring system permissions exist...");
|
|
76
|
-
for (const perm of systemPermissions) {
|
|
77
|
-
const [existing] = await tx.select().from(permissionsTable).where(eq(permissionsTable.name, perm.name));
|
|
78
|
-
let permId = existing?.id;
|
|
79
|
-
if (!existing) {
|
|
80
|
-
const [inserted] = await tx.insert(permissionsTable).values(perm).returning();
|
|
81
|
-
permId = inserted.id;
|
|
82
|
-
}
|
|
83
|
-
await tx.insert(rolesToPermissionsTable).values({
|
|
84
|
-
roleId: adminRole.id,
|
|
85
|
-
permissionId: permId
|
|
86
|
-
}).onConflictDoNothing();
|
|
87
|
-
}
|
|
88
|
-
await tx.insert(usersToRolesTable).values({
|
|
89
|
-
userId: user.id,
|
|
90
|
-
roleId: adminRole.id
|
|
91
|
-
});
|
|
92
|
-
if (selectedModuleIds.length > 0) {
|
|
93
|
-
for (const modId of selectedModuleIds) {
|
|
94
|
-
await tx.insert(systemModulesTable).values({
|
|
95
|
-
id: modId,
|
|
96
|
-
enabled: true,
|
|
97
|
-
system: true,
|
|
98
|
-
installed: true
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
redirect(await getVilioPathPrefix());
|
|
104
|
-
}
|
|
105
|
-
export async function checkDbConnection() {
|
|
106
|
-
try {
|
|
107
|
-
await db.execute(sql`SELECT 1`);
|
|
108
|
-
return { success: true };
|
|
109
|
-
} catch (e) {
|
|
110
|
-
return { success: false, error: String(e) };
|
|
111
|
-
}
|
|
112
|
-
}
|
package/dist/index.cjs
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var _exportNames = {};
|
|
7
|
-
|
|
8
|
-
var _manifest = _interopRequireDefault(require("../manifest.json"));
|
|
9
|
-
var _routes = require("./routes.cjs");
|
|
10
|
-
var _actions = require("./actions.cjs");
|
|
11
|
-
Object.keys(_actions).forEach(function (key) {
|
|
12
|
-
if (key === "default" || key === "__esModule") return;
|
|
13
|
-
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
14
|
-
if (key in exports && exports[key] === _actions[key]) return;
|
|
15
|
-
Object.defineProperty(exports, key, {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () {
|
|
18
|
-
return _actions[key];
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
var _global = _interopRequireDefault(require("../locales/en/global.json"));
|
|
23
|
-
var _global2 = _interopRequireDefault(require("../locales/pl/global.json"));
|
|
24
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
25
|
-
const setupModule = {
|
|
26
|
-
manifest: _manifest.default,
|
|
27
|
-
translations: {
|
|
28
|
-
en: _global.default,
|
|
29
|
-
pl: _global2.default
|
|
30
|
-
},
|
|
31
|
-
init: async () => {
|
|
32
|
-
console.log("[SetupModule] initialized.");
|
|
33
|
-
},
|
|
34
|
-
routes: {
|
|
35
|
-
public: _routes.publicRoutes
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
module.exports = setupModule;
|
package/dist/index.mjs
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import manifest from "../manifest.json";
|
|
2
|
-
import { publicRoutes } from "./routes.mjs";
|
|
3
|
-
export * from "./actions.mjs";
|
|
4
|
-
import localesEn from "../locales/en/global.json" with { type: "json" };
|
|
5
|
-
import localesPl from "../locales/pl/global.json" with { type: "json" };
|
|
6
|
-
const setupModule = {
|
|
7
|
-
manifest,
|
|
8
|
-
translations: {
|
|
9
|
-
en: localesEn,
|
|
10
|
-
pl: localesPl
|
|
11
|
-
},
|
|
12
|
-
init: async () => {
|
|
13
|
-
console.log("[SetupModule] initialized.");
|
|
14
|
-
},
|
|
15
|
-
routes: {
|
|
16
|
-
public: publicRoutes
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
export default setupModule;
|
package/dist/intl.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type messages from "../locales/en/global.json";
|
|
2
|
-
|
|
3
|
-
type JsonDataType = typeof messages;
|
|
4
|
-
|
|
5
|
-
// declare global {
|
|
6
|
-
// interface IntlMessages extends JsonDataType {}
|
|
7
|
-
// }
|
|
8
|
-
|
|
9
|
-
declare module "@vilio/intl" {
|
|
10
|
-
export interface IntlMessages extends JsonDataType { }
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export { };
|
package/dist/routes.cjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.publicRoutes = void 0;
|
|
7
|
-
var _setupWizard = require("./ui/pages/setup-wizard.cjs");
|
|
8
|
-
const publicRoutes = exports.publicRoutes = [{
|
|
9
|
-
path: "/setup",
|
|
10
|
-
component: _setupWizard.SetupWizard,
|
|
11
|
-
auth: false
|
|
12
|
-
}];
|
package/dist/routes.mjs
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
"use client";
|
|
3
|
-
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.SetupWizard = SetupWizard;
|
|
8
|
-
var _intl = require("@vilio/intl");
|
|
9
|
-
var _ui = require("@vilio/ui");
|
|
10
|
-
var _logo = require("@vilio/ui/brand/logo");
|
|
11
|
-
var _loader = require("@vilio/ui/shared/loader");
|
|
12
|
-
var _lucideReact = require("lucide-react");
|
|
13
|
-
var React = _interopRequireWildcard(require("react"));
|
|
14
|
-
var _actions = require("../../actions.cjs");
|
|
15
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
16
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
17
|
-
function SetupWizard() {
|
|
18
|
-
const {
|
|
19
|
-
t
|
|
20
|
-
} = (0, _intl.useTranslation)();
|
|
21
|
-
const [step, setStep] = React.useState(1);
|
|
22
|
-
const [loading, setLoading] = React.useState(false);
|
|
23
|
-
const [syncStatus, setSyncStatus] = React.useState("idle");
|
|
24
|
-
const [availableModules, setAvailableModules] = React.useState([]);
|
|
25
|
-
const [selectedModules, setSelectedModules] = React.useState([]);
|
|
26
|
-
const nextStep = () => setStep(s => s + 1);
|
|
27
|
-
const handleSync = async () => {
|
|
28
|
-
setSyncStatus("syncing");
|
|
29
|
-
const result = await (0, _actions.syncDatabase)();
|
|
30
|
-
if (result.success) {
|
|
31
|
-
setSyncStatus("success");
|
|
32
|
-
const modules = await (0, _actions.getAvailableModules)();
|
|
33
|
-
setAvailableModules(modules.filter(m => !m.system));
|
|
34
|
-
setSelectedModules(modules.filter(m => m.system).map(m => m.id));
|
|
35
|
-
setTimeout(nextStep, 1500);
|
|
36
|
-
} else {
|
|
37
|
-
setSyncStatus("error");
|
|
38
|
-
alert(`Database sync failed: ${result.error}`);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
const toggleModule = id => {
|
|
42
|
-
setSelectedModules(prev => prev.includes(id) ? prev.filter(m => m !== id) : [...prev, id]);
|
|
43
|
-
};
|
|
44
|
-
return /* @__PURE__ */React.createElement("div", {
|
|
45
|
-
className: "min-h-screen flex items-center justify-center bg-muted/30 p-4"
|
|
46
|
-
}, /* @__PURE__ */React.createElement("div", {
|
|
47
|
-
className: "w-full max-w-md space-y-8"
|
|
48
|
-
}, /* @__PURE__ */React.createElement("div", {
|
|
49
|
-
className: "flex flex-col gap-4 items-center justify-center text-center"
|
|
50
|
-
}, /* @__PURE__ */React.createElement(_logo.Logo, {
|
|
51
|
-
className: "mx-auto"
|
|
52
|
-
}), /* @__PURE__ */React.createElement("p", {
|
|
53
|
-
className: "mt-2 text-sm text-muted-foreground"
|
|
54
|
-
}, t("setup_description"))), /* @__PURE__ */React.createElement(_ui.Card, {
|
|
55
|
-
className: "border-2 shadow-xl"
|
|
56
|
-
}, step === 1 && /* @__PURE__ */React.createElement(React.Fragment, null, /* @__PURE__ */React.createElement(_ui.CardHeader, null, /* @__PURE__ */React.createElement(_ui.CardTitle, {
|
|
57
|
-
className: "flex items-center gap-2"
|
|
58
|
-
}, /* @__PURE__ */React.createElement(_lucideReact.Rocket, {
|
|
59
|
-
className: "h-5 w-5 text-primary"
|
|
60
|
-
}), t("welcome")), /* @__PURE__ */React.createElement(_ui.CardDescription, null, t("thank_you"))), /* @__PURE__ */React.createElement(_ui.CardContent, null, /* @__PURE__ */React.createElement("div", {
|
|
61
|
-
className: "space-y-4"
|
|
62
|
-
}, /* @__PURE__ */React.createElement("p", {
|
|
63
|
-
className: "text-sm"
|
|
64
|
-
}, t("step_1_desc")))), /* @__PURE__ */React.createElement(_ui.CardFooter, null, /* @__PURE__ */React.createElement(_ui.Button, {
|
|
65
|
-
onClick: nextStep,
|
|
66
|
-
className: "w-full"
|
|
67
|
-
}, t("get_started")))), step === 2 && /* @__PURE__ */React.createElement(React.Fragment, null, /* @__PURE__ */React.createElement(_ui.CardHeader, null, /* @__PURE__ */React.createElement(_ui.CardTitle, {
|
|
68
|
-
className: "flex items-center gap-2"
|
|
69
|
-
}, /* @__PURE__ */React.createElement(_lucideReact.Database, {
|
|
70
|
-
className: "h-5 w-5 text-primary"
|
|
71
|
-
}), t("db_prep")), /* @__PURE__ */React.createElement(_ui.CardDescription, null, t("db_desc"))), /* @__PURE__ */React.createElement(_ui.CardContent, {
|
|
72
|
-
className: "flex flex-col items-center justify-center py-6"
|
|
73
|
-
}, syncStatus === "idle" && /* @__PURE__ */React.createElement(_lucideReact.Database, {
|
|
74
|
-
className: "h-12 w-12 text-muted-foreground mb-4"
|
|
75
|
-
}), syncStatus === "syncing" && /* @__PURE__ */React.createElement(_loader.Loader, {
|
|
76
|
-
className: "h-12 w-12 text-primary animate-spin mb-4"
|
|
77
|
-
}), syncStatus === "success" && /* @__PURE__ */React.createElement(_lucideReact.CheckCircle2, {
|
|
78
|
-
className: "h-12 w-12 text-green-500 mb-4"
|
|
79
|
-
}), /* @__PURE__ */React.createElement("p", {
|
|
80
|
-
className: "text-center text-sm font-medium"
|
|
81
|
-
}, syncStatus === "idle" && t("db_ready_to_sync"), syncStatus === "syncing" && t("db_creating_tables"), syncStatus === "success" && t("db_ready"), syncStatus === "error" && t("db_sync_failed"))), /* @__PURE__ */React.createElement(_ui.CardFooter, null, /* @__PURE__ */React.createElement(_ui.Button, {
|
|
82
|
-
onClick: handleSync,
|
|
83
|
-
className: "w-full",
|
|
84
|
-
disabled: syncStatus === "syncing" || syncStatus === "success"
|
|
85
|
-
}, syncStatus === "syncing" ? t("db_syncing_btn") : t("db_init_btn")))), step === 3 && /* @__PURE__ */React.createElement(React.Fragment, null, /* @__PURE__ */React.createElement(_ui.CardHeader, null, /* @__PURE__ */React.createElement(_ui.CardTitle, {
|
|
86
|
-
className: "flex items-center gap-2"
|
|
87
|
-
}, /* @__PURE__ */React.createElement(_lucideReact.LayoutGrid, {
|
|
88
|
-
className: "h-5 w-5 text-primary"
|
|
89
|
-
}), t("select_modules")), /* @__PURE__ */React.createElement(_ui.CardDescription, null, t("select_modules_desc"))), /* @__PURE__ */React.createElement(_ui.CardContent, {
|
|
90
|
-
className: "space-y-4 max-h-[300px] overflow-y-auto"
|
|
91
|
-
}, availableModules.map(mod => /* @__PURE__ */React.createElement("label", {
|
|
92
|
-
htmlFor: mod.id,
|
|
93
|
-
key: mod.id,
|
|
94
|
-
className: "cursor-pointer flex items-start space-x-3 space-y-0 rounded-md border p-3"
|
|
95
|
-
}, /* @__PURE__ */React.createElement(_ui.Checkbox, {
|
|
96
|
-
id: mod.id,
|
|
97
|
-
checked: selectedModules.includes(mod.id),
|
|
98
|
-
onCheckedChange: () => toggleModule(mod.id),
|
|
99
|
-
disabled: mod.system
|
|
100
|
-
}), /* @__PURE__ */React.createElement("div", {
|
|
101
|
-
className: "grid gap-1.5 leading-none"
|
|
102
|
-
}, /* @__PURE__ */React.createElement("div", {
|
|
103
|
-
className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 flex items-center gap-2"
|
|
104
|
-
}, mod.name, mod.system && /* @__PURE__ */React.createElement(_ui.Badge, {
|
|
105
|
-
variant: "outline",
|
|
106
|
-
className: "text-[10px] h-4"
|
|
107
|
-
}, "System")), /* @__PURE__ */React.createElement("p", {
|
|
108
|
-
className: "text-xs text-muted-foreground"
|
|
109
|
-
}, mod.description || "No description available."))))), /* @__PURE__ */React.createElement(_ui.CardFooter, null, /* @__PURE__ */React.createElement(_ui.Button, {
|
|
110
|
-
onClick: nextStep,
|
|
111
|
-
className: "w-full"
|
|
112
|
-
}, t("continue_to_admin")))), step === 4 && /* @__PURE__ */React.createElement("form", {
|
|
113
|
-
action: async formData => {
|
|
114
|
-
setLoading(true);
|
|
115
|
-
try {
|
|
116
|
-
await (0, _actions.finishSetup)(formData, selectedModules);
|
|
117
|
-
} catch (_e) {
|
|
118
|
-
setLoading(false);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}, /* @__PURE__ */React.createElement(_ui.CardHeader, null, /* @__PURE__ */React.createElement(_ui.CardTitle, {
|
|
122
|
-
className: "flex items-center gap-2"
|
|
123
|
-
}, /* @__PURE__ */React.createElement(_lucideReact.UserPlus, {
|
|
124
|
-
className: "h-5 w-5 text-primary"
|
|
125
|
-
}), t("admin_account")), /* @__PURE__ */React.createElement(_ui.CardDescription, null, t("admin_description"))), /* @__PURE__ */React.createElement(_ui.CardContent, {
|
|
126
|
-
className: "space-y-4"
|
|
127
|
-
}, /* @__PURE__ */React.createElement("div", {
|
|
128
|
-
className: "space-y-2"
|
|
129
|
-
}, /* @__PURE__ */React.createElement("label", {
|
|
130
|
-
className: "text-sm font-medium"
|
|
131
|
-
}, t("username")), /* @__PURE__ */React.createElement(_ui.Input, {
|
|
132
|
-
name: "username",
|
|
133
|
-
placeholder: "admin",
|
|
134
|
-
required: true
|
|
135
|
-
})), /* @__PURE__ */React.createElement("div", {
|
|
136
|
-
className: "space-y-2"
|
|
137
|
-
}, /* @__PURE__ */React.createElement("label", {
|
|
138
|
-
className: "text-sm font-medium"
|
|
139
|
-
}, t("email")), /* @__PURE__ */React.createElement(_ui.Input, {
|
|
140
|
-
name: "email",
|
|
141
|
-
type: "email",
|
|
142
|
-
placeholder: "admin@vilio.io",
|
|
143
|
-
required: true
|
|
144
|
-
})), /* @__PURE__ */React.createElement("div", {
|
|
145
|
-
className: "space-y-2"
|
|
146
|
-
}, /* @__PURE__ */React.createElement("label", {
|
|
147
|
-
className: "text-sm font-medium"
|
|
148
|
-
}, t("password")), /* @__PURE__ */React.createElement(_ui.Input, {
|
|
149
|
-
name: "password",
|
|
150
|
-
type: "password",
|
|
151
|
-
required: true
|
|
152
|
-
}))), /* @__PURE__ */React.createElement(_ui.CardFooter, {
|
|
153
|
-
className: "mt-4"
|
|
154
|
-
}, /* @__PURE__ */React.createElement(_ui.Button, {
|
|
155
|
-
type: "submit",
|
|
156
|
-
className: "w-full",
|
|
157
|
-
disabled: loading
|
|
158
|
-
}, loading ? /* @__PURE__ */React.createElement(React.Fragment, null, /* @__PURE__ */React.createElement(_loader.Loader, {
|
|
159
|
-
className: "mr-2 h-4 w-4 animate-spin"
|
|
160
|
-
}), t("setting_up")) : t("complete"))))), /* @__PURE__ */React.createElement("div", {
|
|
161
|
-
className: "flex justify-center gap-2"
|
|
162
|
-
}, [1, 2, 3, 4].map(s => /* @__PURE__ */React.createElement("div", {
|
|
163
|
-
key: s,
|
|
164
|
-
className: `h-1.5 w-8 rounded-full transition-colors ${step >= s ? "bg-primary" : "bg-primary/10"}`
|
|
165
|
-
})))));
|
|
166
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useTranslation } from "@vilio/intl";
|
|
3
|
-
import {
|
|
4
|
-
Badge,
|
|
5
|
-
Button,
|
|
6
|
-
Card,
|
|
7
|
-
CardContent,
|
|
8
|
-
CardDescription,
|
|
9
|
-
CardFooter,
|
|
10
|
-
CardHeader,
|
|
11
|
-
CardTitle,
|
|
12
|
-
Checkbox,
|
|
13
|
-
Input
|
|
14
|
-
} from "@vilio/ui";
|
|
15
|
-
import { Logo } from "@vilio/ui/brand/logo";
|
|
16
|
-
import { Loader } from "@vilio/ui/shared/loader";
|
|
17
|
-
import {
|
|
18
|
-
CheckCircle2,
|
|
19
|
-
Database,
|
|
20
|
-
LayoutGrid,
|
|
21
|
-
Rocket,
|
|
22
|
-
UserPlus
|
|
23
|
-
} from "lucide-react";
|
|
24
|
-
import * as React from "react";
|
|
25
|
-
import { finishSetup, getAvailableModules, syncDatabase } from "../../actions.mjs";
|
|
26
|
-
export function SetupWizard() {
|
|
27
|
-
const { t } = useTranslation();
|
|
28
|
-
const [step, setStep] = React.useState(1);
|
|
29
|
-
const [loading, setLoading] = React.useState(false);
|
|
30
|
-
const [syncStatus, setSyncStatus] = React.useState("idle");
|
|
31
|
-
const [availableModules, setAvailableModules] = React.useState([]);
|
|
32
|
-
const [selectedModules, setSelectedModules] = React.useState([]);
|
|
33
|
-
const nextStep = () => setStep((s) => s + 1);
|
|
34
|
-
const handleSync = async () => {
|
|
35
|
-
setSyncStatus("syncing");
|
|
36
|
-
const result = await syncDatabase();
|
|
37
|
-
if (result.success) {
|
|
38
|
-
setSyncStatus("success");
|
|
39
|
-
const modules = await getAvailableModules();
|
|
40
|
-
setAvailableModules(modules.filter((m) => !m.system));
|
|
41
|
-
setSelectedModules(modules.filter((m) => m.system).map((m) => m.id));
|
|
42
|
-
setTimeout(nextStep, 1500);
|
|
43
|
-
} else {
|
|
44
|
-
setSyncStatus("error");
|
|
45
|
-
alert(`Database sync failed: ${result.error}`);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
const toggleModule = (id) => {
|
|
49
|
-
setSelectedModules(
|
|
50
|
-
(prev) => prev.includes(id) ? prev.filter((m) => m !== id) : [...prev, id]
|
|
51
|
-
);
|
|
52
|
-
};
|
|
53
|
-
return /* @__PURE__ */ React.createElement("div", { className: "min-h-screen flex items-center justify-center bg-muted/30 p-4" }, /* @__PURE__ */ React.createElement("div", { className: "w-full max-w-md space-y-8" }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-4 items-center justify-center text-center" }, /* @__PURE__ */ React.createElement(Logo, { className: "mx-auto" }), /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-sm text-muted-foreground" }, t("setup_description"))), /* @__PURE__ */ React.createElement(Card, { className: "border-2 shadow-xl" }, step === 1 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CardHeader, null, /* @__PURE__ */ React.createElement(CardTitle, { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(Rocket, { className: "h-5 w-5 text-primary" }), t("welcome")), /* @__PURE__ */ React.createElement(CardDescription, null, t("thank_you"))), /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React.createElement("p", { className: "text-sm" }, t("step_1_desc")))), /* @__PURE__ */ React.createElement(CardFooter, null, /* @__PURE__ */ React.createElement(Button, { onClick: nextStep, className: "w-full" }, t("get_started")))), step === 2 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CardHeader, null, /* @__PURE__ */ React.createElement(CardTitle, { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(Database, { className: "h-5 w-5 text-primary" }), t("db_prep")), /* @__PURE__ */ React.createElement(CardDescription, null, t("db_desc"))), /* @__PURE__ */ React.createElement(CardContent, { className: "flex flex-col items-center justify-center py-6" }, syncStatus === "idle" && /* @__PURE__ */ React.createElement(Database, { className: "h-12 w-12 text-muted-foreground mb-4" }), syncStatus === "syncing" && /* @__PURE__ */ React.createElement(Loader, { className: "h-12 w-12 text-primary animate-spin mb-4" }), syncStatus === "success" && /* @__PURE__ */ React.createElement(CheckCircle2, { className: "h-12 w-12 text-green-500 mb-4" }), /* @__PURE__ */ React.createElement("p", { className: "text-center text-sm font-medium" }, syncStatus === "idle" && t("db_ready_to_sync"), syncStatus === "syncing" && t("db_creating_tables"), syncStatus === "success" && t("db_ready"), syncStatus === "error" && t("db_sync_failed"))), /* @__PURE__ */ React.createElement(CardFooter, null, /* @__PURE__ */ React.createElement(
|
|
54
|
-
Button,
|
|
55
|
-
{
|
|
56
|
-
onClick: handleSync,
|
|
57
|
-
className: "w-full",
|
|
58
|
-
disabled: syncStatus === "syncing" || syncStatus === "success"
|
|
59
|
-
},
|
|
60
|
-
syncStatus === "syncing" ? t("db_syncing_btn") : t("db_init_btn")
|
|
61
|
-
))), step === 3 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CardHeader, null, /* @__PURE__ */ React.createElement(CardTitle, { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(LayoutGrid, { className: "h-5 w-5 text-primary" }), t("select_modules")), /* @__PURE__ */ React.createElement(CardDescription, null, t("select_modules_desc"))), /* @__PURE__ */ React.createElement(CardContent, { className: "space-y-4 max-h-[300px] overflow-y-auto" }, availableModules.map((mod) => /* @__PURE__ */ React.createElement(
|
|
62
|
-
"label",
|
|
63
|
-
{
|
|
64
|
-
htmlFor: mod.id,
|
|
65
|
-
key: mod.id,
|
|
66
|
-
className: "cursor-pointer flex items-start space-x-3 space-y-0 rounded-md border p-3"
|
|
67
|
-
},
|
|
68
|
-
/* @__PURE__ */ React.createElement(
|
|
69
|
-
Checkbox,
|
|
70
|
-
{
|
|
71
|
-
id: mod.id,
|
|
72
|
-
checked: selectedModules.includes(mod.id),
|
|
73
|
-
onCheckedChange: () => toggleModule(mod.id),
|
|
74
|
-
disabled: mod.system
|
|
75
|
-
}
|
|
76
|
-
),
|
|
77
|
-
/* @__PURE__ */ React.createElement("div", { className: "grid gap-1.5 leading-none" }, /* @__PURE__ */ React.createElement("div", { className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 flex items-center gap-2" }, mod.name, mod.system && /* @__PURE__ */ React.createElement(Badge, { variant: "outline", className: "text-[10px] h-4" }, "System")), /* @__PURE__ */ React.createElement("p", { className: "text-xs text-muted-foreground" }, mod.description || "No description available."))
|
|
78
|
-
))), /* @__PURE__ */ React.createElement(CardFooter, null, /* @__PURE__ */ React.createElement(Button, { onClick: nextStep, className: "w-full" }, t("continue_to_admin")))), step === 4 && /* @__PURE__ */ React.createElement(
|
|
79
|
-
"form",
|
|
80
|
-
{
|
|
81
|
-
action: async (formData) => {
|
|
82
|
-
setLoading(true);
|
|
83
|
-
try {
|
|
84
|
-
await finishSetup(formData, selectedModules);
|
|
85
|
-
} catch (_e) {
|
|
86
|
-
setLoading(false);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
/* @__PURE__ */ React.createElement(CardHeader, null, /* @__PURE__ */ React.createElement(CardTitle, { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(UserPlus, { className: "h-5 w-5 text-primary" }), t("admin_account")), /* @__PURE__ */ React.createElement(CardDescription, null, t("admin_description"))),
|
|
91
|
-
/* @__PURE__ */ React.createElement(CardContent, { className: "space-y-4" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement("label", { className: "text-sm font-medium" }, t("username")), /* @__PURE__ */ React.createElement(Input, { name: "username", placeholder: "admin", required: true })), /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement("label", { className: "text-sm font-medium" }, t("email")), /* @__PURE__ */ React.createElement(
|
|
92
|
-
Input,
|
|
93
|
-
{
|
|
94
|
-
name: "email",
|
|
95
|
-
type: "email",
|
|
96
|
-
placeholder: "admin@vilio.io",
|
|
97
|
-
required: true
|
|
98
|
-
}
|
|
99
|
-
)), /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement("label", { className: "text-sm font-medium" }, t("password")), /* @__PURE__ */ React.createElement(Input, { name: "password", type: "password", required: true }))),
|
|
100
|
-
/* @__PURE__ */ React.createElement(CardFooter, { className: "mt-4" }, /* @__PURE__ */ React.createElement(Button, { type: "submit", className: "w-full", disabled: loading }, loading ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Loader, { className: "mr-2 h-4 w-4 animate-spin" }), t("setting_up")) : t("complete")))
|
|
101
|
-
)), /* @__PURE__ */ React.createElement("div", { className: "flex justify-center gap-2" }, [1, 2, 3, 4].map((s) => /* @__PURE__ */ React.createElement(
|
|
102
|
-
"div",
|
|
103
|
-
{
|
|
104
|
-
key: s,
|
|
105
|
-
className: `h-1.5 w-8 rounded-full transition-colors ${step >= s ? "bg-primary" : "bg-primary/10"}`
|
|
106
|
-
}
|
|
107
|
-
)))));
|
|
108
|
-
}
|