alepha 0.15.4 → 0.15.5

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.
Files changed (282) hide show
  1. package/README.md +26 -11
  2. package/dist/api/audits/index.d.ts +3 -3
  3. package/dist/api/audits/index.js +3 -3
  4. package/dist/api/audits/index.js.map +1 -1
  5. package/dist/api/files/index.d.ts +3 -3
  6. package/dist/api/files/index.js +3 -3
  7. package/dist/api/files/index.js.map +1 -1
  8. package/dist/api/jobs/index.d.ts +47 -4
  9. package/dist/api/jobs/index.d.ts.map +1 -1
  10. package/dist/api/jobs/index.js +100 -5
  11. package/dist/api/jobs/index.js.map +1 -1
  12. package/dist/api/keys/index.d.ts +3 -3
  13. package/dist/api/keys/index.js +3 -3
  14. package/dist/api/keys/index.js.map +1 -1
  15. package/dist/api/notifications/index.d.ts +3 -3
  16. package/dist/api/notifications/index.js +3 -3
  17. package/dist/api/notifications/index.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +263 -263
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/parameters/index.js +31 -30
  21. package/dist/api/parameters/index.js.map +1 -1
  22. package/dist/api/users/index.d.ts +373 -67
  23. package/dist/api/users/index.d.ts.map +1 -1
  24. package/dist/api/users/index.js +273 -72
  25. package/dist/api/users/index.js.map +1 -1
  26. package/dist/api/verifications/index.d.ts +3 -3
  27. package/dist/api/verifications/index.js +3 -3
  28. package/dist/api/verifications/index.js.map +1 -1
  29. package/dist/batch/index.d.ts +7 -7
  30. package/dist/batch/index.js +3 -3
  31. package/dist/batch/index.js.map +1 -1
  32. package/dist/bucket/index.d.ts +3 -3
  33. package/dist/bucket/index.js +6 -6
  34. package/dist/bucket/index.js.map +1 -1
  35. package/dist/cache/core/index.d.ts +3 -3
  36. package/dist/cache/core/index.js +3 -3
  37. package/dist/cache/core/index.js.map +1 -1
  38. package/dist/cli/index.d.ts +5607 -20
  39. package/dist/cli/index.d.ts.map +1 -1
  40. package/dist/cli/index.js +103 -89
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/command/index.d.ts +11 -4
  43. package/dist/command/index.d.ts.map +1 -1
  44. package/dist/command/index.js +8 -6
  45. package/dist/command/index.js.map +1 -1
  46. package/dist/core/index.browser.js.map +1 -1
  47. package/dist/core/index.d.ts +4 -8
  48. package/dist/core/index.d.ts.map +1 -1
  49. package/dist/core/index.js +3 -3
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/core/index.native.js.map +1 -1
  52. package/dist/datetime/index.d.ts +3 -3
  53. package/dist/datetime/index.js +3 -3
  54. package/dist/datetime/index.js.map +1 -1
  55. package/dist/email/index.d.ts +3 -3
  56. package/dist/email/index.js +8 -8
  57. package/dist/email/index.js.map +1 -1
  58. package/dist/fake/index.d.ts +3 -3
  59. package/dist/fake/index.js +3 -3
  60. package/dist/fake/index.js.map +1 -1
  61. package/dist/lock/core/index.d.ts +3 -3
  62. package/dist/lock/core/index.js +3 -3
  63. package/dist/lock/core/index.js.map +1 -1
  64. package/dist/logger/index.d.ts +3 -3
  65. package/dist/logger/index.js +6 -3
  66. package/dist/logger/index.js.map +1 -1
  67. package/dist/mcp/index.d.ts +3 -3
  68. package/dist/mcp/index.js +3 -3
  69. package/dist/mcp/index.js.map +1 -1
  70. package/dist/orm/index.d.ts +12 -12
  71. package/dist/orm/index.js +4 -4
  72. package/dist/orm/index.js.map +1 -1
  73. package/dist/queue/core/index.d.ts +3 -3
  74. package/dist/queue/core/index.js +3 -3
  75. package/dist/queue/core/index.js.map +1 -1
  76. package/dist/react/auth/index.d.ts +3 -3
  77. package/dist/react/auth/index.js +3 -3
  78. package/dist/react/auth/index.js.map +1 -1
  79. package/dist/react/core/index.d.ts +3 -3
  80. package/dist/react/core/index.js +3 -3
  81. package/dist/react/core/index.js.map +1 -1
  82. package/dist/react/form/index.d.ts +3 -3
  83. package/dist/react/form/index.js +3 -3
  84. package/dist/react/form/index.js.map +1 -1
  85. package/dist/react/head/index.d.ts +3 -3
  86. package/dist/react/head/index.js +3 -3
  87. package/dist/react/head/index.js.map +1 -1
  88. package/dist/react/i18n/index.d.ts +3 -3
  89. package/dist/react/i18n/index.js +3 -3
  90. package/dist/react/i18n/index.js.map +1 -1
  91. package/dist/react/intro/index.css +337 -0
  92. package/dist/react/intro/index.css.map +1 -0
  93. package/dist/react/intro/index.d.ts +10 -0
  94. package/dist/react/intro/index.d.ts.map +1 -0
  95. package/dist/react/intro/index.js +222 -0
  96. package/dist/react/intro/index.js.map +1 -0
  97. package/dist/react/router/index.browser.js +2 -2
  98. package/dist/react/router/index.browser.js.map +1 -1
  99. package/dist/react/router/index.d.ts +1 -1
  100. package/dist/react/router/index.d.ts.map +1 -1
  101. package/dist/react/router/index.js +5 -5
  102. package/dist/react/router/index.js.map +1 -1
  103. package/dist/redis/index.d.ts +17 -17
  104. package/dist/redis/index.js +3 -3
  105. package/dist/redis/index.js.map +1 -1
  106. package/dist/retry/index.d.ts +3 -3
  107. package/dist/retry/index.js +3 -3
  108. package/dist/retry/index.js.map +1 -1
  109. package/dist/scheduler/index.d.ts +3 -3
  110. package/dist/scheduler/index.js +3 -3
  111. package/dist/scheduler/index.js.map +1 -1
  112. package/dist/security/index.d.ts +3 -3
  113. package/dist/security/index.js +5 -5
  114. package/dist/security/index.js.map +1 -1
  115. package/dist/server/auth/index.d.ts +3 -3
  116. package/dist/server/auth/index.js +3 -3
  117. package/dist/server/auth/index.js.map +1 -1
  118. package/dist/server/cache/index.d.ts +3 -3
  119. package/dist/server/cache/index.js +3 -3
  120. package/dist/server/cache/index.js.map +1 -1
  121. package/dist/server/compress/index.d.ts +3 -3
  122. package/dist/server/compress/index.js +3 -3
  123. package/dist/server/compress/index.js.map +1 -1
  124. package/dist/server/cookies/index.d.ts +3 -3
  125. package/dist/server/cookies/index.js +3 -3
  126. package/dist/server/cookies/index.js.map +1 -1
  127. package/dist/server/core/index.d.ts +5 -16
  128. package/dist/server/core/index.d.ts.map +1 -1
  129. package/dist/server/core/index.js +13 -29
  130. package/dist/server/core/index.js.map +1 -1
  131. package/dist/server/cors/index.d.ts +3 -3
  132. package/dist/server/cors/index.js +3 -3
  133. package/dist/server/cors/index.js.map +1 -1
  134. package/dist/server/health/index.d.ts +20 -20
  135. package/dist/server/health/index.js +3 -3
  136. package/dist/server/health/index.js.map +1 -1
  137. package/dist/server/helmet/index.d.ts +3 -3
  138. package/dist/server/helmet/index.js +3 -3
  139. package/dist/server/helmet/index.js.map +1 -1
  140. package/dist/server/links/index.d.ts +42 -42
  141. package/dist/server/links/index.d.ts.map +1 -1
  142. package/dist/server/links/index.js +3 -3
  143. package/dist/server/links/index.js.map +1 -1
  144. package/dist/server/metrics/index.d.ts +3 -3
  145. package/dist/server/metrics/index.js +3 -3
  146. package/dist/server/metrics/index.js.map +1 -1
  147. package/dist/server/multipart/index.d.ts +3 -3
  148. package/dist/server/multipart/index.js +3 -3
  149. package/dist/server/multipart/index.js.map +1 -1
  150. package/dist/server/proxy/index.d.ts +3 -3
  151. package/dist/server/proxy/index.js +3 -3
  152. package/dist/server/proxy/index.js.map +1 -1
  153. package/dist/server/rate-limit/index.d.ts +3 -3
  154. package/dist/server/rate-limit/index.js +3 -3
  155. package/dist/server/rate-limit/index.js.map +1 -1
  156. package/dist/server/static/index.d.ts +3 -3
  157. package/dist/server/static/index.js +6 -6
  158. package/dist/server/static/index.js.map +1 -1
  159. package/dist/server/swagger/index.d.ts +3 -3
  160. package/dist/server/swagger/index.js +6 -6
  161. package/dist/server/swagger/index.js.map +1 -1
  162. package/dist/sms/index.d.ts +3 -3
  163. package/dist/sms/index.js +6 -6
  164. package/dist/sms/index.js.map +1 -1
  165. package/dist/system/index.d.ts +3 -3
  166. package/dist/system/index.js +3 -3
  167. package/dist/system/index.js.map +1 -1
  168. package/dist/thread/index.d.ts +3 -3
  169. package/dist/thread/index.js +3 -3
  170. package/dist/thread/index.js.map +1 -1
  171. package/dist/topic/core/index.d.ts +3 -3
  172. package/dist/topic/core/index.js +3 -3
  173. package/dist/topic/core/index.js.map +1 -1
  174. package/dist/vite/index.d.ts +6284 -3
  175. package/dist/vite/index.d.ts.map +1 -1
  176. package/dist/websocket/index.d.ts +3 -3
  177. package/dist/websocket/index.js +3 -3
  178. package/dist/websocket/index.js.map +1 -1
  179. package/package.json +7 -2
  180. package/src/api/audits/index.ts +3 -3
  181. package/src/api/files/index.ts +3 -3
  182. package/src/api/jobs/controllers/AdminJobController.ts +15 -2
  183. package/src/api/jobs/index.ts +4 -3
  184. package/src/api/jobs/services/JobAudits.spec.ts +89 -0
  185. package/src/api/jobs/services/JobAudits.ts +101 -0
  186. package/src/api/keys/index.ts +3 -3
  187. package/src/api/notifications/index.ts +3 -3
  188. package/src/api/parameters/index.ts +5 -3
  189. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1 -1
  190. package/src/api/users/__tests__/ApiKeys.spec.ts +1 -1
  191. package/src/api/users/__tests__/EmailVerification.spec.ts +16 -1
  192. package/src/api/users/__tests__/PasswordReset.spec.ts +11 -0
  193. package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -0
  194. package/src/api/users/index.ts +8 -9
  195. package/src/api/users/primitives/$realm.ts +117 -19
  196. package/src/api/users/providers/RealmProvider.ts +15 -7
  197. package/src/api/users/services/CredentialService.spec.ts +11 -0
  198. package/src/api/users/services/CredentialService.ts +47 -24
  199. package/src/api/users/services/IdentityService.ts +12 -4
  200. package/src/api/users/services/RegistrationService.spec.ts +11 -0
  201. package/src/api/users/services/RegistrationService.ts +33 -12
  202. package/src/api/users/services/SessionService.ts +83 -12
  203. package/src/api/users/services/UserAudits.ts +47 -0
  204. package/src/api/users/services/UserFiles.ts +19 -0
  205. package/src/api/users/services/UserJobs.spec.ts +107 -0
  206. package/src/api/users/services/UserJobs.ts +62 -0
  207. package/src/api/users/services/UserParameters.ts +23 -0
  208. package/src/api/users/services/UserService.ts +34 -17
  209. package/src/api/verifications/index.ts +3 -3
  210. package/src/batch/index.ts +3 -3
  211. package/src/bucket/index.ts +3 -3
  212. package/src/cache/core/index.ts +3 -3
  213. package/src/cli/commands/db.ts +9 -0
  214. package/src/cli/commands/init.spec.ts +2 -17
  215. package/src/cli/commands/init.ts +37 -1
  216. package/src/cli/providers/ViteDevServerProvider.ts +5 -2
  217. package/src/cli/services/AlephaCliUtils.ts +17 -0
  218. package/src/cli/services/PackageManagerUtils.ts +15 -1
  219. package/src/cli/services/ProjectScaffolder.ts +8 -13
  220. package/src/cli/templates/agentMd.ts +2 -25
  221. package/src/cli/templates/apiAppSecurityTs.ts +37 -2
  222. package/src/cli/templates/mainCss.ts +2 -32
  223. package/src/cli/templates/webAppRouterTs.ts +5 -5
  224. package/src/cli/templates/webHomeComponentTsx.ts +10 -0
  225. package/src/command/helpers/Runner.ts +14 -1
  226. package/src/command/index.ts +3 -3
  227. package/src/core/helpers/primitive.ts +0 -5
  228. package/src/core/index.ts +3 -3
  229. package/src/datetime/index.ts +3 -3
  230. package/src/email/index.ts +3 -3
  231. package/src/email/providers/LocalEmailProvider.ts +2 -2
  232. package/src/fake/index.ts +3 -3
  233. package/src/lock/core/index.ts +3 -3
  234. package/src/logger/index.ts +3 -3
  235. package/src/logger/providers/PrettyFormatterProvider.ts +7 -0
  236. package/src/mcp/index.ts +3 -3
  237. package/src/orm/index.ts +3 -3
  238. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  239. package/src/queue/core/index.ts +3 -3
  240. package/src/react/auth/index.ts +3 -3
  241. package/src/react/core/index.ts +3 -3
  242. package/src/react/form/index.ts +3 -3
  243. package/src/react/head/index.ts +3 -3
  244. package/src/react/i18n/index.ts +3 -3
  245. package/src/react/intro/components/GettingStarted.css +334 -0
  246. package/src/react/intro/components/GettingStarted.tsx +276 -0
  247. package/src/react/intro/index.ts +1 -0
  248. package/src/react/router/index.browser.ts +2 -0
  249. package/src/react/router/index.ts +2 -0
  250. package/src/redis/index.ts +3 -3
  251. package/src/retry/index.ts +3 -3
  252. package/src/router/index.ts +3 -3
  253. package/src/scheduler/index.ts +3 -3
  254. package/src/security/index.ts +3 -3
  255. package/src/security/providers/JwtProvider.ts +2 -2
  256. package/src/server/auth/index.ts +3 -3
  257. package/src/server/cache/index.ts +3 -3
  258. package/src/server/compress/index.ts +3 -3
  259. package/src/server/cookies/index.ts +3 -3
  260. package/src/server/core/index.ts +3 -3
  261. package/src/server/core/primitives/$action.spec.ts +3 -2
  262. package/src/server/core/primitives/$action.ts +6 -2
  263. package/src/server/core/providers/NodeHttpServerProvider.ts +2 -15
  264. package/src/server/core/providers/ServerProvider.ts +4 -2
  265. package/src/server/core/providers/ServerRouterProvider.ts +5 -27
  266. package/src/server/cors/index.ts +3 -3
  267. package/src/server/health/index.ts +3 -3
  268. package/src/server/helmet/index.ts +3 -3
  269. package/src/server/links/index.ts +3 -3
  270. package/src/server/metrics/index.ts +3 -3
  271. package/src/server/multipart/index.ts +3 -3
  272. package/src/server/proxy/index.ts +3 -3
  273. package/src/server/rate-limit/index.ts +3 -3
  274. package/src/server/static/index.ts +3 -3
  275. package/src/server/swagger/index.ts +3 -3
  276. package/src/sms/index.ts +3 -3
  277. package/src/system/index.ts +3 -3
  278. package/src/thread/index.ts +3 -3
  279. package/src/topic/core/index.ts +3 -3
  280. package/src/websocket/index.ts +3 -3
  281. package/src/cli/templates/webHelloComponentTsx.ts +0 -30
  282. /package/src/api/users/{notifications → services}/UserNotifications.ts +0 -0
