create-cundi-app 1.0.1 → 1.0.6

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
@@ -1,8 +1,10 @@
1
1
  # create-cundi-app
2
2
 
3
- Create a new Cundi app with React + Refine + Ant Design.
3
+ Create a new Cundi web application with React + Refine + Ant Design.
4
4
 
5
- ## Usage
5
+ [![npm version](https://img.shields.io/npm/v/create-cundi-app.svg)](https://www.npmjs.com/package/create-cundi-app)
6
+
7
+ ## Quick Start
6
8
 
7
9
  ```bash
8
10
  # Using npm
@@ -22,48 +24,55 @@ pnpm create cundi-app my-app
22
24
 
23
25
  The generated project includes:
24
26
 
25
- - **Framework**: React 19 + TypeScript
26
- - **Build Tool**: Vite
27
- - **UI Library**: Ant Design
28
- - **Metasystem**: [Refine](https://refine.dev/)
29
- - **Core SDK**: `@cundi/refine-xaf`
27
+ | Category | Technology |
28
+ |----------|------------|
29
+ | Framework | React 19 + TypeScript |
30
+ | Build Tool | Vite |
31
+ | UI Library | Ant Design |
32
+ | Metasystem | [Refine](https://refine.dev/) |
33
+ | Core SDK | [@cundi/refine-xaf](https://www.npmjs.com/package/@cundi/refine-xaf) |
30
34
 
31
35
  ### Features
32
36
 
33
- - 🔐 Authentication (Local + Keycloak SSO)
34
- - 👤 User Management
35
- - 🛡️ Role-based Access Control
36
- - 🌍 Internationalization (i18n)
37
- - 🌙 Dark Mode Support
38
- - 📊 Dashboard Template
37
+ - 🔐 **Dual Authentication**: Local login + Keycloak SSO
38
+ - 👤 **User Management**: Pre-built user CRUD pages
39
+ - 🛡️ **RBAC**: Role-based Access Control
40
+ - 🌍 **i18n**: English and Traditional Chinese
41
+ - 🌙 **Dark Mode**: Theme toggle support
42
+ - 📊 **Dashboard**: Starter template
39
43
 
40
44
  ## After Creating
41
45
 
42
- 1. Navigate to your project:
43
- ```bash
44
- cd my-app
45
- ```
46
+ ```bash
47
+ cd my-app
48
+ npm install
49
+ cp .env.example .env # Configure your API URL
50
+ npm run dev
51
+ ```
46
52
 
47
- 2. Install dependencies:
48
- ```bash
49
- npm install
50
- ```
53
+ ### Environment Variables
51
54
 
52
- 3. Configure environment:
53
- ```bash
54
- cp .env.example .env
55
- # Edit .env with your API URL and Keycloak settings
56
- ```
55
+ Edit `.env` to configure:
57
56
 
58
- 4. Start development server:
59
- ```bash
60
- npm run dev
61
- ```
57
+ ```env
58
+ VITE_API_URL=http://localhost:5000/api
59
+
60
+ # Keycloak (Optional)
61
+ VITE_KEYCLOAK_URL=http://localhost:8080
62
+ VITE_KEYCLOAK_REALM=your-realm
63
+ VITE_KEYCLOAK_CLIENT_ID=your-client-id
64
+ VITE_REDIRECT_URI=http://localhost:5173/auth/callback
65
+ ```
62
66
 
63
67
  ## Documentation
64
68
 
65
- - [Refine Documentation](https://refine.dev/docs/)
69
+ - [Cundi Development Guide](https://github.com/antonylu0826/Cundi/blob/main/Development_Guide.md)
66
70
  - [@cundi/refine-xaf SDK](https://www.npmjs.com/package/@cundi/refine-xaf)
71
+ - [Refine Documentation](https://refine.dev/docs/)
72
+
73
+ ## Related
74
+
75
+ - [cundiapi](https://www.nuget.org/packages/Cundi.Api.Template) - Backend template for .NET
67
76
 
68
77
  ## License
69
78
 
package/index.js CHANGED
@@ -114,13 +114,19 @@ VITE_REDIRECT_URI=http://localhost:5173/auth/callback
114
114
  await fs.rename(gitignoreSrc, gitignoreDest);
115
115
  }
116
116
 
117
+ // Create .env from .env.example
118
+ const envPath = path.join(targetDir, ".env");
119
+ if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) {
120
+ await fs.copy(envExamplePath, envPath);
121
+ }
122
+
117
123
  console.log(kleur.green("✔ Project created successfully!"));
118
124
  console.log();
119
125
  console.log(kleur.cyan("Next steps:"));
120
126
  console.log();
121
127
  console.log(` ${kleur.gray("$")} cd ${projectName}`);
122
128
  console.log(` ${kleur.gray("$")} npm install`);
123
- console.log(` ${kleur.gray("$")} cp .env.example .env ${kleur.gray("# Configure your environment")}`);
129
+ // console.log(` ${kleur.gray("$")} cp .env.example .env ${kleur.gray("# Configure your environment")}`);
124
130
  console.log(` ${kleur.gray("$")} npm run dev`);
125
131
  console.log();
126
132
  console.log(kleur.gray("────────────────────────────────────"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-cundi-app",
3
- "version": "1.0.1",
3
+ "version": "1.0.6",
4
4
  "description": "Create a new Cundi app with React + Refine + Ant Design",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,6 +10,9 @@
10
10
  "index.js",
11
11
  "template"
12
12
  ],
13
+ "scripts": {
14
+ "pack": "npm pack --pack-destination ../../output/npm"
15
+ },
13
16
  "keywords": [
14
17
  "create",
15
18
  "cundi",
@@ -24,19 +24,23 @@
24
24
  "dependencies": {
25
25
  "@ant-design/icons": "^5.5.1",
26
26
  "@ant-design/v5-patch-for-react-19": "^1.0.3",
27
- "@cundi/refine-xaf": "^1.0.4",
27
+ "@cundi/refine-xaf": "^1.0.7",
28
28
  "@refinedev/antd": "^6.0.3",
29
29
  "@refinedev/cli": "^2.16.50",
30
30
  "@refinedev/core": "^5.0.6",
31
- "@refinedev/react-router": "^2.0.3",
31
+ "@refinedev/inferencer": "^5.0.3",
32
+ "@refinedev/react-router": "^6.0.3",
32
33
  "@refinedev/simple-rest": "^6.0.1",
33
34
  "antd": "^5.23.0",
34
35
  "i18next": "^25.7.3",
35
- "i18next-browser-languagedetector": "^8.2.0",
36
- "react": "^19.1.0",
37
- "react-dom": "^19.1.0",
38
- "react-i18next": "^16.5.0",
39
- "react-router": "^7.0.2"
36
+ "i18next-browser-languagedetector": "^7.1.0",
37
+ "i18next-http-backend": "^2.1.1",
38
+ "react": "^19.0.0",
39
+ "react-dom": "^19.0.0",
40
+ "react-i18next": "^12.3.1",
41
+ "react-live": "^4.1.7",
42
+ "react-router": "^7.1.3",
43
+ "react-router-dom": "^7.1.3"
40
44
  },
41
45
  "devDependencies": {
42
46
  "@types/node": "^20",
@@ -6,14 +6,17 @@ import {
6
6
  useNotificationProvider,
7
7
  ThemedLayout,
8
8
  ErrorComponent,
9
- RefineThemes,
10
9
  } from "@refinedev/antd";
11
10
  import {
12
11
  DashboardOutlined,
13
12
  UserOutlined,
14
13
  SettingOutlined,
15
14
  TeamOutlined,
15
+ FieldTimeOutlined,
16
+ ThunderboltOutlined,
17
+ CopyOutlined,
16
18
  } from "@ant-design/icons";
19
+ import { AntdInferencer } from "@refinedev/inferencer/antd";
17
20
 
18
21
  import routerProvider, {
19
22
  NavigateToResource,
@@ -22,7 +25,7 @@ import routerProvider, {
22
25
  DocumentTitleHandler,
23
26
  } from "@refinedev/react-router";
24
27
  import { BrowserRouter, Routes, Route, Outlet } from "react-router";
25
- import { App as AntdApp, ConfigProvider, theme } from "antd";
28
+ import { App as AntdApp } from "antd";
26
29
  import { useTranslation } from "react-i18next";
27
30
  import "./i18n";
28
31
 
@@ -43,15 +46,16 @@ import {
43
46
  RoleList,
44
47
  RoleCreate,
45
48
  RoleEdit,
49
+ ColorModeContextProvider,
50
+ BackgroundJobList,
51
+ SmartList,
46
52
  } from "@cundi/refine-xaf";
47
53
 
48
- import { ColorModeContextProvider, useColorMode } from "./contexts/color-mode";
49
54
  import { accessControlProvider } from "./accessControlProvider";
50
55
 
51
56
  const API_URL = import.meta.env.VITE_API_URL + "/odata";
52
57
 
53
58
  const InnerApp: React.FC = () => {
54
- const { mode } = useColorMode();
55
59
  const { t, i18n } = useTranslation();
56
60
 
57
61
  const i18nProvider = {
@@ -62,121 +66,170 @@ const InnerApp: React.FC = () => {
62
66
 
63
67
  return (
64
68
  <BrowserRouter>
65
- <ConfigProvider
66
- theme={{
67
- ...RefineThemes.Blue,
68
- algorithm: mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
69
- }}
70
- >
71
- <AntdApp>
72
- <Refine
73
- authProvider={authProvider}
74
- accessControlProvider={accessControlProvider}
75
- dataProvider={dataProvider(API_URL)}
76
- i18nProvider={i18nProvider}
77
- routerProvider={routerProvider}
78
- resources={[
79
- {
80
- name: "dashboard",
81
- list: "/",
82
- meta: {
83
- label: t("sider.dashboard"),
84
- icon: <DashboardOutlined />,
85
- },
69
+ <AntdApp>
70
+ <Refine
71
+ authProvider={authProvider}
72
+ accessControlProvider={accessControlProvider}
73
+ dataProvider={dataProvider(API_URL)}
74
+ i18nProvider={i18nProvider}
75
+ routerProvider={routerProvider}
76
+ resources={[
77
+ {
78
+ name: "dashboard",
79
+ list: "/",
80
+ meta: {
81
+ label: t("sider.dashboard"),
82
+ icon: <DashboardOutlined />,
86
83
  },
87
- {
88
- name: "ApplicationUser",
89
- list: "/ApplicationUsers",
90
- create: "/ApplicationUsers/create",
91
- edit: "/ApplicationUsers/edit/:id",
92
- meta: {
93
- label: t("sider.users"),
94
- icon: <UserOutlined />,
95
- parent: t("sider.settings"),
96
- },
84
+ },
85
+ {
86
+ name: "ApplicationUser",
87
+ list: "/ApplicationUsers",
88
+ create: "/ApplicationUsers/create",
89
+ edit: "/ApplicationUsers/edit/:id",
90
+ meta: {
91
+ label: t("sider.users"),
92
+ icon: <UserOutlined />,
93
+ parent: t("sider.settings"),
97
94
  },
98
- {
99
- name: "PermissionPolicyRole",
100
- list: "/PermissionPolicyRoles",
101
- create: "/PermissionPolicyRoles/create",
102
- edit: "/PermissionPolicyRoles/edit/:id",
103
- meta: {
104
- label: t("sider.roles"),
105
- parent: t("sider.settings"),
106
- icon: <TeamOutlined />,
107
- },
95
+ },
96
+ {
97
+ name: "PermissionPolicyRole",
98
+ list: "/PermissionPolicyRoles",
99
+ create: "/PermissionPolicyRoles/create",
100
+ edit: "/PermissionPolicyRoles/edit/:id",
101
+ meta: {
102
+ label: t("sider.roles"),
103
+ parent: t("sider.settings"),
104
+ icon: <TeamOutlined />,
108
105
  },
109
- {
110
- name: "Settings",
111
- meta: {
112
- label: t("sider.settings"),
113
- icon: <SettingOutlined />,
114
- },
106
+ },
107
+ {
108
+ name: "BackgroundJobs",
109
+ list: "/background-jobs",
110
+ meta: {
111
+ label: t("sider.backgroundJobs"),
112
+ icon: <FieldTimeOutlined />,
113
+ parent: t("sider.settings"),
115
114
  },
116
- ]}
117
- notificationProvider={useNotificationProvider}
118
- options={{
119
- syncWithLocation: true,
120
- warnWhenUnsavedChanges: true,
121
- }}
122
- >
123
- <Routes>
124
- <Route
125
- element={
126
- <Authenticated
127
- key="authenticated-routes"
128
- fallback={<CatchAllNavigate to="/login" />}
129
- >
130
- <ThemedLayout Header={Header}>
131
- <Outlet />
132
- </ThemedLayout>
133
- </Authenticated>
134
- }
135
- >
136
- <Route index element={<DashboardPage />} />
137
-
138
- <Route path="/ApplicationUsers">
139
- <Route index element={<ApplicationUserList />} />
140
- <Route path="create" element={<ApplicationUserCreate />} />
141
- <Route path="edit/:id" element={<ApplicationUserEdit />} />
142
- </Route>
143
-
144
- <Route path="/PermissionPolicyRoles">
145
- <Route index element={<RoleList />} />
146
- <Route path="create" element={<RoleCreate />} />
147
- <Route path="edit/:id" element={<RoleEdit />} />
148
- </Route>
115
+ },
116
+ {
117
+ name: "TriggerRule",
118
+ list: "/TriggerRules",
119
+ create: "/TriggerRules/create",
120
+ edit: "/TriggerRules/edit/:id",
121
+ meta: {
122
+ label: t("sider.triggerRules"),
123
+ parent: t("sider.settings"),
124
+ icon: <ThunderboltOutlined />,
125
+ },
126
+ },
127
+ {
128
+ name: "TriggerLog",
129
+ list: "/TriggerLogs",
130
+ meta: {
131
+ label: t("sider.triggerLogs"),
132
+ parent: t("sider.settings"),
133
+ icon: <ThunderboltOutlined />,
134
+ },
135
+ },
136
+ {
137
+ name: "MirrorTypeMappingConfig",
138
+ list: "/MirrorTypeMappingConfigs",
139
+ create: "/MirrorTypeMappingConfigs/create",
140
+ edit: "/MirrorTypeMappingConfigs/edit/:id",
141
+ meta: {
142
+ label: t("sider.mirrorConfigs"),
143
+ parent: t("sider.settings"),
144
+ icon: <CopyOutlined />,
145
+ },
146
+ },
147
+ {
148
+ name: "Settings",
149
+ meta: {
150
+ label: t("sider.settings"),
151
+ icon: <SettingOutlined />,
152
+ },
153
+ },
154
+ ]}
155
+ notificationProvider={useNotificationProvider}
156
+ options={{
157
+ syncWithLocation: true,
158
+ warnWhenUnsavedChanges: true,
159
+ }}
160
+ >
161
+ <Routes>
162
+ <Route
163
+ element={
164
+ <Authenticated
165
+ key="authenticated-routes"
166
+ fallback={<CatchAllNavigate to="/login" />}
167
+ >
168
+ <ThemedLayout Header={Header}>
169
+ <Outlet />
170
+ </ThemedLayout>
171
+ </Authenticated>
172
+ }
173
+ >
174
+ <Route index element={<DashboardPage />} />
175
+
176
+ <Route path="/ApplicationUsers">
177
+ <Route index element={<ApplicationUserList />} />
178
+ <Route path="create" element={<ApplicationUserCreate />} />
179
+ <Route path="edit/:id" element={<ApplicationUserEdit />} />
149
180
  </Route>
150
181
 
151
- <Route
152
- element={
153
- <Authenticated key="auth-pages" fallback={<Outlet />}>
154
- <NavigateToResource resource="dashboard" />
155
- </Authenticated>
156
- }
157
- >
158
- <Route path="/login" element={<KeycloakLoginPage />} />
159
- <Route path="/login/api" element={<LoginPage />} />
160
- <Route path="/auth/callback" element={<AuthCallback />} />
182
+ <Route path="/PermissionPolicyRoles">
183
+ <Route index element={<RoleList />} />
184
+ <Route path="create" element={<RoleCreate />} />
185
+ <Route path="edit/:id" element={<RoleEdit />} />
161
186
  </Route>
162
187
 
163
- <Route
164
- element={
165
- <Authenticated key="catch-all">
166
- <ThemedLayout Header={Header}>
167
- <Outlet />
168
- </ThemedLayout>
169
- </Authenticated>
170
- }
171
- >
172
- <Route path="*" element={<ErrorComponent />} />
188
+ <Route path="/background-jobs" element={<BackgroundJobList title={t("sider.backgroundJobs")} />} />
189
+
190
+ <Route path="/TriggerRules">
191
+ <Route index element={<SmartList resource="TriggerRule" />} />
192
+ <Route path="create" element={<AntdInferencer />} />
193
+ <Route path="edit/:id" element={<AntdInferencer />} />
194
+ </Route>
195
+ <Route path="/TriggerLogs">
196
+ <Route index element={<SmartList resource="TriggerLog" />} />
197
+ </Route>
198
+ <Route path="/MirrorTypeMappingConfigs">
199
+ <Route index element={<SmartList resource="MirrorTypeMappingConfig" />} />
200
+ <Route path="create" element={<AntdInferencer />} />
201
+ <Route path="edit/:id" element={<AntdInferencer />} />
173
202
  </Route>
174
- </Routes>
175
- <UnsavedChangesNotifier />
176
- <DocumentTitleHandler />
177
- </Refine>
178
- </AntdApp>
179
- </ConfigProvider>
203
+ </Route>
204
+
205
+ <Route
206
+ element={
207
+ <Authenticated key="auth-pages" fallback={<Outlet />}>
208
+ <NavigateToResource resource="dashboard" />
209
+ </Authenticated>
210
+ }
211
+ >
212
+ <Route path="/login" element={<KeycloakLoginPage />} />
213
+ <Route path="/login/api" element={<LoginPage />} />
214
+ <Route path="/auth/callback" element={<AuthCallback />} />
215
+ </Route>
216
+
217
+ <Route
218
+ element={
219
+ <Authenticated key="catch-all">
220
+ <ThemedLayout Header={Header}>
221
+ <Outlet />
222
+ </ThemedLayout>
223
+ </Authenticated>
224
+ }
225
+ >
226
+ <Route path="*" element={<ErrorComponent />} />
227
+ </Route>
228
+ </Routes>
229
+ <UnsavedChangesNotifier />
230
+ <DocumentTitleHandler />
231
+ </Refine>
232
+ </AntdApp>
180
233
  </BrowserRouter>
181
234
  );
182
235
  };
@@ -6,16 +6,36 @@ import { refineXafTranslations } from "@cundi/refine-xaf";
6
6
  // Use translations from the SDK
7
7
  const { en, "zh-TW": zhTW } = refineXafTranslations;
8
8
 
9
+ const enExtended = {
10
+ ...en,
11
+ sider: {
12
+ ...((en as any).sider || {}),
13
+ triggerRules: "Trigger Rules",
14
+ triggerLogs: "Trigger Logs",
15
+ mirrorConfigs: "Mirror Configs",
16
+ },
17
+ };
18
+
19
+ const zhTWExtended = {
20
+ ...zhTW,
21
+ sider: {
22
+ ...((zhTW as any).sider || {}),
23
+ triggerRules: "觸發規則",
24
+ triggerLogs: "觸發紀錄",
25
+ mirrorConfigs: "鏡射設定",
26
+ },
27
+ };
28
+
9
29
  i18n
10
30
  .use(LanguageDetector)
11
31
  .use(initReactI18next)
12
32
  .init({
13
33
  resources: {
14
34
  en: {
15
- translation: en,
35
+ translation: enExtended,
16
36
  },
17
37
  "zh-TW": {
18
- translation: zhTW,
38
+ translation: zhTWExtended,
19
39
  },
20
40
  },
21
41
  lng: "zh-TW", // Default language
@@ -4,6 +4,17 @@ import react from "@vitejs/plugin-react";
4
4
  export default defineConfig({
5
5
  plugins: [react()],
6
6
  resolve: {
7
+ alias: {
8
+ "antd/lib": "antd",
9
+ },
7
10
  dedupe: ["react", "react-dom", "antd", "@refinedev/core", "@refinedev/antd", "@tanstack/react-query"],
8
11
  },
12
+ server: {
13
+ proxy: {
14
+ "/api": {
15
+ target: "http://localhost:5000",
16
+ changeOrigin: true,
17
+ },
18
+ },
19
+ },
9
20
  });
@@ -1,2 +0,0 @@
1
- import { ColorModeContextProvider, useColorMode } from "@cundi/refine-xaf";
2
- export { ColorModeContextProvider, useColorMode };