@agent-native/core 0.4.1 → 0.4.2

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 (221) hide show
  1. package/README.md +31 -0
  2. package/dist/adapters/convex/adapter.d.ts +24 -0
  3. package/dist/adapters/convex/adapter.d.ts.map +1 -0
  4. package/dist/adapters/convex/adapter.js +125 -0
  5. package/dist/adapters/convex/adapter.js.map +1 -0
  6. package/dist/adapters/convex/index.d.ts +4 -0
  7. package/dist/adapters/convex/index.d.ts.map +1 -0
  8. package/dist/adapters/convex/index.js +3 -0
  9. package/dist/adapters/convex/index.js.map +1 -0
  10. package/dist/adapters/drizzle/adapter.d.ts +36 -0
  11. package/dist/adapters/drizzle/adapter.d.ts.map +1 -0
  12. package/dist/adapters/drizzle/adapter.js +210 -0
  13. package/dist/adapters/drizzle/adapter.js.map +1 -0
  14. package/dist/adapters/drizzle/index.d.ts +3 -0
  15. package/dist/adapters/drizzle/index.d.ts.map +1 -0
  16. package/dist/adapters/drizzle/index.js +3 -0
  17. package/dist/adapters/drizzle/index.js.map +1 -0
  18. package/dist/adapters/drizzle/schema.d.ts +146 -0
  19. package/dist/adapters/drizzle/schema.d.ts.map +1 -0
  20. package/dist/adapters/drizzle/schema.js +20 -0
  21. package/dist/adapters/drizzle/schema.js.map +1 -0
  22. package/dist/adapters/firestore/adapter.d.ts +3 -2
  23. package/dist/adapters/firestore/adapter.d.ts.map +1 -1
  24. package/dist/adapters/firestore/adapter.js +23 -6
  25. package/dist/adapters/firestore/adapter.js.map +1 -1
  26. package/dist/adapters/supabase/adapter.d.ts +2 -1
  27. package/dist/adapters/supabase/adapter.d.ts.map +1 -1
  28. package/dist/adapters/supabase/adapter.js +4 -1
  29. package/dist/adapters/supabase/adapter.js.map +1 -1
  30. package/dist/adapters/sync/config.d.ts +22 -2
  31. package/dist/adapters/sync/config.d.ts.map +1 -1
  32. package/dist/adapters/sync/config.js +175 -16
  33. package/dist/adapters/sync/config.js.map +1 -1
  34. package/dist/adapters/sync/create-file-sync.d.ts +32 -0
  35. package/dist/adapters/sync/create-file-sync.d.ts.map +1 -0
  36. package/dist/adapters/sync/create-file-sync.js +218 -0
  37. package/dist/adapters/sync/create-file-sync.js.map +1 -0
  38. package/dist/adapters/sync/file-sync.d.ts +40 -6
  39. package/dist/adapters/sync/file-sync.d.ts.map +1 -1
  40. package/dist/adapters/sync/file-sync.js +442 -97
  41. package/dist/adapters/sync/file-sync.js.map +1 -1
  42. package/dist/adapters/sync/index.d.ts +3 -2
  43. package/dist/adapters/sync/index.d.ts.map +1 -1
  44. package/dist/adapters/sync/index.js +3 -1
  45. package/dist/adapters/sync/index.js.map +1 -1
  46. package/dist/adapters/sync/merge.js +3 -2
  47. package/dist/adapters/sync/merge.js.map +1 -1
  48. package/dist/adapters/sync/types.d.ts +36 -2
  49. package/dist/adapters/sync/types.d.ts.map +1 -1
  50. package/dist/adapters/sync/types.js +22 -1
  51. package/dist/adapters/sync/types.js.map +1 -1
  52. package/dist/agent/index.d.ts +3 -0
  53. package/dist/agent/index.d.ts.map +1 -0
  54. package/dist/agent/index.js +2 -0
  55. package/dist/agent/index.js.map +1 -0
  56. package/dist/agent/production-agent.d.ts +16 -0
  57. package/dist/agent/production-agent.d.ts.map +1 -0
  58. package/dist/agent/production-agent.js +152 -0
  59. package/dist/agent/production-agent.js.map +1 -0
  60. package/dist/agent/types.d.ts +38 -0
  61. package/dist/agent/types.d.ts.map +1 -0
  62. package/dist/agent/types.js +2 -0
  63. package/dist/agent/types.js.map +1 -0
  64. package/dist/cli/create.d.ts.map +1 -1
  65. package/dist/cli/create.js +2 -0
  66. package/dist/cli/create.js.map +1 -1
  67. package/dist/cli/index.js +37 -11
  68. package/dist/cli/index.js.map +1 -1
  69. package/dist/client/PoweredByBadge.d.ts +14 -0
  70. package/dist/client/PoweredByBadge.d.ts.map +1 -0
  71. package/dist/client/PoweredByBadge.js +60 -0
  72. package/dist/client/PoweredByBadge.js.map +1 -0
  73. package/dist/client/ProductionAgentPanel.d.ts +10 -0
  74. package/dist/client/ProductionAgentPanel.d.ts.map +1 -0
  75. package/dist/client/ProductionAgentPanel.js +121 -0
  76. package/dist/client/ProductionAgentPanel.js.map +1 -0
  77. package/dist/client/Turnstile.d.ts +35 -0
  78. package/dist/client/Turnstile.d.ts.map +1 -0
  79. package/dist/client/Turnstile.js +77 -0
  80. package/dist/client/Turnstile.js.map +1 -0
  81. package/dist/client/index.d.ts +6 -0
  82. package/dist/client/index.d.ts.map +1 -1
  83. package/dist/client/index.js +6 -0
  84. package/dist/client/index.js.map +1 -1
  85. package/dist/client/use-file-sync-status.d.ts +21 -0
  86. package/dist/client/use-file-sync-status.d.ts.map +1 -0
  87. package/dist/client/use-file-sync-status.js +65 -0
  88. package/dist/client/use-file-sync-status.js.map +1 -0
  89. package/dist/client/use-session.d.ts +16 -0
  90. package/dist/client/use-session.d.ts.map +1 -0
  91. package/dist/client/use-session.js +49 -0
  92. package/dist/client/use-session.js.map +1 -0
  93. package/dist/client/useProductionAgent.d.ts +18 -0
  94. package/dist/client/useProductionAgent.d.ts.map +1 -0
  95. package/dist/client/useProductionAgent.js +135 -0
  96. package/dist/client/useProductionAgent.js.map +1 -0
  97. package/dist/db/index.d.ts +21 -0
  98. package/dist/db/index.d.ts.map +1 -0
  99. package/dist/db/index.js +17 -0
  100. package/dist/db/index.js.map +1 -0
  101. package/dist/index.browser.d.ts +1 -1
  102. package/dist/index.browser.d.ts.map +1 -1
  103. package/dist/index.browser.js +1 -1
  104. package/dist/index.browser.js.map +1 -1
  105. package/dist/index.d.ts +3 -2
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +4 -2
  108. package/dist/index.js.map +1 -1
  109. package/dist/router/index.d.ts +3 -0
  110. package/dist/router/index.d.ts.map +1 -0
  111. package/dist/router/index.js +5 -0
  112. package/dist/router/index.js.map +1 -0
  113. package/dist/scripts/core-scripts.d.ts +10 -0
  114. package/dist/scripts/core-scripts.d.ts.map +1 -0
  115. package/dist/scripts/core-scripts.js +15 -0
  116. package/dist/scripts/core-scripts.js.map +1 -0
  117. package/dist/scripts/db/exec.d.ts +11 -0
  118. package/dist/scripts/db/exec.d.ts.map +1 -0
  119. package/dist/scripts/db/exec.js +86 -0
  120. package/dist/scripts/db/exec.js.map +1 -0
  121. package/dist/scripts/db/index.d.ts +2 -0
  122. package/dist/scripts/db/index.d.ts.map +1 -0
  123. package/dist/scripts/db/index.js +6 -0
  124. package/dist/scripts/db/index.js.map +1 -0
  125. package/dist/scripts/db/query.d.ts +10 -0
  126. package/dist/scripts/db/query.d.ts.map +1 -0
  127. package/dist/scripts/db/query.js +96 -0
  128. package/dist/scripts/db/query.js.map +1 -0
  129. package/dist/scripts/db/schema.d.ts +12 -0
  130. package/dist/scripts/db/schema.d.ts.map +1 -0
  131. package/dist/scripts/db/schema.js +112 -0
  132. package/dist/scripts/db/schema.js.map +1 -0
  133. package/dist/scripts/index.d.ts +4 -0
  134. package/dist/scripts/index.d.ts.map +1 -1
  135. package/dist/scripts/index.js +4 -0
  136. package/dist/scripts/index.js.map +1 -1
  137. package/dist/scripts/runner.d.ts +3 -0
  138. package/dist/scripts/runner.d.ts.map +1 -1
  139. package/dist/scripts/runner.js +53 -14
  140. package/dist/scripts/runner.js.map +1 -1
  141. package/dist/server/auth.d.ts +59 -0
  142. package/dist/server/auth.d.ts.map +1 -0
  143. package/dist/server/auth.js +442 -0
  144. package/dist/server/auth.js.map +1 -0
  145. package/dist/server/captcha.d.ts +12 -0
  146. package/dist/server/captcha.d.ts.map +1 -0
  147. package/dist/server/captcha.js +43 -0
  148. package/dist/server/captcha.js.map +1 -0
  149. package/dist/server/create-server.d.ts +13 -10
  150. package/dist/server/create-server.d.ts.map +1 -1
  151. package/dist/server/create-server.js +41 -27
  152. package/dist/server/create-server.js.map +1 -1
  153. package/dist/server/index.d.ts +5 -1
  154. package/dist/server/index.d.ts.map +1 -1
  155. package/dist/server/index.js +6 -1
  156. package/dist/server/index.js.map +1 -1
  157. package/dist/server/missing-key.d.ts +9 -5
  158. package/dist/server/missing-key.d.ts.map +1 -1
  159. package/dist/server/missing-key.js +12 -7
  160. package/dist/server/missing-key.js.map +1 -1
  161. package/dist/server/sse.d.ts +12 -7
  162. package/dist/server/sse.d.ts.map +1 -1
  163. package/dist/server/sse.js +79 -15
  164. package/dist/server/sse.js.map +1 -1
  165. package/dist/vite/client.d.ts +28 -5
  166. package/dist/vite/client.d.ts.map +1 -1
  167. package/dist/vite/client.js +36 -15
  168. package/dist/vite/client.js.map +1 -1
  169. package/dist/vite/dev-api-server.d.ts +10 -0
  170. package/dist/vite/dev-api-server.d.ts.map +1 -0
  171. package/dist/vite/dev-api-server.js +148 -0
  172. package/dist/vite/dev-api-server.js.map +1 -0
  173. package/dist/vite/index.d.ts +2 -3
  174. package/dist/vite/index.d.ts.map +1 -1
  175. package/dist/vite/index.js +2 -3
  176. package/dist/vite/index.js.map +1 -1
  177. package/package.json +26 -17
  178. package/src/templates/default/AGENTS.md +148 -22
  179. package/src/templates/default/_gitignore +9 -5
  180. package/src/templates/default/client/entry.client.tsx +4 -0
  181. package/src/templates/default/client/entry.server.tsx +55 -0
  182. package/src/templates/default/client/root.tsx +82 -0
  183. package/src/templates/default/client/routes/_index.tsx +19 -0
  184. package/src/templates/default/client/routes.ts +4 -0
  185. package/src/templates/default/client/vite-env.d.ts +5 -0
  186. package/src/templates/default/package.json +5 -7
  187. package/src/templates/default/react-router.config.ts +6 -0
  188. package/src/templates/default/server/lib/watcher.ts +21 -0
  189. package/src/templates/default/server/plugins/auth.ts +5 -0
  190. package/src/templates/default/server/plugins/file-sync.ts +39 -0
  191. package/src/templates/default/server/routes/[...page].get.ts +12 -0
  192. package/src/templates/default/server/routes/api/events.get.ts +7 -0
  193. package/src/templates/default/server/routes/api/file-sync/status.get.ts +13 -0
  194. package/src/templates/default/server/routes/api/hello.get.ts +5 -0
  195. package/src/templates/default/tsconfig.json +9 -1
  196. package/src/templates/default/vite.config.ts +4 -1
  197. package/tsconfig.base.json +3 -1
  198. package/dist/adapters/neon/adapter.d.ts +0 -28
  199. package/dist/adapters/neon/adapter.d.ts.map +0 -1
  200. package/dist/adapters/neon/adapter.js +0 -135
  201. package/dist/adapters/neon/adapter.js.map +0 -1
  202. package/dist/adapters/neon/index.d.ts +0 -3
  203. package/dist/adapters/neon/index.d.ts.map +0 -1
  204. package/dist/adapters/neon/index.js +0 -3
  205. package/dist/adapters/neon/index.js.map +0 -1
  206. package/dist/server/production.d.ts +0 -18
  207. package/dist/server/production.d.ts.map +0 -1
  208. package/dist/server/production.js +0 -37
  209. package/dist/server/production.js.map +0 -1
  210. package/dist/vite/express-plugin.d.ts +0 -14
  211. package/dist/vite/express-plugin.d.ts.map +0 -1
  212. package/dist/vite/express-plugin.js +0 -53
  213. package/dist/vite/express-plugin.js.map +0 -1
  214. package/dist/vite/server.d.ts +0 -21
  215. package/dist/vite/server.d.ts.map +0 -1
  216. package/dist/vite/server.js +0 -68
  217. package/dist/vite/server.js.map +0 -1
  218. package/src/templates/default/index.html +0 -14
  219. package/src/templates/default/server/index.ts +0 -22
  220. package/src/templates/default/server/node-build.ts +0 -4
  221. package/src/templates/default/vite.config.server.ts +0 -3
