@rc-tool/unified-auth-hosted-service 0.2.10 → 0.3.0
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 +109 -114
- package/dist/cli/config-file.d.ts +7 -0
- package/dist/cli/config-file.d.ts.map +1 -0
- package/dist/cli/config-file.js +77 -0
- package/dist/cli/config-file.js.map +1 -0
- package/dist/cli/config.d.ts +21 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +174 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/database.d.ts +33 -0
- package/dist/cli/database.d.ts.map +1 -0
- package/dist/cli/database.js +346 -0
- package/dist/cli/database.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +44 -79
- package/dist/cli/index.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +32 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -0
- package/dist/hosted-service/applications.d.ts +0 -6
- package/dist/hosted-service/applications.d.ts.map +1 -1
- package/dist/hosted-service/applications.js +50 -8
- package/dist/hosted-service/applications.js.map +1 -1
- package/dist/hosted-service/better-auth.d.ts +10 -0
- package/dist/hosted-service/better-auth.d.ts.map +1 -0
- package/dist/hosted-service/better-auth.js +213 -0
- package/dist/hosted-service/better-auth.js.map +1 -0
- package/dist/hosted-service/constants.d.ts +0 -4
- package/dist/hosted-service/constants.d.ts.map +1 -1
- package/dist/hosted-service/constants.js +0 -4
- package/dist/hosted-service/constants.js.map +1 -1
- package/dist/hosted-service/http.d.ts.map +1 -1
- package/dist/hosted-service/http.js +6 -8
- package/dist/hosted-service/http.js.map +1 -1
- package/dist/hosted-service/login-page/components.d.ts +0 -1
- package/dist/hosted-service/login-page/components.d.ts.map +1 -1
- package/dist/hosted-service/login-page/components.js +0 -6
- package/dist/hosted-service/login-page/components.js.map +1 -1
- package/dist/hosted-service/login-page/index.d.ts.map +1 -1
- package/dist/hosted-service/login-page/index.js +2 -18
- package/dist/hosted-service/login-page/index.js.map +1 -1
- package/dist/hosted-service/login-page/links.d.ts.map +1 -1
- package/dist/hosted-service/login-page/links.js +1 -12
- package/dist/hosted-service/login-page/links.js.map +1 -1
- package/dist/hosted-service/login-page/styles.d.ts +1 -1
- package/dist/hosted-service/login-page/styles.d.ts.map +1 -1
- package/dist/hosted-service/login-page/styles.js +0 -2
- package/dist/hosted-service/login-page/styles.js.map +1 -1
- package/dist/hosted-service/login-page/types.d.ts +2 -8
- package/dist/hosted-service/login-page/types.d.ts.map +1 -1
- package/dist/hosted-service/routes.d.ts.map +1 -1
- package/dist/hosted-service/routes.js +3 -12
- package/dist/hosted-service/routes.js.map +1 -1
- package/dist/hosted-service/service.d.ts +5 -8
- package/dist/hosted-service/service.d.ts.map +1 -1
- package/dist/hosted-service/service.js +56 -168
- package/dist/hosted-service/service.js.map +1 -1
- package/dist/hosted-service/types.d.ts +36 -46
- package/dist/hosted-service/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
- package/dist/cli/env.d.ts +0 -40
- package/dist/cli/env.d.ts.map +0 -1
- package/dist/cli/env.js +0 -353
- package/dist/cli/env.js.map +0 -1
- package/dist/hosted-service/cookies.d.ts +0 -17
- package/dist/hosted-service/cookies.d.ts.map +0 -1
- package/dist/hosted-service/cookies.js +0 -56
- package/dist/hosted-service/cookies.js.map +0 -1
- package/dist/hosted-service/crypto.d.ts +0 -3
- package/dist/hosted-service/crypto.d.ts.map +0 -1
- package/dist/hosted-service/crypto.js +0 -39
- package/dist/hosted-service/crypto.js.map +0 -1
- package/dist/hosted-service/oauth.d.ts +0 -11
- package/dist/hosted-service/oauth.d.ts.map +0 -1
- package/dist/hosted-service/oauth.js +0 -37
- package/dist/hosted-service/oauth.js.map +0 -1
- package/dist/hosted-service/providers/feishu.d.ts +0 -4
- package/dist/hosted-service/providers/feishu.d.ts.map +0 -1
- package/dist/hosted-service/providers/feishu.js +0 -72
- package/dist/hosted-service/providers/feishu.js.map +0 -1
- package/dist/hosted-service/providers/github.d.ts +0 -4
- package/dist/hosted-service/providers/github.d.ts.map +0 -1
- package/dist/hosted-service/providers/github.js +0 -73
- package/dist/hosted-service/providers/github.js.map +0 -1
- package/dist/hosted-service/providers/google.d.ts +0 -4
- package/dist/hosted-service/providers/google.d.ts.map +0 -1
- package/dist/hosted-service/providers/google.js +0 -54
- package/dist/hosted-service/providers/google.js.map +0 -1
- package/dist/hosted-service/session.d.ts +0 -11
- package/dist/hosted-service/session.d.ts.map +0 -1
- package/dist/hosted-service/session.js +0 -54
- package/dist/hosted-service/session.js.map +0 -1
- package/dist/hosted-service/store/file.d.ts +0 -6
- package/dist/hosted-service/store/file.d.ts.map +0 -1
- package/dist/hosted-service/store/file.js +0 -63
- package/dist/hosted-service/store/file.js.map +0 -1
- package/dist/hosted-service/store/index.d.ts +0 -6
- package/dist/hosted-service/store/index.d.ts.map +0 -1
- package/dist/hosted-service/store/index.js +0 -3
- package/dist/hosted-service/store/index.js.map +0 -1
- package/dist/hosted-service/store/memory.d.ts +0 -6
- package/dist/hosted-service/store/memory.d.ts.map +0 -1
- package/dist/hosted-service/store/memory.js +0 -19
- package/dist/hosted-service/store/memory.js.map +0 -1
- package/dist/hosted-service/store/state.d.ts +0 -9
- package/dist/hosted-service/store/state.d.ts.map +0 -1
- package/dist/hosted-service/store/state.js +0 -156
- package/dist/hosted-service/store/state.js.map +0 -1
- package/dist/hosted-service/store/types.d.ts +0 -56
- package/dist/hosted-service/store/types.d.ts.map +0 -1
- package/dist/hosted-service/store/types.js +0 -2
- package/dist/hosted-service/store/types.js.map +0 -1
- package/dist/hosted-service-cli.d.ts +0 -2
- package/dist/hosted-service-cli.d.ts.map +0 -1
- package/dist/hosted-service-cli.js +0 -85
- package/dist/hosted-service-cli.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
# @rc-tool/unified-auth-hosted-service
|
|
2
2
|
|
|
3
|
-
Hosted
|
|
3
|
+
Hosted Login runtime for Unified Auth. This package is Better Auth-only: it renders the SDK login page, starts provider sign-in through Better Auth, exposes SDK context/session/user endpoints, and passes the rest of `/api/auth/*` directly to `auth.handler`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It does not ship a file store, memory store, custom OAuth callback implementation, custom session cookie, or standalone auth database adapter.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add @rc-tool/unified-auth-sdk @rc-tool/unified-auth-hosted-service
|
|
10
|
+
pnpm add @rc-tool/unified-auth-sdk @rc-tool/unified-auth-hosted-service better-auth drizzle-orm
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Next.js Embedded Routes
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
16
|
import {
|
|
17
|
-
|
|
17
|
+
createHostedAuthRouteHandlers,
|
|
18
|
+
} from "@rc-tool/unified-auth-hosted-service";
|
|
19
|
+
import { auth } from "@/lib/auth/server";
|
|
20
|
+
import config from "@/unified-auth.config";
|
|
21
|
+
|
|
22
|
+
export const hostedAuth = createHostedAuthRouteHandlers({
|
|
23
|
+
auth,
|
|
24
|
+
config,
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Customize the hosted login page only when the default page is not enough:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import {
|
|
18
32
|
createHostedAuthLoginPageComponent,
|
|
19
33
|
createHostedAuthRouteHandlers,
|
|
20
34
|
} from "@rc-tool/unified-auth-hosted-service";
|
|
35
|
+
import { auth } from "@/lib/auth/server";
|
|
36
|
+
import config from "@/unified-auth.config";
|
|
21
37
|
|
|
22
38
|
const LoginPage = createHostedAuthLoginPageComponent({
|
|
23
39
|
backgroundImageUrl: "https://cdn.example.com/auth/login-bg.jpg",
|
|
@@ -29,17 +45,9 @@ const LoginPage = createHostedAuthLoginPageComponent({
|
|
|
29
45
|
});
|
|
30
46
|
|
|
31
47
|
export const hostedAuth = createHostedAuthRouteHandlers({
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
appName: process.env.AUTH_CLIENT_NAME ?? "AI PM",
|
|
35
|
-
authBaseURL: process.env.AUTH_SERVICE_URL ?? "http://localhost:3004",
|
|
36
|
-
clientId: process.env.AUTH_CLIENT_ID ?? "ai-pm",
|
|
48
|
+
auth,
|
|
49
|
+
config,
|
|
37
50
|
loginPageComponent: LoginPage,
|
|
38
|
-
redirectURI: process.env.AUTH_ALLOWED_REDIRECT_URI ?? "http://localhost:3004/",
|
|
39
|
-
sessionSecret: process.env.AUTH_SESSION_SECRET!,
|
|
40
|
-
store: createFileAuthStore({
|
|
41
|
-
filePath: process.env.AUTH_STORE_FILE ?? ".auth/unified-auth-store.json",
|
|
42
|
-
}),
|
|
43
51
|
});
|
|
44
52
|
```
|
|
45
53
|
|
|
@@ -48,101 +56,63 @@ export const hostedAuth = createHostedAuthRouteHandlers({
|
|
|
48
56
|
export { GET } from "@/lib/hosted-auth";
|
|
49
57
|
```
|
|
50
58
|
|
|
59
|
+
```ts
|
|
60
|
+
// app/logout/route.ts
|
|
61
|
+
export { GET } from "@/lib/hosted-auth";
|
|
62
|
+
```
|
|
63
|
+
|
|
51
64
|
```ts
|
|
52
65
|
// app/api/auth/[...auth]/route.ts
|
|
53
66
|
export { GET, POST } from "@/lib/hosted-auth";
|
|
54
67
|
```
|
|
55
68
|
|
|
56
|
-
##
|
|
69
|
+
## Better Auth Server
|
|
57
70
|
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
```ts
|
|
72
|
+
import { createAuthServer } from "@rc-tool/unified-auth-sdk/server";
|
|
73
|
+
import { db } from "@/db";
|
|
74
|
+
import config from "@/unified-auth.config";
|
|
75
|
+
|
|
76
|
+
export const auth = createAuthServer({
|
|
77
|
+
config,
|
|
78
|
+
database: db,
|
|
79
|
+
});
|
|
61
80
|
```
|
|
62
81
|
|
|
63
|
-
|
|
82
|
+
`createHostedAuthRouteHandlers` reads app id, display name, origin, redirect URI, provider visibility, and realm from `unified-auth.config.ts`. OAuth state, callback verification, account binding, session persistence, cookie refresh, and sign-out are all delegated to Better Auth.
|
|
64
83
|
|
|
65
|
-
##
|
|
84
|
+
## Provider Routing
|
|
66
85
|
|
|
67
|
-
|
|
86
|
+
Login page provider links point at SDK start routes:
|
|
68
87
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
88
|
+
- `/api/auth/feishu/start`
|
|
89
|
+
- `/api/auth/google/start`
|
|
90
|
+
- `/api/auth/github/start`
|
|
72
91
|
|
|
73
|
-
|
|
92
|
+
Those routes call Better Auth with `disableRedirect: true`, then forward the returned provider URL to the browser.
|
|
74
93
|
|
|
75
|
-
|
|
94
|
+
Remaining Better Auth routes are passed through unchanged, so provider consoles should use Better Auth standard callback paths:
|
|
76
95
|
|
|
77
|
-
|
|
96
|
+
- Feishu generic OAuth: `/api/auth/oauth2/callback/feishu`
|
|
97
|
+
- Google: `/api/auth/callback/google`
|
|
98
|
+
- GitHub: `/api/auth/callback/github`
|
|
78
99
|
|
|
79
|
-
|
|
80
|
-
import {
|
|
81
|
-
createFileAuthStore,
|
|
82
|
-
createHostedAuthLoginPageComponent,
|
|
83
|
-
createHostedAuthRouteHandlers,
|
|
84
|
-
} from "@rc-tool/unified-auth-hosted-service";
|
|
100
|
+
If your Better Auth provider id differs from the visible login provider id, map it explicitly:
|
|
85
101
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
logoUrl: "https://cdn.example.com/auth/logo.png",
|
|
95
|
-
panelDescription: "使用企业授权账号完成登录。",
|
|
96
|
-
panelTitle: "用飞书账号登录",
|
|
97
|
-
primaryProvider: "feishu",
|
|
98
|
-
providers: ["feishu", "google", "github"],
|
|
99
|
-
statusText: "企业 SSO",
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
export const hostedAuth = createHostedAuthRouteHandlers({
|
|
103
|
-
allowedRedirectURIs: [process.env.AUTH_ALLOWED_REDIRECT_URI ?? "http://localhost:3004/"],
|
|
104
|
-
appName: process.env.AUTH_CLIENT_NAME ?? "AI PM",
|
|
105
|
-
authBaseURL: process.env.AUTH_SERVICE_URL ?? "http://localhost:3004",
|
|
106
|
-
clientId: process.env.AUTH_CLIENT_ID ?? "ai-pm",
|
|
107
|
-
loginPageComponent: LoginPage,
|
|
108
|
-
redirectURI: process.env.AUTH_ALLOWED_REDIRECT_URI ?? "http://localhost:3004/",
|
|
109
|
-
sessionSecret: process.env.AUTH_SESSION_SECRET!,
|
|
110
|
-
store: createFileAuthStore({
|
|
111
|
-
filePath: process.env.AUTH_STORE_FILE ?? ".auth/unified-auth-store.json",
|
|
112
|
-
}),
|
|
102
|
+
```ts
|
|
103
|
+
createHostedAuthRouteHandlers({
|
|
104
|
+
auth,
|
|
105
|
+
config,
|
|
106
|
+
authProviders: {
|
|
107
|
+
feishu: { providerId: "feishu-primary" },
|
|
108
|
+
github: { scopes: ["read:user", "user:email"] },
|
|
109
|
+
},
|
|
113
110
|
});
|
|
114
111
|
```
|
|
115
112
|
|
|
116
|
-
|
|
113
|
+
## Login Page Component
|
|
117
114
|
|
|
118
|
-
|
|
119
|
-
| --- | --- |
|
|
120
|
-
| `backgroundImageUrl` | 登录页背景图地址。可以是 CDN、业务项目 public 图片的绝对 URL,或任何浏览器可访问的图片。 |
|
|
121
|
-
| `logoUrl` | 左侧品牌图标。未配置时使用 SDK 默认闪电标识。 |
|
|
122
|
-
| `brandName` | 左侧品牌名称,默认取应用 `name`。 |
|
|
123
|
-
| `brandLabel` / `heroKicker` | 左侧标题上方的小标签。 |
|
|
124
|
-
| `heroTitle` | 左侧主标题。 |
|
|
125
|
-
| `heroDescription` | 左侧说明文案。 |
|
|
126
|
-
| `panelTitle` | 右侧登录面板标题。 |
|
|
127
|
-
| `panelDescription` | 右侧登录面板说明。 |
|
|
128
|
-
| `primaryProvider` | 主按钮登录方式,可选 `feishu`、`google`、`github`。 |
|
|
129
|
-
| `providers` | 登录方式展示顺序和范围,例如只展示 `["feishu"]`。未配置时展示全部已启用 provider。 |
|
|
130
|
-
| `statusText` | 右上角状态标签,传空字符串可以隐藏。 |
|
|
131
|
-
| `devLoginLabel` | 开发登录入口文案。 |
|
|
132
|
-
| `footerText` | 底部说明文案,传空字符串可以隐藏。 |
|
|
133
|
-
|
|
134
|
-
业务侧不需要配置多应用数组。内嵌 Hosted Auth 的定位是“当前业务项目自己挂登录页和 `/api/auth/*`”,因此一个项目只需要在 `createHostedAuthRouteHandlers` 上传当前项目的 `clientId`、`appName`、`redirectURI`、`allowedRedirectURIs` 和 `loginPageComponent`。
|
|
135
|
-
|
|
136
|
-
登录页组件的配置优先级是:
|
|
137
|
-
|
|
138
|
-
1. `createHostedAuthRouteHandlers({ loginPageComponent })`
|
|
139
|
-
2. SDK 默认登录页组件
|
|
140
|
-
|
|
141
|
-
旧的 `loginPage` 和 `appearance.backgroundImageUrl` 仍然兼容,但新项目推荐用 `loginPageComponent`。
|
|
142
|
-
|
|
143
|
-
独立 Auth Service 启动器不读取 `AUTH_LOGIN_*` 这类全局样式环境变量;后续如果要做共享域名的独立服务,样式会走服务侧自己的应用配置入口,不要求业务项目在 SDK 接入代码里维护应用数组。
|
|
144
|
-
|
|
145
|
-
也可以完全自定义组件,但组件只拿 SDK 生成好的 `model`,不需要接触 secret、state 签名、callback 或 session:
|
|
115
|
+
Hosted Login is a server-rendered component. Custom components receive only the SDK-generated model; they do not need OAuth secrets, state, sessions, or database access.
|
|
146
116
|
|
|
147
117
|
```ts
|
|
148
118
|
const LoginPage = ({ model }) => {
|
|
@@ -156,37 +126,62 @@ const LoginPage = ({ model }) => {
|
|
|
156
126
|
};
|
|
157
127
|
```
|
|
158
128
|
|
|
159
|
-
|
|
129
|
+
Default component config:
|
|
160
130
|
|
|
161
|
-
|
|
|
131
|
+
| Field | Purpose |
|
|
162
132
|
| --- | --- |
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
133
|
+
| `backgroundImageUrl` | Login page background image URL. |
|
|
134
|
+
| `logoUrl` | Brand logo URL. |
|
|
135
|
+
| `brandName` | Brand/application name. |
|
|
136
|
+
| `brandLabel` / `heroKicker` | Small hero label. |
|
|
137
|
+
| `heroTitle` / `heroDescription` | Hero title and copy. |
|
|
138
|
+
| `panelTitle` / `panelDescription` | Login panel title and copy. |
|
|
139
|
+
| `primaryProvider` | Primary provider: `feishu`, `google`, or `github`. |
|
|
140
|
+
| `providers` | Visible provider order and subset. |
|
|
141
|
+
| `statusText` | Top-right status label; pass `""` to hide. |
|
|
142
|
+
| `footerText` | Footer copy; pass `""` to hide. |
|
|
167
143
|
|
|
168
|
-
|
|
144
|
+
## CLI
|
|
169
145
|
|
|
170
|
-
|
|
171
|
-
| --- | --- |
|
|
172
|
-
| `AUTH_SESSION_SECRET` | session cookie 签名密钥,CLI 会自动生成。 |
|
|
173
|
-
| `AUTH_ALLOW_DEV_LOGIN` | 是否允许开发账号登录,生产环境建议设置为 `false`。 |
|
|
174
|
-
| `AUTH_STORE_PROVIDER` | 认证数据存储方式,默认 `file`,可选 `prisma`。 |
|
|
175
|
-
| `AUTH_STORE_FILE` | file store 的 JSON 文件路径,默认 `.auth/unified-auth-store.json`。 |
|
|
176
|
-
| `AUTH_DATABASE_URL` | Prisma store 的认证库 PostgreSQL 连接串。 |
|
|
146
|
+
Create `unified-auth.config.ts` in the business project:
|
|
177
147
|
|
|
178
|
-
|
|
148
|
+
```ts
|
|
149
|
+
import { defineUnifiedAuthConfig } from "@rc-tool/unified-auth-hosted-service/config";
|
|
150
|
+
|
|
151
|
+
export default defineUnifiedAuthConfig({
|
|
152
|
+
app: {
|
|
153
|
+
id: "ai-pm",
|
|
154
|
+
name: "AI PM",
|
|
155
|
+
origin: "http://localhost:3004",
|
|
156
|
+
redirectURI: "http://localhost:3004/",
|
|
157
|
+
},
|
|
158
|
+
auth: {
|
|
159
|
+
origin: "http://localhost:3004",
|
|
160
|
+
secret: () => process.env.BETTER_AUTH_SECRET,
|
|
161
|
+
},
|
|
162
|
+
database: {
|
|
163
|
+
url: () => process.env.DATABASE_URL,
|
|
164
|
+
},
|
|
165
|
+
providers: ["feishu", "google", "github"],
|
|
166
|
+
realm: "ai-pm",
|
|
167
|
+
});
|
|
168
|
+
```
|
|
179
169
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
170
|
+
First-time setup creates the config file if it is missing. The CLI reads `unified-auth.config.ts` and does not generate env files:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pnpm dlx @rc-tool/unified-auth-hosted-service init
|
|
174
|
+
```
|
|
185
175
|
|
|
186
|
-
|
|
176
|
+
Prepare the auth database and verify the project:
|
|
187
177
|
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
GITHUB_REDIRECT_URI=http://localhost:3004/api/auth/github/callback
|
|
178
|
+
```bash
|
|
179
|
+
pnpm dlx @rc-tool/unified-auth-hosted-service db migrate
|
|
180
|
+
pnpm dlx @rc-tool/unified-auth-hosted-service doctor
|
|
192
181
|
```
|
|
182
|
+
|
|
183
|
+
`db migrate` is safe to run repeatedly in CI/CD. It does not require migration records: it compares the real PostgreSQL schema, tables, columns, indexes, and constraints for the configured `realm`, creates compatible missing pieces, and fails on incompatible existing structure.
|
|
184
|
+
|
|
185
|
+
`doctor` checks the config, database connectivity, selected auth schema, required Better Auth tables, indexes, and constraints.
|
|
186
|
+
|
|
187
|
+
`realm` selects the auth table namespace. For example, `a` maps to PostgreSQL schema `auth_a`; multiple business projects can share that realm, while another project can use `b` and stay isolated in `auth_b`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UnifiedAuthConfig } from "../config.js";
|
|
2
|
+
export interface LoadedUnifiedAuthConfig {
|
|
3
|
+
config?: UnifiedAuthConfig;
|
|
4
|
+
path?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadUnifiedAuthConfig(cwd: string, configPath?: string): Promise<LoadedUnifiedAuthConfig>;
|
|
7
|
+
//# sourceMappingURL=config-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../../src/cli/config-file.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAUD,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAW9G"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, extname, resolve } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
const configFileNames = [
|
|
7
|
+
"unified-auth.config.ts",
|
|
8
|
+
"unified-auth.config.mts",
|
|
9
|
+
"unified-auth.config.js",
|
|
10
|
+
"unified-auth.config.mjs",
|
|
11
|
+
"unified-auth.config.cjs",
|
|
12
|
+
];
|
|
13
|
+
export async function loadUnifiedAuthConfig(cwd, configPath) {
|
|
14
|
+
const path = resolveConfigPath(cwd, configPath);
|
|
15
|
+
if (!path) {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
const mod = await loadConfigModule(path);
|
|
19
|
+
const config = readConfigExport(mod);
|
|
20
|
+
return { config, path };
|
|
21
|
+
}
|
|
22
|
+
function resolveConfigPath(cwd, configPath) {
|
|
23
|
+
if (configPath) {
|
|
24
|
+
const path = resolve(cwd, configPath);
|
|
25
|
+
if (!existsSync(path)) {
|
|
26
|
+
throw new Error(`Unified Auth config file not found: ${path}`);
|
|
27
|
+
}
|
|
28
|
+
return path;
|
|
29
|
+
}
|
|
30
|
+
return configFileNames.map((name) => resolve(cwd, name)).find((path) => existsSync(path));
|
|
31
|
+
}
|
|
32
|
+
async function loadConfigModule(path) {
|
|
33
|
+
const extension = extname(path);
|
|
34
|
+
if (extension === ".cjs" || extension === ".cts") {
|
|
35
|
+
return loadCommonJSConfig(path);
|
|
36
|
+
}
|
|
37
|
+
if (extension === ".ts" || extension === ".mts") {
|
|
38
|
+
return loadTypeScriptConfig(path);
|
|
39
|
+
}
|
|
40
|
+
return import(`${pathToFileURL(path).href}?t=${Date.now()}`);
|
|
41
|
+
}
|
|
42
|
+
function loadCommonJSConfig(path) {
|
|
43
|
+
const require = createRequire(import.meta.url);
|
|
44
|
+
return require(path);
|
|
45
|
+
}
|
|
46
|
+
async function loadTypeScriptConfig(path) {
|
|
47
|
+
const ts = await import("typescript");
|
|
48
|
+
const source = readFileSync(path, "utf8");
|
|
49
|
+
const output = rewriteConfigImports(ts.transpileModule(source, {
|
|
50
|
+
compilerOptions: {
|
|
51
|
+
module: ts.ModuleKind.ESNext,
|
|
52
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
53
|
+
target: ts.ScriptTarget.ES2022,
|
|
54
|
+
},
|
|
55
|
+
fileName: basename(path),
|
|
56
|
+
}).outputText);
|
|
57
|
+
const tempPath = resolve(dirname(path), `.unified-auth.config.${process.pid}.${Date.now()}.${randomBytes(4).toString("hex")}.mjs`);
|
|
58
|
+
writeFileSync(tempPath, output);
|
|
59
|
+
try {
|
|
60
|
+
return await import(`${pathToFileURL(tempPath).href}?t=${Date.now()}`);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
unlinkSync(tempPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function rewriteConfigImports(output) {
|
|
67
|
+
const configModuleURL = new URL("../config.js", import.meta.url).href;
|
|
68
|
+
return output.replace(/from\s+["']@rc-tool\/unified-auth-hosted-service\/config["']/g, `from ${JSON.stringify(configModuleURL)}`);
|
|
69
|
+
}
|
|
70
|
+
function readConfigExport(mod) {
|
|
71
|
+
const value = mod.default ?? mod.config ?? mod.unifiedAuth;
|
|
72
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
73
|
+
throw new Error("Unified Auth config must export a config object as default.");
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=config-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/cli/config-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { UnifiedAuthConfig } from "../config.js";
|
|
2
|
+
export type CheckStatus = "fail" | "pass" | "warn";
|
|
3
|
+
export interface InitUnifiedAuthConfigOptions {
|
|
4
|
+
configPath?: string;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface InitUnifiedAuthConfigResult {
|
|
8
|
+
created: boolean;
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
export interface DoctorCheck {
|
|
12
|
+
message: string;
|
|
13
|
+
status: CheckStatus;
|
|
14
|
+
}
|
|
15
|
+
export interface DoctorUnifiedAuthConfigResult {
|
|
16
|
+
checks: DoctorCheck[];
|
|
17
|
+
ok: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function initUnifiedAuthConfig(options?: InitUnifiedAuthConfigOptions): InitUnifiedAuthConfigResult;
|
|
20
|
+
export declare function doctorUnifiedAuthConfig(config: UnifiedAuthConfig | undefined, path: string | undefined): DoctorUnifiedAuthConfigResult;
|
|
21
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,EAAE,EAAE,OAAO,CAAC;CACb;AAKD,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,GAAG,2BAA2B,CAY7G;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,iBAAiB,GAAG,SAAS,EACrC,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,6BAA6B,CAsB/B"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, resolve } from "node:path";
|
|
3
|
+
import { resolveUnifiedAuthConfigValue } from "../config.js";
|
|
4
|
+
const defaultConfigFileName = "unified-auth.config.ts";
|
|
5
|
+
const allowedProviders = new Set(["feishu", "github", "google"]);
|
|
6
|
+
export function initUnifiedAuthConfig(options = {}) {
|
|
7
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
8
|
+
const path = resolve(cwd, options.configPath ?? defaultConfigFileName);
|
|
9
|
+
if (existsSync(path)) {
|
|
10
|
+
return { created: false, path };
|
|
11
|
+
}
|
|
12
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
13
|
+
writeFileSync(path, createDefaultConfigSource(cwd));
|
|
14
|
+
return { created: true, path };
|
|
15
|
+
}
|
|
16
|
+
export function doctorUnifiedAuthConfig(config, path) {
|
|
17
|
+
const checks = [];
|
|
18
|
+
if (path) {
|
|
19
|
+
checks.push(pass(`${basename(path)} exists`));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
checks.push(fail(`${defaultConfigFileName} is missing; run unified-auth init`));
|
|
23
|
+
}
|
|
24
|
+
if (!config) {
|
|
25
|
+
return { checks, ok: false };
|
|
26
|
+
}
|
|
27
|
+
checkApp(checks, config);
|
|
28
|
+
checkAuth(checks, config);
|
|
29
|
+
checkDatabase(checks, config);
|
|
30
|
+
checkRealm(checks, config);
|
|
31
|
+
checkProviders(checks, config.providers);
|
|
32
|
+
return {
|
|
33
|
+
checks,
|
|
34
|
+
ok: !checks.some((check) => check.status === "fail"),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function createDefaultConfigSource(cwd) {
|
|
38
|
+
const appId = inferClientId(cwd);
|
|
39
|
+
const appName = titleFromClientId(appId);
|
|
40
|
+
return `import { defineUnifiedAuthConfig } from "@rc-tool/unified-auth-hosted-service/config";
|
|
41
|
+
|
|
42
|
+
export default defineUnifiedAuthConfig({
|
|
43
|
+
app: {
|
|
44
|
+
id: "${appId}",
|
|
45
|
+
name: "${appName}",
|
|
46
|
+
origin: "http://localhost:3004",
|
|
47
|
+
redirectURI: "http://localhost:3004/",
|
|
48
|
+
},
|
|
49
|
+
auth: {
|
|
50
|
+
origin: "http://localhost:3004",
|
|
51
|
+
secret: () => process.env.BETTER_AUTH_SECRET,
|
|
52
|
+
},
|
|
53
|
+
database: {
|
|
54
|
+
url: () => process.env.DATABASE_URL,
|
|
55
|
+
},
|
|
56
|
+
providers: ["feishu", "google", "github"],
|
|
57
|
+
realm: "${normalizeRealmId(appId)}",
|
|
58
|
+
});
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
function checkApp(checks, config) {
|
|
62
|
+
if (config.app?.id) {
|
|
63
|
+
checks.push(pass("app.id is set"));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
checks.push(fail("app.id is missing"));
|
|
67
|
+
}
|
|
68
|
+
if (config.app?.name) {
|
|
69
|
+
checks.push(pass("app.name is set"));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
checks.push(warn("app.name is missing; app.id will be used as display name"));
|
|
73
|
+
}
|
|
74
|
+
const origin = config.app?.origin ?? getURLOrigin(config.app?.url);
|
|
75
|
+
const redirectURI = config.app?.redirectURI ?? config.app?.url;
|
|
76
|
+
checkURL(checks, origin, "app.origin");
|
|
77
|
+
checkURL(checks, redirectURI, "app.redirectURI");
|
|
78
|
+
}
|
|
79
|
+
function checkAuth(checks, config) {
|
|
80
|
+
const authOrigin = config.auth?.origin ?? config.auth?.url ?? config.app?.origin ?? getURLOrigin(config.app?.url);
|
|
81
|
+
checkURL(checks, authOrigin, "auth.origin");
|
|
82
|
+
if (resolveUnifiedAuthConfigValue(config.auth?.secret)) {
|
|
83
|
+
checks.push(pass("auth.secret is provided by config"));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
checks.push(warn("auth.secret is not set in config; runtime must provide a Better Auth secret"));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function checkDatabase(checks, config) {
|
|
90
|
+
if (resolveUnifiedAuthConfigValue(config.database?.url)) {
|
|
91
|
+
checks.push(pass("database.url is provided by config"));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
checks.push(fail("database.url is missing; db migrate and doctor database checks need a PostgreSQL URL"));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function checkRealm(checks, config) {
|
|
98
|
+
const realm = config.realm ?? config.app?.id;
|
|
99
|
+
if (!realm) {
|
|
100
|
+
checks.push(fail("realm is missing and app.id cannot be used as fallback"));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
checks.push(pass(`realm maps to PostgreSQL schema auth_${normalizeRealmId(realm).replace(/^auth_/, "")}`));
|
|
104
|
+
}
|
|
105
|
+
function checkProviders(checks, providers) {
|
|
106
|
+
if (!providers?.length) {
|
|
107
|
+
checks.push(warn("providers is empty; login page will show all built-in providers unless overridden"));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
for (const provider of providers) {
|
|
111
|
+
if (allowedProviders.has(provider)) {
|
|
112
|
+
checks.push(pass(`${provider} provider is configured`));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
checks.push(fail(`unsupported provider: ${provider}`));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function checkURL(checks, value, label) {
|
|
120
|
+
if (!value) {
|
|
121
|
+
checks.push(fail(`${label} is missing`));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
new URL(value);
|
|
126
|
+
checks.push(pass(`${label} is a valid URL`));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
checks.push(fail(`${label} is not a valid URL`));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function pass(message) {
|
|
133
|
+
return { message, status: "pass" };
|
|
134
|
+
}
|
|
135
|
+
function warn(message) {
|
|
136
|
+
return { message, status: "warn" };
|
|
137
|
+
}
|
|
138
|
+
function fail(message) {
|
|
139
|
+
return { message, status: "fail" };
|
|
140
|
+
}
|
|
141
|
+
function inferClientId(cwd) {
|
|
142
|
+
const id = basename(cwd)
|
|
143
|
+
.toLowerCase()
|
|
144
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
145
|
+
.replace(/^-+|-+$/g, "");
|
|
146
|
+
return id || "app";
|
|
147
|
+
}
|
|
148
|
+
function normalizeRealmId(realmId) {
|
|
149
|
+
return realmId
|
|
150
|
+
.trim()
|
|
151
|
+
.toLowerCase()
|
|
152
|
+
.replace(/[^a-z0-9_]+/g, "_")
|
|
153
|
+
.replace(/^_+|_+$/g, "")
|
|
154
|
+
.replace(/_+/g, "_") || "default";
|
|
155
|
+
}
|
|
156
|
+
function titleFromClientId(clientId) {
|
|
157
|
+
return clientId
|
|
158
|
+
.split(/[-_]/g)
|
|
159
|
+
.filter(Boolean)
|
|
160
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
161
|
+
.join(" ") || "Application";
|
|
162
|
+
}
|
|
163
|
+
function getURLOrigin(value) {
|
|
164
|
+
if (!value) {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
return new URL(value).origin;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { UnifiedAuthConfig } from "../config.js";
|
|
2
|
+
import type { DoctorCheck } from "./config.js";
|
|
3
|
+
interface ColumnInfo {
|
|
4
|
+
dataType: string;
|
|
5
|
+
isNullable: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface TableInspection {
|
|
8
|
+
columns: Map<string, ColumnInfo>;
|
|
9
|
+
constraints: Set<string>;
|
|
10
|
+
exists: boolean;
|
|
11
|
+
indexes: Set<string>;
|
|
12
|
+
}
|
|
13
|
+
export interface AuthDatabaseInspection {
|
|
14
|
+
schemaExists: boolean;
|
|
15
|
+
tables: Map<string, TableInspection>;
|
|
16
|
+
}
|
|
17
|
+
export interface AuthDatabaseAction {
|
|
18
|
+
label: string;
|
|
19
|
+
sql: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AuthDatabasePlan {
|
|
22
|
+
actions: AuthDatabaseAction[];
|
|
23
|
+
schemaName: string;
|
|
24
|
+
warnings: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface AuthDatabaseMigrationResult extends AuthDatabasePlan {
|
|
27
|
+
changed: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare function migrateUnifiedAuthDatabase(config: UnifiedAuthConfig): Promise<AuthDatabaseMigrationResult>;
|
|
30
|
+
export declare function doctorUnifiedAuthDatabase(config: UnifiedAuthConfig): Promise<DoctorCheck[]>;
|
|
31
|
+
export declare function buildAuthDatabasePlan(schemaName: string, inspection: AuthDatabaseInspection): AuthDatabasePlan;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/cli/database.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2B/C,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,2BAA4B,SAAQ,gBAAgB;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AA8FD,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAwBhH;AAED,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAoDjG;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,sBAAsB,GAAG,gBAAgB,CAgE9G"}
|