appflare 0.2.25 → 0.2.27
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/Documentation.md +758 -758
- package/cli/commands/index.ts +238 -238
- package/cli/generate.ts +178 -178
- package/cli/index.ts +120 -120
- package/cli/load-config.ts +184 -184
- package/cli/schema-compiler.ts +1183 -1183
- package/cli/templates/auth/README.md +156 -156
- package/cli/templates/auth/config.ts +61 -61
- package/cli/templates/auth/route-config.ts +1 -1
- package/cli/templates/auth/route-handler.ts +1 -1
- package/cli/templates/auth/route-request-utils.ts +5 -5
- package/cli/templates/auth/route.config.ts +18 -18
- package/cli/templates/auth/route.handler.ts +18 -18
- package/cli/templates/auth/route.request-utils.ts +55 -55
- package/cli/templates/auth/route.ts +14 -14
- package/cli/templates/core/README.md +266 -266
- package/cli/templates/core/app-creation.ts +19 -19
- package/cli/templates/core/client/appflare.ts +112 -112
- package/cli/templates/core/client/handlers/index.ts +748 -748
- package/cli/templates/core/client/handlers.ts +1 -1
- package/cli/templates/core/client/index.ts +7 -7
- package/cli/templates/core/client/storage.ts +205 -180
- package/cli/templates/core/client/types.ts +186 -184
- package/cli/templates/core/client-modules/appflare.ts +1 -1
- package/cli/templates/core/client-modules/handlers.ts +1 -1
- package/cli/templates/core/client-modules/index.ts +1 -1
- package/cli/templates/core/client-modules/storage.ts +1 -1
- package/cli/templates/core/client-modules/types.ts +1 -1
- package/cli/templates/core/client.artifacts.ts +39 -39
- package/cli/templates/core/client.ts +4 -4
- package/cli/templates/core/drizzle.ts +15 -15
- package/cli/templates/core/export.ts +14 -14
- package/cli/templates/core/handlers.route.ts +24 -24
- package/cli/templates/core/handlers.ts +1 -1
- package/cli/templates/core/imports.ts +9 -9
- package/cli/templates/core/server.ts +38 -38
- package/cli/templates/core/types.ts +6 -6
- package/cli/templates/core/wrangler.ts +109 -109
- package/cli/templates/dashboard/builders/functions/index.ts +17 -17
- package/cli/templates/dashboard/builders/functions/render-page/header.ts +20 -20
- package/cli/templates/dashboard/builders/functions/render-page/index.ts +33 -33
- package/cli/templates/dashboard/builders/functions/render-page/request-panel.ts +171 -171
- package/cli/templates/dashboard/builders/functions/render-page/result-panel.ts +85 -85
- package/cli/templates/dashboard/builders/functions/render-page/scripts.ts +554 -554
- package/cli/templates/dashboard/builders/navigation.ts +122 -122
- package/cli/templates/dashboard/builders/storage/index.ts +13 -13
- package/cli/templates/dashboard/builders/storage/routes/create-directory-route.ts +29 -29
- package/cli/templates/dashboard/builders/storage/routes/delete-route.ts +18 -18
- package/cli/templates/dashboard/builders/storage/routes/download-route.ts +23 -23
- package/cli/templates/dashboard/builders/storage/routes/index.ts +22 -22
- package/cli/templates/dashboard/builders/storage/routes/list-route.ts +25 -25
- package/cli/templates/dashboard/builders/storage/routes/preview-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/routes/upload-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/runtime/helpers.ts +72 -72
- package/cli/templates/dashboard/builders/storage/runtime/storage-page.ts +130 -130
- package/cli/templates/dashboard/builders/table-routes/common/drawer-panel.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/common/pagination.ts +30 -30
- package/cli/templates/dashboard/builders/table-routes/common/search-bar.ts +23 -23
- package/cli/templates/dashboard/builders/table-routes/fragments.ts +217 -217
- package/cli/templates/dashboard/builders/table-routes/helpers.ts +45 -45
- package/cli/templates/dashboard/builders/table-routes/index.ts +8 -8
- package/cli/templates/dashboard/builders/table-routes/table/actions-cell.ts +71 -71
- package/cli/templates/dashboard/builders/table-routes/table/get-route.ts +291 -291
- package/cli/templates/dashboard/builders/table-routes/table/index.ts +80 -80
- package/cli/templates/dashboard/builders/table-routes/table/post-routes.ts +163 -163
- package/cli/templates/dashboard/builders/table-routes/table-route.ts +7 -7
- package/cli/templates/dashboard/builders/table-routes/users/get-route.ts +69 -69
- package/cli/templates/dashboard/builders/table-routes/users/html/modals.ts +57 -57
- package/cli/templates/dashboard/builders/table-routes/users/html/page.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/users/html/table.ts +128 -128
- package/cli/templates/dashboard/builders/table-routes/users/index.ts +32 -32
- package/cli/templates/dashboard/builders/table-routes/users/post-routes.ts +150 -150
- package/cli/templates/dashboard/builders/table-routes/users/redirect.ts +14 -14
- package/cli/templates/dashboard/builders/table-routes/users-route.ts +10 -10
- package/cli/templates/dashboard/components/dashboard-home.ts +23 -23
- package/cli/templates/dashboard/components/layout.ts +388 -388
- package/cli/templates/dashboard/components/login-page.ts +65 -65
- package/cli/templates/dashboard/index.ts +61 -61
- package/cli/templates/dashboard/types.ts +9 -9
- package/cli/templates/handlers/README.md +353 -353
- package/cli/templates/handlers/auth.ts +37 -37
- package/cli/templates/handlers/execution.ts +42 -42
- package/cli/templates/handlers/generators/context/context-creation.ts +101 -101
- package/cli/templates/handlers/generators/context/error-helpers.ts +11 -11
- package/cli/templates/handlers/generators/context/scheduler.ts +24 -24
- package/cli/templates/handlers/generators/context/storage-api.ts +82 -112
- package/cli/templates/handlers/generators/context/storage-helpers.ts +59 -59
- package/cli/templates/handlers/generators/context/types.ts +18 -18
- package/cli/templates/handlers/generators/context.ts +43 -43
- package/cli/templates/handlers/generators/execution.ts +15 -15
- package/cli/templates/handlers/generators/handlers.ts +13 -13
- package/cli/templates/handlers/generators/registration/modules/cron.ts +26 -26
- package/cli/templates/handlers/generators/registration/modules/realtime/auth.ts +75 -75
- package/cli/templates/handlers/generators/registration/modules/realtime/durable-object.ts +144 -144
- package/cli/templates/handlers/generators/registration/modules/realtime/index.ts +14 -14
- package/cli/templates/handlers/generators/registration/modules/realtime/publisher.ts +102 -102
- package/cli/templates/handlers/generators/registration/modules/realtime/routes.ts +164 -164
- package/cli/templates/handlers/generators/registration/modules/realtime/types.ts +30 -30
- package/cli/templates/handlers/generators/registration/modules/realtime/utils.ts +516 -516
- package/cli/templates/handlers/generators/registration/modules/scheduler.ts +56 -56
- package/cli/templates/handlers/generators/registration/modules/storage.ts +192 -194
- package/cli/templates/handlers/generators/registration/sections.ts +210 -210
- package/cli/templates/handlers/generators/types/context.ts +67 -66
- package/cli/templates/handlers/generators/types/core.ts +106 -106
- package/cli/templates/handlers/generators/types/operations.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/filter-and-where-types.ts +259 -259
- package/cli/templates/handlers/generators/types/query-definitions/query-api-types.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/query-helper-functions.ts +1031 -1031
- package/cli/templates/handlers/generators/types/query-definitions/schema-and-table-types.ts +246 -246
- package/cli/templates/handlers/generators/types/query-definitions.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/handled-error.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/runtime-aggregate-and-footer.ts +174 -174
- package/cli/templates/handlers/generators/types/query-runtime/runtime-read.ts +121 -121
- package/cli/templates/handlers/generators/types/query-runtime/runtime-setup.ts +45 -45
- package/cli/templates/handlers/generators/types/query-runtime/runtime-write.ts +676 -676
- package/cli/templates/handlers/generators/types/query-runtime.ts +15 -15
- package/cli/templates/handlers/index.ts +43 -43
- package/cli/templates/handlers/operations.ts +116 -116
- package/cli/templates/handlers/registration.ts +91 -91
- package/cli/templates/handlers/types.ts +15 -15
- package/cli/templates/handlers/utils.ts +48 -48
- package/cli/types.ts +110 -110
- package/cli/utils/handler-discovery.ts +466 -466
- package/cli/utils/json-utils.ts +24 -24
- package/cli/utils/path-utils.ts +19 -19
- package/cli/utils/schema-discovery.ts +399 -399
- package/dist/cli/index.js +95 -99
- package/dist/cli/index.mjs +95 -99
- package/index.ts +18 -18
- package/package.json +58 -58
- package/react/index.ts +5 -5
- package/react/use-infinite-query.ts +252 -252
- package/react/use-mutation.ts +89 -89
- package/react/use-query.ts +207 -207
- package/schema.ts +415 -415
- package/test-better-auth-hash.ts +2 -2
- package/tsconfig.json +6 -6
- package/tsup.config.ts +82 -82
- package/dist/cli/index.d.mts +0 -2
- package/dist/cli/index.d.ts +0 -2
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Builds the POST route handlers code string for the users management routes:
|
|
3
|
-
* /admin/users/edit, /admin/users/ban, /admin/users/unban, /admin/users/delete
|
|
4
|
-
*/
|
|
5
|
-
export function buildUsersPostRoutes(): string {
|
|
6
|
-
return `
|
|
7
|
-
\tadminApp.post('/users/edit', async (c) => {
|
|
8
|
-
\t\tconst session = await requireAdminSession(c);
|
|
9
|
-
\t\tif (!session) {
|
|
10
|
-
\t\t\treturn c.redirect('/admin');
|
|
11
|
-
\t\t}
|
|
12
|
-
|
|
13
|
-
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
14
|
-
\t\tconst formData = await c.req.formData();
|
|
15
|
-
\t\tconst id = String(formData.get('id') || '').trim();
|
|
16
|
-
\t\tconst name = String(formData.get('name') || '').trim();
|
|
17
|
-
\t\tconst email = String(formData.get('email') || '').trim();
|
|
18
|
-
\t\tconst role = String(formData.get('role') || '').trim();
|
|
19
|
-
\t\tconst page = String(formData.get('page') || '1');
|
|
20
|
-
\t\tconst search = String(formData.get('search') || '');
|
|
21
|
-
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
22
|
-
\t\tconst order = String(formData.get('order') || 'desc');
|
|
23
|
-
|
|
24
|
-
\t\tif (!id || !name || !email || !role || !['admin', 'user'].includes(role)) {
|
|
25
|
-
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
26
|
-
\t\t}
|
|
27
|
-
|
|
28
|
-
\t\tif (id === session.user.id && role !== 'admin') {
|
|
29
|
-
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
30
|
-
\t\t}
|
|
31
|
-
|
|
32
|
-
\t\tawait db
|
|
33
|
-
\t\t\t.update(users)
|
|
34
|
-
\t\t\t.set({ name, email, role })
|
|
35
|
-
\t\t\t.where(eq(users.id, id));
|
|
36
|
-
|
|
37
|
-
\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
38
|
-
\t});
|
|
39
|
-
|
|
40
|
-
\tadminApp.post('/users/ban', async (c) => {
|
|
41
|
-
\t\tconst session = await requireAdminSession(c);
|
|
42
|
-
\t\tif (!session) {
|
|
43
|
-
\t\t\treturn c.redirect('/admin');
|
|
44
|
-
\t\t}
|
|
45
|
-
|
|
46
|
-
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
47
|
-
\t\tconst formData = await c.req.formData();
|
|
48
|
-
\t\tconst id = String(formData.get('id') || '').trim();
|
|
49
|
-
\t\tconst page = String(formData.get('page') || '1');
|
|
50
|
-
\t\tconst search = String(formData.get('search') || '');
|
|
51
|
-
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
52
|
-
\t\tconst order = String(formData.get('order') || 'desc');
|
|
53
|
-
|
|
54
|
-
\t\tif (!id || id === session.user.id) {
|
|
55
|
-
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
56
|
-
\t\t}
|
|
57
|
-
|
|
58
|
-
\t\tawait db
|
|
59
|
-
\t\t\t.update(users)
|
|
60
|
-
\t\t\t.set({
|
|
61
|
-
\t\t\t\tbanned: true,
|
|
62
|
-
\t\t\t\tbanReason: 'Banned via admin dashboard',
|
|
63
|
-
\t\t\t\tbanExpires: null,
|
|
64
|
-
\t\t\t})
|
|
65
|
-
\t\t\t.where(eq(users.id, id));
|
|
66
|
-
|
|
67
|
-
\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
68
|
-
\t});
|
|
69
|
-
|
|
70
|
-
\tadminApp.post('/users/unban', async (c) => {
|
|
71
|
-
\t\tconst session = await requireAdminSession(c);
|
|
72
|
-
\t\tif (!session) {
|
|
73
|
-
\t\t\treturn c.redirect('/admin');
|
|
74
|
-
\t\t}
|
|
75
|
-
|
|
76
|
-
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
77
|
-
\t\tconst formData = await c.req.formData();
|
|
78
|
-
\t\tconst id = String(formData.get('id') || '').trim();
|
|
79
|
-
\t\tconst page = String(formData.get('page') || '1');
|
|
80
|
-
\t\tconst search = String(formData.get('search') || '');
|
|
81
|
-
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
82
|
-
\t\tconst order = String(formData.get('order') || 'desc');
|
|
83
|
-
|
|
84
|
-
\t\tif (!id) {
|
|
85
|
-
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
86
|
-
\t\t}
|
|
87
|
-
|
|
88
|
-
\t\tawait db
|
|
89
|
-
\t\t\t.update(users)
|
|
90
|
-
\t\t\t.set({
|
|
91
|
-
\t\t\t\tbanned: false,
|
|
92
|
-
\t\t\t\tbanReason: null,
|
|
93
|
-
\t\t\t\tbanExpires: null,
|
|
94
|
-
\t\t\t})
|
|
95
|
-
\t\t\t.where(eq(users.id, id));
|
|
96
|
-
|
|
97
|
-
\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
98
|
-
\t});
|
|
99
|
-
|
|
100
|
-
\tadminApp.post('/users/delete', async (c) => {
|
|
101
|
-
\t\tconst session = await requireAdminSession(c);
|
|
102
|
-
\t\tif (!session) {
|
|
103
|
-
\t\t\treturn c.redirect('/admin');
|
|
104
|
-
\t\t}
|
|
105
|
-
|
|
106
|
-
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
107
|
-
\t\tconst formData = await c.req.formData();
|
|
108
|
-
\t\tconst id = String(formData.get('id') || '').trim();
|
|
109
|
-
\t\tconst page = String(formData.get('page') || '1');
|
|
110
|
-
\t\tconst search = String(formData.get('search') || '');
|
|
111
|
-
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
112
|
-
\t\tconst order = String(formData.get('order') || 'desc');
|
|
113
|
-
|
|
114
|
-
\t\tif (!id || id === session.user.id) {
|
|
115
|
-
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
116
|
-
\t\t}
|
|
117
|
-
|
|
118
|
-
\t\tconst targetUsers = await db
|
|
119
|
-
\t\t\t.select({ role: users.role })
|
|
120
|
-
\t\t\t.from(users)
|
|
121
|
-
\t\t\t.where(eq(users.id, id))
|
|
122
|
-
\t\t\t.limit(1);
|
|
123
|
-
|
|
124
|
-
\t\tif (!targetUsers[0]) {
|
|
125
|
-
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
126
|
-
\t\t}
|
|
127
|
-
|
|
128
|
-
\t\tif (targetUsers[0].role === 'admin') {
|
|
129
|
-
\t\t\tconst adminCountResult = await db
|
|
130
|
-
\t\t\t\t.select({ count: sql\`count(*)\` })
|
|
131
|
-
\t\t\t\t.from(users)
|
|
132
|
-
\t\t\t\t.where(eq(users.role, 'admin'));
|
|
133
|
-
\t\t\tconst adminCount = Number(adminCountResult[0]?.count || 0);
|
|
134
|
-
\t\t\tif (adminCount <= 1) {
|
|
135
|
-
\t\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
136
|
-
\t\t\t}
|
|
137
|
-
\t\t}
|
|
138
|
-
|
|
139
|
-
\t\tawait db.delete(users).where(eq(users.id, id));
|
|
140
|
-
|
|
141
|
-
\t\tconst nextPageCandidate = Math.max(1, parseInt(page || '1', 10));
|
|
142
|
-
\t\tconst limit = 20;
|
|
143
|
-
\t\tconst totalResult = await db.select({ count: sql\`count(*)\` }).from(users);
|
|
144
|
-
\t\tconst total = Number(totalResult[0]?.count || 0);
|
|
145
|
-
\t\tconst totalPages = Math.max(1, Math.ceil(total / limit));
|
|
146
|
-
\t\tconst resolvedPage = String(Math.min(nextPageCandidate, totalPages));
|
|
147
|
-
|
|
148
|
-
\t\treturn c.redirect(buildUsersRedirect({ page: resolvedPage, search, sort, order }));
|
|
149
|
-
\t});`;
|
|
150
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Builds the POST route handlers code string for the users management routes:
|
|
3
|
+
* /admin/users/edit, /admin/users/ban, /admin/users/unban, /admin/users/delete
|
|
4
|
+
*/
|
|
5
|
+
export function buildUsersPostRoutes(): string {
|
|
6
|
+
return `
|
|
7
|
+
\tadminApp.post('/users/edit', async (c) => {
|
|
8
|
+
\t\tconst session = await requireAdminSession(c);
|
|
9
|
+
\t\tif (!session) {
|
|
10
|
+
\t\t\treturn c.redirect('/admin');
|
|
11
|
+
\t\t}
|
|
12
|
+
|
|
13
|
+
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
14
|
+
\t\tconst formData = await c.req.formData();
|
|
15
|
+
\t\tconst id = String(formData.get('id') || '').trim();
|
|
16
|
+
\t\tconst name = String(formData.get('name') || '').trim();
|
|
17
|
+
\t\tconst email = String(formData.get('email') || '').trim();
|
|
18
|
+
\t\tconst role = String(formData.get('role') || '').trim();
|
|
19
|
+
\t\tconst page = String(formData.get('page') || '1');
|
|
20
|
+
\t\tconst search = String(formData.get('search') || '');
|
|
21
|
+
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
22
|
+
\t\tconst order = String(formData.get('order') || 'desc');
|
|
23
|
+
|
|
24
|
+
\t\tif (!id || !name || !email || !role || !['admin', 'user'].includes(role)) {
|
|
25
|
+
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
26
|
+
\t\t}
|
|
27
|
+
|
|
28
|
+
\t\tif (id === session.user.id && role !== 'admin') {
|
|
29
|
+
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
30
|
+
\t\t}
|
|
31
|
+
|
|
32
|
+
\t\tawait db
|
|
33
|
+
\t\t\t.update(users)
|
|
34
|
+
\t\t\t.set({ name, email, role })
|
|
35
|
+
\t\t\t.where(eq(users.id, id));
|
|
36
|
+
|
|
37
|
+
\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
38
|
+
\t});
|
|
39
|
+
|
|
40
|
+
\tadminApp.post('/users/ban', async (c) => {
|
|
41
|
+
\t\tconst session = await requireAdminSession(c);
|
|
42
|
+
\t\tif (!session) {
|
|
43
|
+
\t\t\treturn c.redirect('/admin');
|
|
44
|
+
\t\t}
|
|
45
|
+
|
|
46
|
+
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
47
|
+
\t\tconst formData = await c.req.formData();
|
|
48
|
+
\t\tconst id = String(formData.get('id') || '').trim();
|
|
49
|
+
\t\tconst page = String(formData.get('page') || '1');
|
|
50
|
+
\t\tconst search = String(formData.get('search') || '');
|
|
51
|
+
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
52
|
+
\t\tconst order = String(formData.get('order') || 'desc');
|
|
53
|
+
|
|
54
|
+
\t\tif (!id || id === session.user.id) {
|
|
55
|
+
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
56
|
+
\t\t}
|
|
57
|
+
|
|
58
|
+
\t\tawait db
|
|
59
|
+
\t\t\t.update(users)
|
|
60
|
+
\t\t\t.set({
|
|
61
|
+
\t\t\t\tbanned: true,
|
|
62
|
+
\t\t\t\tbanReason: 'Banned via admin dashboard',
|
|
63
|
+
\t\t\t\tbanExpires: null,
|
|
64
|
+
\t\t\t})
|
|
65
|
+
\t\t\t.where(eq(users.id, id));
|
|
66
|
+
|
|
67
|
+
\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
68
|
+
\t});
|
|
69
|
+
|
|
70
|
+
\tadminApp.post('/users/unban', async (c) => {
|
|
71
|
+
\t\tconst session = await requireAdminSession(c);
|
|
72
|
+
\t\tif (!session) {
|
|
73
|
+
\t\t\treturn c.redirect('/admin');
|
|
74
|
+
\t\t}
|
|
75
|
+
|
|
76
|
+
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
77
|
+
\t\tconst formData = await c.req.formData();
|
|
78
|
+
\t\tconst id = String(formData.get('id') || '').trim();
|
|
79
|
+
\t\tconst page = String(formData.get('page') || '1');
|
|
80
|
+
\t\tconst search = String(formData.get('search') || '');
|
|
81
|
+
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
82
|
+
\t\tconst order = String(formData.get('order') || 'desc');
|
|
83
|
+
|
|
84
|
+
\t\tif (!id) {
|
|
85
|
+
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
86
|
+
\t\t}
|
|
87
|
+
|
|
88
|
+
\t\tawait db
|
|
89
|
+
\t\t\t.update(users)
|
|
90
|
+
\t\t\t.set({
|
|
91
|
+
\t\t\t\tbanned: false,
|
|
92
|
+
\t\t\t\tbanReason: null,
|
|
93
|
+
\t\t\t\tbanExpires: null,
|
|
94
|
+
\t\t\t})
|
|
95
|
+
\t\t\t.where(eq(users.id, id));
|
|
96
|
+
|
|
97
|
+
\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
98
|
+
\t});
|
|
99
|
+
|
|
100
|
+
\tadminApp.post('/users/delete', async (c) => {
|
|
101
|
+
\t\tconst session = await requireAdminSession(c);
|
|
102
|
+
\t\tif (!session) {
|
|
103
|
+
\t\t\treturn c.redirect('/admin');
|
|
104
|
+
\t\t}
|
|
105
|
+
|
|
106
|
+
\t\tconst db = drizzle(c.env[options.databaseBinding]);
|
|
107
|
+
\t\tconst formData = await c.req.formData();
|
|
108
|
+
\t\tconst id = String(formData.get('id') || '').trim();
|
|
109
|
+
\t\tconst page = String(formData.get('page') || '1');
|
|
110
|
+
\t\tconst search = String(formData.get('search') || '');
|
|
111
|
+
\t\tconst sort = String(formData.get('sort') || 'createdAt');
|
|
112
|
+
\t\tconst order = String(formData.get('order') || 'desc');
|
|
113
|
+
|
|
114
|
+
\t\tif (!id || id === session.user.id) {
|
|
115
|
+
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
116
|
+
\t\t}
|
|
117
|
+
|
|
118
|
+
\t\tconst targetUsers = await db
|
|
119
|
+
\t\t\t.select({ role: users.role })
|
|
120
|
+
\t\t\t.from(users)
|
|
121
|
+
\t\t\t.where(eq(users.id, id))
|
|
122
|
+
\t\t\t.limit(1);
|
|
123
|
+
|
|
124
|
+
\t\tif (!targetUsers[0]) {
|
|
125
|
+
\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
126
|
+
\t\t}
|
|
127
|
+
|
|
128
|
+
\t\tif (targetUsers[0].role === 'admin') {
|
|
129
|
+
\t\t\tconst adminCountResult = await db
|
|
130
|
+
\t\t\t\t.select({ count: sql\`count(*)\` })
|
|
131
|
+
\t\t\t\t.from(users)
|
|
132
|
+
\t\t\t\t.where(eq(users.role, 'admin'));
|
|
133
|
+
\t\t\tconst adminCount = Number(adminCountResult[0]?.count || 0);
|
|
134
|
+
\t\t\tif (adminCount <= 1) {
|
|
135
|
+
\t\t\t\treturn c.redirect(buildUsersRedirect({ page, search, sort, order }));
|
|
136
|
+
\t\t\t}
|
|
137
|
+
\t\t}
|
|
138
|
+
|
|
139
|
+
\t\tawait db.delete(users).where(eq(users.id, id));
|
|
140
|
+
|
|
141
|
+
\t\tconst nextPageCandidate = Math.max(1, parseInt(page || '1', 10));
|
|
142
|
+
\t\tconst limit = 20;
|
|
143
|
+
\t\tconst totalResult = await db.select({ count: sql\`count(*)\` }).from(users);
|
|
144
|
+
\t\tconst total = Number(totalResult[0]?.count || 0);
|
|
145
|
+
\t\tconst totalPages = Math.max(1, Math.ceil(total / limit));
|
|
146
|
+
\t\tconst resolvedPage = String(Math.min(nextPageCandidate, totalPages));
|
|
147
|
+
|
|
148
|
+
\t\treturn c.redirect(buildUsersRedirect({ page: resolvedPage, search, sort, order }));
|
|
149
|
+
\t});`;
|
|
150
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Builds a redirect URL for user management pages, preserving all query parameters.
|
|
3
|
-
* This is embedded as a runtime function in the generated route code.
|
|
4
|
-
*/
|
|
5
|
-
export function buildUsersRedirectHelper(): string {
|
|
6
|
-
return `
|
|
7
|
-
\tconst buildUsersRedirect = (params: { page?: string; sort?: string; order?: string; search?: string }) => {
|
|
8
|
-
\t\tconst page = params.page && params.page.trim() ? params.page : '1';
|
|
9
|
-
\t\tconst sort = params.sort && params.sort.trim() ? params.sort : 'createdAt';
|
|
10
|
-
\t\tconst order = params.order === 'asc' ? 'asc' : 'desc';
|
|
11
|
-
\t\tconst search = params.search ? params.search : '';
|
|
12
|
-
\t\treturn '/admin/users?page=' + encodeURIComponent(page) + '&sort=' + encodeURIComponent(sort) + '&order=' + encodeURIComponent(order) + '&search=' + encodeURIComponent(search);
|
|
13
|
-
\t};`;
|
|
14
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Builds a redirect URL for user management pages, preserving all query parameters.
|
|
3
|
+
* This is embedded as a runtime function in the generated route code.
|
|
4
|
+
*/
|
|
5
|
+
export function buildUsersRedirectHelper(): string {
|
|
6
|
+
return `
|
|
7
|
+
\tconst buildUsersRedirect = (params: { page?: string; sort?: string; order?: string; search?: string }) => {
|
|
8
|
+
\t\tconst page = params.page && params.page.trim() ? params.page : '1';
|
|
9
|
+
\t\tconst sort = params.sort && params.sort.trim() ? params.sort : 'createdAt';
|
|
10
|
+
\t\tconst order = params.order === 'asc' ? 'asc' : 'desc';
|
|
11
|
+
\t\tconst search = params.search ? params.search : '';
|
|
12
|
+
\t\treturn '/admin/users?page=' + encodeURIComponent(page) + '&sort=' + encodeURIComponent(sort) + '&order=' + encodeURIComponent(order) + '&search=' + encodeURIComponent(search);
|
|
13
|
+
\t};`;
|
|
14
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Re-exported from the modular users/ directory.
|
|
2
|
-
// The actual implementation has been split into focused files:
|
|
3
|
-
// - users/redirect.ts — runtime buildUsersRedirect helper
|
|
4
|
-
// - users/html/modals.ts — ban/delete confirmation modals
|
|
5
|
-
// - users/html/table.ts — sortable table with inline edit drawer
|
|
6
|
-
// - users/html/page.ts — page header + search bar wrapper
|
|
7
|
-
// - users/get-route.ts — GET /admin/users handler
|
|
8
|
-
// - users/post-routes.ts — POST edit/ban/unban/delete handlers
|
|
9
|
-
// - users/index.ts — orchestrating buildUsersRoute()
|
|
10
|
-
export { buildUsersRoute } from "./users/index";
|
|
1
|
+
// Re-exported from the modular users/ directory.
|
|
2
|
+
// The actual implementation has been split into focused files:
|
|
3
|
+
// - users/redirect.ts — runtime buildUsersRedirect helper
|
|
4
|
+
// - users/html/modals.ts — ban/delete confirmation modals
|
|
5
|
+
// - users/html/table.ts — sortable table with inline edit drawer
|
|
6
|
+
// - users/html/page.ts — page header + search bar wrapper
|
|
7
|
+
// - users/get-route.ts — GET /admin/users handler
|
|
8
|
+
// - users/post-routes.ts — POST edit/ban/unban/delete handlers
|
|
9
|
+
// - users/index.ts — orchestrating buildUsersRoute()
|
|
10
|
+
export { buildUsersRoute } from "./users/index";
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates the dashboard home route source code (as a string to be embedded in generated output).
|
|
3
|
-
*/
|
|
4
|
-
export function buildDashboardHomeRoute(dashboardCards: string): string {
|
|
5
|
-
return `
|
|
6
|
-
\tadminApp.get('/', (c) => {
|
|
7
|
-
\t\treturn c.html(Layout({
|
|
8
|
-
\t\t\ttitle: "Admin Dashboard",
|
|
9
|
-
\t\t\tchildren: html\`
|
|
10
|
-
\t\t\t\t<div id="main-content">
|
|
11
|
-
\t\t\t\t\t<div class="mb-6">
|
|
12
|
-
\t\t\t\t\t\t<h1 class="text-2xl font-semibold mb-1">Collections</h1>
|
|
13
|
-
\t\t\t\t\t\t<p class="text-base-content/50 text-sm">Select a collection to view and manage its data.</p>
|
|
14
|
-
\t\t\t\t\t</div>
|
|
15
|
-
\t\t\t\t\t<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
16
|
-
\t\t\t\t\t\t${dashboardCards}
|
|
17
|
-
\t\t\t\t\t</div>
|
|
18
|
-
\t\t\t\t</div>
|
|
19
|
-
\t\t\t\`
|
|
20
|
-
\t\t}));
|
|
21
|
-
\t});
|
|
22
|
-
`;
|
|
23
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Generates the dashboard home route source code (as a string to be embedded in generated output).
|
|
3
|
+
*/
|
|
4
|
+
export function buildDashboardHomeRoute(dashboardCards: string): string {
|
|
5
|
+
return `
|
|
6
|
+
\tadminApp.get('/', (c) => {
|
|
7
|
+
\t\treturn c.html(Layout({
|
|
8
|
+
\t\t\ttitle: "Admin Dashboard",
|
|
9
|
+
\t\t\tchildren: html\`
|
|
10
|
+
\t\t\t\t<div id="main-content">
|
|
11
|
+
\t\t\t\t\t<div class="mb-6">
|
|
12
|
+
\t\t\t\t\t\t<h1 class="text-2xl font-semibold mb-1">Collections</h1>
|
|
13
|
+
\t\t\t\t\t\t<p class="text-base-content/50 text-sm">Select a collection to view and manage its data.</p>
|
|
14
|
+
\t\t\t\t\t</div>
|
|
15
|
+
\t\t\t\t\t<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
16
|
+
\t\t\t\t\t\t${dashboardCards}
|
|
17
|
+
\t\t\t\t\t</div>
|
|
18
|
+
\t\t\t\t</div>
|
|
19
|
+
\t\t\t\`
|
|
20
|
+
\t\t}));
|
|
21
|
+
\t});
|
|
22
|
+
`;
|
|
23
|
+
}
|