@@ -0,0 +1,442 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { defineEventHandler, readBody, getMethod, setResponseHeader, setResponseStatus, getCookie, setCookie, deleteCookie, } from "h3";
5
+ // ---------------------------------------------------------------------------
6
+ // Constants
7
+ // ---------------------------------------------------------------------------
8
+ const COOKIE_NAME = "an_session";
9
+ const DEFAULT_MAX_AGE = 60 * 60 * 24 * 30; // 30 days
10
+ const DEFAULT_SESSIONS_PATH = "data/.sessions.json";
11
+ let sessions = new Map();
12
+ let sessionsFilePath = DEFAULT_SESSIONS_PATH;
13
+ let sessionMaxAge = DEFAULT_MAX_AGE;
14
+ function resolveSessionsPath(customPath) {
15
+ return path.resolve(process.cwd(), customPath ?? DEFAULT_SESSIONS_PATH);
16
+ }
17
+ function loadSessions() {
18
+ try {
19
+ const raw = fs.readFileSync(sessionsFilePath, "utf-8");
20
+ const entries = JSON.parse(raw);
21
+ sessions = new Map(entries.map((s) => [s.token, s]));
22
+ }
23
+ catch {
24
+ sessions = new Map();
25
+ }
26
+ }
27
+ function saveSessions() {
28
+ const dir = path.dirname(sessionsFilePath);
29
+ fs.mkdirSync(dir, { recursive: true });
30
+ const entries = Array.from(sessions.values());
31
+ fs.writeFileSync(sessionsFilePath, JSON.stringify(entries, null, 2));
32
+ }
33
+ function pruneExpiredSessions() {
34
+ const now = Date.now();
35
+ let pruned = false;
36
+ for (const [token, session] of sessions) {
37
+ if (now - session.createdAt > sessionMaxAge * 1000) {
38
+ sessions.delete(token);
39
+ pruned = true;
40
+ }
41
+ }
42
+ if (pruned)
43
+ saveSessions();
44
+ }
45
+ function addSession(token) {
46
+ sessions.set(token, { token, createdAt: Date.now() });
47
+ saveSessions();
48
+ }
49
+ function removeSession(token) {
50
+ sessions.delete(token);
51
+ saveSessions();
52
+ }
53
+ function hasSession(token) {
54
+ const session = sessions.get(token);
55
+ if (!session)
56
+ return false;
57
+ if (Date.now() - session.createdAt > sessionMaxAge * 1000) {
58
+ sessions.delete(token);
59
+ saveSessions();
60
+ return false;
61
+ }
62
+ return true;
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Token resolution — supports ACCESS_TOKEN (single) or ACCESS_TOKENS (multi)
66
+ // ---------------------------------------------------------------------------
67
+ function getAccessTokens() {
68
+ const single = process.env.ACCESS_TOKEN;
69
+ const multi = process.env.ACCESS_TOKENS;
70
+ const tokens = [];
71
+ if (single)
72
+ tokens.push(single);
73
+ if (multi) {
74
+ for (const t of multi.split(",")) {
75
+ const trimmed = t.trim();
76
+ if (trimmed && !tokens.includes(trimmed))
77
+ tokens.push(trimmed);
78
+ }
79
+ }
80
+ return tokens;
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // Dev mode detection
84
+ // ---------------------------------------------------------------------------
85
+ function isDevMode() {
86
+ return process.env.NODE_ENV !== "production";
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // getSession — the auth contract
90
+ // ---------------------------------------------------------------------------
91
+ let customGetSession = null;
92
+ let authDisabledMode = false;
93
+ const DEV_SESSION = { email: "local@localhost" };
94
+ /**
95
+ * Get the current auth session for a request.
96
+ *
97
+ * - In dev mode: always returns { email: "local@localhost" }
98
+ * - In production with built-in auth: returns session if cookie is valid
99
+ * - With custom auth (BYOA): delegates to the custom getSession
100
+ */
101
+ export async function getSession(event) {
102
+ if (isDevMode())
103
+ return DEV_SESSION;
104
+ if (authDisabledMode)
105
+ return DEV_SESSION;
106
+ if (customGetSession)
107
+ return customGetSession(event);
108
+ const cookie = getCookie(event, COOKIE_NAME);
109
+ if (cookie && hasSession(cookie)) {
110
+ return { email: "user", token: cookie };
111
+ }
112
+ return null;
113
+ }
114
+ // ---------------------------------------------------------------------------
115
+ // Constant-time token comparison
116
+ // ---------------------------------------------------------------------------
117
+ function safeTokenMatch(input, tokens) {
118
+ const inputBuf = Buffer.from(input);
119
+ for (const token of tokens) {
120
+ const tokenBuf = Buffer.from(token);
121
+ if (inputBuf.length === tokenBuf.length &&
122
+ crypto.timingSafeEqual(inputBuf, tokenBuf)) {
123
+ return true;
124
+ }
125
+ }
126
+ return false;
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // Login page HTML
130
+ // ---------------------------------------------------------------------------
131
+ const LOGIN_HTML = `<!DOCTYPE html>
132
+ <html lang="en">
133
+ <head>
134
+ <meta charset="UTF-8">
135
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
136
+ <title>Sign in</title>
137
+ <style>
138
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
139
+ body {
140
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
141
+ background: #0a0a0a;
142
+ color: #e5e5e5;
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: center;
146
+ min-height: 100vh;
147
+ }
148
+ .card {
149
+ width: 100%;
150
+ max-width: 360px;
151
+ padding: 2rem;
152
+ background: #141414;
153
+ border: 1px solid rgba(255,255,255,0.08);
154
+ border-radius: 12px;
155
+ }
156
+ h1 { font-size: 1.125rem; font-weight: 600; margin-bottom: 1.5rem; color: #fff; }
157
+ label { display: block; font-size: 0.8125rem; color: #888; margin-bottom: 0.375rem; }
158
+ input {
159
+ width: 100%;
160
+ padding: 0.625rem 0.75rem;
161
+ background: #1e1e1e;
162
+ border: 1px solid rgba(255,255,255,0.12);
163
+ border-radius: 8px;
164
+ color: #e5e5e5;
165
+ font-size: 0.9375rem;
166
+ outline: none;
167
+ transition: border-color 0.15s;
168
+ }
169
+ input:focus { border-color: rgba(255,255,255,0.3); }
170
+ button {
171
+ width: 100%;
172
+ margin-top: 1rem;
173
+ padding: 0.625rem;
174
+ background: #fff;
175
+ color: #000;
176
+ border: none;
177
+ border-radius: 8px;
178
+ font-size: 0.9375rem;
179
+ font-weight: 500;
180
+ cursor: pointer;
181
+ transition: opacity 0.15s;
182
+ }
183
+ button:hover { opacity: 0.85; }
184
+ .error { margin-top: 0.75rem; font-size: 0.8125rem; color: #f87171; display: none; }
185
+ .error.show { display: block; }
186
+ </style>
187
+ </head>
188
+ <body>
189
+ <div class="card">
190
+ <h1>Sign in</h1>
191
+ <form id="form">
192
+ <label for="token">Access token</label>
193
+ <input id="token" type="password" autocomplete="current-password" autofocus placeholder="Enter access token" />
194
+ <button type="submit">Continue</button>
195
+ <p class="error" id="err">Invalid token. Please try again.</p>
196
+ </form>
197
+ </div>
198
+ <script>
199
+ document.getElementById('form').addEventListener('submit', async (e) => {
200
+ e.preventDefault();
201
+ const token = document.getElementById('token').value;
202
+ const res = await fetch('/api/auth/login', {
203
+ method: 'POST',
204
+ headers: { 'Content-Type': 'application/json' },
205
+ body: JSON.stringify({ token }),
206
+ });
207
+ if (res.ok) {
208
+ window.location.reload();
209
+ } else {
210
+ document.getElementById('err').classList.add('show');
211
+ }
212
+ });
213
+ </script>
214
+ </body>
215
+ </html>`;
216
+ // ---------------------------------------------------------------------------
217
+ // mountAuthMiddleware — mounts login/logout/session routes + auth guard
218
+ // ---------------------------------------------------------------------------
219
+ /**
220
+ * Mount auth middleware + login/logout/session routes onto an H3 app.
221
+ *
222
+ * @deprecated Use `autoMountAuth(app, options?)` instead for automatic
223
+ * dev/prod behavior. This function is kept for backwards compatibility
224
+ * when you need explicit control over the access token.
225
+ */
226
+ export function mountAuthMiddleware(app, accessToken) {
227
+ mountAuthRoutes(app, [accessToken]);
228
+ }
229
+ function isPublicPath(url, publicPaths) {
230
+ const p = url.split("?")[0];
231
+ return publicPaths.some((pp) => p === pp || p.startsWith(pp + "/"));
232
+ }
233
+ function mountAuthRoutes(app, accessTokens, publicPaths = []) {
234
+ // POST /api/auth/login
235
+ app.use("/api/auth/login", defineEventHandler(async (event) => {
236
+ if (getMethod(event) !== "POST") {
237
+ setResponseStatus(event, 405);
238
+ return { error: "Method not allowed" };
239
+ }
240
+ const body = await readBody(event);
241
+ if (!body?.token ||
242
+ typeof body.token !== "string" ||
243
+ !safeTokenMatch(body.token, accessTokens)) {
244
+ setResponseStatus(event, 401);
245
+ return { error: "Invalid token" };
246
+ }
247
+ const sessionToken = crypto.randomBytes(32).toString("hex");
248
+ addSession(sessionToken);
249
+ setCookie(event, COOKIE_NAME, sessionToken, {
250
+ httpOnly: true,
251
+ secure: true,
252
+ sameSite: "lax",
253
+ path: "/",
254
+ maxAge: sessionMaxAge,
255
+ });
256
+ return { ok: true };
257
+ }));
258
+ // POST /api/auth/logout
259
+ app.use("/api/auth/logout", defineEventHandler((event) => {
260
+ const cookie = getCookie(event, COOKIE_NAME);
261
+ if (cookie)
262
+ removeSession(cookie);
263
+ deleteCookie(event, COOKIE_NAME, { path: "/" });
264
+ return { ok: true };
265
+ }));
266
+ // GET /api/auth/session — client session check
267
+ app.use("/api/auth/session", defineEventHandler(async (event) => {
268
+ if (getMethod(event) !== "GET") {
269
+ setResponseStatus(event, 405);
270
+ return { error: "Method not allowed" };
271
+ }
272
+ const session = await getSession(event);
273
+ return session ?? { error: "Not authenticated" };
274
+ }));
275
+ // Auth guard — runs before all other handlers
276
+ app.use(defineEventHandler(async (event) => {
277
+ const url = event.node.req.url ?? "/";
278
+ const p = url.split("?")[0];
279
+ // Skip auth routes
280
+ if (p === "/api/auth/login" ||
281
+ p === "/api/auth/logout" ||
282
+ p === "/api/auth/session") {
283
+ return;
284
+ }
285
+ // Skip public paths
286
+ if (isPublicPath(url, publicPaths)) {
287
+ return;
288
+ }
289
+ // Use getSession() so BYOA custom auth is respected
290
+ const session = await getSession(event);
291
+ if (session) {
292
+ return; // Authenticated
293
+ }
294
+ // Unauthenticated
295
+ if (p.startsWith("/api/")) {
296
+ setResponseStatus(event, 401);
297
+ setResponseHeader(event, "Content-Type", "application/json");
298
+ event.node.res.end(JSON.stringify({ error: "Unauthorized" }));
299
+ return;
300
+ }
301
+ setResponseHeader(event, "Content-Type", "text/html");
302
+ event.node.res.end(LOGIN_HTML);
303
+ }));
304
+ }
305
+ // ---------------------------------------------------------------------------
306
+ // autoMountAuth — the recommended entry point
307
+ // ---------------------------------------------------------------------------
308
+ /**
309
+ * Automatically configure auth based on the environment:
310
+ *
311
+ * - **Dev mode** (`NODE_ENV !== "production"`): Auth is skipped entirely.
312
+ * `getSession()` returns `{ email: "local@localhost" }` for all requests.
313
+ *
314
+ * - **Production with ACCESS_TOKEN/ACCESS_TOKENS set**: Auth middleware is
315
+ * mounted. Unauthenticated requests see a login page. One env var is all
316
+ * you need.
317
+ *
318
+ * - **Production without tokens and AUTH_DISABLED !== "true"**: Refuses to
319
+ * start. Logs a clear error explaining what to do.
320
+ *
321
+ * - **Production with AUTH_DISABLED=true**: Auth is skipped (for apps behind
322
+ * infrastructure-level auth like Cloudflare Access or a VPN).
323
+ *
324
+ * Returns true if auth was mounted, false if skipped.
325
+ */
326
+ export function autoMountAuth(app, options = {}) {
327
+ // In Nitro 3.0 dev mode, the H3 app may not be available yet.
328
+ // In dev mode auth is bypassed anyway, so we can safely skip.
329
+ if (!app) {
330
+ if (isDevMode()) {
331
+ authDisabledMode = false;
332
+ customGetSession = null;
333
+ return false;
334
+ }
335
+ throw new Error("autoMountAuth: H3 app is required. In Nitro plugins, pass nitroApp.h3App.");
336
+ }
337
+ // Reset globals to avoid stale state from prior calls
338
+ customGetSession = null;
339
+ authDisabledMode = false;
340
+ sessionMaxAge = options.maxAge ?? DEFAULT_MAX_AGE;
341
+ sessionsFilePath = resolveSessionsPath(options.sessionsPath);
342
+ const publicPaths = options.publicPaths ?? [];
343
+ if (options.getSession) {
344
+ customGetSession = options.getSession;
345
+ }
346
+ // Dev mode — skip auth entirely
347
+ if (isDevMode()) {
348
+ // Mount a session endpoint that returns the dev stub
349
+ app.use("/api/auth/session", defineEventHandler(async (event) => {
350
+ if (getMethod(event) !== "GET") {
351
+ setResponseStatus(event, 405);
352
+ return { error: "Method not allowed" };
353
+ }
354
+ return DEV_SESSION;
355
+ }));
356
+ // Mount no-op login/logout so client code doesn't break
357
+ app.use("/api/auth/login", defineEventHandler(() => ({ ok: true })));
358
+ app.use("/api/auth/logout", defineEventHandler(() => ({ ok: true })));
359
+ return false;
360
+ }
361
+ // BYOA with custom getSession — skip token check, mount session/guard routes
362
+ if (customGetSession) {
363
+ // Mount session endpoint
364
+ app.use("/api/auth/session", defineEventHandler(async (event) => {
365
+ if (getMethod(event) !== "GET") {
366
+ setResponseStatus(event, 405);
367
+ return { error: "Method not allowed" };
368
+ }
369
+ const session = await getSession(event);
370
+ return session ?? { error: "Not authenticated" };
371
+ }));
372
+ app.use("/api/auth/login", defineEventHandler(() => ({ ok: true })));
373
+ app.use("/api/auth/logout", defineEventHandler(() => ({ ok: true })));
374
+ // Mount auth guard that delegates to custom getSession
375
+ app.use(defineEventHandler(async (event) => {
376
+ const url = event.node.req.url ?? "/";
377
+ const p = url.split("?")[0];
378
+ if (p === "/api/auth/login" ||
379
+ p === "/api/auth/logout" ||
380
+ p === "/api/auth/session") {
381
+ return;
382
+ }
383
+ // Skip public paths
384
+ if (isPublicPath(url, publicPaths)) {
385
+ return;
386
+ }
387
+ const session = await getSession(event);
388
+ if (session)
389
+ return;
390
+ if (p.startsWith("/api/")) {
391
+ setResponseStatus(event, 401);
392
+ setResponseHeader(event, "Content-Type", "application/json");
393
+ event.node.res.end(JSON.stringify({ error: "Unauthorized" }));
394
+ return;
395
+ }
396
+ setResponseHeader(event, "Content-Type", "text/html");
397
+ event.node.res.end(LOGIN_HTML);
398
+ }));
399
+ console.log("[agent-native] Auth enabled — custom getSession provider.");
400
+ return true;
401
+ }
402
+ // Production — check for tokens
403
+ const tokens = getAccessTokens();
404
+ if (tokens.length === 0) {
405
+ // No tokens set — check if auth is explicitly disabled
406
+ if (process.env.AUTH_DISABLED === "true") {
407
+ authDisabledMode = true;
408
+ console.warn("[agent-native] AUTH_DISABLED=true — running in production without auth. " +
409
+ "Ensure this app is behind infrastructure-level auth (Cloudflare Access, VPN, etc.).");
410
+ // Mount session endpoint — getSession() will return DEV_SESSION
411
+ app.use("/api/auth/session", defineEventHandler(async (event) => {
412
+ if (getMethod(event) !== "GET") {
413
+ setResponseStatus(event, 405);
414
+ return { error: "Method not allowed" };
415
+ }
416
+ return DEV_SESSION;
417
+ }));
418
+ app.use("/api/auth/login", defineEventHandler(() => ({ ok: true })));
419
+ app.use("/api/auth/logout", defineEventHandler(() => ({ ok: true })));
420
+ return false;
421
+ }
422
+ // Refuse to start without auth in production
423
+ const msg = "\n" +
424
+ "=".repeat(70) +
425
+ "\n" +
426
+ " ERROR: Running in production without authentication.\n\n" +
427
+ " Set ACCESS_TOKEN=<your-secret> to enable auth, or\n" +
428
+ " set AUTH_DISABLED=true if this app is behind infrastructure auth.\n\n" +
429
+ " For multi-user access: ACCESS_TOKENS=token1,token2,token3\n" +
430
+ "=".repeat(70) +
431
+ "\n";
432
+ console.error(msg);
433
+ process.exit(1);
434
+ }
435
+ // Production with tokens — mount auth
436
+ loadSessions();
437
+ pruneExpiredSessions();
438
+ mountAuthRoutes(app, tokens, publicPaths);
439
+ console.log(`[agent-native] Auth enabled — ${tokens.length} access token(s) configured.`);
440
+ return true;
441
+ }
442
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface CaptchaVerifyResult {
2
+ success: boolean;
3
+ errorCodes?: string[];
4
+ }
5
+ /**
6
+ * Verify a Cloudflare Turnstile token server-side.
7
+ *
8
+ * - If no secret key is provided (param or env), returns success (captcha is opt-in).
9
+ * - In dev mode (NODE_ENV !== "production"), always returns success.
10
+ */
11
+ export declare function verifyCaptcha(token: string, secretKey?: string): Promise<CaptchaVerifyResult>;
12
+ //# sourceMappingURL=captcha.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captcha.d.ts","sourceRoot":"","sources":["../../src/server/captcha.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAKD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAyC9B"}
@@ -0,0 +1,43 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Cloudflare Turnstile — server-side verification
3
+ // ---------------------------------------------------------------------------
4
+ const TURNSTILE_VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
5
+ /**
6
+ * Verify a Cloudflare Turnstile token server-side.
7
+ *
8
+ * - If no secret key is provided (param or env), returns success (captcha is opt-in).
9
+ * - In dev mode (NODE_ENV !== "production"), always returns success.
10
+ */
11
+ export async function verifyCaptcha(token, secretKey) {
12
+ // Dev mode — skip captcha
13
+ if (process.env.NODE_ENV !== "production") {
14
+ return { success: true };
15
+ }
16
+ const secret = secretKey ?? process.env.TURNSTILE_SECRET_KEY;
17
+ // No secret configured — captcha is opt-in, allow through
18
+ if (!secret) {
19
+ console.warn("[captcha] TURNSTILE_SECRET_KEY is not set — captcha verification is disabled. " +
20
+ "Set TURNSTILE_SECRET_KEY and VITE_TURNSTILE_SITE_KEY to enable bot protection.");
21
+ return { success: true };
22
+ }
23
+ // No token provided by client
24
+ if (!token) {
25
+ return { success: false, errorCodes: ["missing-input-response"] };
26
+ }
27
+ try {
28
+ const res = await fetch(TURNSTILE_VERIFY_URL, {
29
+ method: "POST",
30
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
31
+ body: new URLSearchParams({ secret, response: token }),
32
+ });
33
+ const data = (await res.json());
34
+ return {
35
+ success: data.success,
36
+ errorCodes: data["error-codes"],
37
+ };
38
+ }
39
+ catch {
40
+ return { success: false, errorCodes: ["network-error"] };
41
+ }
42
+ }
43
+ //# sourceMappingURL=captcha.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../src/server/captcha.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kDAAkD;AAClD,8EAA8E;AAO9E,MAAM,oBAAoB,GACxB,2DAA2D,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,SAAkB;IAElB,0BAA0B;IAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAE7D,0DAA0D;IAC1D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CACV,gFAAgF;YAC9E,gFAAgF,CACnF,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,wBAAwB,CAAC,EAAE,CAAC;IACpE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,EAAE;YAC5C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;SACvD,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;SAChC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;IAC3D,CAAC;AACH,CAAC"}
@@ -1,5 +1,4 @@
1
- import express from "express";
2
- import cors from "cors";
1
+ import { createApp, createRouter } from "h3";
3
2
  export interface EnvKeyConfig {
4
3
  /** Environment variable name (e.g. "HUBSPOT_ACCESS_TOKEN") */
5
4
  key: string;
@@ -9,9 +8,9 @@ export interface EnvKeyConfig {
9
8
  required?: boolean;
10
9
  }
11
10
  export interface CreateServerOptions {
12
- /** CORS options. Pass false to disable. Default: enabled with defaults. */
13
- cors?: cors.CorsOptions | false;
14
- /** JSON body parser limit. Default: "50mb" */
11
+ /** CORS options. Ignored (H3 handles CORS via middleware). Default: enabled. */
12
+ cors?: Record<string, unknown> | false;
13
+ /** JSON body parser limit. Kept for API compatibility (H3 uses readBody). */
15
14
  jsonLimit?: string;
16
15
  /** Custom ping message. Default: reads PING_MESSAGE env var, falls back to "pong" */
17
16
  pingMessage?: string;
@@ -20,13 +19,17 @@ export interface CreateServerOptions {
20
19
  /** Env key configuration for the settings UI. Enables /api/env-status and /api/env-vars routes. */
21
20
  envKeys?: EnvKeyConfig[];
22
21
  }
22
+ export interface CreateServerResult {
23
+ app: ReturnType<typeof createApp>;
24
+ router: ReturnType<typeof createRouter>;
25
+ }
23
26
  /**
24
- * Create a pre-configured Express app with standard agent-native middleware:
25
- * - CORS
26
- * - JSON body parser (50mb limit)
27
- * - URL-encoded body parser
27
+ * Create a pre-configured H3 app with standard agent-native setup:
28
+ * - CORS headers via middleware
28
29
  * - /api/ping health check
29
30
  * - /api/env-status and /api/env-vars (when envKeys is provided)
31
+ *
32
+ * Returns { app, router } — mount routes on `router`.
30
33
  */
31
- export declare function createServer(options?: CreateServerOptions): express.Express;
34
+ export declare function createServer(options?: CreateServerOptions): CreateServerResult;
32
35
  //# sourceMappingURL=create-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-server.d.ts","sourceRoot":"","sources":["../../src/server/create-server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AAKxB,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,IAAI,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAChC,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mGAAmG;IACnG,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAuED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,OAAO,CAmEjB"}
1
+ {"version":3,"file":"create-server.d.ts","sourceRoot":"","sources":["../../src/server/create-server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EAKb,MAAM,IAAI,CAAC;AAKZ,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IACvC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mGAAmG;IACnG,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAuED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;IAClC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CACzC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CAqGpB"}