@visiblebase/core 0.2.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.
Files changed (110) hide show
  1. package/README.md +127 -0
  2. package/bin/core/auth/authenticator.d.ts +68 -0
  3. package/bin/core/auth/authenticator.d.ts.map +1 -0
  4. package/bin/core/auth/authenticator.js +106 -0
  5. package/bin/core/auth/authenticator.js.map +1 -0
  6. package/bin/core/auth/token-signer.d.ts +27 -0
  7. package/bin/core/auth/token-signer.d.ts.map +1 -0
  8. package/bin/core/auth/token-signer.js +116 -0
  9. package/bin/core/auth/token-signer.js.map +1 -0
  10. package/bin/core/auth/types.d.ts +94 -0
  11. package/bin/core/auth/types.d.ts.map +1 -0
  12. package/bin/core/auth/types.js +7 -0
  13. package/bin/core/auth/types.js.map +1 -0
  14. package/bin/core/base/base.d.ts +98 -0
  15. package/bin/core/base/base.d.ts.map +1 -0
  16. package/bin/core/base/base.js +281 -0
  17. package/bin/core/base/base.js.map +1 -0
  18. package/bin/core/runtime.d.ts +112 -0
  19. package/bin/core/runtime.d.ts.map +1 -0
  20. package/bin/core/runtime.js +19 -0
  21. package/bin/core/runtime.js.map +1 -0
  22. package/bin/core/types.d.ts +39 -0
  23. package/bin/core/types.d.ts.map +1 -0
  24. package/bin/core/types.js +7 -0
  25. package/bin/core/types.js.map +1 -0
  26. package/bin/index.d.ts +39 -0
  27. package/bin/index.d.ts.map +1 -0
  28. package/bin/index.js +45 -0
  29. package/bin/index.js.map +1 -0
  30. package/bin/service/ai/ai-service.d.ts +80 -0
  31. package/bin/service/ai/ai-service.d.ts.map +1 -0
  32. package/bin/service/ai/ai-service.js +184 -0
  33. package/bin/service/ai/ai-service.js.map +1 -0
  34. package/bin/service/ai/provider.d.ts +77 -0
  35. package/bin/service/ai/provider.d.ts.map +1 -0
  36. package/bin/service/ai/provider.js +71 -0
  37. package/bin/service/ai/provider.js.map +1 -0
  38. package/bin/service/ai/types.d.ts +72 -0
  39. package/bin/service/ai/types.d.ts.map +1 -0
  40. package/bin/service/ai/types.js +7 -0
  41. package/bin/service/ai/types.js.map +1 -0
  42. package/bin/service/env/env-service.d.ts +14 -0
  43. package/bin/service/env/env-service.d.ts.map +1 -0
  44. package/bin/service/env/env-service.js +42 -0
  45. package/bin/service/env/env-service.js.map +1 -0
  46. package/bin/service/env/env-store.d.ts +15 -0
  47. package/bin/service/env/env-store.d.ts.map +1 -0
  48. package/bin/service/env/env-store.js +35 -0
  49. package/bin/service/env/env-store.js.map +1 -0
  50. package/bin/service/env/schema.d.ts +171 -0
  51. package/bin/service/env/schema.d.ts.map +1 -0
  52. package/bin/service/env/schema.js +52 -0
  53. package/bin/service/env/schema.js.map +1 -0
  54. package/bin/service/env/types.d.ts +37 -0
  55. package/bin/service/env/types.d.ts.map +1 -0
  56. package/bin/service/env/types.js +8 -0
  57. package/bin/service/env/types.js.map +1 -0
  58. package/bin/service/hook.d.ts +20 -0
  59. package/bin/service/hook.d.ts.map +1 -0
  60. package/bin/service/hook.js +52 -0
  61. package/bin/service/hook.js.map +1 -0
  62. package/bin/service/plugin.d.ts +141 -0
  63. package/bin/service/plugin.d.ts.map +1 -0
  64. package/bin/service/plugin.js +124 -0
  65. package/bin/service/plugin.js.map +1 -0
  66. package/bin/service/products/product-store.d.ts +17 -0
  67. package/bin/service/products/product-store.d.ts.map +1 -0
  68. package/bin/service/products/product-store.js +49 -0
  69. package/bin/service/products/product-store.js.map +1 -0
  70. package/bin/service/products/products-service.d.ts +16 -0
  71. package/bin/service/products/products-service.d.ts.map +1 -0
  72. package/bin/service/products/products-service.js +52 -0
  73. package/bin/service/products/products-service.js.map +1 -0
  74. package/bin/service/products/schema.d.ts +207 -0
  75. package/bin/service/products/schema.d.ts.map +1 -0
  76. package/bin/service/products/schema.js +60 -0
  77. package/bin/service/products/schema.js.map +1 -0
  78. package/bin/service/products/types.d.ts +51 -0
  79. package/bin/service/products/types.d.ts.map +1 -0
  80. package/bin/service/products/types.js +7 -0
  81. package/bin/service/products/types.js.map +1 -0
  82. package/bin/service/service.d.ts +118 -0
  83. package/bin/service/service.d.ts.map +1 -0
  84. package/bin/service/service.js +114 -0
  85. package/bin/service/service.js.map +1 -0
  86. package/bin/service/types.d.ts +17 -0
  87. package/bin/service/types.d.ts.map +1 -0
  88. package/bin/service/types.js +5 -0
  89. package/bin/service/types.js.map +1 -0
  90. package/bin/store/db.d.ts +64 -0
  91. package/bin/store/db.d.ts.map +1 -0
  92. package/bin/store/db.js +28 -0
  93. package/bin/store/db.js.map +1 -0
  94. package/bin/store/table-api.d.ts +42 -0
  95. package/bin/store/table-api.d.ts.map +1 -0
  96. package/bin/store/table-api.js +98 -0
  97. package/bin/store/table-api.js.map +1 -0
  98. package/bin/store/types.d.ts +14 -0
  99. package/bin/store/types.d.ts.map +1 -0
  100. package/bin/store/types.js +7 -0
  101. package/bin/store/types.js.map +1 -0
  102. package/bin/utils/helpers.d.ts +101 -0
  103. package/bin/utils/helpers.d.ts.map +1 -0
  104. package/bin/utils/helpers.js +192 -0
  105. package/bin/utils/helpers.js.map +1 -0
  106. package/bin/utils/validation.d.ts +18 -0
  107. package/bin/utils/validation.d.ts.map +1 -0
  108. package/bin/utils/validation.js +28 -0
  109. package/bin/utils/validation.js.map +1 -0
  110. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # @visiblebase/base
