alepha 0.20.2 → 0.20.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/README.md +0 -1
- package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/assets/swagger-ui/swagger-ui.css +1 -1
- package/dist/api/audits/index.browser.js +49 -0
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.js +49 -0
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +2 -61
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +4 -4
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.d.ts +1 -10
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/parameters/index.browser.js +37 -0
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +12 -68
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +57 -4
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/users/index.browser.js +6 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +148 -227
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +60 -14
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +2 -1
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/bucket/index.d.ts +77 -107
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +153 -5
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +12 -2
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +26 -0
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +11 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js +11 -1
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/captcha/index.js.map +1 -1
- package/dist/cli/config/index.d.ts +7 -5
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js +2 -3
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +637 -11660
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +707 -532
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +4 -8
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js +20 -16
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +51 -77
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +65 -15
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +10 -13
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +30 -12
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/command/index.js +1 -1
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +27 -3
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +8 -11
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +27 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +27 -3
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +27 -3
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/datetime/index.d.ts +69 -10
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +135 -13
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/core/index.js.map +1 -1
- package/dist/email/smtp/index.js +130 -16
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +30 -2
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +35 -12
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.js.map +1 -1
- package/dist/logger/index.js +32 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +238 -31
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +198 -67
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +2 -362
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +18 -409
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +41 -194
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +27 -422
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js +17 -20
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +1 -5
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js +17 -20
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/react/core/index.d.ts +102 -1
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +65 -1
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +6 -0
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +7 -7
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +7 -1
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +6 -0
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.js +22 -17
- package/dist/react/intro/index.js.map +1 -1
- package/dist/react/router/index.browser.js +98 -4
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +58 -5
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +122 -6
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/{chunk-DBEY4PJZ.js → chunk-6Ep1yQYe.js} +1 -1
- package/dist/react/testing/index.js +1 -1
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +195 -1
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js +64 -1
- package/dist/react/ui/index.js.map +1 -1
- package/dist/react/websocket/index.js.map +1 -1
- package/dist/redis/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +1 -2
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +1 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js +1 -1
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +2 -2
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +24 -10
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.browser.js +10 -3
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +1 -4
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +47 -9
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.js +19 -1
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +4 -5
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js.map +1 -1
- package/dist/system/index.js.map +1 -1
- package/dist/system/index.workerd.js.map +1 -1
- package/dist/topic/core/index.js.map +1 -1
- package/dist/websocket/index.browser.js +32 -5
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +3 -1
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +42 -6
- package/dist/websocket/index.js.map +1 -1
- package/package.json +685 -274
- package/src/api/files/__tests__/FileController.spec.ts +1 -1
- package/src/api/jobs/__tests__/$job.spec.ts +5 -1
- package/src/api/parameters/services/ParameterProvider.ts +21 -4
- package/src/api/users/__tests__/SessionService.spec.ts +99 -0
- package/src/api/users/__tests__/UserJobs.spec.ts +67 -0
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +15 -0
- package/src/api/users/entities/sessions.ts +6 -0
- package/src/api/users/jobs/UserJobs.ts +44 -17
- package/src/api/users/providers/RealmProvider.ts +4 -0
- package/src/api/users/schemas/userQuerySchema.ts +0 -1
- package/src/api/users/services/SessionService.ts +27 -0
- package/src/api/users/services/UserService.ts +1 -5
- package/src/api/verifications/__tests__/CodeVerification.spec.ts +14 -0
- package/src/api/verifications/__tests__/LinkVerification.spec.ts +14 -0
- package/src/api/verifications/services/VerificationService.ts +1 -0
- package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +74 -0
- package/src/bucket/index.ts +19 -2
- package/src/bucket/primitives/$bucket.ts +9 -1
- package/src/bucket/providers/CloudflareR2Provider.ts +2 -137
- package/src/bucket/providers/NodeS3BucketProvider.ts +218 -0
- package/src/cache/core/index.ts +29 -0
- package/src/cache/core/primitives/$cache.ts +14 -1
- package/src/cli/config/defineConfig.ts +13 -15
- package/src/cli/core/__tests__/init.spec.ts +214 -7
- package/src/cli/core/commands/init.ts +12 -0
- package/src/cli/core/services/PackageManagerUtils.ts +23 -6
- package/src/cli/core/services/ProjectScaffolder.ts +315 -33
- package/src/cli/core/tasks/BuildCloudflareTask.ts +5 -0
- package/src/cli/core/tasks/BuildDockerTask.ts +9 -10
- package/src/cli/core/tasks/BuildServerTask.ts +8 -0
- package/src/cli/core/templates/agentMd.ts +2 -10
- package/src/cli/core/templates/apiIndexTs.ts +23 -1
- package/src/cli/core/templates/componentsJsonTs.ts +39 -0
- package/src/cli/core/templates/mainCss.ts +1 -0
- package/src/cli/core/templates/saasAdminLayoutTsx.ts +77 -0
- package/src/cli/core/templates/saasAdminPagesTsx.ts +26 -0
- package/src/cli/core/templates/saasAuthLayoutTsx.ts +20 -0
- package/src/cli/core/templates/saasAuthPagesTsx.ts +62 -0
- package/src/cli/core/templates/saasRealmProviderTs.ts +46 -0
- package/src/cli/core/templates/webAppRouterTs.ts +104 -1
- package/src/cli/core/templates/webIndexTs.ts +23 -1
- package/src/cli/devtools/index.ts +12 -26
- package/src/cli/platform/__tests__/SecretsCommand.spec.ts +2 -0
- package/src/cli/platform/index.ts +15 -24
- package/src/cli/vendor/atoms/vendorOptions.ts +1 -1
- package/src/cli/vendor/index.ts +14 -23
- package/src/command/providers/CliProvider.ts +1 -1
- package/src/core/Alepha.ts +11 -1
- package/src/core/helpers/ref.ts +18 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/interfaces/Service.ts +3 -1
- package/src/core/providers/SchemaValidator.ts +9 -1
- package/src/core/providers/TypeProvider.ts +2 -3
- package/src/datetime/REFACTORING.md +118 -0
- package/src/datetime/providers/DateTimeProvider.ts +203 -24
- package/src/lock/core/index.ts +31 -0
- package/src/lock/core/primitives/$lock.ts +14 -1
- package/src/logger/services/Logger.ts +1 -1
- package/src/mcp/__tests__/$resource.spec.ts +1 -1
- package/src/mcp/__tests__/$tool.spec.ts +1 -1
- package/src/mcp/__tests__/McpServerProvider.spec.ts +1 -1
- package/src/mcp/__tests__/jsonrpc.spec.ts +1 -1
- package/src/mcp/helpers/jsonrpc.ts +26 -1
- package/src/mcp/index.ts +10 -5
- package/src/mcp/interfaces/McpTypes.ts +83 -6
- package/src/mcp/primitives/$prompt.ts +18 -1
- package/src/mcp/primitives/$resource.ts +18 -1
- package/src/mcp/primitives/$tool.ts +83 -7
- package/src/mcp/providers/McpServerProvider.ts +74 -16
- package/src/mcp/transports/StreamableHttpMcpTransport.ts +226 -0
- package/src/orm/REFACTORING.md +330 -0
- package/src/orm/__tests__/$repository-tests.ts +1 -0
- package/src/orm/__tests__/orm-next-tests.ts +2 -67
- package/src/orm/__tests__/orm-next.spec.ts +0 -21
- package/src/orm/core/index.shared.ts +0 -2
- package/src/orm/core/index.ts +1 -2
- package/src/orm/core/primitives/$repository.ts +3 -6
- package/src/orm/core/primitives/$transactional.ts +11 -0
- package/src/orm/core/providers/drivers/DatabaseProvider.ts +0 -5
- package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +11 -13
- package/src/orm/core/schemas/updateSchema.ts +1 -1
- package/src/orm/core/services/ModelBuilder.ts +1 -13
- package/src/orm/core/services/PgRelationManager.ts +4 -2
- package/src/orm/core/services/Repository.ts +1 -42
- package/src/orm/core/services/SqliteModelBuilder.ts +2 -33
- package/src/orm/postgres/services/PostgresModelBuilder.ts +10 -45
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +86 -0
- package/src/react/core/hooks/useQuery.ts +153 -0
- package/src/react/core/index.ts +1 -0
- package/src/react/form/services/FormModel.ts +15 -6
- package/src/react/form/services/parseField.ts +8 -0
- package/src/react/i18n/providers/I18nProvider.ts +8 -2
- package/src/react/intro/components/GettingStartedAuthSlide.tsx +11 -4
- package/src/react/router/__tests__/$page.spec.tsx +0 -16
- package/src/react/router/__tests__/ReactBrowserProvider.browser.spec.ts +213 -2
- package/src/react/router/__tests__/ssr.spec.tsx +339 -0
- package/src/react/router/primitives/$page.ts +28 -4
- package/src/react/router/providers/ReactBrowserProvider.ts +73 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +1 -1
- package/src/react/router/providers/ReactPageProvider.ts +27 -9
- package/src/react/router/providers/ReactPreloadProvider.ts +1 -1
- package/src/react/router/providers/ReactServerProvider.ts +1 -0
- package/src/react/ui/atoms/uiThemeListAtom.ts +36 -0
- package/src/react/ui/index.ts +6 -0
- package/src/react/ui/services/SchemaControl.ts +209 -0
- package/src/scheduler/providers/CronProvider.ts +1 -1
- package/src/security/primitives/$basicAuth.ts +1 -1
- package/src/security/primitives/$issuer.ts +6 -3
- package/src/server/auth/providers/ServerAuthProvider.ts +5 -1
- package/src/server/core/__tests__/ServerRouterProvider-serializationError.spec.ts +75 -0
- package/src/server/core/__tests__/ServerRouterProvider-validationError.spec.ts +306 -0
- package/src/server/core/errors/ValidationError.ts +13 -1
- package/src/server/core/interfaces/ServerRequest.ts +1 -0
- package/src/server/core/primitives/$action.ts +16 -5
- package/src/server/core/providers/ServerProvider.ts +1 -1
- package/src/server/core/providers/ServerRouterProvider.ts +28 -6
- package/src/server/core/services/HttpClient.ts +1 -1
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +6 -8
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +10 -4
- package/src/websocket/services/WebSocketClient.ts +11 -5
- package/src/mcp/transports/SseMcpTransport.ts +0 -182
- package/src/orm/core/__tests__/parseQueryString.spec.ts +0 -196
- package/src/orm/core/helpers/parseQueryString.ts +0 -502
- package/src/orm/core/primitives/$view.ts +0 -88
|
@@ -11,6 +11,7 @@ export const mainCss = (opts: { tailwind?: boolean } = {}) => {
|
|
|
11
11
|
*
|
|
12
12
|
* Options:
|
|
13
13
|
* - Tailwind CSS: Use \`alepha init --tailwind\` to add Tailwind CSS
|
|
14
|
+
* - shadcn/ui: Use \`alepha init --shadcn\` to add shadcn/ui setup
|
|
14
15
|
* - Raw CSS: Write your own styles below
|
|
15
16
|
*/
|
|
16
17
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SaaS admin layout — full AppShell on /admin with a sidebar, breadcrumbs,
|
|
3
|
+
* a Sonner toaster, and a confirm provider. The page list grows with
|
|
4
|
+
* whatever `admin-*` registry components the user adds.
|
|
5
|
+
*
|
|
6
|
+
* All UI primitives come from `src/components/*` where `shadcn add` drops
|
|
7
|
+
* them; alepha app code lives in `src/web/*` and references them via the
|
|
8
|
+
* `@/components/*` alias.
|
|
9
|
+
*/
|
|
10
|
+
export const saasAdminLayoutTsx = () =>
|
|
11
|
+
`import { AppShell } from "@/components/app-shell";
|
|
12
|
+
import { Toaster } from "@/components/ui/sonner";
|
|
13
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
14
|
+
import { DialogProvider } from "@/components/use-dialog";
|
|
15
|
+
import { NestedView, useRouterState } from "alepha/react/router";
|
|
16
|
+
import { ShieldCheck, Users } from "lucide-react";
|
|
17
|
+
|
|
18
|
+
const NAV = [
|
|
19
|
+
{
|
|
20
|
+
label: "Identity",
|
|
21
|
+
items: [
|
|
22
|
+
{ href: "/admin/users", label: "Users", icon: Users },
|
|
23
|
+
{ href: "/admin/sessions", label: "Sessions", icon: ShieldCheck },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
] as const;
|
|
27
|
+
|
|
28
|
+
const findCrumbs = (pathname: string): { label: string; href?: string }[] => {
|
|
29
|
+
for (const group of NAV) {
|
|
30
|
+
const match = group.items.find((it) => it.href === pathname);
|
|
31
|
+
if (match) return [{ label: group.label }, { label: match.label }];
|
|
32
|
+
}
|
|
33
|
+
return [];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const AdminLayout = () => {
|
|
37
|
+
const state = useRouterState();
|
|
38
|
+
const crumbs = findCrumbs(state.url.pathname);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<TooltipProvider>
|
|
42
|
+
<DialogProvider>
|
|
43
|
+
<AppShell
|
|
44
|
+
brand={
|
|
45
|
+
<a
|
|
46
|
+
href="/admin"
|
|
47
|
+
className="flex items-center gap-2 px-2 py-2 font-semibold group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:px-0"
|
|
48
|
+
>
|
|
49
|
+
<span className="bg-primary text-primary-foreground flex size-7 shrink-0 items-center justify-center rounded">
|
|
50
|
+
α
|
|
51
|
+
</span>
|
|
52
|
+
<span className="truncate group-data-[collapsible=icon]:hidden">
|
|
53
|
+
Admin
|
|
54
|
+
</span>
|
|
55
|
+
</a>
|
|
56
|
+
}
|
|
57
|
+
nav={NAV.map((group) => ({
|
|
58
|
+
label: group.label,
|
|
59
|
+
items: group.items.map((it) => ({
|
|
60
|
+
href: it.href,
|
|
61
|
+
label: it.label,
|
|
62
|
+
icon: it.icon,
|
|
63
|
+
active: it.href === state.url.pathname,
|
|
64
|
+
})),
|
|
65
|
+
}))}
|
|
66
|
+
breadcrumbs={crumbs.length ? crumbs : undefined}
|
|
67
|
+
>
|
|
68
|
+
<NestedView />
|
|
69
|
+
</AppShell>
|
|
70
|
+
<Toaster />
|
|
71
|
+
</DialogProvider>
|
|
72
|
+
</TooltipProvider>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export default AdminLayout;
|
|
77
|
+
`;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin pages — each is a thin wrapper around the matching `admin-*`
|
|
3
|
+
* registry component (placed at `src/components/admin/*`). The starter
|
|
4
|
+
* ships with Users + Sessions; add more by `shadcn add @alepha/admin-…`
|
|
5
|
+
* and a matching `$page(...)` in AppRouter.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const saasAdminUsersTsx = () =>
|
|
9
|
+
`import { AdminUsers } from "@/components/admin/admin-users";
|
|
10
|
+
|
|
11
|
+
const AdminUsersPage = () => {
|
|
12
|
+
return <AdminUsers />;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default AdminUsersPage;
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
export const saasAdminSessionsTsx = () =>
|
|
19
|
+
`import { AdminSessions } from "@/components/admin/admin-sessions";
|
|
20
|
+
|
|
21
|
+
const AdminSessionsPage = () => {
|
|
22
|
+
return <AdminSessions />;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default AdminSessionsPage;
|
|
26
|
+
`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SaaS auth layout — wraps every /auth/* page with a centered card.
|
|
3
|
+
* Routes (login, register, reset-password, verify-email) are mounted as
|
|
4
|
+
* children so they share this shell.
|
|
5
|
+
*/
|
|
6
|
+
export const saasAuthLayoutTsx = () =>
|
|
7
|
+
`import { NestedView } from "alepha/react/router";
|
|
8
|
+
|
|
9
|
+
const AuthLayout = () => {
|
|
10
|
+
return (
|
|
11
|
+
<div className="bg-background flex min-h-screen items-center justify-center p-4">
|
|
12
|
+
<div className="w-full max-w-md">
|
|
13
|
+
<NestedView />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default AuthLayout;
|
|
20
|
+
`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-page wrapper around the registry components. The registry component
|
|
3
|
+
* receives the realm config from the page loader; the page itself stays a
|
|
4
|
+
* thin shell so apps can layer their branding around it.
|
|
5
|
+
*
|
|
6
|
+
* Registry components land at `src/components/auth/*` (shadcn defaults).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const saasAuthLoginTsx = () =>
|
|
10
|
+
`import { AuthLogin } from "@/components/auth/auth-login";
|
|
11
|
+
import type { RealmConfig } from "alepha/api/users";
|
|
12
|
+
|
|
13
|
+
export interface AuthLoginPageProps {
|
|
14
|
+
realmConfig: RealmConfig;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const AuthLoginPage = (props: AuthLoginPageProps) => {
|
|
18
|
+
return <AuthLogin realmConfig={props.realmConfig} />;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default AuthLoginPage;
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
export const saasAuthRegisterTsx = () =>
|
|
25
|
+
`import { AuthRegister } from "@/components/auth/auth-register";
|
|
26
|
+
import type { RealmConfig } from "alepha/api/users";
|
|
27
|
+
|
|
28
|
+
export interface AuthRegisterPageProps {
|
|
29
|
+
realmConfig: RealmConfig;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const AuthRegisterPage = (props: AuthRegisterPageProps) => {
|
|
33
|
+
return <AuthRegister realmConfig={props.realmConfig} />;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default AuthRegisterPage;
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
export const saasAuthResetPasswordTsx = () =>
|
|
40
|
+
`import { AuthResetPassword } from "@/components/auth/auth-reset-password";
|
|
41
|
+
import type { RealmConfig } from "alepha/api/users";
|
|
42
|
+
|
|
43
|
+
export interface AuthResetPasswordPageProps {
|
|
44
|
+
realmConfig: RealmConfig;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const AuthResetPasswordPage = (props: AuthResetPasswordPageProps) => {
|
|
48
|
+
return <AuthResetPassword realmConfig={props.realmConfig} />;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default AuthResetPasswordPage;
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
export const saasAuthVerifyEmailTsx = () =>
|
|
55
|
+
`import { AuthVerifyEmail } from "@/components/auth/auth-verify-email";
|
|
56
|
+
|
|
57
|
+
const AuthVerifyEmailPage = () => {
|
|
58
|
+
return <AuthVerifyEmail />;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default AuthVerifyEmailPage;
|
|
62
|
+
`;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface SaasRealmProviderOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Email seeded as the default admin. Detected from `git config user.email`
|
|
4
|
+
* at init time; falls through to `admin@example.com` if git isn't configured.
|
|
5
|
+
*/
|
|
6
|
+
adminEmail?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Realm provider scaffolded by `alepha init --saas`.
|
|
11
|
+
*
|
|
12
|
+
* Minimal hello-world setup: credentials login with email, one admin seeded
|
|
13
|
+
* with the developer's git email at scaffold time, and an `admin:ui`
|
|
14
|
+
* permission used by the AppRouter to gate `/admin/*`. The default `admin`
|
|
15
|
+
* role grants `*` (so it inherits `admin:ui`); the default `user` role
|
|
16
|
+
* excludes `admin:*` (so non-admins get a 403 before the shell renders).
|
|
17
|
+
*
|
|
18
|
+
* Add `$env`, more permissions, or stricter settings as the project grows.
|
|
19
|
+
*/
|
|
20
|
+
export const saasRealmProviderTs = (options: SaasRealmProviderOptions = {}) => {
|
|
21
|
+
const adminEmail = options.adminEmail ?? "admin@example.com";
|
|
22
|
+
return `import { $realm } from "alepha/api/users";
|
|
23
|
+
import { $permission } from "alepha/security";
|
|
24
|
+
|
|
25
|
+
export class RealmProvider {
|
|
26
|
+
/**
|
|
27
|
+
* Permission required to open the admin UI. Wired into AppRouter.adminLayout
|
|
28
|
+
* via \`$secure({ permissions: ["admin:ui"] })\`.
|
|
29
|
+
*/
|
|
30
|
+
adminUi = $permission({
|
|
31
|
+
group: "admin",
|
|
32
|
+
name: "ui",
|
|
33
|
+
description: "Access to the admin UI shell",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
realm = $realm({
|
|
37
|
+
settings: {
|
|
38
|
+
adminEmails: [${JSON.stringify(adminEmail)}],
|
|
39
|
+
},
|
|
40
|
+
identities: {
|
|
41
|
+
credentials: true,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
};
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface WebAppRouterOptions {
|
|
2
|
+
api?: boolean;
|
|
3
|
+
saas?: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const webAppRouterTs = (options: WebAppRouterOptions) => {
|
|
7
|
+
if (options.saas) {
|
|
8
|
+
return saasAppRouterTs();
|
|
9
|
+
}
|
|
10
|
+
return basicAppRouterTs(options);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const basicAppRouterTs = (options: WebAppRouterOptions) => {
|
|
2
14
|
const imports: string[] = ['import { $page } from "alepha/react/router";'];
|
|
3
15
|
const classMembers: string[] = [];
|
|
4
16
|
|
|
@@ -27,3 +39,94 @@ export class AppRouter {
|
|
|
27
39
|
${classMembers.join("\n\n")}
|
|
28
40
|
}`;
|
|
29
41
|
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* SaaS router wires three trees onto the app:
|
|
45
|
+
* / → Home
|
|
46
|
+
* /auth/* → AuthLayout + login / register / reset / verify
|
|
47
|
+
* /admin/* → AdminLayout + users / sessions / api-keys / parameters / audits
|
|
48
|
+
*
|
|
49
|
+
* Each auth page resolves the realm config from its loader, so the registry
|
|
50
|
+
* components render with everything they need on first paint.
|
|
51
|
+
*/
|
|
52
|
+
const saasAppRouterTs =
|
|
53
|
+
() => `import type { RealmController } from "alepha/api/users";
|
|
54
|
+
import { $page, NotFound } from "alepha/react/router";
|
|
55
|
+
import { $secure } from "alepha/security";
|
|
56
|
+
import { $client } from "alepha/server/links";
|
|
57
|
+
import type { HelloController } from "../api/controllers/HelloController.ts";
|
|
58
|
+
|
|
59
|
+
export class AppRouter {
|
|
60
|
+
protected readonly api = $client<HelloController>();
|
|
61
|
+
protected readonly realmApi = $client<RealmController>();
|
|
62
|
+
|
|
63
|
+
home = $page({
|
|
64
|
+
path: "/",
|
|
65
|
+
lazy: () => import("./components/Home.tsx"),
|
|
66
|
+
loader: () => this.api.hello(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ── /auth — login, register, reset, verify ─────────────────────────────
|
|
70
|
+
authLayout = $page({
|
|
71
|
+
path: "/auth",
|
|
72
|
+
lazy: () => import("./components/auth/AuthLayout.tsx"),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
login = $page({
|
|
76
|
+
parent: this.authLayout,
|
|
77
|
+
path: "/login",
|
|
78
|
+
name: "login",
|
|
79
|
+
head: { title: "Sign in" },
|
|
80
|
+
lazy: () => import("./components/auth/Login.tsx"),
|
|
81
|
+
loader: async () => ({ realmConfig: await this.realmApi.getRealmConfig() }),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
register = $page({
|
|
85
|
+
parent: this.authLayout,
|
|
86
|
+
path: "/register",
|
|
87
|
+
name: "register",
|
|
88
|
+
head: { title: "Sign up" },
|
|
89
|
+
lazy: () => import("./components/auth/Register.tsx"),
|
|
90
|
+
loader: async () => ({ realmConfig: await this.realmApi.getRealmConfig() }),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
resetPassword = $page({
|
|
94
|
+
parent: this.authLayout,
|
|
95
|
+
path: "/reset-password",
|
|
96
|
+
head: { title: "Reset password" },
|
|
97
|
+
lazy: () => import("./components/auth/ResetPassword.tsx"),
|
|
98
|
+
loader: async () => ({ realmConfig: await this.realmApi.getRealmConfig() }),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
verifyEmail = $page({
|
|
102
|
+
parent: this.authLayout,
|
|
103
|
+
path: "/verify-email",
|
|
104
|
+
head: { title: "Verify email" },
|
|
105
|
+
lazy: () => import("./components/auth/VerifyEmail.tsx"),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ── /admin — gated by 'admin:ui' permission, declared in RealmProvider.
|
|
109
|
+
// Children inherit the gate via the parent chain.
|
|
110
|
+
adminLayout = $page({
|
|
111
|
+
path: "/admin",
|
|
112
|
+
use: [$secure({ permissions: ["admin:ui"] })],
|
|
113
|
+
lazy: () => import("./components/admin/AdminLayout.tsx"),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
adminUsers = $page({
|
|
117
|
+
parent: this.adminLayout,
|
|
118
|
+
path: "/users",
|
|
119
|
+
head: { title: "Users" },
|
|
120
|
+
lazy: () => import("./components/admin/Users.tsx"),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
adminSessions = $page({
|
|
124
|
+
parent: this.adminLayout,
|
|
125
|
+
path: "/sessions",
|
|
126
|
+
head: { title: "Sessions" },
|
|
127
|
+
lazy: () => import("./components/admin/Sessions.tsx"),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
notFound = $page({ path: "/*", component: NotFound });
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
export interface WebIndexTsOptions {
|
|
2
2
|
appName?: string;
|
|
3
|
+
/**
|
|
4
|
+
* SaaS bundle: auth pages need `useAuth()` (ReactAuth) which lives in the
|
|
5
|
+
* `alepha.react.auth` module. Importing it here registers ReactAuth in the
|
|
6
|
+
* container so the auth-* registry components can inject it.
|
|
7
|
+
*/
|
|
8
|
+
saas?: boolean;
|
|
3
9
|
}
|
|
4
10
|
|
|
5
11
|
export const webIndexTs = (options: WebIndexTsOptions = {}) => {
|
|
6
|
-
const { appName = "app" } = options;
|
|
12
|
+
const { appName = "app", saas = false } = options;
|
|
13
|
+
|
|
14
|
+
if (saas) {
|
|
15
|
+
return `
|
|
16
|
+
import { $module } from "alepha";
|
|
17
|
+
import { AlephaReactAuth } from "alepha/react/auth";
|
|
18
|
+
import { AlephaReactI18n } from "alepha/react/i18n";
|
|
19
|
+
import { AppRouter } from "./AppRouter.ts";
|
|
20
|
+
|
|
21
|
+
export const WebModule = $module({
|
|
22
|
+
name: "${appName}.web",
|
|
23
|
+
services: [AppRouter],
|
|
24
|
+
imports: [AlephaReactAuth, AlephaReactI18n],
|
|
25
|
+
});
|
|
26
|
+
`.trim();
|
|
27
|
+
}
|
|
28
|
+
|
|
7
29
|
return `
|
|
8
30
|
import { $module } from "alepha";
|
|
9
31
|
import { AppRouter } from "./AppRouter.ts";
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import { $module, AlephaError } from "alepha";
|
|
4
|
+
import { $context, $module, AlephaError } from "alepha";
|
|
5
5
|
import { ViteDevServerProvider } from "alepha/cli";
|
|
6
|
-
import { cliConfigPlugins } from "alepha/cli/config";
|
|
7
6
|
import {
|
|
8
7
|
type DevtoolsOptions,
|
|
9
8
|
devtoolsOptions,
|
|
@@ -11,14 +10,6 @@ import {
|
|
|
11
10
|
|
|
12
11
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
13
12
|
|
|
14
|
-
declare module "alepha/cli/config" {
|
|
15
|
-
interface AlephaCliConfig {
|
|
16
|
-
devtools?: DevtoolsOptions;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// ---------------------------------------------------------------------------------------------------------------------
|
|
21
|
-
|
|
22
13
|
const DEVTOOLS_OVERLAY_SCRIPT = `
|
|
23
14
|
(function () {
|
|
24
15
|
if (window.__alepha_devtools_injected) return;
|
|
@@ -29,23 +20,19 @@ const DEVTOOLS_OVERLAY_SCRIPT = `
|
|
|
29
20
|
// Button
|
|
30
21
|
const btn = document.createElement("button");
|
|
31
22
|
btn.id = "alepha-devtools-btn";
|
|
32
|
-
btn.innerHTML = \`<svg width="
|
|
23
|
+
btn.innerHTML = \`<svg width="28" height="28" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="adb" x1="142.3" x2="159.6" y1="123.3" y2="176.7" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#33a72c"/><stop offset="1" stop-color="#2d8d40"/></linearGradient><linearGradient id="adc" x1="61.6" x2="100.7" y1="218.5" y2="174" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#298e35"/><stop offset="1" stop-color="#327952"/></linearGradient><linearGradient id="add" x1="262.7" x2="242.2" y1="178.4" y2="220.1" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32a62d"/><stop offset="1" stop-color="#2d8d40"/></linearGradient><linearGradient id="ade" x1="81.2" x2="69.1" y1="126.7" y2="92.3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#299a2c"/><stop offset="1" stop-color="#51be40"/></linearGradient><clipPath id="ada"><path fill="none" d="M0 0h300v241H0z"/></clipPath></defs><g fill="none" stroke-miterlimit="10" clip-path="url(#ada)"><path fill="url(#adb)" d="M54 174a182 182 0 0 1 106-51c19-2 37-6 54-15l16-11 3-4 1 1 1 4 1 6v9c0 6-2 12-5 18l-1 4-7 8c-5 7-12 14-19 19l-4 2-11 7v1l-1-1-3 2a120 120 0 0 1-30 8l-8 1-20-1c-21-3-44-10-64 0-5 2-9 4-12 8l-9 9h1l14-9c7-4 15-6 23-7h7l25 3 3 1-2 5-3 5c-4 7-10 14-15 18l-4 3c-12 8-25 12-39 13h-5l-5 1h-8l-7-1H15c0-3 4-7 5-9l7-11 5-8c6-10 14-19 22-28z"/><path fill="#1d524a" d="M178 141c9-1 17-4 24-8l8-4-6 4c-9 7-20 11-32 13l-39 5h-5l-15 3 16 13 18 15-20-1c-21-3-44-10-64 0-5 2-9 4-12 8l-9 9h1l14-9c7-4 15-6 23-7h7l25 3 3 1-2 5-3 5c-4 7-10 14-15 18l-4 3c-12 8-25 12-39 13h-5l-5 1h-8l-7-1H15c0-3 4-7 5-9l7-11 5-8c6-10 14-19 22-28l4-2 23-14 11-5c21-7 43-9 65-9l21-3z"/><path fill="url(#adc)" d="M57 189c7-4 15-6 23-7h7l25 3 3 1-2 5-3 5c-4 7-10 14-15 18l-4 3c-12 8-25 12-39 13h-5l-4-9-2-5 5-2 9-4 10-5 10-4c5-2 10-3 14-6l3-1h-1a1136 1136 0 0 0-43 14c1-6 6-14 9-19 1 0 0 0 0 0z"/><path fill="#2d6f4d" d="m41 216 5-2 9-4 5 3c9 4 18 6 27 4h4c-12 8-25 12-39 13h-5l-4-9-2-5zm16-27s1 0 0 0c-3 5-8 13-9 19l-15 8c0-3 1-9 3-11l3-3 4-4 14-9z"/><path fill="#49b63b" d="M42 198h1l-4 4 3-4z"/><path fill="#2d6f4d" d="m113 154 15-3 11 2 18 8c11 6 23 8 35 5l8-2-11 7v1l-1-1-3 2a120 120 0 0 1-30 8l-8 1-18-15-16-13z"/><path fill="#49b63b" d="M81 158c2-4 11-7 15-8 18-6 36-7 55-8l12-1h15l-21 3c-22 0-44 2-65 9l-11 5z"/><path fill="#2d913b" d="m110 52 2-5 9-14c7-8 19-14 29-18l10-3 12-6 1-1 1 1 1 5v6l6 12 5 10 12 26 2 5 4 10 7 17 4 8c-9 5-20 9-30 12l-16 3-7-14-6-14-5-10-1-3-4 7-13 27-6 11-6 2-24 9 2-4c11-16 14-36 11-56l-3 1-9 5 1-3 9-21 2-5z"/><path fill="#2d6f4d" d="m175 17 6 12 5 10 12 26 2 5 4 10 7 17 4 8c-9 5-20 9-30 12l-16 3-7-14-6-14-5-10-1-3c0-2 5-8 6-10l1-2c9-13 17-28 18-45v-5z"/><path fill="#1d524a" d="m175 17 6 12 5 10 12 26 2 5-3-1-13-8-7 4 3 7-4 1-2-3-5-12-5 7a136 136 0 0 1-10 15l-3 2-1-3c0-2 5-8 6-10l1-2c9-13 17-28 18-45v-5z"/><path fill="#2d6f4d" d="m186 39 12 26 2 5-3-1-13-8-7 4-6-12 8-7 7-7z"/><path fill="#2d913b" d="m177 65 7-4 13 8 3 1 4 10-3 7-7 14-2 8-1-4-6-19a99 99 0 0 0-8-21zm-3 5 2 3 12 32h-1l-8 5c-4 1-9 0-13-2l-1-1c-1-8 2-15 4-22 1-5 2-10 5-15z"/><path fill="#1d524a" d="m110 52 2-5 9-14c7-8 19-14 29-18l10-3 12-6 1-1 1 1c-3 1-3 2-4 4l-11 14-5 5v1c-11 11-22 24-31 37l-5 6-6 11h1l6 12c3 7 8 13 14 17l-6 11-6 2-24 9 2-4c11-16 14-36 11-56l-3 1-9 5 1-3 9-21 2-5z"/><path fill="#49b63b" d="m110 52 2-5 9-14c7-8 19-14 29-18l10-3 12-6 1-1 1 1c-3 1-3 2-4 4l-11 14-5 5-8 7-13 11-5 6c-5-2-10-5-15-3l-3 2z"/><path fill="#2d913b" d="m110 52 3-2c5-2 10 1 15 3l-12 13-6 9-3 1-9 5 1-3 9-21 2-5z"/><path fill="#2d6f4d" d="M121 92c10-5 19-9 28-17l7-6c-1 2-6 8-6 10l-4 7-13 27c-6-4-11-10-14-17l-6-12 4-5 4 13z"/><path fill="#49b63b" d="m154 30-1 11c0 4-3 9-6 12-6 9-19 10-25 19-1 0-3 2-4 1l5-6c9-13 20-26 31-37z"/><path fill="url(#add)" d="m230 135 3 6 11 17 2 5 4 5 3 6 9 14 19 36 4 5c-2 2-19 2-22 2l-5-1h-2c-12 0-25-4-35-10l-4-3c-10-8-15-16-21-27l-7-18v-1l11-7 4-2c7-5 14-12 19-19l7-8z"/><path fill="#1d524a" d="m230 135 3 6 11 17 2 5 4 5 3 6h-1c-10-8-20-9-32-4l23 23 13 12 1 2-20-14-13-12-4-3-5-6c-2 0-2 3-2 5l-1 10c-1 8-2 11 1 19l2 6 2 5c-10-8-15-16-21-27l-7-18v-1l11-7 4-2c7-5 14-12 19-19l7-8z"/><path fill="#2d6f4d" d="m233 141 11 17 2 5 4 5 3 6h-1c-10-8-20-9-32-4l-7-9 15-15 5-5zm-16 76-2-5-2-6c-3-8-2-11-1-19l1-10c0-2 0-5 2-5l5 6 4 3h-1c0 4 8 22 11 26 6 10 15 18 25 22 2 0 3 0 4 2l-5-1h-2c-12 0-25-4-35-10l-4-3z"/><path fill="#2d913b" d="M110 75c3 20 0 40-11 56l-2 4a145 145 0 0 0-43 31l-5 4-11 15v-7l-1-10a143 143 0 0 1 5-29l9-20c13-18 32-29 52-37l4-3 3-4z"/><path fill="url(#ade)" d="m42 139 9-20c13-18 32-29 52-37l4-3-3 7c-4 5-8 11-13 15l-3 3c-6 6-13 12-18 19l-8 11-20 5z"/><path fill="#1d524a" d="M91 101c0 2-4 6-6 8-5 5-10 11-14 18l-9 13-4 9 5 1c4 0 16-9 19-7-10 7-20 14-28 23l-5 4-11 15v-7l-1-10a143 143 0 0 1 5-29l20-5 8-11c5-7 12-13 18-19l3-3z"/><path fill="#2d6f4d" d="m62 134-9 16-3 7-2 4c-3 3-8 5-10 8l-1-1a143 143 0 0 1 5-29l20-5zm0 6 11-5 7-4c5-1 14-2 19 0l-2 4-15 8c-3-2-15 7-19 7l-5-1 4-9z"/></g></svg>\`;
|
|
33
24
|
Object.assign(btn.style, {
|
|
34
|
-
position: "fixed", bottom: "16px",
|
|
25
|
+
position: "fixed", bottom: "16px", left: "16px", zIndex: "99998",
|
|
35
26
|
width: "40px", height: "40px", borderRadius: "50%",
|
|
36
|
-
background: "#
|
|
27
|
+
background: "#fff", border: "1px solid #2a2a4a",
|
|
37
28
|
cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
|
|
38
29
|
boxShadow: "0 2px 8px rgba(0,0,0,0.3)", transition: "all 0.2s",
|
|
39
30
|
padding: "0", fontSize: "0",
|
|
40
31
|
});
|
|
41
32
|
btn.addEventListener("mouseenter", () => {
|
|
42
|
-
btn.style.background = "#2a2a4e";
|
|
43
|
-
btn.style.color = "#c0c0e0";
|
|
44
33
|
btn.style.transform = "scale(1.1)";
|
|
45
34
|
});
|
|
46
35
|
btn.addEventListener("mouseleave", () => {
|
|
47
|
-
btn.style.background = "#1a1a2e";
|
|
48
|
-
btn.style.color = "#a0a0c0";
|
|
49
36
|
btn.style.transform = "scale(1)";
|
|
50
37
|
});
|
|
51
38
|
|
|
@@ -110,10 +97,10 @@ const DEVTOOLS_OVERLAY_SCRIPT = `
|
|
|
110
97
|
*
|
|
111
98
|
* Usage in `alepha.config.ts`:
|
|
112
99
|
* ```ts
|
|
113
|
-
* import {
|
|
100
|
+
* import { devtools } from "alepha/cli/devtools";
|
|
114
101
|
*
|
|
115
102
|
* export default defineConfig({
|
|
116
|
-
*
|
|
103
|
+
* plugins: [devtools()],
|
|
117
104
|
* });
|
|
118
105
|
* ```
|
|
119
106
|
*
|
|
@@ -201,13 +188,12 @@ export const AlephaCliDevtoolsPlugin = $module({
|
|
|
201
188
|
},
|
|
202
189
|
});
|
|
203
190
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
});
|
|
191
|
+
export const devtools = (options: DevtoolsOptions = {}) => {
|
|
192
|
+
return () => {
|
|
193
|
+
const { alepha } = $context();
|
|
194
|
+
alepha.with(AlephaCliDevtoolsPlugin).set(devtoolsOptions, options);
|
|
195
|
+
};
|
|
196
|
+
};
|
|
211
197
|
|
|
212
198
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
213
199
|
|
|
@@ -252,8 +252,10 @@ describe("SecretsCommand", () => {
|
|
|
252
252
|
|
|
253
253
|
const output = writes.join("");
|
|
254
254
|
expect(output).toContain("env:");
|
|
255
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: GitHub Actions `${{ ... }}` syntax in plain string
|
|
255
256
|
expect(output).toContain("API_KEY: ${{ secrets.API_KEY }}");
|
|
256
257
|
expect(output).toContain(
|
|
258
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: GitHub Actions `${{ ... }}` syntax in plain string
|
|
257
259
|
"GITHUB_CLIENT_ID: ${{ secrets.APP_GITHUB_CLIENT_ID }}",
|
|
258
260
|
);
|
|
259
261
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { $module } from "alepha";
|
|
1
|
+
import { $context, $module } from "alepha";
|
|
2
2
|
import { AlephaCli } from "alepha/cli";
|
|
3
|
-
import { cliConfigPlugins } from "alepha/cli/config";
|
|
4
3
|
import { CloudflareAdapter } from "./adapters/CloudflareAdapter.ts";
|
|
5
4
|
import { VercelAdapter } from "./adapters/VercelAdapter.ts";
|
|
6
5
|
import {
|
|
@@ -23,14 +22,6 @@ import { WranglerApi } from "./services/WranglerApi.ts";
|
|
|
23
22
|
|
|
24
23
|
// ---------------------------------------------------------------------------
|
|
25
24
|
|
|
26
|
-
declare module "alepha/cli/config" {
|
|
27
|
-
interface AlephaCliConfig {
|
|
28
|
-
platform?: PlatformOptions;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
|
|
34
25
|
/**
|
|
35
26
|
* CLI plugin for multi-cloud deployment orchestration.
|
|
36
27
|
*
|
|
@@ -51,15 +42,16 @@ declare module "alepha/cli/config" {
|
|
|
51
42
|
* Configuration in `alepha.config.ts`:
|
|
52
43
|
*
|
|
53
44
|
* ```typescript
|
|
54
|
-
* import {
|
|
45
|
+
* import { platform } from "alepha/cli/platform";
|
|
55
46
|
*
|
|
56
47
|
* export default defineConfig({
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
48
|
+
* plugins: [
|
|
49
|
+
* platform({
|
|
50
|
+
* environments: {
|
|
51
|
+
* production: { adapter: "cloudflare", domain: "myapp.com" },
|
|
52
|
+
* },
|
|
53
|
+
* }),
|
|
54
|
+
* ],
|
|
63
55
|
* });
|
|
64
56
|
* ```
|
|
65
57
|
*/
|
|
@@ -85,13 +77,12 @@ export const AlephaCliPlatformPlugin = $module({
|
|
|
85
77
|
],
|
|
86
78
|
});
|
|
87
79
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
});
|
|
80
|
+
export const platform = (options: PlatformOptions) => {
|
|
81
|
+
return () => {
|
|
82
|
+
const { alepha } = $context();
|
|
83
|
+
alepha.with(AlephaCliPlatformPlugin).set(platformOptions, options);
|
|
84
|
+
};
|
|
85
|
+
};
|
|
95
86
|
|
|
96
87
|
// ---------------------------------------------------------------------------
|
|
97
88
|
|
package/src/cli/vendor/index.ts
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import { $module } from "alepha";
|
|
2
|
-
import { cliConfigPlugins } from "alepha/cli/config";
|
|
1
|
+
import { $context, $module } from "alepha";
|
|
3
2
|
import { type VendorOptions, vendorOptions } from "./atoms/vendorOptions.ts";
|
|
4
3
|
import { VendorCommand } from "./commands/VendorCommand.ts";
|
|
5
4
|
import { VendorService } from "./services/VendorService.ts";
|
|
6
5
|
|
|
7
6
|
// ---------------------------------------------------------------------------
|
|
8
7
|
|
|
9
|
-
declare module "alepha/cli/config" {
|
|
10
|
-
interface AlephaCliConfig {
|
|
11
|
-
vendor?: VendorOptions;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
|
|
17
8
|
/**
|
|
18
9
|
* CLI plugin for vendoring Alepha packages into external projects.
|
|
19
10
|
*
|
|
@@ -28,14 +19,15 @@ declare module "alepha/cli/config" {
|
|
|
28
19
|
* Configuration in `alepha.config.ts`:
|
|
29
20
|
*
|
|
30
21
|
* ```typescript
|
|
31
|
-
* import {
|
|
22
|
+
* import { vendor } from "alepha/cli/vendor";
|
|
32
23
|
*
|
|
33
24
|
* export default defineConfig({
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
25
|
+
* plugins: [
|
|
26
|
+
* vendor({
|
|
27
|
+
* branch: "main",
|
|
28
|
+
* packages: ["alepha", "@alepha/payments-stripe"],
|
|
29
|
+
* }),
|
|
30
|
+
* ],
|
|
39
31
|
* });
|
|
40
32
|
* ```
|
|
41
33
|
*/
|
|
@@ -45,13 +37,12 @@ export const AlephaCliVendorPlugin = $module({
|
|
|
45
37
|
services: [VendorCommand, VendorService],
|
|
46
38
|
});
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
40
|
+
export const vendor = (options: VendorOptions) => {
|
|
41
|
+
return () => {
|
|
42
|
+
const { alepha } = $context();
|
|
43
|
+
alepha.with(AlephaCliVendorPlugin).set(vendorOptions, options);
|
|
44
|
+
};
|
|
45
|
+
};
|
|
55
46
|
|
|
56
47
|
// ---------------------------------------------------------------------------
|
|
57
48
|
|
|
@@ -555,7 +555,7 @@ export class CliProvider {
|
|
|
555
555
|
const parsed = this.parseFlags(argv, flagDefs);
|
|
556
556
|
|
|
557
557
|
// Remove the mode flag from parsed result (it's handled separately)
|
|
558
|
-
|
|
558
|
+
parsed.__mode__ = undefined;
|
|
559
559
|
|
|
560
560
|
// apply manually defaults for optional properties that have defaults
|
|
561
561
|
for (const [key, value] of Object.entries(schema.properties)) {
|