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,122 +1,122 @@
|
|
|
1
|
-
import { DiscoveredSchema } from "../../../utils/schema-discovery";
|
|
2
|
-
import { DiscoveredHandlerOperation } from "../../../utils/handler-discovery";
|
|
3
|
-
import { TableInfo } from "../types";
|
|
4
|
-
|
|
5
|
-
export function collectTablesInfo(schema: DiscoveredSchema): TableInfo[] {
|
|
6
|
-
return schema.tables.map((table) => ({
|
|
7
|
-
exportName: table.exportName,
|
|
8
|
-
tableName: table.tableName,
|
|
9
|
-
columns: table.columns.map((column) => column.name),
|
|
10
|
-
}));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** Generates the right-pane list items: users entry first, then schema tables */
|
|
14
|
-
export function buildSidebarTableList(tablesInfo: TableInfo[]): string {
|
|
15
|
-
const tableItems = tablesInfo
|
|
16
|
-
.map(
|
|
17
|
-
(table) =>
|
|
18
|
-
`<li data-name="${table.tableName}">
|
|
19
|
-
\t\t\t\t\t\t<a href="/admin/table/${table.exportName}" hx-get="/admin/table/${table.exportName}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
20
|
-
\t\t\t\t\t\t\t<iconify-icon icon="mdi:table" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
21
|
-
\t\t\t\t\t\t\t<span class="truncate">${table.tableName}</span>
|
|
22
|
-
\t\t\t\t\t\t</a>
|
|
23
|
-
\t\t\t\t\t</li>`,
|
|
24
|
-
)
|
|
25
|
-
.join("\n\t\t\t\t\t");
|
|
26
|
-
|
|
27
|
-
return `<li data-name="users">
|
|
28
|
-
\t\t\t\t\t\t<a href="/admin/users" hx-get="/admin/users" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
29
|
-
\t\t\t\t\t\t\t<iconify-icon icon="mdi:account-group" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
30
|
-
\t\t\t\t\t\t\t<span class="truncate">users</span>
|
|
31
|
-
\t\t\t\t\t\t</a>
|
|
32
|
-
\t\t\t\t\t</li>
|
|
33
|
-
\t\t\t\t\t${tableItems}`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function buildSidebarFunctionList(
|
|
37
|
-
handlers: DiscoveredHandlerOperation[],
|
|
38
|
-
): string {
|
|
39
|
-
const queries = handlers.filter((h) => h.kind === "query");
|
|
40
|
-
const mutations = handlers.filter((h) => h.kind === "mutation");
|
|
41
|
-
|
|
42
|
-
const queryItems = queries
|
|
43
|
-
.map(
|
|
44
|
-
(h) => `
|
|
45
|
-
<li data-name="${h.exportName}">
|
|
46
|
-
<a href="/admin/functions${h.routePath}" hx-get="/admin/functions${h.routePath}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
47
|
-
<iconify-icon icon="solar:reorder-linear" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
48
|
-
<span class="truncate">${h.exportName}</span>
|
|
49
|
-
</a>
|
|
50
|
-
</li>`,
|
|
51
|
-
)
|
|
52
|
-
.join("");
|
|
53
|
-
|
|
54
|
-
const mutationItems = mutations
|
|
55
|
-
.map(
|
|
56
|
-
(h) => `
|
|
57
|
-
<li data-name="${h.exportName}">
|
|
58
|
-
<a href="/admin/functions${h.routePath}" hx-get="/admin/functions${h.routePath}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
59
|
-
<iconify-icon icon="solar:bolt-linear" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
60
|
-
<span class="truncate">${h.exportName}</span>
|
|
61
|
-
</a>
|
|
62
|
-
</li>`,
|
|
63
|
-
)
|
|
64
|
-
.join("");
|
|
65
|
-
|
|
66
|
-
return `
|
|
67
|
-
<div id="pane-functions" class="flex flex-col h-full hidden">
|
|
68
|
-
<div class="px-3 pt-5 pb-3">
|
|
69
|
-
<p class="text-[10px] font-semibold uppercase tracking-widest opacity-35 mb-3 px-1">Functions</p>
|
|
70
|
-
<div class="relative">
|
|
71
|
-
<iconify-icon icon="solar:magnifer-linear" width="13" height="13" class="absolute left-2.5 top-1/2 -translate-y-1/2 opacity-35 pointer-events-none"></iconify-icon>
|
|
72
|
-
<input
|
|
73
|
-
type="text"
|
|
74
|
-
id="function-search"
|
|
75
|
-
placeholder="Search functions..."
|
|
76
|
-
class="input input-sm border border-base-200 bg-base-200/50 focus:bg-base-100 focus:border-primary focus:outline-none w-full pl-7 text-xs rounded-lg h-8"
|
|
77
|
-
onkeyup="filterFunctions(this.value)"
|
|
78
|
-
/>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
<nav class="flex-1 overflow-y-auto px-2 pb-4">
|
|
82
|
-
${
|
|
83
|
-
queries.length > 0
|
|
84
|
-
? `<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Queries</p>
|
|
85
|
-
<ul class="flex flex-col gap-0.5">${queryItems}</ul>`
|
|
86
|
-
: ""
|
|
87
|
-
}
|
|
88
|
-
${
|
|
89
|
-
mutations.length > 0
|
|
90
|
-
? `<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Mutations</p>
|
|
91
|
-
<ul class="flex flex-col gap-0.5">${mutationItems}</ul>`
|
|
92
|
-
: ""
|
|
93
|
-
}
|
|
94
|
-
</nav>
|
|
95
|
-
</div>
|
|
96
|
-
`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function buildDashboardCards(tablesInfo: TableInfo[]): string {
|
|
100
|
-
return tablesInfo
|
|
101
|
-
.map((table) =>
|
|
102
|
-
`
|
|
103
|
-
<a
|
|
104
|
-
href="/admin/table/${table.exportName}"
|
|
105
|
-
class="card bg-base-100 border border-base-200 hover:border-primary/30 hover:shadow-md transition-all cursor-pointer group"
|
|
106
|
-
>
|
|
107
|
-
<div class="card-body p-5">
|
|
108
|
-
<div class="flex items-center gap-3">
|
|
109
|
-
<div class="w-9 h-9 rounded-lg bg-primary/10 flex items-center justify-center">
|
|
110
|
-
<iconify-icon icon="mdi:table" width="20" height="20" class="text-primary"></iconify-icon>
|
|
111
|
-
</div>
|
|
112
|
-
<div>
|
|
113
|
-
<h2 class="font-semibold text-sm capitalize group-hover:text-primary transition-colors">${table.tableName}</h2>
|
|
114
|
-
<p class="text-xs opacity-40 mt-0.5">Manage records</p>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</div>
|
|
118
|
-
</a>
|
|
119
|
-
`.replace(/\n/g, "\\n"),
|
|
120
|
-
)
|
|
121
|
-
.join("");
|
|
122
|
-
}
|
|
1
|
+
import { DiscoveredSchema } from "../../../utils/schema-discovery";
|
|
2
|
+
import { DiscoveredHandlerOperation } from "../../../utils/handler-discovery";
|
|
3
|
+
import { TableInfo } from "../types";
|
|
4
|
+
|
|
5
|
+
export function collectTablesInfo(schema: DiscoveredSchema): TableInfo[] {
|
|
6
|
+
return schema.tables.map((table) => ({
|
|
7
|
+
exportName: table.exportName,
|
|
8
|
+
tableName: table.tableName,
|
|
9
|
+
columns: table.columns.map((column) => column.name),
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Generates the right-pane list items: users entry first, then schema tables */
|
|
14
|
+
export function buildSidebarTableList(tablesInfo: TableInfo[]): string {
|
|
15
|
+
const tableItems = tablesInfo
|
|
16
|
+
.map(
|
|
17
|
+
(table) =>
|
|
18
|
+
`<li data-name="${table.tableName}">
|
|
19
|
+
\t\t\t\t\t\t<a href="/admin/table/${table.exportName}" hx-get="/admin/table/${table.exportName}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
20
|
+
\t\t\t\t\t\t\t<iconify-icon icon="mdi:table" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
21
|
+
\t\t\t\t\t\t\t<span class="truncate">${table.tableName}</span>
|
|
22
|
+
\t\t\t\t\t\t</a>
|
|
23
|
+
\t\t\t\t\t</li>`,
|
|
24
|
+
)
|
|
25
|
+
.join("\n\t\t\t\t\t");
|
|
26
|
+
|
|
27
|
+
return `<li data-name="users">
|
|
28
|
+
\t\t\t\t\t\t<a href="/admin/users" hx-get="/admin/users" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
29
|
+
\t\t\t\t\t\t\t<iconify-icon icon="mdi:account-group" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
30
|
+
\t\t\t\t\t\t\t<span class="truncate">users</span>
|
|
31
|
+
\t\t\t\t\t\t</a>
|
|
32
|
+
\t\t\t\t\t</li>
|
|
33
|
+
\t\t\t\t\t${tableItems}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function buildSidebarFunctionList(
|
|
37
|
+
handlers: DiscoveredHandlerOperation[],
|
|
38
|
+
): string {
|
|
39
|
+
const queries = handlers.filter((h) => h.kind === "query");
|
|
40
|
+
const mutations = handlers.filter((h) => h.kind === "mutation");
|
|
41
|
+
|
|
42
|
+
const queryItems = queries
|
|
43
|
+
.map(
|
|
44
|
+
(h) => `
|
|
45
|
+
<li data-name="${h.exportName}">
|
|
46
|
+
<a href="/admin/functions${h.routePath}" hx-get="/admin/functions${h.routePath}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
47
|
+
<iconify-icon icon="solar:reorder-linear" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
48
|
+
<span class="truncate">${h.exportName}</span>
|
|
49
|
+
</a>
|
|
50
|
+
</li>`,
|
|
51
|
+
)
|
|
52
|
+
.join("");
|
|
53
|
+
|
|
54
|
+
const mutationItems = mutations
|
|
55
|
+
.map(
|
|
56
|
+
(h) => `
|
|
57
|
+
<li data-name="${h.exportName}">
|
|
58
|
+
<a href="/admin/functions${h.routePath}" hx-get="/admin/functions${h.routePath}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
59
|
+
<iconify-icon icon="solar:bolt-linear" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
60
|
+
<span class="truncate">${h.exportName}</span>
|
|
61
|
+
</a>
|
|
62
|
+
</li>`,
|
|
63
|
+
)
|
|
64
|
+
.join("");
|
|
65
|
+
|
|
66
|
+
return `
|
|
67
|
+
<div id="pane-functions" class="flex flex-col h-full hidden">
|
|
68
|
+
<div class="px-3 pt-5 pb-3">
|
|
69
|
+
<p class="text-[10px] font-semibold uppercase tracking-widest opacity-35 mb-3 px-1">Functions</p>
|
|
70
|
+
<div class="relative">
|
|
71
|
+
<iconify-icon icon="solar:magnifer-linear" width="13" height="13" class="absolute left-2.5 top-1/2 -translate-y-1/2 opacity-35 pointer-events-none"></iconify-icon>
|
|
72
|
+
<input
|
|
73
|
+
type="text"
|
|
74
|
+
id="function-search"
|
|
75
|
+
placeholder="Search functions..."
|
|
76
|
+
class="input input-sm border border-base-200 bg-base-200/50 focus:bg-base-100 focus:border-primary focus:outline-none w-full pl-7 text-xs rounded-lg h-8"
|
|
77
|
+
onkeyup="filterFunctions(this.value)"
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
<nav class="flex-1 overflow-y-auto px-2 pb-4">
|
|
82
|
+
${
|
|
83
|
+
queries.length > 0
|
|
84
|
+
? `<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Queries</p>
|
|
85
|
+
<ul class="flex flex-col gap-0.5">${queryItems}</ul>`
|
|
86
|
+
: ""
|
|
87
|
+
}
|
|
88
|
+
${
|
|
89
|
+
mutations.length > 0
|
|
90
|
+
? `<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Mutations</p>
|
|
91
|
+
<ul class="flex flex-col gap-0.5">${mutationItems}</ul>`
|
|
92
|
+
: ""
|
|
93
|
+
}
|
|
94
|
+
</nav>
|
|
95
|
+
</div>
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function buildDashboardCards(tablesInfo: TableInfo[]): string {
|
|
100
|
+
return tablesInfo
|
|
101
|
+
.map((table) =>
|
|
102
|
+
`
|
|
103
|
+
<a
|
|
104
|
+
href="/admin/table/${table.exportName}"
|
|
105
|
+
class="card bg-base-100 border border-base-200 hover:border-primary/30 hover:shadow-md transition-all cursor-pointer group"
|
|
106
|
+
>
|
|
107
|
+
<div class="card-body p-5">
|
|
108
|
+
<div class="flex items-center gap-3">
|
|
109
|
+
<div class="w-9 h-9 rounded-lg bg-primary/10 flex items-center justify-center">
|
|
110
|
+
<iconify-icon icon="mdi:table" width="20" height="20" class="text-primary"></iconify-icon>
|
|
111
|
+
</div>
|
|
112
|
+
<div>
|
|
113
|
+
<h2 class="font-semibold text-sm capitalize group-hover:text-primary transition-colors">${table.tableName}</h2>
|
|
114
|
+
<p class="text-xs opacity-40 mt-0.5">Manage records</p>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</a>
|
|
119
|
+
`.replace(/\n/g, "\\n"),
|
|
120
|
+
)
|
|
121
|
+
.join("");
|
|
122
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { buildStorageRuntimeHelpers } from "./runtime/helpers";
|
|
2
|
-
import { buildStoragePageRuntime } from "./runtime/storage-page";
|
|
3
|
-
import { buildStorageRouteHandlers } from "./routes";
|
|
4
|
-
|
|
5
|
-
export function buildStorageRoutes(): string {
|
|
6
|
-
return `
|
|
7
|
-
${buildStorageRuntimeHelpers()}
|
|
8
|
-
|
|
9
|
-
${buildStoragePageRuntime()}
|
|
10
|
-
|
|
11
|
-
${buildStorageRouteHandlers()}
|
|
12
|
-
`;
|
|
13
|
-
}
|
|
1
|
+
import { buildStorageRuntimeHelpers } from "./runtime/helpers";
|
|
2
|
+
import { buildStoragePageRuntime } from "./runtime/storage-page";
|
|
3
|
+
import { buildStorageRouteHandlers } from "./routes";
|
|
4
|
+
|
|
5
|
+
export function buildStorageRoutes(): string {
|
|
6
|
+
return `
|
|
7
|
+
${buildStorageRuntimeHelpers()}
|
|
8
|
+
|
|
9
|
+
${buildStoragePageRuntime()}
|
|
10
|
+
|
|
11
|
+
${buildStorageRouteHandlers()}
|
|
12
|
+
`;
|
|
13
|
+
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
export function buildStorageCreateDirectoryRoute(): string {
|
|
2
|
-
return `
|
|
3
|
-
adminApp.post('/storage/directory', async (c) => {
|
|
4
|
-
const bucket = getStorageBucket(c);
|
|
5
|
-
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
-
|
|
7
|
-
const body = await c.req.parseBody();
|
|
8
|
-
const prefix = normalizePrefix((body['prefix'] as string) || '');
|
|
9
|
-
const directory = ((body['directory'] as string) || '').trim();
|
|
10
|
-
|
|
11
|
-
if (directory) {
|
|
12
|
-
const normalizedDirectory = directory
|
|
13
|
-
.split('/')
|
|
14
|
-
.map((part) => part.trim())
|
|
15
|
-
.filter(Boolean)
|
|
16
|
-
.join('/');
|
|
17
|
-
|
|
18
|
-
if (normalizedDirectory) {
|
|
19
|
-
const markerKey = prefix + normalizedDirectory + '/.keep';
|
|
20
|
-
await bucket.put(markerKey, '', {
|
|
21
|
-
httpMetadata: { contentType: 'text/plain; charset=utf-8' },
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return c.redirect(prefixToStoragePath(prefix));
|
|
27
|
-
});
|
|
28
|
-
`;
|
|
29
|
-
}
|
|
1
|
+
export function buildStorageCreateDirectoryRoute(): string {
|
|
2
|
+
return `
|
|
3
|
+
adminApp.post('/storage/directory', async (c) => {
|
|
4
|
+
const bucket = getStorageBucket(c);
|
|
5
|
+
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
+
|
|
7
|
+
const body = await c.req.parseBody();
|
|
8
|
+
const prefix = normalizePrefix((body['prefix'] as string) || '');
|
|
9
|
+
const directory = ((body['directory'] as string) || '').trim();
|
|
10
|
+
|
|
11
|
+
if (directory) {
|
|
12
|
+
const normalizedDirectory = directory
|
|
13
|
+
.split('/')
|
|
14
|
+
.map((part) => part.trim())
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.join('/');
|
|
17
|
+
|
|
18
|
+
if (normalizedDirectory) {
|
|
19
|
+
const markerKey = prefix + normalizedDirectory + '/.keep';
|
|
20
|
+
await bucket.put(markerKey, '', {
|
|
21
|
+
httpMetadata: { contentType: 'text/plain; charset=utf-8' },
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return c.redirect(prefixToStoragePath(prefix));
|
|
27
|
+
});
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
export function buildStorageDeleteRoute(): string {
|
|
2
|
-
return `
|
|
3
|
-
adminApp.delete('/storage/delete', async (c) => {
|
|
4
|
-
const bucket = getStorageBucket(c);
|
|
5
|
-
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
-
|
|
7
|
-
const key = c.req.query('key');
|
|
8
|
-
const prefix = normalizePrefix(c.req.query('prefix') || '');
|
|
9
|
-
|
|
10
|
-
if (key) {
|
|
11
|
-
await bucket.delete(key);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
c.header('HX-Redirect', prefixToStoragePath(prefix));
|
|
15
|
-
return c.html('');
|
|
16
|
-
});
|
|
17
|
-
`;
|
|
18
|
-
}
|
|
1
|
+
export function buildStorageDeleteRoute(): string {
|
|
2
|
+
return `
|
|
3
|
+
adminApp.delete('/storage/delete', async (c) => {
|
|
4
|
+
const bucket = getStorageBucket(c);
|
|
5
|
+
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
+
|
|
7
|
+
const key = c.req.query('key');
|
|
8
|
+
const prefix = normalizePrefix(c.req.query('prefix') || '');
|
|
9
|
+
|
|
10
|
+
if (key) {
|
|
11
|
+
await bucket.delete(key);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
c.header('HX-Redirect', prefixToStoragePath(prefix));
|
|
15
|
+
return c.html('');
|
|
16
|
+
});
|
|
17
|
+
`;
|
|
18
|
+
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
export function buildStorageDownloadRoute(): string {
|
|
2
|
-
return `
|
|
3
|
-
adminApp.get('/storage/download', async (c) => {
|
|
4
|
-
const bucket = getStorageBucket(c);
|
|
5
|
-
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
-
|
|
7
|
-
const key = c.req.query('key');
|
|
8
|
-
if (!key) return c.text("Missing key", 400);
|
|
9
|
-
|
|
10
|
-
const object = await bucket.get(key);
|
|
11
|
-
if (!object) return c.text("Not found", 404);
|
|
12
|
-
|
|
13
|
-
const headers = new Headers();
|
|
14
|
-
object.writeHttpMetadata(headers);
|
|
15
|
-
headers.set('etag', object.httpEtag);
|
|
16
|
-
|
|
17
|
-
const filename = key.split('/').pop() || 'download';
|
|
18
|
-
headers.set('Content-Disposition', \`attachment; filename="\${filename}"\`);
|
|
19
|
-
|
|
20
|
-
return new Response(object.body, { headers });
|
|
21
|
-
});
|
|
22
|
-
`;
|
|
23
|
-
}
|
|
1
|
+
export function buildStorageDownloadRoute(): string {
|
|
2
|
+
return `
|
|
3
|
+
adminApp.get('/storage/download', async (c) => {
|
|
4
|
+
const bucket = getStorageBucket(c);
|
|
5
|
+
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
+
|
|
7
|
+
const key = c.req.query('key');
|
|
8
|
+
if (!key) return c.text("Missing key", 400);
|
|
9
|
+
|
|
10
|
+
const object = await bucket.get(key);
|
|
11
|
+
if (!object) return c.text("Not found", 404);
|
|
12
|
+
|
|
13
|
+
const headers = new Headers();
|
|
14
|
+
object.writeHttpMetadata(headers);
|
|
15
|
+
headers.set('etag', object.httpEtag);
|
|
16
|
+
|
|
17
|
+
const filename = key.split('/').pop() || 'download';
|
|
18
|
+
headers.set('Content-Disposition', \`attachment; filename="\${filename}"\`);
|
|
19
|
+
|
|
20
|
+
return new Response(object.body, { headers });
|
|
21
|
+
});
|
|
22
|
+
`;
|
|
23
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { buildStorageListRoute } from "./list-route";
|
|
2
|
-
import { buildStorageUploadRoute } from "./upload-route";
|
|
3
|
-
import { buildStorageDeleteRoute } from "./delete-route";
|
|
4
|
-
import { buildStorageCreateDirectoryRoute } from "./create-directory-route";
|
|
5
|
-
import { buildStorageDownloadRoute } from "./download-route";
|
|
6
|
-
import { buildStoragePreviewRoute } from "./preview-route";
|
|
7
|
-
|
|
8
|
-
export function buildStorageRouteHandlers(): string {
|
|
9
|
-
return `
|
|
10
|
-
${buildStorageDownloadRoute()}
|
|
11
|
-
|
|
12
|
-
${buildStoragePreviewRoute()}
|
|
13
|
-
|
|
14
|
-
${buildStorageUploadRoute()}
|
|
15
|
-
|
|
16
|
-
${buildStorageDeleteRoute()}
|
|
17
|
-
|
|
18
|
-
${buildStorageCreateDirectoryRoute()}
|
|
19
|
-
|
|
20
|
-
${buildStorageListRoute()}
|
|
21
|
-
`;
|
|
22
|
-
}
|
|
1
|
+
import { buildStorageListRoute } from "./list-route";
|
|
2
|
+
import { buildStorageUploadRoute } from "./upload-route";
|
|
3
|
+
import { buildStorageDeleteRoute } from "./delete-route";
|
|
4
|
+
import { buildStorageCreateDirectoryRoute } from "./create-directory-route";
|
|
5
|
+
import { buildStorageDownloadRoute } from "./download-route";
|
|
6
|
+
import { buildStoragePreviewRoute } from "./preview-route";
|
|
7
|
+
|
|
8
|
+
export function buildStorageRouteHandlers(): string {
|
|
9
|
+
return `
|
|
10
|
+
${buildStorageDownloadRoute()}
|
|
11
|
+
|
|
12
|
+
${buildStoragePreviewRoute()}
|
|
13
|
+
|
|
14
|
+
${buildStorageUploadRoute()}
|
|
15
|
+
|
|
16
|
+
${buildStorageDeleteRoute()}
|
|
17
|
+
|
|
18
|
+
${buildStorageCreateDirectoryRoute()}
|
|
19
|
+
|
|
20
|
+
${buildStorageListRoute()}
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
export function buildStorageListRoute(): string {
|
|
2
|
-
return `
|
|
3
|
-
const handleStorageListRoute = async (c: any) => {
|
|
4
|
-
const bucket = getStorageBucket(c);
|
|
5
|
-
if (!bucket) {
|
|
6
|
-
return renderStoragePage(c, buildStorageNotConfiguredContent());
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const pathPrefix = storagePathToPrefix(c.req.path);
|
|
10
|
-
const queryPrefix = normalizePrefix(c.req.query('prefix') || '');
|
|
11
|
-
const prefix = pathPrefix || queryPrefix;
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const listed = await bucket.list({ prefix, delimiter: '/' });
|
|
15
|
-
const content = buildStorageListingContent(listed, prefix);
|
|
16
|
-
return renderStoragePage(c, content);
|
|
17
|
-
} catch (e: any) {
|
|
18
|
-
return c.text("Error listing storage: " + e.message, 500);
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
adminApp.get('/storage', handleStorageListRoute);
|
|
23
|
-
adminApp.get('/storage/*', handleStorageListRoute);
|
|
24
|
-
`;
|
|
25
|
-
}
|
|
1
|
+
export function buildStorageListRoute(): string {
|
|
2
|
+
return `
|
|
3
|
+
const handleStorageListRoute = async (c: any) => {
|
|
4
|
+
const bucket = getStorageBucket(c);
|
|
5
|
+
if (!bucket) {
|
|
6
|
+
return renderStoragePage(c, buildStorageNotConfiguredContent());
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const pathPrefix = storagePathToPrefix(c.req.path);
|
|
10
|
+
const queryPrefix = normalizePrefix(c.req.query('prefix') || '');
|
|
11
|
+
const prefix = pathPrefix || queryPrefix;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const listed = await bucket.list({ prefix, delimiter: '/' });
|
|
15
|
+
const content = buildStorageListingContent(listed, prefix);
|
|
16
|
+
return renderStoragePage(c, content);
|
|
17
|
+
} catch (e: any) {
|
|
18
|
+
return c.text("Error listing storage: " + e.message, 500);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
adminApp.get('/storage', handleStorageListRoute);
|
|
23
|
+
adminApp.get('/storage/*', handleStorageListRoute);
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
export function buildStoragePreviewRoute(): string {
|
|
2
|
-
return `
|
|
3
|
-
adminApp.get('/storage/preview', async (c) => {
|
|
4
|
-
const bucket = getStorageBucket(c);
|
|
5
|
-
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
-
|
|
7
|
-
const key = c.req.query('key');
|
|
8
|
-
if (!key) return c.text("Missing key", 400);
|
|
9
|
-
|
|
10
|
-
const object = await bucket.get(key);
|
|
11
|
-
if (!object) return c.text("Not found", 404);
|
|
12
|
-
|
|
13
|
-
const headers = new Headers();
|
|
14
|
-
object.writeHttpMetadata(headers);
|
|
15
|
-
headers.set('etag', object.httpEtag);
|
|
16
|
-
headers.set('Cache-Control', 'public, max-age=31536000');
|
|
17
|
-
|
|
18
|
-
return new Response(object.body, { headers });
|
|
19
|
-
});
|
|
20
|
-
`;
|
|
21
|
-
}
|
|
1
|
+
export function buildStoragePreviewRoute(): string {
|
|
2
|
+
return `
|
|
3
|
+
adminApp.get('/storage/preview', async (c) => {
|
|
4
|
+
const bucket = getStorageBucket(c);
|
|
5
|
+
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
+
|
|
7
|
+
const key = c.req.query('key');
|
|
8
|
+
if (!key) return c.text("Missing key", 400);
|
|
9
|
+
|
|
10
|
+
const object = await bucket.get(key);
|
|
11
|
+
if (!object) return c.text("Not found", 404);
|
|
12
|
+
|
|
13
|
+
const headers = new Headers();
|
|
14
|
+
object.writeHttpMetadata(headers);
|
|
15
|
+
headers.set('etag', object.httpEtag);
|
|
16
|
+
headers.set('Cache-Control', 'public, max-age=31536000');
|
|
17
|
+
|
|
18
|
+
return new Response(object.body, { headers });
|
|
19
|
+
});
|
|
20
|
+
`;
|
|
21
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
export function buildStorageUploadRoute(): string {
|
|
2
|
-
return `
|
|
3
|
-
adminApp.post('/storage/upload', async (c) => {
|
|
4
|
-
const bucket = getStorageBucket(c);
|
|
5
|
-
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
-
|
|
7
|
-
const body = await c.req.parseBody();
|
|
8
|
-
const file = body['file'];
|
|
9
|
-
const prefix = normalizePrefix((body['prefix'] as string) || '');
|
|
10
|
-
|
|
11
|
-
if (file && file instanceof File) {
|
|
12
|
-
const key = prefix + file.name;
|
|
13
|
-
await bucket.put(key, await file.arrayBuffer(), {
|
|
14
|
-
httpMetadata: { contentType: file.type },
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return c.redirect(prefixToStoragePath(prefix));
|
|
19
|
-
});
|
|
20
|
-
`;
|
|
21
|
-
}
|
|
1
|
+
export function buildStorageUploadRoute(): string {
|
|
2
|
+
return `
|
|
3
|
+
adminApp.post('/storage/upload', async (c) => {
|
|
4
|
+
const bucket = getStorageBucket(c);
|
|
5
|
+
if (!bucket) return c.text("Storage not configured", 400);
|
|
6
|
+
|
|
7
|
+
const body = await c.req.parseBody();
|
|
8
|
+
const file = body['file'];
|
|
9
|
+
const prefix = normalizePrefix((body['prefix'] as string) || '');
|
|
10
|
+
|
|
11
|
+
if (file && file instanceof File) {
|
|
12
|
+
const key = prefix + file.name;
|
|
13
|
+
await bucket.put(key, await file.arrayBuffer(), {
|
|
14
|
+
httpMetadata: { contentType: file.type },
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return c.redirect(prefixToStoragePath(prefix));
|
|
19
|
+
});
|
|
20
|
+
`;
|
|
21
|
+
}
|