2
+
3
+ `@visiblebase/base` 是 VisibleBase 的服务端 Runtime。
4
+
5
+ 它负责这些共用能力:
6
+
7
+ - 初始化默认 Runtime 数据库 `products`
8
+ - 校验 `user_token`
9
+ - 提供 Fetch 风格 HTTP handler
10
+ - 管理 Runtime `.env`
11
+ - 用 `base.model(meta).handle()` 注册场景模型和执行 handler
12
+
13
+ ## 安装
14
+
15
+ ```bash
16
+ pnpm add @visiblebase/base
17
+ ```
18
+
19
+ 需要 Node `>=22.13.0`。
20
+
21
+ ## 最小示例
22
+
23
+ ```ts
24
+ import { Base } from "@visiblebase/base";
25
+
26
+ const base = new Base();
27
+
28
+ base.model({
29
+ id: "local-echo",
30
+ name: "Local Echo",
31
+ default: ["text"],
32
+ }).handle({
33
+ text: async (ctx) => ({
34
+ id: crypto.randomUUID(),
35
+ role: "assistant",
36
+ parts: [
37
+ {
38
+ type: "text",
39
+ text: `echo: ${ctx.input.prompt}`,
40
+ state: "done",
41
+ },
42
+ ],
43
+ }),
44
+ });
45
+
46
+ const server = await base.serve({
47
+ host: "127.0.0.1",
48
+ port: 3001,
49
+ });
50
+
51
+ console.log(`VisibleBase listening on http://${server.host}:${server.port}`);
52
+ ```
53
+
54
+ 这段代码不要求你自己打开 SQLite 或手写 `visiblebase_models`。`client.models()` 读取的是 `base.model(meta).handle()` 注册出来的运行时目录。
55
+
56
+ 默认情况下,Base 会在第一次 `serve()`、`handleRequest()`、`models()`、`invoke()` 或 `table()` 操作时自动初始化。常规使用不需要手动调用 `init()`。
57
+
58
+ ## 主要导出
59
+
60
+ - `Base`
61
+ - `VisibleBase`
62
+ - 模型类型:`ModelMeta`、`ModelHandlers`、`RuntimeModel`
63
+ - 插件类型:`BasePlugin`、`BasePluginRoute`、`BasePluginContext`
64
+ - 默认数据库 schema:`sqliteProducts`、`pgProducts`
65
+ - `DotenvRuntimeEnv`
66
+
67
+ ## 业务表
68
+
69
+ 业务表通过 `new Base({ schema })` 注册,然后用 `base.table(name)` 操作:
70
+
71
+ ```ts
72
+ import { sqliteTable, text } from "drizzle-orm/sqlite-core";
73
+ import { Base } from "@visiblebase/base";
74
+
75
+ const notes = sqliteTable("notes", {
76
+ id: text("id").primaryKey(),
77
+ title: text("title").notNull(),
78
+ });
79
+
80
+ const base = new Base({
81
+ schema: {
82
+ notes,
83
+ },
84
+ });
85
+
86
+ await base.table("notes").insert({
87
+ id: "note_1",
88
+ title: "First note",
89
+ });
90
+
91
+ const rows = await base.table("notes").select();
92
+ ```
93
+
94
+ ## 插件
95
+
96
+ 插件用于把多个 client 产品会复用的 Base 能力封装起来,例如用户注册登录、支付、订阅权益、usage 扣费或通知。
97
+
98
+ ```ts
99
+ import { Base } from "@visiblebase/base";
100
+ import { authPlugin } from "@visiblebase/plugin-auth";
101
+ import { usagePlugin } from "@visiblebase/plugin-usage";
102
+ import { stripePaymentPlugin } from "@visiblebase/plugin-payment-stripe";
103
+
104
+ const base = new Base({
105
+ plugins: [
106
+ authPlugin(),
107
+ usagePlugin(),
108
+ stripePaymentPlugin(),
109
+ ],
110
+ });
111
+ ```
112
+
113
+ Base 使用者不需要为官方插件定义数据库表。插件包内部会声明自己的表,Base 在首次运行时自动创建。
114
+
115
+ `models` 和 `products` 也是默认内置插件。你不传 `plugins` 时,Base 会自动启用它们;你传入其他插件时,它们仍然保留;如果你传入同 ID 的 `models` 或 `products` 插件,则会替换默认实现。
116
+
117
+ 插件路由按鉴权模式挂载:
118
+
119
+ - `auth: "public"` 和 `auth: "user"`:`/v1/plugins/{pluginId}/{path}`
120
+ - `auth: "admin"`:`/api/admin/plugins/{pluginId}/{path}`
121
+
122
+ 如果你在开发插件,插件可以声明自己的 `schema`,并通过 `ctx.table(name)` 读写插件表;也可以通过 `ctx.hook.before()`、`ctx.hook.after()` 和 `ctx.hook.onError()` 介入 service 调用。
123
+
124
+ ## 文档
125
+
126
+ - 仓库首页:[visiblebase](https://github.com/wangenius/visiblebase)
127
+ - 文档目录:[homepage/content/docs](https://github.com/wangenius/visiblebase/tree/main/homepage/content/docs)
@@ -0,0 +1,68 @@
1
+ /**
2
+ * 统一鉴权模块。
3
+ *
4
+ * Authenticator 统一处理 admin(secret key)和 user(JWT token)两种鉴权方式。
5
+ * 所有鉴权失败统一抛出 httpError(ErrorWithStatus)。
6
+ *
7
+ * TokenSigner 实例通过 getSigner() 缓存,避免重复 new TokenSigner(key)。
8
+ */
9
+ import type { RouteAuth } from "../../service/service.js";
10
+ import type { EnvProvider } from "../runtime.js";
11
+ import type { CreateUserTokenInput, UserTokenPayload, UserTokenIssueResult, RuntimeUser } from "./types.js";
12
+ /** 鉴权级别 */
13
+ /** 鉴权结果 */
14
+ export interface AuthResult {
15
+ /** 鉴权后的实际级别 */
16
+ level: RouteAuth;
17
+ /** 解析出的用户信息(user 级别时可用) */
18
+ user?: RuntimeUser;
19
+ /** 解析出的 Product 信息(user 级别时可用) */
20
+ product?: {
21
+ product_id: string;
22
+ status: string;
23
+ };
24
+ }
25
+ /** 统一鉴权器 */
26
+ export declare class Authenticator {
27
+ private env;
28
+ private store;
29
+ /** 缓存的 TokenSigner 实例 */
30
+ private tokenSigner?;
31
+ constructor(env: EnvProvider, store: () => Promise<{
32
+ product: {
33
+ get(id: string): Promise<{
34
+ product_id: string;
35
+ status: string;
36
+ } | undefined>;
37
+ };
38
+ }>);
39
+ /**
40
+ * 获取(或创建)TokenSigner 单例。
41
+ *
42
+ * 首次调用时从 env 读取 VISIBLEBASE_TOKEN_SIGNING_KEY 创建实例并缓存。
43
+ */
44
+ private getSigner;
45
+ /**
46
+ * 对请求执行鉴权。
47
+ *
48
+ * @param request - 原始 HTTP Request
49
+ * @param required - 要求的鉴权级别
50
+ * @returns 鉴权结果(含 user/product 信息)
51
+ */
52
+ authenticate(request: Request, required: RouteAuth): Promise<AuthResult>;
53
+ /**
54
+ * 签发 user_token(验证 product 状态后签发)。
55
+ *
56
+ * @param input - token 创建参数
57
+ * @returns 签发结果(含 token 字符串)
58
+ */
59
+ createToken(input: CreateUserTokenInput): Promise<UserTokenIssueResult>;
60
+ /**
61
+ * 校验 user_token 并返回载荷。
62
+ *
63
+ * @param token - user_token 字符串
64
+ * @returns 解析出的 token 载荷
65
+ */
66
+ verifyToken(token: string): Promise<UserTokenPayload>;
67
+ }
68
+ //# sourceMappingURL=authenticator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticator.d.ts","sourceRoot":"","sources":["../../../src/core/auth/authenticator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5G,WAAW;AACX,WAAW;AACX,MAAM,WAAW,UAAU;IACzB,eAAe;IACf,KAAK,EAAE,SAAS,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,kCAAkC;IAClC,OAAO,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD;AAED,YAAY;AACZ,qBAAa,aAAa;IAKtB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,KAAK;IALf,yBAAyB;IACzB,OAAO,CAAC,WAAW,CAAC,CAAc;gBAGxB,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,EAAE;YAAE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;gBAAE,UAAU,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,SAAS,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;IAG7H;;;;OAIG;IACH,OAAO,CAAC,SAAS;IASjB;;;;;;OAMG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IAgC9E;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiB7E;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAG5D"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * 统一鉴权模块。
3
+ *
4
+ * Authenticator 统一处理 admin(secret key)和 user(JWT token)两种鉴权方式。
5
+ * 所有鉴权失败统一抛出 httpError(ErrorWithStatus)。
6
+ *
7
+ * TokenSigner 实例通过 getSigner() 缓存,避免重复 new TokenSigner(key)。
8
+ */
9
+ import { bearerToken, httpError } from "../../utils/helpers.js";
10
+ import { TokenSigner } from "./token-signer.js";
11
+ /** 统一鉴权器 */
12
+ export class Authenticator {
13
+ env;
14
+ store;
15
+ /** 缓存的 TokenSigner 实例 */
16
+ tokenSigner;
17
+ constructor(env, store) {
18
+ this.env = env;
19
+ this.store = store;
20
+ }
21
+ /**
22
+ * 获取(或创建)TokenSigner 单例。
23
+ *
24
+ * 首次调用时从 env 读取 VISIBLEBASE_TOKEN_SIGNING_KEY 创建实例并缓存。
25
+ */
26
+ getSigner() {
27
+ if (!this.tokenSigner) {
28
+ const signingKey = this.env.get("VISIBLEBASE_TOKEN_SIGNING_KEY");
29
+ if (!signingKey)
30
+ throw new Error("VISIBLEBASE_TOKEN_SIGNING_KEY is required");
31
+ this.tokenSigner = new TokenSigner(signingKey);
32
+ }
33
+ return this.tokenSigner;
34
+ }
35
+ /**
36
+ * 对请求执行鉴权。
37
+ *
38
+ * @param request - 原始 HTTP Request
39
+ * @param required - 要求的鉴权级别
40
+ * @returns 鉴权结果(含 user/product 信息)
41
+ */
42
+ async authenticate(request, required) {
43
+ if (required === "public") {
44
+ return { level: "public" };
45
+ }
46
+ const token = bearerToken(request);
47
+ if (!token) {
48
+ throw httpError(401, "Missing authorization token");
49
+ }
50
+ // admin 鉴权
51
+ if (required === "admin") {
52
+ const adminKey = this.env.get("VISIBLEBASE_ADMIN_SECRET_KEY");
53
+ if (!adminKey)
54
+ throw httpError(500, "VISIBLEBASE_ADMIN_SECRET_KEY is required");
55
+ if (token !== adminKey)
56
+ throw httpError(401, "Invalid admin_secret_key");
57
+ return { level: "admin" };
58
+ }
59
+ // user 鉴权
60
+ const payload = await this.getSigner().verify(token);
61
+ const store = await this.store();
62
+ const product = await store.product.get(payload.product_id);
63
+ if (!product)
64
+ throw httpError(401, "Unknown token product");
65
+ if (product.status !== "active")
66
+ throw httpError(403, "Token product is not active");
67
+ return {
68
+ level: "user",
69
+ user: { user_id: payload.user_id, metadata: payload.metadata ?? {} },
70
+ product,
71
+ };
72
+ }
73
+ /**
74
+ * 签发 user_token(验证 product 状态后签发)。
75
+ *
76
+ * @param input - token 创建参数
77
+ * @returns 签发结果(含 token 字符串)
78
+ */
79
+ async createToken(input) {
80
+ const store = await this.store();
81
+ const product = await store.product.get(input.product_id);
82
+ if (!product)
83
+ throw new Error(`Unknown product: ${input.product_id}`);
84
+ if (product.status !== "active")
85
+ throw new Error(`Product is not active: ${input.product_id}`);
86
+ const user_token = await this.getSigner().sign(input);
87
+ return {
88
+ user_token,
89
+ product_id: input.product_id,
90
+ user_id: input.user_id,
91
+ ...(input.ttl
92
+ ? { expires_at: new Date(Date.now() + TokenSigner.parseTTL(input.ttl) * 1000).toISOString() }
93
+ : {}),
94
+ };
95
+ }
96
+ /**
97
+ * 校验 user_token 并返回载荷。
98
+ *
99
+ * @param token - user_token 字符串
100
+ * @returns 解析出的 token 载荷
101
+ */
102
+ async verifyToken(token) {
103
+ return this.getSigner().verify(token);
104
+ }
105
+ }
106
+ //# sourceMappingURL=authenticator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticator.js","sourceRoot":"","sources":["../../../src/core/auth/authenticator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiBhD,YAAY;AACZ,MAAM,OAAO,aAAa;IAKd;IACA;IALV,yBAAyB;IACjB,WAAW,CAAe;IAElC,YACU,GAAgB,EAChB,KAAmH;QADnH,QAAG,GAAH,GAAG,CAAa;QAChB,UAAK,GAAL,KAAK,CAA8G;IAC1H,CAAC;IAEJ;;;;OAIG;IACK,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;YACjE,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC9E,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,UAAU,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAC,OAAgB,EAAE,QAAmB;QACtD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QAC7B,CAAC;QAED,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,SAAS,CAAC,GAAG,EAAE,6BAA6B,CAAC,CAAC;QACtD,CAAC;QAED,WAAW;QACX,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC9D,IAAI,CAAC,QAAQ;gBAAE,MAAM,SAAS,CAAC,GAAG,EAAE,0CAA0C,CAAC,CAAC;YAChF,IAAI,KAAK,KAAK,QAAQ;gBAAE,MAAM,SAAS,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAC;YACzE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC5B,CAAC;QAED,UAAU;QACV,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO;YAAE,MAAM,SAAS,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;QAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ;YAAE,MAAM,SAAS,CAAC,GAAG,EAAE,6BAA6B,CAAC,CAAC;QAErF,OAAO;YACL,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE;YACpE,OAAO;SACR,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,KAA2B;QAC3C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QACtE,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAE/F,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO;YACL,UAAU;YACV,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,KAAK,CAAC,GAAG;gBACX,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;gBAC7F,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * user_token 签发与校验模块。
3
+ *
4
+ * VisibleBase 使用 Web Crypto API 的 HMAC-SHA256 生成最小可用的 user_token。
5
+ * 零 Node.js 依赖,兼容所有现代运行时(Node、Workers、Deno、Bun、浏览器)。
6
+ */
7
+ import type { CreateUserTokenInput, UserTokenPayload } from "./types.js";
8
+ export declare class TokenSigner {
9
+ readonly signingKey: string;
10
+ /** 缓存的 CryptoKey,避免每次签名都重新 import */
11
+ private cryptoKey?;
12
+ constructor(signingKey: string);
13
+ /**
14
+ * 获取(或缓存)HMAC CryptoKey。
15
+ *
16
+ * 使用 Web Crypto API 的 crypto.subtle.importKey,
17
+ * 首次调用时创建并缓存 Promise,后续复用。
18
+ */
19
+ private getCryptoKey;
20
+ /** 签发 user_token */
21
+ sign(input: CreateUserTokenInput): Promise<string>;
22
+ /** 校验并解析 user_token,失败抛 httpError(401) */
23
+ verify(token: string): Promise<UserTokenPayload>;
24
+ /** 把 ttl 解析成秒数 */
25
+ static parseTTL(ttl: string | number): number;
26
+ }
27
+ //# sourceMappingURL=token-signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-signer.d.ts","sourceRoot":"","sources":["../../../src/core/auth/token-signer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEzE,qBAAa,WAAW;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,qCAAqC;IACrC,OAAO,CAAC,SAAS,CAAC,CAAqB;gBAE3B,UAAU,EAAE,MAAM;IAO9B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAcpB,oBAAoB;IACd,IAAI,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BxD,0CAA0C;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA6BtD,kBAAkB;IAClB,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;CAyB9C"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * user_token 签发与校验模块。
3
+ *
4
+ * VisibleBase 使用 Web Crypto API 的 HMAC-SHA256 生成最小可用的 user_token。
5
+ * 零 Node.js 依赖,兼容所有现代运行时(Node、Workers、Deno、Bun、浏览器)。
6
+ */
7
+ import { httpError, base64UrlEncode, base64UrlDecode, base64UrlEncodeBytes, base64UrlDecodeBytes, timingSafeEqualBytes } from "../../utils/helpers.js";
8
+ export class TokenSigner {
9
+ signingKey;
10
+ /** 缓存的 CryptoKey,避免每次签名都重新 import */
11
+ cryptoKey;
12
+ constructor(signingKey) {
13
+ if (!signingKey) {
14
+ throw new Error("TokenSigner requires a signing key");
15
+ }
16
+ this.signingKey = signingKey;
17
+ }
18
+ /**
19
+ * 获取(或缓存)HMAC CryptoKey。
20
+ *
21
+ * 使用 Web Crypto API 的 crypto.subtle.importKey,
22
+ * 首次调用时创建并缓存 Promise,后续复用。
23
+ */
24
+ getCryptoKey() {
25
+ if (!this.cryptoKey) {
26
+ const encoder = new TextEncoder();
27
+ this.cryptoKey = crypto.subtle.importKey("raw", encoder.encode(this.signingKey), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
28
+ }
29
+ return this.cryptoKey;
30
+ }
31
+ /** 签发 user_token */
32
+ async sign(input) {
33
+ if (!input || typeof input.product_id !== "string" || input.product_id.length === 0) {
34
+ throw new TypeError("product_id is required");
35
+ }
36
+ if (typeof input.user_id !== "string" || input.user_id.length === 0) {
37
+ throw new TypeError("user_id is required");
38
+ }
39
+ const ttl = input.ttl;
40
+ const now = Math.floor(Date.now() / 1000);
41
+ const payload = {
42
+ aud: "visiblebase:user",
43
+ product_id: input.product_id,
44
+ user_id: input.user_id,
45
+ metadata: input.metadata ?? {},
46
+ iat: now,
47
+ };
48
+ if (ttl) {
49
+ payload.exp = now + TokenSigner.parseTTL(ttl);
50
+ }
51
+ const encodedPayload = base64UrlEncode(JSON.stringify(payload));
52
+ const signature = await signPayload(await this.getCryptoKey(), encodedPayload);
53
+ return `ub_${encodedPayload}.${signature}`;
54
+ }
55
+ /** 校验并解析 user_token,失败抛 httpError(401) */
56
+ async verify(token) {
57
+ const rawToken = token.startsWith("ub_") ? token.slice(3) : token;
58
+ const [encodedPayload, signature] = rawToken.split(".");
59
+ if (!encodedPayload || !signature) {
60
+ throw httpError(401, "Invalid user token");
61
+ }
62
+ if (!await verifyPayload(await this.getCryptoKey(), encodedPayload, signature)) {
63
+ throw httpError(401, "Invalid user token signature");
64
+ }
65
+ const payload = JSON.parse(base64UrlDecode(encodedPayload));
66
+ const now = Math.floor(Date.now() / 1000);
67
+ if (payload.exp && payload.exp <= now) {
68
+ throw httpError(401, "User token expired");
69
+ }
70
+ if (payload.aud !== "visiblebase:user") {
71
+ throw httpError(401, "Invalid user token audience");
72
+ }
73
+ if (!payload.product_id || !payload.user_id) {
74
+ throw httpError(401, "Invalid user token payload");
75
+ }
76
+ return payload;
77
+ }
78
+ /** 把 ttl 解析成秒数 */
79
+ static parseTTL(ttl) {
80
+ if (typeof ttl === "number" && Number.isFinite(ttl) && ttl > 0) {
81
+ return ttl;
82
+ }
83
+ if (typeof ttl !== "string") {
84
+ throw new TypeError("ttl must be a positive number of seconds or a string like 1h");
85
+ }
86
+ const match = ttl.match(/^(\d+)(s|m|h|d)$/);
87
+ if (!match) {
88
+ throw new Error(`Invalid ttl: ${ttl}`);
89
+ }
90
+ const value = Number(match[1]);
91
+ const unit = match[2];
92
+ const multipliers = {
93
+ s: 1,
94
+ m: 60,
95
+ h: 60 * 60,
96
+ d: 24 * 60 * 60,
97
+ };
98
+ return value * multipliers[unit];
99
+ }
100
+ }
101
+ /**
102
+ * 使用 HMAC-SHA256 对 payload 签名,返回 base64url 编码的签名。
103
+ */
104
+ async function signPayload(cryptoKey, encodedPayload) {
105
+ const signature = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(encodedPayload));
106
+ return base64UrlEncodeBytes(new Uint8Array(signature));
107
+ }
108
+ /**
109
+ * 验证 HMAC-SHA256 签名是否匹配。
110
+ */
111
+ async function verifyPayload(cryptoKey, encodedPayload, signature) {
112
+ const expected = base64UrlDecodeBytes(signature);
113
+ const actual = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(encodedPayload));
114
+ return timingSafeEqualBytes(new Uint8Array(actual), expected);
115
+ }
116
+ //# sourceMappingURL=token-signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-signer.js","sourceRoot":"","sources":["../../../src/core/auth/token-signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Auth 域公共类型。
3
+ *
4
+ * 包含 token 相关的用户、载荷和签发结果类型。
5
+ */
6
+ /**
7
+ * Runtime 中的终端用户信息。
8
+ */
9
+ export interface RuntimeUser {
10
+ /**
11
+ * 开发者系统中的用户主键。
12
+ */
13
+ user_id: string;
14
+ /**
15
+ * 附带在 token 中的业务元数据。
16
+ */
17
+ metadata?: Record<string, unknown>;
18
+ }
19
+ /**
20
+ * 签发 user_token 的输入。
21
+ */
22
+ export interface CreateUserTokenInput {
23
+ /**
24
+ * token 所属的 Product ID。
25
+ */
26
+ product_id: string;
27
+ /**
28
+ * token 所属的终端用户 ID。
29
+ */
30
+ user_id: string;
31
+ /**
32
+ * 附带进 token 的业务元数据。
33
+ */
34
+ metadata?: Record<string, unknown>;
35
+ /**
36
+ * token 有效期。
37
+ *
38
+ * 支持 `30m`、`1h`、`7d` 或秒数。
39
+ */
40
+ ttl?: string | number;
41
+ }
42
+ /**
43
+ * user_token 的标准载荷。
44
+ */
45
+ export interface UserTokenPayload {
46
+ /**
47
+ * token 受众。
48
+ */
49
+ aud: "visiblebase:user";
50
+ /**
51
+ * token 所属 Product ID。
52
+ */
53
+ product_id: string;
54
+ /**
55
+ * token 所属用户 ID。
56
+ */
57
+ user_id: string;
58
+ /**
59
+ * 业务元数据。
60
+ */
61
+ metadata?: Record<string, unknown>;
62
+ /**
63
+ * 签发时间。
64
+ */
65
+ iat: number;
66
+ /**
67
+ * 过期时间。
68
+ */
69
+ exp?: number;
70
+ }
71
+ /**
72
+ * Base 返回给管理端的发 token 结果。
73
+ */
74
+ export interface UserTokenIssueResult {
75
+ /**
76
+ * 可交给 UserClient 使用的 token。
77
+ */
78
+ user_token: string;
79
+ /**
80
+ * token 所属 Product ID。
81
+ */
82
+ product_id: string;
83
+ /**
84
+ * token 所属用户 ID。
85
+ */
86
+ user_id: string;
87
+ /**
88
+ * token 过期时间。
89
+ *
90
+ * 未设置 ttl 时省略。
91
+ */
92
+ expires_at?: string;
93
+ }
94
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,GAAG,EAAE,kBAAkB,CAAC;IAExB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Auth 域公共类型。
3
+ *
4
+ * 包含 token 相关的用户、载荷和签发结果类型。
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Base Runtime 主模块。
3
+ *
4
+ * Base 是运行时容器,只负责:Service 路由、鉴权、HTTP。
5
+ * 不知道任何具体 Service 的实现,所有 Service 通过 _onInit() 自初始化。
6
+ *
7
+ * 数据库连接、环境变量存储等运行时特定逻辑由 Runtime 适配器注入。
8
+ *
9
+ * 使用方式:
10
+ * ```ts
11
+ * import { Base } from "@visiblebase/core";
12
+ * import { node } from "@visiblebase/node";
13
+ *
14
+ * const base = new Base({ runtime: node({ database: "sqlite:./data.sqlite" }) });
15
+ * base.use(new AIService());
16
+ * // 路由始终是标准 Hono app
17
+ * serve({ fetch: base.router().fetch, port: 3000 });
18
+ * ```
19
+ */
20
+ import { Hono } from "hono";
21
+ import { type BaseTableApi } from "../../store/table-api.js";
22
+ import { Service } from "../../service/service.js";
23
+ import { type BasePlugin } from "../../service/plugin.js";
24
+ import { Authenticator } from "../auth/authenticator.js";
25
+ import type { BaseOptions, BaseHealthStatus } from "../types.js";
26
+ import type { RuntimeUser } from "../auth/types.js";
27
+ declare module "hono" {
28
+ interface ContextVariableMap {
29
+ user?: RuntimeUser;
30
+ product?: {
31
+ product_id: string;
32
+ status: string;
33
+ };
34
+ }
35
+ }
36
+ /**
37
+ * VisibleBase 运行时容器。
38
+ *
39
+ * 接收 Service 注册、构建 Hono 路由、管理初始化生命周期。
40
+ * 数据库和 env 通过 Runtime 适配器注入,不依赖任何特定运行时。
41
+ */
42
+ export declare class Base {
43
+ private readonly runtime;
44
+ private readonly services;
45
+ private database?;
46
+ private client?;
47
+ private tableMap?;
48
+ private initPromise?;
49
+ private hono?;
50
+ private authenticator?;
51
+ constructor(options: BaseOptions);
52
+ /**
53
+ * 注册一个 Service。
54
+ *
55
+ * Service 在 Base 初始化时自动获得数据库、鉴权器、env 等基础设施。
56
+ */
57
+ use(svc: Service | BasePlugin): this;
58
+ /** 获取指定 ID 的 Service */
59
+ getService(id: string): Service | undefined;
60
+ /** 获取所有已注册的 Service */
61
+ getServices(): Service[];
62
+ getAuthenticator(): Promise<Authenticator>;
63
+ /**
64
+ * 获取指定名称的数据库表 API。
65
+ *
66
+ * @param name - 表名(格式为 "service_id.table_name" 或内置表名)
67
+ */
68
+ table<TRow extends Record<string, unknown> = Record<string, unknown>>(name: string): Promise<BaseTableApi<TRow>>;
69
+ /**
70
+ * 获取 Hono 路由实例(需先完成初始化)。
71
+ *
72
+ * 路由可以直接挂载到任何支持 fetch 的 HTTP 服务器:
73
+ * ```ts
74
+ * // Node.js
75
+ * serve({ fetch: base.router().fetch, port: 3000 });
76
+ *
77
+ * // Cloudflare Workers
78
+ * export default { fetch: base.router().fetch };
79
+ * ```
80
+ */
81
+ router(): Hono;
82
+ /**
83
+ * 直接处理一个 Request(用于 Serverless 场景)。
84
+ */
85
+ handleRequest(request: Request): Promise<Response>;
86
+ /**
87
+ * 健康检查。
88
+ */
89
+ health(): Promise<BaseHealthStatus>;
90
+ private initialize;
91
+ private collectServiceSchemas;
92
+ private buildHono;
93
+ private ensureReady;
94
+ private requireReadySync;
95
+ private requireReady;
96
+ }
97
+ export { Base as VisibleBase };
98
+ //# sourceMappingURL=base.d.ts.map