@arch-cadre/sample-module 1.0.7 → 1.0.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arch-cadre/sample-module",
3
- "version": "1.0.7",
3
+ "version": "1.0.10",
4
4
  "description": "Sample module for Kryo framework",
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "files": [
15
15
  "dist",
16
+ "src",
16
17
  "locales",
17
18
  "manifest.json"
18
19
  ],
@@ -26,8 +27,8 @@
26
27
  },
27
28
  "dependencies": {
28
29
  "@hookform/resolvers": "^3.10.0",
29
- "@arch-cadre/ui": "^0.0.47",
30
- "@arch-cadre/modules": "^0.0.73",
30
+ "@arch-cadre/ui": "^0.0.54",
31
+ "@arch-cadre/modules": "^0.0.80",
31
32
  "lucide-react": "^0.475.0",
32
33
  "react-hook-form": "^7.54.2",
33
34
  "drizzle-orm": "1.0.0-beta.6-4414a19",
@@ -35,7 +36,7 @@
35
36
  "zod": "^3.24.1"
36
37
  },
37
38
  "devDependencies": {
38
- "@arch-cadre/core": "^0.0.47",
39
+ "@arch-cadre/core": "^0.0.54",
39
40
  "@types/react": "^19",
40
41
  "next": "16.1.1",
41
42
  "react": "^19.0.0",
@@ -43,9 +44,9 @@
43
44
  "unbuild": "^3.6.1"
44
45
  },
45
46
  "peerDependencies": {
46
- "@arch-cadre/core": "^0.0.47",
47
- "@arch-cadre/intl": "^0.0.47",
48
- "@arch-cadre/ui": "^0.0.47",
47
+ "@arch-cadre/core": "^0.0.54",
48
+ "@arch-cadre/intl": "^0.0.54",
49
+ "@arch-cadre/ui": "^0.0.54",
49
50
  "next": ">=13.0.0",
50
51
  "react": "^19.0.0"
51
52
  },