@@ -0,0 +1,334 @@
1
+ .alepha-blank {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ min-height: 100svh;
6
+ background: #fafafa;
7
+ font-family: system-ui, -apple-system, sans-serif;
8
+ color: #171717;
9
+ position: absolute;
10
+ left: 0;
11
+ right: 0;
12
+ bottom: 0;
13
+ top: 0;
14
+ width: 100%;
15
+ }
16
+
17
+ .alepha-blank-content {
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ text-align: center;
22
+ max-width: 640px;
23
+ }
24
+
25
+ .alepha-blank-text-block {
26
+ min-height: 320px;
27
+ display: flex;
28
+ flex-direction: column;
29
+ align-items: center;
30
+ justify-content: center;
31
+ }
32
+
33
+ /* Message */
34
+
35
+ .alepha-blank-message {
36
+ font-size: clamp(2rem, 8vw, 3rem);
37
+ font-weight: 600;
38
+ letter-spacing: -0.02em;
39
+ margin: 0;
40
+ line-height: 1.1;
41
+ }
42
+
43
+ .alepha-blank-sub {
44
+ font-size: 1.0625rem;
45
+ color: #525252;
46
+ margin: 1rem 0 0;
47
+ font-weight: 400;
48
+ line-height: 1.5;
49
+ }
50
+
51
+ .alepha-blank-detail {
52
+ font-size: 0.875rem;
53
+ color: #a3a3a3;
54
+ margin: 0.5rem 0 0;
55
+ font-weight: 400;
56
+ line-height: 1.5;
57
+ }
58
+
59
+ /* Slide Animations */
60
+
61
+ .alepha-blank-slide-next {
62
+ animation: alepha-blank-slideNext 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
63
+ }
64
+
65
+ .alepha-blank-slide-prev {
66
+ animation: alepha-blank-slidePrev 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
67
+ }
68
+
69
+ @keyframes alepha-blank-slideNext {
70
+ from {
71
+ opacity: 0;
72
+ transform: translateX(20px);
73
+ }
74
+ to {
75
+ opacity: 1;
76
+ transform: translateX(0);
77
+ }
78
+ }
79
+
80
+ @keyframes alepha-blank-slidePrev {
81
+ from {
82
+ opacity: 0;
83
+ transform: translateX(-20px);
84
+ }
85
+ to {
86
+ opacity: 1;
87
+ transform: translateX(0);
88
+ }
89
+ }
90
+
91
+ /* Steps */
92
+
93
+ .alepha-blank-steps {
94
+ display: flex;
95
+ flex-direction: column;
96
+ gap: 0.25rem;
97
+ margin-top: 1.25rem;
98
+ text-align: left;
99
+ }
100
+
101
+ .alepha-blank-step {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 0.625rem;
105
+ padding: 0.25rem 0;
106
+ opacity: 0;
107
+ animation: alepha-blank-stepIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) forwards;
108
+ }
109
+
110
+ .alepha-blank-step-num {
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ width: 20px;
115
+ height: 20px;
116
+ border-radius: 50%;
117
+ background: #171717;
118
+ color: #fff;
119
+ font-size: 0.6875rem;
120
+ font-weight: 600;
121
+ flex-shrink: 0;
122
+ }
123
+
124
+ .alepha-blank-step-text {
125
+ font-size: 0.8125rem;
126
+ color: #525252;
127
+ line-height: 1.5;
128
+ }
129
+
130
+ .alepha-blank-step-text code {
131
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
132
+ font-size: 0.75rem;
133
+ background: #f5f5f5;
134
+ color: #171717;
135
+ padding: 0.0625rem 0.375rem;
136
+ border-radius: 3px;
137
+ border: 1px solid #e5e5e5;
138
+ }
139
+
140
+ .alepha-blank-step-text a {
141
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
142
+ color: #525252;
143
+ text-decoration: underline;
144
+ text-underline-offset: 2px;
145
+ transition: color 0.15s ease;
146
+ }
147
+
148
+ .alepha-blank-step-text a:hover {
149
+ color: #171717;
150
+ }
151
+
152
+ @keyframes alepha-blank-stepIn {
153
+ from {
154
+ opacity: 0;
155
+ transform: translateY(10px);
156
+ }
157
+ to {
158
+ opacity: 1;
159
+ transform: translateY(0);
160
+ }
161
+ }
162
+
163
+ /* Links */
164
+
165
+ .alepha-blank-links {
166
+ display: flex;
167
+ gap: 1.5rem;
168
+ margin-top: 1.25rem;
169
+ }
170
+
171
+ .alepha-blank-links a {
172
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
173
+ font-size: 0.875rem;
174
+ color: #525252;
175
+ text-decoration: none;
176
+ position: relative;
177
+ opacity: 0;
178
+ animation: alepha-blank-fadeIn 0.3s ease-out forwards;
179
+ transition: color 0.2s ease;
180
+ }
181
+
182
+ .alepha-blank-links a::after {
183
+ content: "";
184
+ position: absolute;
185
+ left: 0;
186
+ right: 0;
187
+ bottom: -2px;
188
+ height: 1px;
189
+ background: #a3a3a3;
190
+ transform: scaleX(1);
191
+ transform-origin: left;
192
+ transition:
193
+ transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
194
+ background 0.2s ease;
195
+ }
196
+
197
+ .alepha-blank-links a:hover {
198
+ color: #171717;
199
+ }
200
+
201
+ .alepha-blank-links a:hover::after {
202
+ background: #171717;
203
+ transform: scaleX(1.05);
204
+ }
205
+
206
+ /* Slider */
207
+
208
+ .alepha-blank-slider {
209
+ display: flex;
210
+ align-items: center;
211
+ gap: 1rem;
212
+ margin-top: 2.5rem;
213
+ }
214
+
215
+ .alepha-blank-dots {
216
+ display: flex;
217
+ align-items: center;
218
+ gap: 0.5rem;
219
+ }
220
+
221
+ .alepha-blank-dot {
222
+ width: 8px;
223
+ height: 8px;
224
+ border-radius: 50%;
225
+ background: transparent;
226
+ border: 1.5px solid #d4d4d4;
227
+ padding: 0;
228
+ cursor: pointer;
229
+ transition: all 0.25s cubic-bezier(0.22, 1, 0.36, 1);
230
+ }
231
+
232
+ .alepha-blank-dot:hover {
233
+ border-color: #a3a3a3;
234
+ transform: scale(1.2);
235
+ }
236
+
237
+ .alepha-blank-dot:focus-visible {
238
+ outline: 2px solid #737373;
239
+ outline-offset: 2px;
240
+ }
241
+
242
+ .alepha-blank-dot.active {
243
+ background: #737373;
244
+ border-color: #737373;
245
+ transform: scale(1.1);
246
+ }
247
+
248
+ /* Nav Buttons */
249
+
250
+ .alepha-blank-nav-btn {
251
+ width: 32px;
252
+ height: 32px;
253
+ display: flex;
254
+ align-items: center;
255
+ justify-content: center;
256
+ padding: 0;
257
+ font-family: inherit;
258
+ background: transparent;
259
+ color: #a3a3a3;
260
+ border: 1.5px solid transparent;
261
+ border-radius: 8px;
262
+ cursor: pointer;
263
+ transition: all 0.2s cubic-bezier(0.22, 1, 0.36, 1);
264
+ }
265
+
266
+ .alepha-blank-nav-btn:hover {
267
+ color: #525252;
268
+ background: #f0f0f0;
269
+ }
270
+
271
+ .alepha-blank-nav-btn:focus-visible {
272
+ outline: none;
273
+ border-color: #737373;
274
+ color: #525252;
275
+ }
276
+
277
+ .alepha-blank-nav-btn:active {
278
+ transform: scale(0.92);
279
+ background: #e5e5e5;
280
+ }
281
+
282
+ /* Hint */
283
+
284
+ .alepha-blank-hint {
285
+ margin-top: 2rem;
286
+ font-size: 0.75rem;
287
+ color: #a3a3a3;
288
+ display: flex;
289
+ align-items: center;
290
+ gap: 0.375rem;
291
+ opacity: 0;
292
+ animation: alepha-blank-fadeIn 0.5s ease-out 0.5s forwards;
293
+ }
294
+
295
+ .alepha-blank-hint kbd {
296
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
297
+ font-size: 0.6875rem;
298
+ background: #f0f0f0;
299
+ border: 1px solid #e5e5e5;
300
+ border-radius: 4px;
301
+ padding: 0.125rem 0.375rem;
302
+ box-shadow: 0 1px 0 #d4d4d4;
303
+ }
304
+
305
+ /* Fade In Animation */
306
+
307
+ @keyframes alepha-blank-fadeIn {
308
+ from {
309
+ opacity: 0;
310
+ }
311
+ to {
312
+ opacity: 1;
313
+ }
314
+ }
315
+
316
+ /* Respect reduced motion */
317
+
318
+ @media (prefers-reduced-motion: reduce) {
319
+ .alepha-blank-slide-next,
320
+ .alepha-blank-slide-prev,
321
+ .alepha-blank-links a,
322
+ .alepha-blank-hint,
323
+ .alepha-blank-step {
324
+ animation: none;
325
+ opacity: 1;
326
+ }
327
+
328
+ .alepha-blank-dot,
329
+ .alepha-blank-nav-btn,
330
+ .alepha-blank-links a,
331
+ .alepha-blank-links a::after {
332
+ transition: none;
333
+ }
334
+ }
@@ -0,0 +1,276 @@
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+ import "./GettingStarted.css";
3
+ import { useRouter } from "alepha/react/router";
4
+ import type { ReactNode } from "react";
5
+
6
+ type Step = {
7
+ num: string;
8
+ text: ReactNode;
9
+ };
10
+
11
+ type Message = {
12
+ text: string;
13
+ sub: string;
14
+ detail?: string;
15
+ steps?: Step[];
16
+ links?: { label: string; href: string }[];
17
+ };
18
+
19
+ const messages: Message[] = [
20
+ {
21
+ text: "Let's begin.",
22
+ sub: "Every story starts with a blank page.",
23
+ detail: "This one is yours.",
24
+ },
25
+ {
26
+ text: "Need help?",
27
+ sub: "We've got you covered.",
28
+ detail: "Even our AI friends can read the docs.",
29
+ links: [
30
+ { label: "alepha.dev", href: "https://alepha.dev" },
31
+ { label: "llms.txt", href: "https://alepha.dev/llms.txt" },
32
+ ],
33
+ },
34
+ ];
35
+
36
+ /**
37
+ * A welcome component displayed when creating a new Alepha application.
38
+ */
39
+ const GettingStarted = () => {
40
+ const [index, setIndex] = useState(0);
41
+ const [direction, setDirection] = useState<"next" | "prev">("next");
42
+
43
+ const router = useRouter();
44
+ const hasAdmin = router.pages.find((it) => it.name === "adminLayout");
45
+ const hasAuth = router.pages.find((it) => it.name === "authLayout");
46
+
47
+ const adminAnchorProps = hasAdmin
48
+ ? router.anchor(router.path("adminLayout"))
49
+ : undefined;
50
+ const authAnchorProps = hasAuth
51
+ ? router.anchor(router.path("login"))
52
+ : undefined;
53
+
54
+ const filteredMessages = useMemo(() => {
55
+ const result: Message[] = [];
56
+
57
+ // Add static messages up to "What's next?"
58
+ for (const msg of messages) {
59
+ if (msg.text === "Need help?") break;
60
+ result.push(msg);
61
+ }
62
+
63
+ // Add auth message if available
64
+ if (hasAuth && authAnchorProps) {
65
+ result.push({
66
+ text: "Who are you?",
67
+ sub: "Create your first account.",
68
+ steps: [
69
+ {
70
+ num: "1",
71
+ text: (
72
+ <>
73
+ Sign up at <a {...authAnchorProps}>/auth/login</a>
74
+ </>
75
+ ),
76
+ },
77
+ {
78
+ num: "2",
79
+ text: (
80
+ <>
81
+ Customize in <code>src/api/AppSecurity.ts</code>
82
+ </>
83
+ ),
84
+ },
85
+ ],
86
+ });
87
+ }
88
+
89
+ // Add admin message if available
90
+ if (hasAdmin && adminAnchorProps) {
91
+ result.push({
92
+ text: "Take the wheel.",
93
+ sub: "Become admin in three steps.",
94
+ steps: [
95
+ {
96
+ num: "1",
97
+ text: (
98
+ <>
99
+ Add your email to <code>adminEmails</code> in{" "}
100
+ <code>AppSecurity.ts</code>
101
+ </>
102
+ ),
103
+ },
104
+ { num: "2", text: "Create a user account with that email" },
105
+ {
106
+ num: "3",
107
+ text: (
108
+ <>
109
+ Go to <a {...adminAnchorProps}>/admin</a>
110
+ </>
111
+ ),
112
+ },
113
+ ],
114
+ });
115
+ }
116
+
117
+ // Add "Need help?" message
118
+ const helpMsg = messages.find((msg) => msg.text === "Need help?");
119
+ if (helpMsg) {
120
+ result.push(helpMsg);
121
+ }
122
+
123
+ return result;
124
+ }, [hasAuth, hasAdmin, authAnchorProps, adminAnchorProps]);
125
+
126
+ const current = filteredMessages[index];
127
+
128
+ const prev = useCallback(() => {
129
+ setDirection("prev");
130
+ setIndex(
131
+ (i) => (i - 1 + filteredMessages.length) % filteredMessages.length,
132
+ );
133
+ }, [filteredMessages.length]);
134
+
135
+ const next = useCallback(() => {
136
+ setDirection("next");
137
+ setIndex((i) => (i + 1) % filteredMessages.length);
138
+ }, [filteredMessages.length]);
139
+
140
+ const goTo = useCallback(
141
+ (i: number) => {
142
+ setDirection(i > index ? "next" : "prev");
143
+ setIndex(i);
144
+ },
145
+ [index],
146
+ );
147
+
148
+ useEffect(() => {
149
+ const handleKeyDown = (e: KeyboardEvent) => {
150
+ if (e.key === "ArrowLeft") {
151
+ prev();
152
+ } else if (e.key === "ArrowRight") {
153
+ next();
154
+ }
155
+ };
156
+ window.addEventListener("keydown", handleKeyDown);
157
+ return () => window.removeEventListener("keydown", handleKeyDown);
158
+ }, [prev, next]);
159
+
160
+ return (
161
+ <main className="alepha-blank">
162
+ <div className="alepha-blank-content">
163
+ <div className="alepha-blank-text-block">
164
+ <h1
165
+ className={`alepha-blank-message alepha-blank-slide-${direction}`}
166
+ key={index}
167
+ >
168
+ {current.text}
169
+ </h1>
170
+ <p
171
+ className={`alepha-blank-sub alepha-blank-slide-${direction}`}
172
+ key={`sub-${index}`}
173
+ >
174
+ {current.sub}
175
+ </p>
176
+ {current.detail && (
177
+ <p
178
+ className={`alepha-blank-detail alepha-blank-slide-${direction}`}
179
+ key={`detail-${index}`}
180
+ >
181
+ {current.detail}
182
+ </p>
183
+ )}
184
+ {current.steps && (
185
+ <div
186
+ className={`alepha-blank-steps alepha-blank-slide-${direction}`}
187
+ key={`steps-${index}`}
188
+ >
189
+ {current.steps.map((step, i) => (
190
+ <div
191
+ key={i}
192
+ className="alepha-blank-step"
193
+ style={{ animationDelay: `${0.15 + i * 0.08}s` }}
194
+ >
195
+ <span className="alepha-blank-step-num">{step.num}</span>
196
+ <span className="alepha-blank-step-text">{step.text}</span>
197
+ </div>
198
+ ))}
199
+ </div>
200
+ )}
201
+ {current.links && (
202
+ <div
203
+ className={`alepha-blank-links alepha-blank-slide-${direction}`}
204
+ key={`links-${index}`}
205
+ >
206
+ {current.links.map((link, i) => (
207
+ <a
208
+ key={link.href}
209
+ href={link.href}
210
+ target={link.href.startsWith("http") ? "_blank" : undefined}
211
+ rel={
212
+ link.href.startsWith("http")
213
+ ? "noopener noreferrer"
214
+ : undefined
215
+ }
216
+ style={{ animationDelay: `${0.1 + i * 0.05}s` }}
217
+ >
218
+ {link.label}
219
+ </a>
220
+ ))}
221
+ </div>
222
+ )}
223
+ </div>
224
+
225
+ <div className="alepha-blank-slider">
226
+ <button
227
+ className="alepha-blank-nav-btn"
228
+ onClick={prev}
229
+ aria-label="Previous"
230
+ >
231
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
232
+ <path
233
+ d="M9 3L5 7L9 11"
234
+ stroke="currentColor"
235
+ strokeWidth="1.5"
236
+ strokeLinecap="round"
237
+ strokeLinejoin="round"
238
+ />
239
+ </svg>
240
+ </button>
241
+ <div className="alepha-blank-dots">
242
+ {filteredMessages.map((_, i) => (
243
+ <button
244
+ key={i}
245
+ className={`alepha-blank-dot ${i === index ? "active" : ""}`}
246
+ onClick={() => goTo(i)}
247
+ aria-label={`Go to message ${i + 1}`}
248
+ />
249
+ ))}
250
+ </div>
251
+ <button
252
+ className="alepha-blank-nav-btn"
253
+ onClick={next}
254
+ aria-label="Next"
255
+ >
256
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
257
+ <path
258
+ d="M5 3L9 7L5 11"
259
+ stroke="currentColor"
260
+ strokeWidth="1.5"
261
+ strokeLinecap="round"
262
+ strokeLinejoin="round"
263
+ />
264
+ </svg>
265
+ </button>
266
+ </div>
267
+
268
+ <div className="alepha-blank-hint">
269
+ <kbd>←</kbd> <kbd>→</kbd> to navigate
270
+ </div>
271
+ </div>
272
+ </main>
273
+ );
274
+ };
275
+
276
+ export default GettingStarted;
@@ -0,0 +1 @@
1
+ export { default as GettingStarted } from "./components/GettingStarted.tsx";
@@ -1,6 +1,7 @@
1
1
  import { $module } from "alepha";
