mates-fullstack 1.0.0-beta.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 +311 -0
- package/dist/arctic-auth.d.ts +101 -0
- package/dist/arctic-auth.d.ts.map +1 -0
- package/dist/arctic-auth.js +538 -0
- package/dist/arctic-auth.js.map +1 -0
- package/dist/asset-manifest.d.ts +14 -0
- package/dist/asset-manifest.d.ts.map +1 -0
- package/dist/asset-manifest.js +102 -0
- package/dist/asset-manifest.js.map +1 -0
- package/dist/browser.d.ts +18 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +25 -0
- package/dist/browser.js.map +1 -0
- package/dist/build-esbuild.d.ts +29 -0
- package/dist/build-esbuild.d.ts.map +1 -0
- package/dist/build-esbuild.js +699 -0
- package/dist/build-esbuild.js.map +1 -0
- package/dist/build-prod.d.ts +126 -0
- package/dist/build-prod.d.ts.map +1 -0
- package/dist/build-prod.js +1014 -0
- package/dist/build-prod.js.map +1 -0
- package/dist/cli-new.d.ts +14 -0
- package/dist/cli-new.d.ts.map +1 -0
- package/dist/cli-new.js +637 -0
- package/dist/cli-new.js.map +1 -0
- package/dist/client.d.ts +43 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +130 -0
- package/dist/client.js.map +1 -0
- package/dist/cors.d.ts +16 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +60 -0
- package/dist/cors.js.map +1 -0
- package/dist/ctx.d.ts +78 -0
- package/dist/ctx.d.ts.map +1 -0
- package/dist/ctx.js +280 -0
- package/dist/ctx.js.map +1 -0
- package/dist/dev-watcher.d.ts +23 -0
- package/dist/dev-watcher.d.ts.map +1 -0
- package/dist/dev-watcher.js +136 -0
- package/dist/dev-watcher.js.map +1 -0
- package/dist/docs-generator.d.ts +69 -0
- package/dist/docs-generator.d.ts.map +1 -0
- package/dist/docs-generator.js +557 -0
- package/dist/docs-generator.js.map +1 -0
- package/dist/docs-page.d.ts +20 -0
- package/dist/docs-page.d.ts.map +1 -0
- package/dist/docs-page.js +1152 -0
- package/dist/docs-page.js.map +1 -0
- package/dist/download.d.ts +78 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +202 -0
- package/dist/download.js.map +1 -0
- package/dist/env-loader.d.ts +76 -0
- package/dist/env-loader.d.ts.map +1 -0
- package/dist/env-loader.js +213 -0
- package/dist/env-loader.js.map +1 -0
- package/dist/errors.d.ts +146 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +386 -0
- package/dist/errors.js.map +1 -0
- package/dist/head.d.ts +31 -0
- package/dist/head.d.ts.map +1 -0
- package/dist/head.js +245 -0
- package/dist/head.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-prefixes.d.ts +16 -0
- package/dist/internal-prefixes.d.ts.map +1 -0
- package/dist/internal-prefixes.js +16 -0
- package/dist/internal-prefixes.js.map +1 -0
- package/dist/internal.d.ts +25 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +25 -0
- package/dist/internal.js.map +1 -0
- package/dist/jwt.d.ts +166 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +261 -0
- package/dist/jwt.js.map +1 -0
- package/dist/log.d.ts +44 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +66 -0
- package/dist/log.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +138 -0
- package/dist/logger.js.map +1 -0
- package/dist/main-runner.d.ts +59 -0
- package/dist/main-runner.d.ts.map +1 -0
- package/dist/main-runner.js +157 -0
- package/dist/main-runner.js.map +1 -0
- package/dist/mates-auth.d.ts +82 -0
- package/dist/mates-auth.d.ts.map +1 -0
- package/dist/mates-auth.js +323 -0
- package/dist/mates-auth.js.map +1 -0
- package/dist/middleware.d.ts +30 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +67 -0
- package/dist/middleware.js.map +1 -0
- package/dist/project-resolver.d.ts +102 -0
- package/dist/project-resolver.d.ts.map +1 -0
- package/dist/project-resolver.js +271 -0
- package/dist/project-resolver.js.map +1 -0
- package/dist/rate-limit.d.ts +37 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +109 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/redirect.d.ts +84 -0
- package/dist/redirect.d.ts.map +1 -0
- package/dist/redirect.js +105 -0
- package/dist/redirect.js.map +1 -0
- package/dist/renderer.d.ts +91 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +630 -0
- package/dist/renderer.js.map +1 -0
- package/dist/request-logger.d.ts +12 -0
- package/dist/request-logger.d.ts.map +1 -0
- package/dist/request-logger.js +55 -0
- package/dist/request-logger.js.map +1 -0
- package/dist/rest.d.ts +25 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +93 -0
- package/dist/rest.js.map +1 -0
- package/dist/router.d.ts +71 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +222 -0
- package/dist/router.js.map +1 -0
- package/dist/rpc-registry.d.ts +84 -0
- package/dist/rpc-registry.d.ts.map +1 -0
- package/dist/rpc-registry.js +271 -0
- package/dist/rpc-registry.js.map +1 -0
- package/dist/rpc-runner.d.ts +82 -0
- package/dist/rpc-runner.d.ts.map +1 -0
- package/dist/rpc-runner.js +564 -0
- package/dist/rpc-runner.js.map +1 -0
- package/dist/sanitize.d.ts +61 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +193 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/security-headers.d.ts +114 -0
- package/dist/security-headers.d.ts.map +1 -0
- package/dist/security-headers.js +121 -0
- package/dist/security-headers.js.map +1 -0
- package/dist/server-fn.d.ts +323 -0
- package/dist/server-fn.d.ts.map +1 -0
- package/dist/server-fn.js +373 -0
- package/dist/server-fn.js.map +1 -0
- package/dist/server-public.d.ts +13 -0
- package/dist/server-public.d.ts.map +1 -0
- package/dist/server-public.js +12 -0
- package/dist/server-public.js.map +1 -0
- package/dist/server-timeout.d.ts +38 -0
- package/dist/server-timeout.d.ts.map +1 -0
- package/dist/server-timeout.js +46 -0
- package/dist/server-timeout.js.map +1 -0
- package/dist/server.d.ts +100 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1218 -0
- package/dist/server.js.map +1 -0
- package/dist/socket-router.d.ts +153 -0
- package/dist/socket-router.d.ts.map +1 -0
- package/dist/socket-router.js +612 -0
- package/dist/socket-router.js.map +1 -0
- package/dist/sso.d.ts +90 -0
- package/dist/sso.d.ts.map +1 -0
- package/dist/sso.js +261 -0
- package/dist/sso.js.map +1 -0
- package/dist/ssr-context.d.ts +49 -0
- package/dist/ssr-context.d.ts.map +1 -0
- package/dist/ssr-context.js +85 -0
- package/dist/ssr-context.js.map +1 -0
- package/dist/ssr-globals.d.ts +32 -0
- package/dist/ssr-globals.d.ts.map +1 -0
- package/dist/ssr-globals.js +1010 -0
- package/dist/ssr-globals.js.map +1 -0
- package/dist/ssr-template.d.ts +73 -0
- package/dist/ssr-template.d.ts.map +1 -0
- package/dist/ssr-template.js +507 -0
- package/dist/ssr-template.js.map +1 -0
- package/dist/stack-mapper.d.ts +25 -0
- package/dist/stack-mapper.d.ts.map +1 -0
- package/dist/stack-mapper.js +139 -0
- package/dist/stack-mapper.js.map +1 -0
- package/dist/stream.d.ts +89 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +299 -0
- package/dist/stream.js.map +1 -0
- package/dist/upload.d.ts +69 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +110 -0
- package/dist/upload.js.map +1 -0
- package/dist/validate.d.ts +58 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +89 -0
- package/dist/validate.js.map +1 -0
- package/dist/verify-package.d.ts +3 -0
- package/dist/verify-package.d.ts.map +1 -0
- package/dist/verify-package.js +128 -0
- package/dist/verify-package.js.map +1 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# mates-fullstack
|
|
2
|
+
|
|
3
|
+
TypeScript-first full-stack framework for Mates apps. It adds SSR, direct RPC-style server functions, raw HTTP escape hatches, WebSockets, static assets, and production builds without requiring a compiler in production.
|
|
4
|
+
|
|
5
|
+
**Custom SSR engine** — no DOM, no happy-dom, no per-request global patching, fully concurrent. `TemplateResult` objects are serialized directly to HTML using a 300-line pure-JS serializer. No virtual DOM, no fake browser, no overhead per request.
|
|
6
|
+
|
|
7
|
+
No JSX. No virtual DOM. No Express/Hono/Fastify. Runtime server is pure Node.js (`node:http`). Bundling and TypeScript transforms use esbuild.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install mates-fullstack-beta mates
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Add scripts to your app:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"scripts": {
|
|
22
|
+
"dev": "mates-fullstack dev",
|
|
23
|
+
"build": "mates-fullstack build",
|
|
24
|
+
"start": "mates-fullstack start"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Project structure
|
|
32
|
+
|
|
33
|
+
`mates-fullstack` is convention-based; no config file is required.
|
|
34
|
+
|
|
35
|
+
```txt
|
|
36
|
+
my-app/
|
|
37
|
+
client/
|
|
38
|
+
App.ts # SSR root component and client router
|
|
39
|
+
client.ts # browser entry; calls renderX(App, ...)
|
|
40
|
+
server/
|
|
41
|
+
api/ # RPC functions callable from client imports
|
|
42
|
+
helpers/ # server-only utilities; never bundled for browser
|
|
43
|
+
main.ts # optional middleware registration
|
|
44
|
+
socket/ # optional WebSocket handlers
|
|
45
|
+
shared/ # code/types used by both sides
|
|
46
|
+
public/ # static files copied to dist/public in production
|
|
47
|
+
package.json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Minimal app
|
|
53
|
+
|
|
54
|
+
### `client/App.ts`
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { html } from "mates";
|
|
58
|
+
|
|
59
|
+
export default () => {
|
|
60
|
+
return () => html`<h1>Hello from mates-fullstack</h1>`;
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `client/client.ts`
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { renderX } from "mates";
|
|
68
|
+
import App from "./App";
|
|
69
|
+
|
|
70
|
+
renderX(App, document.getElementById("app")!);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `server/api/todos.ts`
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import type { ServerCtx } from "mates-fullstack";
|
|
77
|
+
import { ValidationError } from "mates-fullstack";
|
|
78
|
+
|
|
79
|
+
export async function listTodos(_payload: {}, _ctx: ServerCtx) {
|
|
80
|
+
return [{ id: 1, title: "Write docs" }];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function addTodo(payload: { title: string }, _ctx: ServerCtx) {
|
|
84
|
+
if (!payload.title.trim()) {
|
|
85
|
+
throw new ValidationError("Invalid todo", {
|
|
86
|
+
fields: { title: "Required" },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return { id: Date.now(), title: payload.title };
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Client code calls server functions directly
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { asyncAction, html } from "mates";
|
|
97
|
+
import { listTodos } from "../server/api/todos";
|
|
98
|
+
|
|
99
|
+
const TodoPage = () => {
|
|
100
|
+
const load = asyncAction(() => listTodos({}));
|
|
101
|
+
load();
|
|
102
|
+
|
|
103
|
+
return () => html`
|
|
104
|
+
<pre>${JSON.stringify(load.data(), null, 2)}</pre>
|
|
105
|
+
`;
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
During development and production builds, imports from `server/api/**` are converted into browser-safe RPC stubs. Imports from any other `server/**` path are blocked from client code.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Commands
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm run dev # native ESM dev server, no browser bundle
|
|
117
|
+
npm run build # production client bundle + compiled server runtime
|
|
118
|
+
npm run start # start production server from dist/
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Development mode
|
|
122
|
+
|
|
123
|
+
Development intentionally serves source modules instead of a client bundle:
|
|
124
|
+
|
|
125
|
+
- app source modules: `/_src/**`
|
|
126
|
+
- package modules: `/_pkg/**`
|
|
127
|
+
- framework helpers: `/_mates/**`
|
|
128
|
+
- import map injected into the HTML shell
|
|
129
|
+
- chokidar watches `client/`, `server/`, `shared/`, `public/`, `.env*`, and config files
|
|
130
|
+
- reload generation is owned by the parent dev process and delivered through SSE
|
|
131
|
+
|
|
132
|
+
This makes stack traces point at source-like module URLs and keeps rebuilds fast.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Authentication
|
|
137
|
+
|
|
138
|
+
### Email/Password + Social Login
|
|
139
|
+
|
|
140
|
+
`mates-fullstack` provides a complete auth system out of the box. Access tokens are short-lived (15 min default), stored in httpOnly cookies. Refresh tokens (30 days) live in a separate httpOnly cookie and rotate automatically, with JTI replay detection.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// server/main.ts
|
|
144
|
+
import { matesAuth, auth, useArctic } from "mates-fullstack";
|
|
145
|
+
|
|
146
|
+
matesAuth({ secret: process.env.AUTH_JWT_SECRET! });
|
|
147
|
+
|
|
148
|
+
useArctic({
|
|
149
|
+
google: {
|
|
150
|
+
clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
151
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
152
|
+
onSuccess: async (profile, ctx) => {
|
|
153
|
+
const user = await db.users.upsert({ ... });
|
|
154
|
+
await auth.login(ctx, { userId: user.id, email: user.email });
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Routes `/auth/google` and `/auth/google/callback` are registered automatically. `onSuccess` gives you full control — call `auth.login()` to issue tokens, or skip it to just link accounts.
|
|
161
|
+
|
|
162
|
+
10 built-in OAuth providers: Google, GitHub, Discord, Microsoft, Twitter, LinkedIn, Facebook, Apple, Spotify, GitLab. Custom providers via `arcticProvider({ handler, ... })`.
|
|
163
|
+
|
|
164
|
+
### Cross-Domain SSO
|
|
165
|
+
|
|
166
|
+
For apps on different domains sharing one auth server. The auth server signs a 30-second code JWT with a shared secret — each app verifies it locally, no round-trip needed.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
// auth.com/server/main.ts
|
|
170
|
+
import { useSsoProvider } from "mates-fullstack";
|
|
171
|
+
|
|
172
|
+
useSsoProvider({
|
|
173
|
+
secret: process.env.SSO_SECRET!,
|
|
174
|
+
login: "/login",
|
|
175
|
+
allowedOrigins: ["https://app1.com", "https://app2.com"],
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// app1.com/server/main.ts
|
|
179
|
+
import { useSsoClient } from "mates-fullstack";
|
|
180
|
+
|
|
181
|
+
useSsoClient({
|
|
182
|
+
authUrl: "https://auth.com",
|
|
183
|
+
secret: process.env.SSO_SECRET!,
|
|
184
|
+
protected: ["/dashboard", "/settings"],
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Each app issues its own httpOnly session cookies. Works with social login — put `useArctic()` on the auth server, `useSsoClient()` on every app.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Middleware
|
|
193
|
+
|
|
194
|
+
All middleware registers globally in `server/main.ts` and runs in registration order.
|
|
195
|
+
|
|
196
|
+
**Recommended `server/main.ts`:**
|
|
197
|
+
```ts
|
|
198
|
+
import {
|
|
199
|
+
matesAuth, requestLogger, useSecurityHeaders, useCors, rateLimit,
|
|
200
|
+
} from "mates-fullstack";
|
|
201
|
+
|
|
202
|
+
matesAuth({ secret: process.env.AUTH_JWT_SECRET! });
|
|
203
|
+
requestLogger({ skip: [/^\/health$/, /^\/_mates\//] });
|
|
204
|
+
useSecurityHeaders();
|
|
205
|
+
useCors({ origins: "https://app.example.com" });
|
|
206
|
+
rateLimit({ max: 10, window: "15m", pathPrefix: "/auth" });
|
|
207
|
+
rateLimit({ max: 300, window: "1m" });
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Request Logger
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
requestLogger({ skip: [/^\/health$/, /^\/assets\//] });
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Logs every request (method, path, IP) on arrival and every RPC response (status, ms) on completion. Stamps `x-request-id` on every response. Structured logging — NDJSON in production, pretty-printed in dev.
|
|
217
|
+
|
|
218
|
+
### Security Headers
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
useSecurityHeaders();
|
|
222
|
+
useSecurityHeaders({ contentSecurityPolicy: "default-src 'self'", xFrameOptions: "DENY" });
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Sets 14 standard security headers on every response — complete helmet-equivalent coverage. Every header individually overridable or disableable. HSTS auto-enabled in production, skipped in dev. CSP and Permissions-Policy are opt-in.
|
|
226
|
+
|
|
227
|
+
### CORS
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
useCors({ origins: "https://app.example.com", credentials: true });
|
|
231
|
+
useCors({ origins: (origin) => origin.endsWith(".example.com") });
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Handles preflight `OPTIONS` automatically (returns 204). Reflects origin when `credentials: true` as required by the CORS spec. Sets `Vary: Origin`.
|
|
235
|
+
|
|
236
|
+
### Rate Limiting
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
rateLimit({ max: 100, window: "1m" }); // all routes
|
|
240
|
+
rateLimit({ max: 10, window: "15m", pathPrefix: "/auth" }); // auth only
|
|
241
|
+
rateLimit({ max: 5, window: "1h", key: (_req, ctx) => String(ctx.auth.userId) }); // per-user
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Sliding-window counter, in-memory. Returns 429 with `Retry-After` and `X-RateLimit-*` headers. Auto-evicts expired entries. Custom key function for per-user or per-endpoint limiting.
|
|
245
|
+
|
|
246
|
+
### Raw HTTP hooks
|
|
247
|
+
|
|
248
|
+
For cases where an external service dictates the HTTP contract (webhooks, custom OAuth flows):
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { onHttpRequest } from "mates-fullstack";
|
|
252
|
+
|
|
253
|
+
onHttpRequest(async (req, ctx) => {
|
|
254
|
+
const url = new URL(req.url);
|
|
255
|
+
if (req.method === "POST" && url.pathname === "/stripe-webhook") {
|
|
256
|
+
const body = await req.text();
|
|
257
|
+
await handleWebhook(body, ctx.reqHeaders["stripe-signature"]);
|
|
258
|
+
return new Response("ok");
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Request Limits / Resource Protection
|
|
266
|
+
|
|
267
|
+
Built-in limits prevent CPU and memory exhaustion. All have safe defaults — override only to tune for your app.
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
// server/main.ts — at the top, before middleware
|
|
271
|
+
import { configureRpcRunner } from "mates-fullstack/internal";
|
|
272
|
+
|
|
273
|
+
configureRpcRunner({
|
|
274
|
+
maxJsonBytes: 5 * 1024 * 1024, // default 1MB
|
|
275
|
+
maxJsonDepth: 30, // default 50
|
|
276
|
+
maxArrayLength: 5000, // default 10_000
|
|
277
|
+
maxStringLength: 50_000, // default 100_000
|
|
278
|
+
maxUploadBytes: 50 * 1024 * 1024, // default 10MB
|
|
279
|
+
maxMultipartParts: 100, // default 200
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Or set server-level limits when starting:
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
await startServer({
|
|
287
|
+
maxConnections: 2000, // default 1000
|
|
288
|
+
staticStreamTimeout: 120_000, // default 60s
|
|
289
|
+
maxSseClients: 1000, // default 500
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
All defaults are active without any configuration call. See `DOCS.md` for full details.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Public entrypoints
|
|
298
|
+
|
|
299
|
+
| Import | Use for |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `mates-fullstack` | stable app API: errors, redirects, middleware registration, `ServerCtx`, validation/sanitize/upload helpers |
|
|
302
|
+
| `mates-fullstack/client` | browser hydration and RPC helpers |
|
|
303
|
+
| `mates-fullstack/browser` | browser-safe error/redirect/stream/download helpers |
|
|
304
|
+
| `mates-fullstack/server` | server-safe helpers and middleware runners |
|
|
305
|
+
| `mates-fullstack/internal` | unstable build/runtime/scanner internals for tooling |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { type OAuth2Tokens } from "arctic";
|
|
2
|
+
import type { CookieOptions, Context } from "./ctx.js";
|
|
3
|
+
export type ArcticBuiltInProvider = "apple" | "discord" | "facebook" | "github" | "gitlab" | "google" | "linkedin" | "microsoft" | "spotify" | "twitter";
|
|
4
|
+
export interface ArcticTokenSet {
|
|
5
|
+
accessToken: string | null;
|
|
6
|
+
refreshToken: string | null;
|
|
7
|
+
idToken: string | null;
|
|
8
|
+
tokenType: string | null;
|
|
9
|
+
expiresAt: Date | null;
|
|
10
|
+
scopes: string[] | null;
|
|
11
|
+
raw: object;
|
|
12
|
+
}
|
|
13
|
+
export interface ArcticProfile<Raw = unknown> {
|
|
14
|
+
provider: string;
|
|
15
|
+
id: string;
|
|
16
|
+
email: string | null;
|
|
17
|
+
name: string | null;
|
|
18
|
+
avatar: string | null;
|
|
19
|
+
username?: string | null;
|
|
20
|
+
raw: Raw;
|
|
21
|
+
tokens: ArcticTokenSet;
|
|
22
|
+
}
|
|
23
|
+
export interface ArcticProviderConfig {
|
|
24
|
+
clientId: string;
|
|
25
|
+
clientSecret?: string | null;
|
|
26
|
+
redirectUri?: string;
|
|
27
|
+
scopes?: string[];
|
|
28
|
+
/** Microsoft Entra ID tenant. Defaults to "common". */
|
|
29
|
+
tenant?: string;
|
|
30
|
+
/** Apple Team ID. */
|
|
31
|
+
teamId?: string;
|
|
32
|
+
/** Apple Key ID. */
|
|
33
|
+
keyId?: string;
|
|
34
|
+
/** Apple private key in PKCS#8 PEM format. */
|
|
35
|
+
privateKey?: string;
|
|
36
|
+
/** GitLab base URL. Defaults to https://gitlab.com. */
|
|
37
|
+
baseURL?: string;
|
|
38
|
+
/** Override the built-in profile fetcher or add one for custom providers. */
|
|
39
|
+
profile?: ArcticProfileLoader;
|
|
40
|
+
/** Override whether this provider uses PKCE. */
|
|
41
|
+
usesPKCE?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Called after the provider returns a profile.
|
|
44
|
+
* Return the claims to bake into the JWT — typically after an upsert in your DB.
|
|
45
|
+
*/
|
|
46
|
+
onSuccess: ArcticSuccessHandler;
|
|
47
|
+
}
|
|
48
|
+
export type ArcticProvidersConfig = Partial<Record<ArcticBuiltInProvider | string, ArcticProviderConfig | ArcticCustomProvider>>;
|
|
49
|
+
/**
|
|
50
|
+
* Called after the provider returns a verified profile.
|
|
51
|
+
* You are fully in control — call `auth.login(ctx, claims)` to issue tokens,
|
|
52
|
+
* update the DB to link an account, or do nothing at all.
|
|
53
|
+
* Return a path string to override the post-OAuth redirect.
|
|
54
|
+
*/
|
|
55
|
+
export type ArcticSuccessHandler = (profile: ArcticProfile, ctx: Context) => string | void | Promise<string | void>;
|
|
56
|
+
export interface ArcticUseOptions {
|
|
57
|
+
/** Route base for OAuth endpoints. Default: "/auth". */
|
|
58
|
+
basePath?: string;
|
|
59
|
+
/** Default redirect after login. Default: "/". */
|
|
60
|
+
afterLogin?: string;
|
|
61
|
+
/** Redirect after OAuth failure. If omitted, failures return JSON. */
|
|
62
|
+
onErrorRedirect?: string;
|
|
63
|
+
/** Cookie path/domain/sameSite/secure controls for temporary OAuth cookies. */
|
|
64
|
+
cookie?: Pick<CookieOptions, "path" | "domain" | "sameSite" | "secure">;
|
|
65
|
+
/** Temporary OAuth state cookie lifetime in seconds. Default: 10 minutes. */
|
|
66
|
+
stateMaxAge?: number;
|
|
67
|
+
}
|
|
68
|
+
export interface ArcticProviderHandler {
|
|
69
|
+
defaultScopes: string[];
|
|
70
|
+
usesPKCE: boolean;
|
|
71
|
+
start(config: ArcticProviderConfig, redirectUri: string, state: string, codeVerifier: string | null): Promise<URL> | URL;
|
|
72
|
+
callback(config: ArcticProviderConfig, redirectUri: string, code: string, codeVerifier: string | null, providerName: string): Promise<ArcticProfile>;
|
|
73
|
+
}
|
|
74
|
+
export interface ArcticCustomProvider extends ArcticProviderConfig {
|
|
75
|
+
handler: ArcticProviderHandler;
|
|
76
|
+
}
|
|
77
|
+
export type ArcticProfileLoader = (tokens: OAuth2Tokens, providerName: string) => Promise<Omit<ArcticProfile, "provider" | "tokens">>;
|
|
78
|
+
/**
|
|
79
|
+
* Register social login routes for every configured provider.
|
|
80
|
+
*
|
|
81
|
+
* The framework automatically handles:
|
|
82
|
+
* GET /auth/:provider — redirect to provider
|
|
83
|
+
* GET /auth/:provider/callback — exchange code, call onSuccess, set cookies
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* useArctic({
|
|
87
|
+
* google: {
|
|
88
|
+
* clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
89
|
+
* clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
90
|
+
* onSuccess: async (profile) => {
|
|
91
|
+
* const user = await db.upsert({ provider: profile.provider, providerId: profile.id, ... });
|
|
92
|
+
* return { userId: user.id, email: user.email, roles: user.roles };
|
|
93
|
+
* },
|
|
94
|
+
* },
|
|
95
|
+
* });
|
|
96
|
+
*/
|
|
97
|
+
export declare function useArctic(providers: ArcticProvidersConfig, options?: ArcticUseOptions): void;
|
|
98
|
+
/** Define a custom Arctic provider adapter for providers without a built-in profile normalizer. */
|
|
99
|
+
export declare function arcticProvider(config: ArcticCustomProvider): ArcticCustomProvider;
|
|
100
|
+
export declare function listArcticProviders(): ArcticBuiltInProvider[];
|
|
101
|
+
//# sourceMappingURL=arctic-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arctic-auth.d.ts","sourceRoot":"","sources":["../src/arctic-auth.ts"],"names":[],"mappings":"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"}
|