@@ -0,0 +1,44 @@
1
+ "use server";
2
+
3
+ import { eventBus } from "@arch-cadre/core";
4
+ import { getCurrentSession } from "@arch-cadre/core/server";
5
+ import {
6
+ getKryoPathPrefix,
7
+ getModuleConfig,
8
+ updateModuleConfig,
9
+ } from "@arch-cadre/modules/server";
10
+ import { revalidatePath } from "next/cache";
11
+
12
+ export interface SampleConfig {
13
+ defaultVar: string;
14
+ }
15
+
16
+ export async function getSampleConfig() {
17
+ const config = await getModuleConfig<SampleConfig>("sample-module");
18
+
19
+ return (
20
+ config ?? {
21
+ defaultVar: "",
22
+ }
23
+ );
24
+ }
25
+
26
+ export async function updateSampleConfig(config: SampleConfig) {
27
+ await updateModuleConfig("sample-module", config);
28
+ revalidatePath(`${getKryoPathPrefix()}/sample-module/settings`);
29
+
30
+ const { user } = await getCurrentSession();
31
+
32
+ await eventBus.publish(
33
+ "activity.create",
34
+ {
35
+ action: "sample-module.config.updated",
36
+ description: `User updated sample module config`,
37
+ userId: user?.id,
38
+ metadata: config,
39
+ },
40
+ "sample-module",
41
+ );
42
+
43
+ return { success: true };
44
+ }
package/src/index.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { db } from "@arch-cadre/core/server";
2
+ import { i18n } from "@arch-cadre/intl";
3
+ import type { IModule } from "@arch-cadre/modules";
4
+ import { sql } from "drizzle-orm";
5
+ import manifest from "../manifest.json";
6
+ import { apiRoutes, privateRoutes } from "./routes";
7
+
8
+ const module: IModule = {
9
+ manifest,
10
+
11
+ onEnable: async () => { },
12
+
13
+ onDisable: async () => {
14
+ console.log("[Module:Sample] onDisable: Dropping all tables physically...");
15
+ try {
16
+ const tables = ["sample"];
17
+ for (const table of tables) {
18
+ await db.execute(sql.raw(`DROP TABLE IF EXISTS ${table} CASCADE`));
19
+ }
20
+ } catch (e) {
21
+ console.error("[Module:Sample] onDisable Error:", e);
22
+ }
23
+ },
24
+
25
+ routes: {
26
+ private: privateRoutes,
27
+ api: apiRoutes,
28
+ },
29
+
30
+ navigation: {
31
+ admin: {
32
+ [i18n("General")]: [
33
+ {
34
+ id: "sample-settings",
35
+ title: i18n("Sample Configuration"),
36
+ url: "/sample/settings",
37
+ icon: "solar:box-bold-duotone",
38
+ },
39
+ ],
40
+ },
41
+ },
42
+ };
43
+
44
+ export default module;
package/src/intl.d.ts ADDED
@@ -0,0 +1,13 @@
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 "@arch-cadre/intl" {
10
+ export interface IntlMessages extends JsonDataType {}
11
+ }
12
+
13
+ export {};
package/src/routes.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type {
2
+ ApiRouteDefinition,
3
+ PrivateRouteDefinition,
4
+ } from "@arch-cadre/modules";
5
+
6
+ import SampleSettingsPage from "./ui/settings-page";
7
+
8
+ export const privateRoutes: PrivateRouteDefinition[] = [
9
+ {
10
+ path: "/sample/settings", // Będzie widoczne pod /sample/settings
11
+ component: SampleSettingsPage,
12
+ auth: true,
13
+ },
14
+ ];
15
+
16
+ export const apiRoutes: ApiRouteDefinition[] = [];
package/src/schema.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { userTable } from "@arch-cadre/core";
2
+ import { defineRelations } from "drizzle-orm";
3
+ import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
4
+
5
+ export const sampleTable = pgTable("sample", {
6
+ id: text("id")
7
+ .primaryKey()
8
+ .$defaultFn(() => crypto.randomUUID()),
9
+
10
+ userId: text("user_id")
11
+ .references(() => userTable.id, { onDelete: "cascade" })
12
+ .notNull(),
13
+ createdAt: timestamp("created_at").defaultNow().notNull(),
14
+ });
15
+
16
+ export const sampleSchema = {
17
+ sampleTable,
18
+ };
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ import { useTranslation } from "@arch-cadre/intl";
3
+ import { Button } from "@arch-cadre/ui/components/button";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@arch-cadre/ui/components/card";
11
+ import { Input } from "@arch-cadre/ui/components/input";
12
+ import { Label } from "@arch-cadre/ui/components/label";
13
+ import * as React from "react";
14
+ import { useEffect, useState } from "react";
15
+ import { toast } from "sonner";
16
+ import {
17
+ getSampleConfig,
18
+ type SampleConfig,
19
+ updateSampleConfig,
20
+ } from "../actions/settings";
21
+
22
+ export default function SampleSettingsPage() {
23
+ const { t } = useTranslation();
24
+
25
+ const [config, setConfig] = useState<SampleConfig>({
26
+ defaultVar: "",
27
+ });
28
+ const [loading, setLoading] = useState(true);
29
+
30
+ useEffect(() => {
31
+ getSampleConfig().then((data) => {
32
+ setConfig(data);
33
+ setLoading(false);
34
+ });
35
+ }, []);
36
+
37
+ const handleSave = async (e: React.FormEvent) => {
38
+ e.preventDefault();
39
+ try {
40
+ await updateSampleConfig(config);
41
+ toast.success(t("Settings saved successfully"));
42
+ } catch {
43
+ toast.error(t("Failed to save settings"));
44
+ }
45
+ };
46
+
47
+ if (loading) return <div>{t("Loading Sample Settings...")}</div>;
48
+
49
+ return (
50
+ <div className="container mx-auto py-10 max-w-2xl">
51
+ <Card>
52
+ <CardHeader>
53
+ <CardTitle>{t("Sample Settings")}</CardTitle>
54
+ <CardDescription>
55
+ {t("Configure your Sample Configuration.")}
56
+ </CardDescription>
57
+ </CardHeader>
58
+ <CardContent>
59
+ <form onSubmit={handleSave} className="space-y-4">
60
+ <div className="space-y-2">
61
+ <Label htmlFor="defaultVar">{t("Default Var")}</Label>
62
+ <Input
63
+ id="defaultVar"
64
+ value={config.defaultVar}
65
+ onChange={(e) =>
66
+ setConfig({ ...config, defaultVar: e.target.value })
67
+ }
68
+ placeholder=""
69
+ />
70
+ </div>
71
+
72
+ <Button type="submit" className="w-full">
73
+ {t("Save Configuration")}
74
+ </Button>
75
+ </form>
76
+ </CardContent>
77
+ </Card>
78
+ </div>
79
+ );
80
+ }