alepha 0.14.4 → 0.15.1
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 +44 -102
- package/dist/api/audits/index.d.ts +331 -443
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +2 -2
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +0 -113
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +2 -3
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +151 -262
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/notifications/index.browser.js +4 -4
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +164 -276
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +4 -4
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +265 -377
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/users/index.browser.js +1 -2
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +195 -301
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +203 -184
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +1 -2
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js +2 -2
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/cli/index.d.ts +5900 -165
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1481 -639
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +8 -4
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +29 -25
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +563 -54
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +175 -8
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +564 -54
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +563 -54
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +4 -4
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +89 -42
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +129 -33
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +7969 -2
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +22 -22
- package/dist/fake/index.js.map +1 -1
- package/dist/file/index.d.ts +134 -1
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +253 -1
- package/dist/file/index.js.map +1 -1
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/logger/index.d.ts +1 -2
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +1 -5
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +19 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +28 -4
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/chunk-DH6iiROE.js +38 -0
- package/dist/orm/index.browser.js +9 -9
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.bun.js +2821 -0
- package/dist/orm/index.bun.js.map +1 -0
- package/dist/orm/index.d.ts +318 -169
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +2086 -1776
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +4 -4
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/redis/index.bun.js +285 -0
- package/dist/redis/index.bun.js.map +1 -0
- package/dist/redis/index.d.ts +13 -31
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +18 -38
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/scheduler/index.d.ts +83 -1
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +393 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.browser.js +5 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +598 -112
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1808 -97
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +1200 -175
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1268 -37
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +6 -3
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +1 -1
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +3 -3
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +115 -13
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +321 -139
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +0 -1
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/health/index.d.ts +0 -1
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/helmet/index.d.ts.map +1 -1
- package/dist/server/links/index.browser.js +9 -1
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +1 -2
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +14 -7
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +514 -1
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +4462 -4
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts.map +1 -1
- package/dist/server/proxy/index.d.ts +0 -1
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/swagger/index.d.ts +1 -2
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +1 -2
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +3 -1
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +10 -10
- package/dist/sms/index.js.map +1 -1
- package/dist/thread/index.d.ts +0 -1
- package/dist/thread/index.d.ts.map +1 -1
- package/dist/thread/index.js +2 -2
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/vite/index.d.ts +6315 -149
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +140 -469
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js +9 -9
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +28 -28
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +9 -9
- package/dist/websocket/index.js.map +1 -1
- package/package.json +13 -18
- package/src/api/files/controllers/AdminFileStatsController.ts +0 -1
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +5 -0
- package/src/api/users/controllers/{UserRealmController.ts → RealmController.ts} +11 -11
- package/src/api/users/entities/users.ts +1 -1
- package/src/api/users/index.ts +8 -8
- package/src/api/users/primitives/{$userRealm.ts → $realm.ts} +17 -19
- package/src/api/users/providers/{UserRealmProvider.ts → RealmProvider.ts} +26 -30
- package/src/api/users/schemas/{userRealmConfigSchema.ts → realmConfigSchema.ts} +2 -2
- package/src/api/users/services/CredentialService.ts +7 -7
- package/src/api/users/services/IdentityService.ts +4 -4
- package/src/api/users/services/RegistrationService.spec.ts +25 -27
- package/src/api/users/services/RegistrationService.ts +38 -27
- package/src/api/users/services/SessionCrudService.ts +3 -3
- package/src/api/users/services/SessionService.spec.ts +3 -3
- package/src/api/users/services/SessionService.ts +27 -18
- package/src/api/users/services/UserService.ts +7 -7
- package/src/batch/providers/BatchProvider.ts +1 -2
- package/src/cli/apps/AlephaCli.ts +2 -2
- package/src/cli/apps/AlephaPackageBuilderCli.ts +47 -20
- package/src/cli/assets/apiHelloControllerTs.ts +19 -0
- package/src/cli/assets/apiIndexTs.ts +16 -0
- package/src/cli/assets/biomeJson.ts +2 -1
- package/src/cli/assets/claudeMd.ts +308 -0
- package/src/cli/assets/dummySpecTs.ts +2 -1
- package/src/cli/assets/editorconfig.ts +2 -1
- package/src/cli/assets/mainBrowserTs.ts +4 -3
- package/src/cli/assets/mainCss.ts +24 -0
- package/src/cli/assets/mainServerTs.ts +24 -0
- package/src/cli/assets/tsconfigJson.ts +2 -1
- package/src/cli/assets/webAppRouterTs.ts +16 -0
- package/src/cli/assets/webHelloComponentTsx.ts +20 -0
- package/src/cli/assets/webIndexTs.ts +16 -0
- package/src/cli/atoms/appEntryOptions.ts +13 -0
- package/src/cli/atoms/buildOptions.ts +1 -1
- package/src/cli/atoms/changelogOptions.ts +1 -1
- package/src/cli/commands/build.ts +97 -61
- package/src/cli/commands/db.ts +21 -18
- package/src/cli/commands/deploy.ts +17 -5
- package/src/cli/commands/dev.ts +26 -47
- package/src/cli/commands/gen/env.ts +1 -1
- package/src/cli/commands/init.ts +79 -25
- package/src/cli/commands/lint.ts +9 -3
- package/src/cli/commands/test.ts +8 -2
- package/src/cli/commands/typecheck.ts +5 -1
- package/src/cli/commands/verify.ts +4 -2
- package/src/cli/defineConfig.ts +9 -0
- package/src/cli/index.ts +2 -1
- package/src/cli/providers/AppEntryProvider.ts +131 -0
- package/src/cli/providers/ViteBuildProvider.ts +82 -0
- package/src/cli/providers/ViteDevServerProvider.ts +350 -0
- package/src/cli/providers/ViteTemplateProvider.ts +27 -0
- package/src/cli/services/AlephaCliUtils.ts +72 -602
- package/src/cli/services/PackageManagerUtils.ts +308 -0
- package/src/cli/services/ProjectScaffolder.ts +329 -0
- package/src/command/helpers/Runner.ts +15 -3
- package/src/core/Alepha.ts +2 -8
- package/src/core/__tests__/Alepha-graph.spec.ts +4 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +2 -0
- package/src/core/primitives/$hook.ts +6 -2
- package/src/core/primitives/$module.spec.ts +4 -0
- package/src/core/primitives/$module.ts +12 -0
- package/src/core/providers/AlsProvider.ts +1 -1
- package/src/core/providers/CodecManager.spec.ts +12 -6
- package/src/core/providers/CodecManager.ts +26 -6
- package/src/core/providers/EventManager.ts +169 -13
- package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +878 -0
- package/src/core/providers/KeylessJsonSchemaCodec.ts +789 -0
- package/src/core/providers/SchemaValidator.spec.ts +236 -0
- package/src/core/providers/StateManager.spec.ts +27 -16
- package/src/email/providers/LocalEmailProvider.spec.ts +111 -87
- package/src/email/providers/LocalEmailProvider.ts +52 -15
- package/src/email/providers/NodemailerEmailProvider.ts +167 -56
- package/src/file/errors/FileError.ts +7 -0
- package/src/file/index.ts +9 -1
- package/src/file/providers/MemoryFileSystemProvider.ts +393 -0
- package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
- package/src/mcp/errors/McpError.ts +30 -0
- package/src/mcp/index.ts +3 -0
- package/src/mcp/transports/SseMcpTransport.ts +16 -6
- package/src/orm/index.browser.ts +1 -19
- package/src/orm/index.bun.ts +77 -0
- package/src/orm/index.shared-server.ts +22 -0
- package/src/orm/index.shared.ts +15 -0
- package/src/orm/index.ts +19 -39
- package/src/orm/providers/DrizzleKitProvider.ts +3 -5
- package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -5
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +4 -0
- package/src/orm/providers/drivers/DatabaseProvider.ts +4 -0
- package/src/orm/providers/drivers/PglitePostgresProvider.ts +4 -0
- package/src/orm/services/Repository.ts +19 -0
- package/src/redis/index.bun.ts +35 -0
- package/src/redis/providers/BunRedisProvider.ts +12 -43
- package/src/redis/providers/BunRedisSubscriberProvider.ts +2 -3
- package/src/redis/providers/NodeRedisProvider.ts +16 -34
- package/src/{server/security → security}/__tests__/BasicAuth.spec.ts +11 -11
- package/src/{server/security → security}/__tests__/ServerSecurityProvider-realm.spec.ts +21 -16
- package/src/{server/security/providers → security/__tests__}/ServerSecurityProvider.spec.ts +5 -5
- package/src/security/index.browser.ts +5 -0
- package/src/security/index.ts +90 -7
- package/src/security/primitives/{$realm.spec.ts → $issuer.spec.ts} +11 -11
- package/src/security/primitives/{$realm.ts → $issuer.ts} +20 -17
- package/src/security/primitives/$role.ts +5 -5
- package/src/security/primitives/$serviceAccount.spec.ts +5 -5
- package/src/security/primitives/$serviceAccount.ts +3 -3
- package/src/{server/security → security}/providers/ServerSecurityProvider.ts +5 -7
- package/src/server/auth/primitives/$auth.ts +10 -10
- package/src/server/auth/primitives/$authCredentials.ts +3 -3
- package/src/server/auth/primitives/$authGithub.ts +3 -3
- package/src/server/auth/primitives/$authGoogle.ts +3 -3
- package/src/server/auth/providers/ServerAuthProvider.ts +13 -13
- package/src/server/cache/providers/ServerCacheProvider.ts +1 -1
- package/src/server/cookies/providers/ServerCookiesProvider.ts +3 -3
- package/src/server/core/index.ts +1 -1
- package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
- package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
- package/src/server/core/providers/NodeHttpServerProvider.ts +92 -24
- package/src/server/core/providers/ServerBodyParserProvider.ts +19 -23
- package/src/server/core/providers/ServerLoggerProvider.ts +23 -19
- package/src/server/core/providers/ServerProvider.ts +144 -24
- package/src/server/core/providers/ServerRouterProvider.ts +259 -115
- package/src/server/core/providers/ServerTimingProvider.ts +2 -2
- package/src/server/links/atoms/apiLinksAtom.ts +7 -0
- package/src/server/links/index.browser.ts +2 -0
- package/src/server/links/index.ts +3 -1
- package/src/server/links/providers/LinkProvider.ts +1 -1
- package/src/server/swagger/index.ts +1 -1
- package/src/sms/providers/LocalSmsProvider.spec.ts +153 -111
- package/src/sms/providers/LocalSmsProvider.ts +8 -7
- package/src/vite/index.ts +3 -2
- package/src/vite/tasks/buildClient.ts +0 -1
- package/src/vite/tasks/buildServer.ts +80 -22
- package/src/vite/tasks/copyAssets.ts +5 -4
- package/src/vite/tasks/generateCloudflare.ts +7 -0
- package/src/vite/tasks/generateSitemap.ts +64 -23
- package/src/vite/tasks/index.ts +0 -2
- package/src/vite/tasks/prerenderPages.ts +49 -24
- package/dist/server/security/index.browser.js +0 -13
- package/dist/server/security/index.browser.js.map +0 -1
- package/dist/server/security/index.d.ts +0 -173
- package/dist/server/security/index.d.ts.map +0 -1
- package/dist/server/security/index.js +0 -311
- package/dist/server/security/index.js.map +0 -1
- package/src/cli/assets/appRouterTs.ts +0 -9
- package/src/cli/assets/indexHtml.ts +0 -15
- package/src/cli/assets/mainTs.ts +0 -13
- package/src/cli/commands/format.ts +0 -17
- package/src/server/security/index.browser.ts +0 -10
- package/src/server/security/index.ts +0 -94
- package/src/vite/helpers/boot.ts +0 -106
- package/src/vite/plugins/viteAlephaDev.ts +0 -177
- package/src/vite/tasks/devServer.ts +0 -69
- package/src/vite/tasks/runAlepha.ts +0 -270
- /package/src/{server/security → security}/primitives/$basicAuth.ts +0 -0
- /package/src/{server/security → security}/providers/ServerBasicAuthProvider.ts +0 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
export interface ClaudeMdOptions {
|
|
2
|
+
react?: boolean;
|
|
3
|
+
ui?: boolean;
|
|
4
|
+
projectName?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const claudeMd = (options: ClaudeMdOptions = {}) => {
|
|
8
|
+
const { react = false, projectName = "my-app" } = options;
|
|
9
|
+
|
|
10
|
+
const reactSection = react
|
|
11
|
+
? `
|
|
12
|
+
## React & Frontend
|
|
13
|
+
|
|
14
|
+
### Pages with \`$page\`
|
|
15
|
+
\`\`\`tsx
|
|
16
|
+
import { $page } from "@alepha/react/router";
|
|
17
|
+
import { $client } from "alepha/server/links";
|
|
18
|
+
import type { UserController } from "./UserController.ts";
|
|
19
|
+
|
|
20
|
+
class AppRouter {
|
|
21
|
+
api = $client<UserController>();
|
|
22
|
+
|
|
23
|
+
users = $page({
|
|
24
|
+
path: "/users",
|
|
25
|
+
loader: async () => ({ users: await this.api.listUsers() }),
|
|
26
|
+
component: ({ users }) => (
|
|
27
|
+
<ul>{users.map(u => <li key={u.id}>{u.email}</li>)}</ul>
|
|
28
|
+
),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
userDetail = $page({
|
|
32
|
+
path: "/users/:id",
|
|
33
|
+
schema: { params: t.object({ id: t.uuid() }) },
|
|
34
|
+
loader: async ({ params }) => ({ user: await this.api.getUser({ params }) }),
|
|
35
|
+
lazy: () => import("./UserDetail.tsx"), // Code splitting
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
### React Hooks
|
|
41
|
+
\`\`\`typescript
|
|
42
|
+
import { useAlepha, useClient, useStore, useAction, useInject } from "@alepha/react";
|
|
43
|
+
import { useRouter, useActive } from "@alepha/react/router";
|
|
44
|
+
import { useForm } from "@alepha/react/form";
|
|
45
|
+
\`\`\`
|
|
46
|
+
|
|
47
|
+
- \`useClient<Controller>()\` - Type-safe API calls
|
|
48
|
+
- \`useStore(atom)\` - Global state (returns \`[value, setValue]\`)
|
|
49
|
+
- \`useAction({ handler })\` - Async operations with loading/error state
|
|
50
|
+
- \`useRouter<AppRouter>()\` - Type-safe navigation
|
|
51
|
+
- \`useForm({ schema, handler })\` - Type-safe forms with validation
|
|
52
|
+
`
|
|
53
|
+
: "";
|
|
54
|
+
|
|
55
|
+
const projectStructure = react
|
|
56
|
+
? `
|
|
57
|
+
\`\`\`
|
|
58
|
+
${projectName}/
|
|
59
|
+
├── src/
|
|
60
|
+
│ ├── api/ # Backend
|
|
61
|
+
│ │ ├── controllers/ # API controllers with $action
|
|
62
|
+
│ │ ├── services/ # Business logic
|
|
63
|
+
│ │ ├── entities/ # Database entities with $entity
|
|
64
|
+
│ │ ├── providers/ # External service wrappers
|
|
65
|
+
│ │ └── index.ts # API module definition with $module
|
|
66
|
+
│ ├── web/ # Frontend (React only)
|
|
67
|
+
│ │ ├── components/ # React components
|
|
68
|
+
│ │ ├── atoms/ # State atoms with $atom
|
|
69
|
+
│ │ ├── AppRouter.ts # Routes with $page
|
|
70
|
+
│ │ └── index.ts # Web module definition with $module
|
|
71
|
+
│ ├── main.server.ts # Server entry
|
|
72
|
+
│ ├── main.browser.ts # Browser entry (React only)
|
|
73
|
+
│ └── main.css # CSS entry (React only)
|
|
74
|
+
├── package.json
|
|
75
|
+
└── tsconfig.json
|
|
76
|
+
\`\`\`
|
|
77
|
+
`
|
|
78
|
+
: `
|
|
79
|
+
\`\`\`
|
|
80
|
+
${projectName}/
|
|
81
|
+
├── src/
|
|
82
|
+
│ ├── api/ # Backend
|
|
83
|
+
│ │ ├── controllers/ # API controllers with $action
|
|
84
|
+
│ │ ├── services/ # Business logic
|
|
85
|
+
│ │ ├── entities/ # Database entities with $entity
|
|
86
|
+
│ │ ├── providers/ # External service wrappers
|
|
87
|
+
│ │ └── index.ts # API module definition with $module
|
|
88
|
+
│ └── main.server.ts # Server entry (always use main.server.ts)
|
|
89
|
+
├── package.json
|
|
90
|
+
└── tsconfig.json
|
|
91
|
+
\`\`\`
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
return `# CLAUDE.md
|
|
95
|
+
|
|
96
|
+
This file provides guidance to Claude Code when working with this Alepha project.
|
|
97
|
+
|
|
98
|
+
## Overview
|
|
99
|
+
|
|
100
|
+
This is an **Alepha** project - a convention-driven TypeScript framework for type-safe full-stack applications.
|
|
101
|
+
|
|
102
|
+
**Key Concepts:**
|
|
103
|
+
- **Primitives**: Features defined with \`$\`-prefixed functions (\`$action\`, \`$entity\`, \`$page\`)
|
|
104
|
+
- **Class-Based**: Services are classes, primitives are class properties
|
|
105
|
+
- **Zero-Config**: Code structure IS the configuration
|
|
106
|
+
- **End-to-End Types**: Types flow from database → API → ${react ? "React" : "client"}
|
|
107
|
+
|
|
108
|
+
## Rules
|
|
109
|
+
|
|
110
|
+
- Use TypeScript strict mode
|
|
111
|
+
- Use Biome for formatting (\`alepha lint\`)
|
|
112
|
+
- Use Vitest for testing
|
|
113
|
+
- One file = one class
|
|
114
|
+
- Primitives are class properties (except \`$entity\`, \`$atom\`)
|
|
115
|
+
- No decorators, no Express/Fastify patterns
|
|
116
|
+
- No manual instantiation - use dependency injection
|
|
117
|
+
- Use \`protected\` instead of \`private\` for class members
|
|
118
|
+
- Import with file extensions: \`import { User } from "./User.ts"\`
|
|
119
|
+
- Use \`t\` from Alepha for schemas (not Zod)
|
|
120
|
+
- Prefer \`t.text()\` over \`t.string()\` for user input (has default max length, auto-trim, supports lowercase option)
|
|
121
|
+
|
|
122
|
+
## Project Structure
|
|
123
|
+
${projectStructure}
|
|
124
|
+
## Core Primitives
|
|
125
|
+
|
|
126
|
+
### API with \`$action\`
|
|
127
|
+
\`\`\`typescript
|
|
128
|
+
import { t } from "alepha";
|
|
129
|
+
import { $action } from "alepha/server";
|
|
130
|
+
|
|
131
|
+
class UserController {
|
|
132
|
+
getUser = $action({
|
|
133
|
+
path: "/users/:id", // → GET /api/users/:id
|
|
134
|
+
schema: {
|
|
135
|
+
params: t.object({ id: t.uuid() }),
|
|
136
|
+
response: t.object({ id: t.uuid(), email: t.email() }),
|
|
137
|
+
},
|
|
138
|
+
handler: async ({ params }) => this.userRepo.findById(params.id),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
createUser = $action({
|
|
142
|
+
// POST inferred from body schema
|
|
143
|
+
schema: {
|
|
144
|
+
body: t.object({ email: t.email() }),
|
|
145
|
+
response: userEntity.schema,
|
|
146
|
+
},
|
|
147
|
+
handler: async ({ body }) => this.userRepo.create(body),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
\`\`\`
|
|
151
|
+
|
|
152
|
+
### Database with \`$entity\` and \`$repository\`
|
|
153
|
+
\`\`\`typescript
|
|
154
|
+
import { $entity, $repository, db } from "alepha/orm";
|
|
155
|
+
|
|
156
|
+
// Entity defined at module level (for drizzle-kit compatibility)
|
|
157
|
+
export const userEntity = $entity({
|
|
158
|
+
name: "users",
|
|
159
|
+
schema: t.object({
|
|
160
|
+
id: db.primaryKey(),
|
|
161
|
+
email: t.email(),
|
|
162
|
+
createdAt: db.createdAt(),
|
|
163
|
+
updatedAt: db.updatedAt(),
|
|
164
|
+
}),
|
|
165
|
+
indexes: [{ column: "email", unique: true }],
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
class UserService {
|
|
169
|
+
repo = $repository(userEntity);
|
|
170
|
+
|
|
171
|
+
async findById(id: string) {
|
|
172
|
+
return this.repo.findById(id);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
\`\`\`
|
|
176
|
+
|
|
177
|
+
### Dependency Injection
|
|
178
|
+
\`\`\`typescript
|
|
179
|
+
import { $inject } from "alepha";
|
|
180
|
+
|
|
181
|
+
class OrderService {
|
|
182
|
+
userService = $inject(UserService); // Within same module
|
|
183
|
+
|
|
184
|
+
async createOrder(userId: string) {
|
|
185
|
+
const user = await this.userService.findById(userId);
|
|
186
|
+
// ...
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Cross-module: use $client instead of $inject
|
|
191
|
+
class AppRouter {
|
|
192
|
+
api = $client<OrderController>(); // Type-safe HTTP client
|
|
193
|
+
}
|
|
194
|
+
\`\`\`
|
|
195
|
+
|
|
196
|
+
### Modules with \`$module\`
|
|
197
|
+
\`\`\`typescript
|
|
198
|
+
// src/api/index.ts - Groups all API services
|
|
199
|
+
import { $module } from "alepha";
|
|
200
|
+
|
|
201
|
+
export const ApiModule = $module({
|
|
202
|
+
name: "app.api",
|
|
203
|
+
services: [
|
|
204
|
+
UserController,
|
|
205
|
+
OrderController,
|
|
206
|
+
UserService,
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// src/web/index.ts - Groups all web services (React only)
|
|
211
|
+
export const WebModule = $module({
|
|
212
|
+
name: "app.web",
|
|
213
|
+
services: [AppRouter, Toaster],
|
|
214
|
+
register(alepha) {
|
|
215
|
+
// Optional: configure additional services
|
|
216
|
+
alepha.with(SomeLibrary);
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
\`\`\`
|
|
220
|
+
|
|
221
|
+
### Environment Variables
|
|
222
|
+
\`\`\`typescript
|
|
223
|
+
import { $env, t } from "alepha";
|
|
224
|
+
|
|
225
|
+
class AppConfig {
|
|
226
|
+
env = $env(t.object({
|
|
227
|
+
DATABASE_URL: t.string(),
|
|
228
|
+
API_KEY: t.optional(t.string()),
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
\`\`\`
|
|
232
|
+
${reactSection}
|
|
233
|
+
## Quick Reference
|
|
234
|
+
|
|
235
|
+
| Primitive | Import | Purpose |
|
|
236
|
+
|-----------|--------|---------|
|
|
237
|
+
| \`$inject\` | \`alepha\` | Dependency injection |
|
|
238
|
+
| \`$env\` | \`alepha\` | Environment variables |
|
|
239
|
+
| \`$hook\` | \`alepha\` | Lifecycle hooks |
|
|
240
|
+
| \`$logger\` | \`alepha/logger\` | Structured logging |
|
|
241
|
+
| \`$action\` | \`alepha/server\` | REST API endpoints |
|
|
242
|
+
| \`$route\` | \`alepha/server\` | Low-level HTTP routes |
|
|
243
|
+
| \`$entity\` | \`alepha/orm\` | Database tables |
|
|
244
|
+
| \`$repository\` | \`alepha/orm\` | Type-safe data access |
|
|
245
|
+
| \`$queue\` | \`alepha/queue\` | Background jobs |
|
|
246
|
+
| \`$scheduler\` | \`alepha/scheduler\` | Cron tasks |
|
|
247
|
+
| \`$cache\` | \`alepha/cache\` | Cached computations |
|
|
248
|
+
| \`$bucket\` | \`alepha/bucket\` | File storage |
|
|
249
|
+
| \`$issuer\` | \`alepha/security\` | JWT tokens |
|
|
250
|
+
| \`$command\` | \`alepha/command\` | CLI commands |${
|
|
251
|
+
react
|
|
252
|
+
? `
|
|
253
|
+
| \`$page\` | \`@alepha/react/router\` | React pages with SSR |
|
|
254
|
+
| \`$atom\` | \`alepha\` | Global state |`
|
|
255
|
+
: ""
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
## Testing
|
|
259
|
+
|
|
260
|
+
\`\`\`typescript
|
|
261
|
+
import { describe, it, expect } from "vitest";
|
|
262
|
+
import { Alepha } from "alepha";
|
|
263
|
+
|
|
264
|
+
describe("UserService", () => {
|
|
265
|
+
it("should create user", async () => {
|
|
266
|
+
const alepha = Alepha.create().with(UserService);
|
|
267
|
+
const service = alepha.inject(UserService);
|
|
268
|
+
|
|
269
|
+
const user = await service.create({ email: "test@example.com" });
|
|
270
|
+
expect(user.email).toBe("test@example.com");
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("should mock dependencies", async () => {
|
|
274
|
+
const alepha = Alepha.create()
|
|
275
|
+
.with(OrderService)
|
|
276
|
+
.with({ provide: PaymentGateway, use: MockPaymentGateway });
|
|
277
|
+
|
|
278
|
+
const service = alepha.inject(OrderService);
|
|
279
|
+
// PaymentGateway is now mocked
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
\`\`\`
|
|
283
|
+
|
|
284
|
+
## Common Mistakes
|
|
285
|
+
|
|
286
|
+
1. **DON'T use decorators** - Use primitives (\`$action\`, not \`@Get()\`)
|
|
287
|
+
2. **DON'T use Zod** - Use TypeBox via \`t\` from Alepha
|
|
288
|
+
3. **DON'T use Express patterns** - No \`app.get()\`, \`router.use()\`
|
|
289
|
+
4. **DON'T inject across modules** - Use \`$client\` for cross-module calls
|
|
290
|
+
5. **DON'T use async constructors** - Use \`$hook({ on: "start" })\`
|
|
291
|
+
6. **DON'T instantiate manually** - Let DI container manage instances
|
|
292
|
+
|
|
293
|
+
## After Code Changes
|
|
294
|
+
|
|
295
|
+
Always run:
|
|
296
|
+
\`\`\`bash
|
|
297
|
+
alepha lint # Format and lint
|
|
298
|
+
alepha typecheck # Type checking
|
|
299
|
+
alepha test # Run tests (if applicable)
|
|
300
|
+
alepha build # Build the project
|
|
301
|
+
\`\`\`
|
|
302
|
+
|
|
303
|
+
## Documentation
|
|
304
|
+
|
|
305
|
+
- Full docs: https://alepha.dev/llms.txt
|
|
306
|
+
- Detailed docs: https://alepha.dev/llms-full.txt
|
|
307
|
+
`.trim();
|
|
308
|
+
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export const mainBrowserTs = () =>
|
|
1
|
+
export const mainBrowserTs = () =>
|
|
2
|
+
`
|
|
2
3
|
import { Alepha, run } from "alepha";
|
|
3
|
-
import {
|
|
4
|
+
import { WebModule } from "./web/index.ts";
|
|
4
5
|
|
|
5
6
|
const alepha = Alepha.create();
|
|
6
7
|
|
|
7
|
-
alepha.with(
|
|
8
|
+
alepha.with(WebModule);
|
|
8
9
|
|
|
9
10
|
run(alepha);
|
|
10
11
|
`.trim();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const mainCss = () =>
|
|
2
|
+
`
|
|
3
|
+
* {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
margin: 0;
|
|
6
|
+
padding: 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
html,
|
|
10
|
+
body {
|
|
11
|
+
height: 100%;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
16
|
+
"Helvetica Neue", Arial, sans-serif;
|
|
17
|
+
line-height: 1.5;
|
|
18
|
+
-webkit-font-smoothing: antialiased;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#root {
|
|
22
|
+
height: 100%;
|
|
23
|
+
}
|
|
24
|
+
`.trim();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface MainServerTsOptions {
|
|
2
|
+
react?: boolean;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const mainServerTs = (options: MainServerTsOptions = {}) => {
|
|
6
|
+
const { react = false } = options;
|
|
7
|
+
|
|
8
|
+
const webImport = react
|
|
9
|
+
? `import { WebModule } from "./web/index.ts";\n`
|
|
10
|
+
: "";
|
|
11
|
+
|
|
12
|
+
const webWith = react ? `alepha.with(WebModule);\n` : "";
|
|
13
|
+
|
|
14
|
+
return `
|
|
15
|
+
import { Alepha, run } from "alepha";
|
|
16
|
+
import { ApiModule } from "./api/index.ts";
|
|
17
|
+
${webImport}
|
|
18
|
+
const alepha = Alepha.create();
|
|
19
|
+
|
|
20
|
+
alepha.with(ApiModule);
|
|
21
|
+
${webWith}
|
|
22
|
+
run(alepha);
|
|
23
|
+
`.trim();
|
|
24
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const webAppRouterTs = () =>
|
|
2
|
+
`
|
|
3
|
+
import { $page } from "@alepha/react/router";
|
|
4
|
+
import { $client } from "alepha/server/links";
|
|
5
|
+
import type { HelloController } from "../api/controllers/HelloController.ts";
|
|
6
|
+
|
|
7
|
+
export class AppRouter {
|
|
8
|
+
api = $client<HelloController>();
|
|
9
|
+
|
|
10
|
+
home = $page({
|
|
11
|
+
path: "/",
|
|
12
|
+
lazy: () => import("./components/Hello.tsx"),
|
|
13
|
+
loader: () => this.api.hello(),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
`.trim();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const webHelloComponentTsx = () =>
|
|
2
|
+
`import { useState } from "react";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Hello = (props: Props) => {
|
|
9
|
+
const [message, setMessage] = useState(props.message);
|
|
10
|
+
return (
|
|
11
|
+
<div>
|
|
12
|
+
<h1>{message}</h1>
|
|
13
|
+
<input value={message} onChange={e => setMessage(e.target.value)} />
|
|
14
|
+
<p>Edit this component in src/web/components/Hello.tsx</p>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default Hello;
|
|
20
|
+
`.trim();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface WebIndexTsOptions {
|
|
2
|
+
appName?: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const webIndexTs = (options: WebIndexTsOptions = {}) => {
|
|
6
|
+
const { appName = "app" } = options;
|
|
7
|
+
return `
|
|
8
|
+
import { $module } from "alepha";
|
|
9
|
+
import { AppRouter } from "./AppRouter.ts";
|
|
10
|
+
|
|
11
|
+
export const WebModule = $module({
|
|
12
|
+
name: "${appName}.web",
|
|
13
|
+
services: [AppRouter],
|
|
14
|
+
});
|
|
15
|
+
`.trim();
|
|
16
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { $atom, type Static, t } from "alepha";
|
|
2
|
+
|
|
3
|
+
export const appEntryOptions = $atom({
|
|
4
|
+
name: "alepha.cli.appEntry.options",
|
|
5
|
+
schema: t.object({
|
|
6
|
+
server: t.optional(t.text()),
|
|
7
|
+
browser: t.optional(t.text()),
|
|
8
|
+
style: t.optional(t.text()),
|
|
9
|
+
}),
|
|
10
|
+
default: {},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type AppEntryOptions = Static<typeof appEntryOptions.schema>;
|
|
@@ -8,7 +8,7 @@ import { $atom } from "../../core/primitives/$atom.ts";
|
|
|
8
8
|
* Options can be overridden via vite.config.ts or CLI flags.
|
|
9
9
|
*/
|
|
10
10
|
export const buildOptions = $atom({
|
|
11
|
-
name: "alepha.build.options",
|
|
11
|
+
name: "alepha.cli.build.options",
|
|
12
12
|
description: "Build configuration options",
|
|
13
13
|
schema: t.object({
|
|
14
14
|
/**
|