2
2
  import { AlephaDateTime } from "alepha/datetime";
3
3
  import { AlephaReact } from "alepha/react";
4
+ import { AlephaReactHead } from "alepha/react/head";
4
5
  import { AlephaServer } from "alepha/server";
5
6
  import { AlephaServerLinks } from "alepha/server/links";
6
7
  import { $page } from "./primitives/$page.ts";
@@ -34,6 +35,7 @@ export const AlephaReactRouter = $module({
34
35
  register: (alepha) =>
35
36
  alepha
36
37
  .with(AlephaReact)
38
+ .with(AlephaReactHead)
37
39
  .with(AlephaDateTime)
38
40
  .with(AlephaServer)
39
41
  .with(AlephaServerLinks)
@@ -1,6 +1,7 @@
1
1
  import { $module } from "alepha";
2
2
  import { AlephaDateTime } from "alepha/datetime";
3
3
  import { AlephaReact } from "alepha/react";
4
+ import { AlephaReactHead } from "alepha/react/head";
4
5
  import { AlephaServer, type ServerRequest } from "alepha/server";
5
6
  import { AlephaServerCache } from "alepha/server/cache";
6
7
  import { AlephaServerLinks } from "alepha/server/links";
@@ -129,6 +130,7 @@ export const AlephaReactRouter = $module({
129
130
  register: (alepha) =>
130
131
  alepha
131
132
  .with(AlephaReact)
133
+ .with(AlephaReactHead)
132
134
  .with(AlephaDateTime)
133
135
  .with(AlephaServer)
134
136
  .with(AlephaServerCache)
@@ -18,9 +18,9 @@ export * from "./providers/RedisSubscriberProvider.ts";
18
18
  // ---------------------------------------------------------------------------------------------------------------------
19
19
 
20
20
  /**
21
- * | type | quality | stability |
22
- * |------|---------|-----------|
23
- * | backend | standard | stable |
21
+ * | Stability | Since | Runtime |
22
+ * |-----------|-------|---------|
23
+ * | 3 - stable | 0.1.0 | node, bun|
24
24
  *
25
25
  * Redis client wrapper.
26
26
  *
@@ -12,9 +12,9 @@ export * from "./providers/RetryProvider.ts";
12
12
  // ---------------------------------------------------------------------------------------------------------------------
13
13
 
14
14
  /**
15
- * | type | quality | stability |
16
- * |------|---------|-----------|
17
- * | backend | standard | stable |
15
+ * | Stability | Since | Runtime |
16
+ * |-----------|-------|---------|
17
+ * | 3 - stable | 0.12.0 | node, bun, workerd, browser, expo|
18
18
  *
19
19
  * Automatic retry with backoff.
20
20
  *
@@ -1,7 +1,7 @@
1
1
  /**
2
- * | type | quality | stability |
3
- * |------|---------|-----------|
4
- * | frontend | standard | stable |
2
+ * | Stability | Since | Runtime |
3
+ * |-----------|-------|---------|
4
+ * | 3 - stable | 0.2.0 | node, bun, workerd, browser, expo|
5
5
  *
6
6
  * Frontend routing infrastructure.
7
7
  *
@@ -35,9 +35,9 @@ declare module "alepha" {
35
35
  // ---------------------------------------------------------------------------------------------------------------------
36
36
 
37
37
  /**
38
- * | type | quality | stability |
39
- * |------|---------|-----------|
40
- * | backend | rare | stable |
38
+ * | Stability | Since | Runtime |
39
+ * |-----------|-------|---------|
40
+ * | 3 - stable | 0.1.0 | node, bun, workerd|
41
41
  *
42
42
  * Cron and interval-based task execution.
43
43
  *
@@ -89,9 +89,9 @@ declare module "alepha/server" {
89
89
  }
90
90
 
91
91
  /**
92
- * | type | quality | stability |
93
- * |------|---------|-----------|
94
- * | backend | epic | stable |
92
+ * | Stability | Since | Runtime |
93
+ * |-----------|-------|---------|
94
+ * | 3 - stable | 0.1.0 | node, bun, workerd, browser|
95
95
  *
96
96
  * Complete authentication and authorization system with JWT, RBAC, and multi-issuer support.
97
97
  *