@taicode/common-server 3.8.0 → 4.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.
Files changed (145) hide show
  1. package/output/app/auth.test.d.ts +2 -0
  2. package/output/app/auth.test.d.ts.map +1 -0
  3. package/output/app/auth.test.js +148 -0
  4. package/output/app/boot.d.ts +48 -0
  5. package/output/app/boot.d.ts.map +1 -0
  6. package/output/app/boot.js +123 -0
  7. package/output/app/config.test.d.ts +2 -0
  8. package/output/app/config.test.d.ts.map +1 -0
  9. package/output/app/config.test.js +132 -0
  10. package/output/app/context.d.ts +68 -0
  11. package/output/app/context.d.ts.map +1 -0
  12. package/output/app/context.js +73 -0
  13. package/output/app/core/cookie.d.ts +25 -0
  14. package/output/app/core/cookie.d.ts.map +1 -0
  15. package/output/app/core/cookie.js +22 -0
  16. package/output/app/core/identity.d.ts +12 -0
  17. package/output/app/core/identity.d.ts.map +1 -0
  18. package/output/app/core/identity.js +14 -0
  19. package/output/app/core/index.d.ts +44 -0
  20. package/output/app/core/index.d.ts.map +1 -0
  21. package/output/app/core/index.js +57 -0
  22. package/output/app/core/logging.d.ts +13 -0
  23. package/output/app/core/logging.d.ts.map +1 -0
  24. package/output/app/core/logging.js +29 -0
  25. package/output/app/core/openapi.d.ts +17 -0
  26. package/output/app/core/openapi.d.ts.map +1 -0
  27. package/output/app/core/openapi.js +42 -0
  28. package/output/app/core/request-id.d.ts +36 -0
  29. package/output/app/core/request-id.d.ts.map +1 -0
  30. package/output/app/core/request-id.js +66 -0
  31. package/output/app/core/response.d.ts +41 -0
  32. package/output/app/core/response.d.ts.map +1 -0
  33. package/output/app/core/response.js +89 -0
  34. package/output/app/define-server.negative-cases.d.ts +32 -0
  35. package/output/app/define-server.negative-cases.d.ts.map +1 -0
  36. package/output/app/define-server.negative-cases.js +209 -0
  37. package/output/app/define-server.test.js +86 -288
  38. package/output/app/entries.d.ts +29 -0
  39. package/output/app/entries.d.ts.map +1 -0
  40. package/output/app/entries.js +64 -0
  41. package/output/app/env.d.ts +39 -4
  42. package/output/app/env.d.ts.map +1 -1
  43. package/output/app/env.js +32 -4
  44. package/output/app/env.test.js +67 -21
  45. package/output/app/error-contract.test.d.ts +2 -0
  46. package/output/app/error-contract.test.d.ts.map +1 -0
  47. package/output/app/error-contract.test.js +125 -0
  48. package/output/app/errors.d.ts +20 -0
  49. package/output/app/errors.d.ts.map +1 -0
  50. package/output/app/errors.js +51 -0
  51. package/output/app/generate-openapi.test.d.ts +2 -0
  52. package/output/app/generate-openapi.test.d.ts.map +1 -0
  53. package/output/app/generate-openapi.test.js +123 -0
  54. package/output/app/index.d.ts +15 -15
  55. package/output/app/index.d.ts.map +1 -1
  56. package/output/app/index.js +18 -9
  57. package/output/app/lifecycle-logging.test.d.ts +2 -0
  58. package/output/app/lifecycle-logging.test.d.ts.map +1 -0
  59. package/output/app/lifecycle-logging.test.js +155 -0
  60. package/output/app/lifecycle.d.ts +70 -0
  61. package/output/app/lifecycle.d.ts.map +1 -0
  62. package/output/app/lifecycle.js +99 -0
  63. package/output/app/lifecycle.test.d.ts +2 -0
  64. package/output/app/lifecycle.test.d.ts.map +1 -0
  65. package/output/app/lifecycle.test.js +152 -0
  66. package/output/app/middleware/auth.d.ts +71 -0
  67. package/output/app/middleware/auth.d.ts.map +1 -0
  68. package/output/app/middleware/auth.js +190 -0
  69. package/output/app/middleware/context.d.ts +13 -0
  70. package/output/app/middleware/context.d.ts.map +1 -0
  71. package/output/app/middleware/context.js +15 -0
  72. package/output/app/middleware/cors.d.ts +14 -0
  73. package/output/app/middleware/cors.d.ts.map +1 -0
  74. package/output/app/middleware/cors.js +30 -0
  75. package/output/app/middleware/index.d.ts +17 -0
  76. package/output/app/middleware/index.d.ts.map +1 -0
  77. package/output/app/middleware/index.js +16 -0
  78. package/output/app/middleware/rate-limit.d.ts +24 -0
  79. package/output/app/middleware/rate-limit.d.ts.map +1 -0
  80. package/output/app/middleware/rate-limit.js +46 -0
  81. package/output/app/middleware-order.test.d.ts +2 -0
  82. package/output/app/middleware-order.test.d.ts.map +1 -0
  83. package/output/app/middleware-order.test.js +148 -0
  84. package/output/app/permission-operations.d.ts +48 -0
  85. package/output/app/permission-operations.d.ts.map +1 -0
  86. package/output/app/permission-operations.js +77 -0
  87. package/output/app/permission-operations.test.d.ts +2 -0
  88. package/output/app/permission-operations.test.d.ts.map +1 -0
  89. package/output/app/permission-operations.test.js +72 -0
  90. package/output/app/permission-registration.test.d.ts +2 -0
  91. package/output/app/permission-registration.test.d.ts.map +1 -0
  92. package/output/app/permission-registration.test.js +138 -0
  93. package/output/app/redis.d.ts +45 -0
  94. package/output/app/redis.d.ts.map +1 -0
  95. package/output/app/redis.js +61 -0
  96. package/output/app/registered-operations.test.d.ts +2 -0
  97. package/output/app/registered-operations.test.d.ts.map +1 -0
  98. package/output/app/registered-operations.test.js +57 -0
  99. package/output/app/request-id.test.d.ts +2 -0
  100. package/output/app/request-id.test.d.ts.map +1 -0
  101. package/output/app/request-id.test.js +130 -0
  102. package/output/app/resources.test.d.ts +2 -0
  103. package/output/app/resources.test.d.ts.map +1 -0
  104. package/output/app/resources.test.js +197 -0
  105. package/output/app/shutdown.d.ts +17 -4
  106. package/output/app/shutdown.d.ts.map +1 -1
  107. package/output/app/shutdown.js +27 -12
  108. package/output/app/shutdown.test.js +78 -124
  109. package/output/app/signal.d.ts +4 -4
  110. package/output/app/signal.d.ts.map +1 -1
  111. package/output/app/signal.js +3 -3
  112. package/output/app/smoke.test.d.ts +2 -0
  113. package/output/app/smoke.test.d.ts.map +1 -0
  114. package/output/app/smoke.test.js +210 -0
  115. package/output/app/test-support.d.ts +21 -0
  116. package/output/app/test-support.d.ts.map +1 -0
  117. package/output/app/test-support.js +24 -0
  118. package/output/app/type-augment.d.ts +34 -0
  119. package/output/app/type-augment.d.ts.map +1 -0
  120. package/output/app/type-augment.js +7 -0
  121. package/output/app/types.d.ts +185 -123
  122. package/output/app/types.d.ts.map +1 -1
  123. package/output/app/types.js +2 -1
  124. package/package.json +10 -6
  125. package/output/app/assemble.d.ts +0 -16
  126. package/output/app/assemble.d.ts.map +0 -1
  127. package/output/app/assemble.js +0 -124
  128. package/output/app/database.d.ts +0 -36
  129. package/output/app/database.d.ts.map +0 -1
  130. package/output/app/database.js +0 -40
  131. package/output/app/database.test.d.ts +0 -2
  132. package/output/app/database.test.d.ts.map +0 -1
  133. package/output/app/database.test.js +0 -66
  134. package/output/app/default-modules.d.ts +0 -23
  135. package/output/app/default-modules.d.ts.map +0 -1
  136. package/output/app/default-modules.js +0 -40
  137. package/output/app/define-server.d.ts +0 -12
  138. package/output/app/define-server.d.ts.map +0 -1
  139. package/output/app/define-server.js +0 -289
  140. package/output/app/module.d.ts +0 -88
  141. package/output/app/module.d.ts.map +0 -1
  142. package/output/app/module.js +0 -34
  143. package/output/app/steps.d.ts +0 -17
  144. package/output/app/steps.d.ts.map +0 -1
  145. package/output/app/steps.js +0 -41
@@ -1,33 +1,37 @@
1
1
  import type { Disposer } from '@taicode/common-base';
2
- import type { FastifyInstance, FastifyPluginAsync } from 'fastify';
3
- import type { ModuleAssembly } from './module.js';
4
- import type { ShutdownStepName } from './shutdown.js';
5
- import type { StepName } from './steps.js';
6
- /** 原生 Fastify 实例,原样返回(不包 `fastify-plugin`、不返回包装对象) */
7
- export type ServerInstance = FastifyInstance;
8
- export type ServerMode = 'production' | 'test' | 'openapi-build';
9
- /** 错误工厂:由各服务 `errors.ts` 的 `define()` 产出(`class extends Error`) */
10
- export type ErrorFactory = new (...args: never[]) => Error;
11
- export interface ErrorFactories {
12
- UserError: ErrorFactory;
13
- SystemError: ErrorFactory;
14
- }
15
- /** 运行时配置快照(对应各仓导出的 `config` 常量) */
16
- export interface RuntimeConfig {
17
- debug: boolean;
18
- port: number;
19
- }
2
+ import type { FastifyBaseLogger, FastifyInstance, RawServerDefault } from 'fastify';
3
+ import type { ZodTypeProvider } from 'fastify-type-provider-zod';
4
+ import type { IncomingMessage, ServerResponse } from 'node:http';
5
+ import type { ConfigEnv } from './env.js';
20
6
  /**
21
- * 配置模块端口(design §4.2)。`loadConfig` 必填;依赖数据层的服务才需要 `loadPostgresConfig`。
7
+ * `defineServer` 槽位口径与接口类型(N1 / N2,**唯一规格来源**)。
8
+ *
9
+ * 顶层是「一个身份块 + 五个工厂槽位」,**键顺序即分层**:
10
+ *
11
+ * ```
12
+ * app (身份块,无依赖)
13
+ * resources ← env 引导期:唯一读 env 的地方
14
+ * config ← env + resources 引导期:❗不给 services(结构性解耦)
15
+ * services ← resources + config 运行期开始:❗不给 env、不给 services
16
+ * middlewares ← app + services + config (不给 resources / env)
17
+ * routers ← app + services (不给 resources / env / config)
18
+ * ```
19
+ *
20
+ * 槽位只能引用**排在它前面**的产物(向下引用是编译错误);`env` 只属引导期
21
+ * (`resources` / `config` 可见,运行期三层一律看不到)。
22
+ *
23
+ * 类型安全机制(N2 §1):
24
+ * - **M1 分阶段 ctx**:每个工厂只拿到「该阶段该看的字段」;
25
+ * - **M2 `Awaited<>` 归一**:工厂签名写 `(ctx) => R`(不是 `R | Promise<R>`),下游一律
26
+ * `Awaited<R>` / `Awaited<C>` / `Awaited<S>`;
27
+ * - **M3 资源嵌套**:资源包挂在 `ctx.resources` 上(不再摊平到 ctx,键冲突从根上消失);
28
+ * - **M4 `Live<T>` 静态开关**:资源包里值为 `false` 的键在类型上剔除;
29
+ * - **M5 强类型 `services`**:`middlewares` / `routers` 的 `ctx.services` 是 `S` 实体;
30
+ * - **M6 品牌 + 类型守卫**:`Server` 带品牌,`isServer()` 收窄;
31
+ * - **M7 负向类型测试**:`define-server.negative-cases.ts`,由 `tsc --noEmit` 覆盖。
22
32
  *
23
- * 骨架不替调用方加载 env —— 请先自行调用 `loadEnvFiles()`(详见 `./env.js`)。
33
+ * 命名全拼:`requestId` / `database` / `configuration` / `service`(不用 `db` / `cfg`)。
24
34
  */
25
- export interface ConfigModule {
26
- loadConfig: () => RuntimeConfig;
27
- loadPostgresConfig?: () => unknown | Promise<unknown>;
28
- resolveRedisUrl?: () => string | undefined;
29
- resolveCachePrefix?: () => string | undefined;
30
- }
31
35
  /** 骨架只按 `(obj, msg)` 形态打日志;`app.log` 与 `@taicode/common-base` 的 `Logger` 都满足 */
32
36
  export interface LoggerLike {
33
37
  debug: (obj: unknown, msg?: string) => void;
@@ -35,115 +39,173 @@ export interface LoggerLike {
35
39
  warn: (obj: unknown, msg?: string) => void;
36
40
  error: (obj: unknown, msg?: string) => void;
37
41
  }
42
+ /** 同步或异步(`Awaited<>` 归一的原料) */
43
+ export type MaybePromise<T> = T | Promise<T>;
38
44
  /**
39
- * 骨架**不操作** Redis 命令,只持有并在关闭时透传 dispose;
40
- * 因此保持开放类型,各仓注入自己的客户端(如 node-redis)不受约束。
45
+ * 路由级类型安全的载体:带 `ZodTypeProvider` 的 `FastifyInstance`。
46
+ *
47
+ * 裸 `FastifyInstance` 会让路由的 `params` / `body` / `query` 全是 `unknown`;带上 provider 后
48
+ * `request.params.id` 有类型。
41
49
  */
42
- export type RedisLike = unknown;
43
- export interface RedisHandle {
44
- client: RedisLike;
45
- dispose: () => Promise<void>;
46
- }
47
- export type DisposeFunction = () => unknown;
48
- export type UnsubscribeFunction = () => unknown;
49
- export interface GlobalConfigOptions {
50
- redisUrl?: string;
51
- channelPrefix?: string;
52
- }
53
- /** 贯穿步骤 5/6/8 的依赖上下文 */
54
- export interface DbContext<Db = unknown> {
55
- db: Db;
56
- redis?: RedisLike;
57
- globalConfig: unknown;
58
- }
59
- export interface ServicesContext<S = unknown> {
60
- services: S;
50
+ export type AppInstance = FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse, FastifyBaseLogger, ZodTypeProvider>;
51
+ /**
52
+ * 身份块:非 env 派生,出 spec 路径也要用。
53
+ *
54
+ * `version` **必填、无默认值**(缺它就是编译错误,杜绝「悄悄兜底成 1.0.0」)。
55
+ */
56
+ export interface AppIdentity {
57
+ /** 权限注册键 / cache 前缀 / 失效通道前缀 / 日志标签 */
58
+ readonly service: string;
59
+ readonly title: string;
60
+ /** openapi `info.version` + 权限操作自注册;建议从 package.json 读入 */
61
+ readonly version: string;
61
62
  }
62
- export interface InitContext<Db = unknown, S = unknown> extends DbContext<Db> {
63
- services: S;
63
+ /**
64
+ * Redis 句柄(惰性包装)。
65
+ *
66
+ * 框架**不操作** Redis 命令,只持有并在关闭时透传 dispose;构造时不建连、不 ping。
67
+ * 因此保持开放类型,各仓注入自己的客户端实现不受约束。
68
+ */
69
+ export interface RedisHandle {
70
+ client: unknown;
71
+ dispose: () => void | Promise<void>;
64
72
  }
65
- export interface WorkersContext<Db = unknown, S = unknown> extends DbContext<Db> {
66
- services: S;
67
- disposer: Disposer;
73
+ /**
74
+ * 剔掉值为 `false` 的键(编译期静态开关)。
75
+ *
76
+ * 资源包里写 `cache: false` 表示**静态关闭**:`Live<T>` 里该键**不存在**,访问直接编译失败;
77
+ * 而 `cache: Cache | undefined`(显式可选)表示**运行时缺省**:键存在,类型为 `Cache | undefined`。
78
+ */
79
+ export type Live<T> = {
80
+ [K in keyof T as T[K] extends false ? never : K]: T[K];
81
+ };
82
+ /** 框架在 ctx 上暴露的资源视图(`Awaited<>` 归一 + `false` 键剔除) */
83
+ export type ResourcesView<R> = Live<Awaited<R>>;
84
+ /**
85
+ * `resources(ctx)` 的入参:**只有 `env` + `log`**。
86
+ *
87
+ * 结构上排除 `config` / `services` / `app` → 「资源依赖配置」这类循环**编译期写不出来**。
88
+ */
89
+ export interface ResourcesContext {
90
+ readonly env: ConfigEnv;
91
+ readonly log: LoggerLike;
68
92
  }
69
- export interface ReadyContext<S = unknown> {
70
- app: FastifyInstance;
71
- services: S;
93
+ export type ResourcesFactory<R> = (ctx: ResourcesContext) => R;
94
+ /**
95
+ * `config(ctx)` 的入参:`env` + `log` + 资源视图。
96
+ *
97
+ * **没有** `services`(此时尚未构造)/ `app`(此时尚未装配)。
98
+ */
99
+ export interface ConfigContext<R> {
100
+ readonly env: ConfigEnv;
101
+ readonly log: LoggerLike;
102
+ readonly resources: ResourcesView<R>;
72
103
  }
73
- export interface ServerOptions {
74
- port: number;
75
- host?: string;
104
+ export type ConfigFactory<R, C> = (ctx: ConfigContext<R>) => C;
105
+ /**
106
+ * 一个 service 值:可选实现 `init` / `dispose`。
107
+ *
108
+ * **没有 `name` / `dependsOn`**:名字用对象键,依赖不存在(`services` ctx 没有 `services` 字段,
109
+ * 编译期禁止互依)。顺序语义只有一条:按**对象声明序** `init` / **逆序** `dispose`。
110
+ */
111
+ export interface ServiceUnit {
112
+ init?(): void | Promise<void>;
113
+ dispose?(): void | Promise<void>;
76
114
  }
77
- export type ResolveMessage = (type: string, context: unknown, explicit?: string) => string | undefined;
78
- export type MapStatus = (type: string) => number | null;
79
- /** 骨架内部持有的运行时句柄(配置 / 关闭流程用) */
80
- export interface RuntimeState {
81
- app?: FastifyInstance;
82
- db?: unknown;
83
- redis?: RedisHandle;
84
- globalConfig?: unknown;
85
- services?: unknown;
86
- disposer: Disposer;
87
- unsubscribe?: UnsubscribeFunction;
88
- disposeConfig?: DisposeFunction;
115
+ /**
116
+ * `services(ctx)` 的入参:`log` + `disposer` + `resources` + `config`。
117
+ *
118
+ * ❗**故意没有 `env`**(服务层属运行期,不得读 env);❗**故意没有 `services`**(禁 service 互依)。
119
+ */
120
+ export interface ServiceContext<R, C> {
121
+ readonly log: LoggerLike;
122
+ readonly disposer: Disposer;
123
+ readonly resources: ResourcesView<R>;
124
+ readonly config: Awaited<C>;
89
125
  }
90
- /** 每个步骤执行时拿到的上下文(`log` 在 `createFastify` 之后默认降级/升级为 `app.log`) */
91
- export interface StepContext {
92
- options: DefineServerOptions;
93
- state: RuntimeState;
94
- log: LoggerLike;
126
+ export type ServicesFactory<R, C, S> = (ctx: ServiceContext<R, C>) => S;
127
+ /**
128
+ * 中间件单元:一个注册函数(`register(app)`),按**数组序**注册。
129
+ *
130
+ * `name` 仅用于报错定位 / 日志跟踪;**不参与生命周期**(要常驻资源就放 `services`)。
131
+ */
132
+ export interface MiddlewareUnit {
133
+ readonly name?: string;
134
+ register(app: AppInstance): void | Promise<void>;
95
135
  }
96
- export type StepRunner = (ctx: StepContext) => unknown | Promise<unknown>;
97
- export type StepImplementations = Record<StepName, StepRunner>;
98
- export type ShutdownRunner = (ctx: StepContext) => unknown | Promise<unknown>;
99
- export type ShutdownImplementations = Record<ShutdownStepName, ShutdownRunner>;
100
- /** 模块可贡献的生命周期 hook(design §4.2) */
101
- export interface ServerHooks {
102
- beforeShutdown?: () => unknown | Promise<unknown>;
103
- shutdown?: (signal: string) => unknown | Promise<unknown>;
104
- disposeServices?: (ctx: ServicesContext) => unknown | Promise<unknown>;
105
- disposeClients?: () => unknown | Promise<unknown>;
136
+ /**
137
+ * `middlewares(ctx)` 的入参:`app` + `log` + `services` + `config`。
138
+ *
139
+ * ❗**故意没有 `resources` / `env`** —— 中间件要访问数据层必须穿过 service。
140
+ */
141
+ export interface MiddlewareContext<C, S> {
142
+ readonly app: AppInstance;
143
+ readonly log: LoggerLike;
144
+ readonly services: Awaited<S>;
145
+ readonly config: Awaited<C>;
106
146
  }
147
+ export type MiddlewaresFactory<C, S> = (ctx: MiddlewareContext<C, S>) => MiddlewareUnit[];
107
148
  /**
108
- * `defineServer()` 入参(design §3.4)。
149
+ * `routers(ctx)` 的入参:`app` + `log` + `services`。
109
150
  *
110
- * `Db` 由 `modules.database`(`database` 模块的 `createClient` 返回类型)**推断**(决策 10-2),
111
- * 因此调用方**不需要**在 `createServices` 里写 `as PrismaClient` 强转。
151
+ * ❗**故意没有 `resources` / `env` / `config`** —— 路由**只能穿过 service**,绕不过层直连数据层。
112
152
  */
113
- export interface DefineServerOptions<Db = unknown, S = unknown> {
114
- serviceName: string;
115
- title: string;
116
- description: string;
117
- version?: string;
118
- mode?: ServerMode;
119
- serverOptions?: ServerOptions;
120
- serverUrl?: string | (() => string | null);
121
- openapiVersion?: string;
122
- docPath?: string;
123
- log?: LoggerLike;
124
- signal?: boolean;
125
- errors: ErrorFactories;
126
- messages?: Record<string, string>;
127
- resolveMessage?: ResolveMessage;
128
- mapStatus?: MapStatus;
129
- modules?: ModuleAssembly<Db>;
130
- config: ConfigModule;
131
- setupCompilers?: (app: FastifyInstance) => void;
132
- createRedis?: (config: ConfigModule) => RedisHandle | undefined;
133
- initGlobalConfig?: (db: Db, opts: GlobalConfigOptions) => void | DisposeFunction;
134
- onGlobalConfigChange?: (globalConfig: unknown) => void;
135
- initClients?: (ctx: DbContext<Db>) => Promise<void | UnsubscribeFunction>;
136
- extraPlugins?: FastifyPluginAsync[];
137
- createServices: (ctx: DbContext<Db>) => S;
138
- initServices?: (ctx: ServicesContext<S>) => Promise<void>;
139
- backgroundWorkers?: (ctx: WorkersContext<Db, S>) => Promise<void>;
140
- registerRouters: (app: FastifyInstance, ctx: ServicesContext<S>) => Promise<void> | void;
141
- afterInit?: (ctx: InitContext<Db, S>) => Promise<DisposeFunction | void>;
142
- afterReady?: (ctx: ReadyContext<S>) => Promise<void>;
143
- beforeShutdown?: () => Promise<void> | void;
144
- disposeServices?: (ctx: ServicesContext<S>) => Promise<void> | void;
145
- disposeClients?: () => Promise<void> | void;
146
- /** 覆盖默认关闭流程(design §3.4 / §5) */
147
- shutdown?: (signal: string) => Promise<void> | void;
153
+ export interface RouterContext<S> {
154
+ readonly app: AppInstance;
155
+ readonly log: LoggerLike;
156
+ readonly services: Awaited<S>;
148
157
  }
158
+ export type RoutersFactory<S> = (ctx: RouterContext<S>) => void | Promise<void>;
159
+ /**
160
+ * 若某个 service 值声明了 `dependsOn`,该值类型塌成 `never` → 赋值报错。
161
+ */
162
+ export type AssertNoDependencies<S> = {
163
+ [K in keyof S]: S[K] extends {
164
+ dependsOn: unknown;
165
+ } ? never : S[K];
166
+ };
167
+ /**
168
+ * `services` 返回值形状闸门:
169
+ * - 原始类型值(`string` / `number` / `boolean`)**拒绝**(防把配置塞进 services);
170
+ * - 声明了 `dependsOn` 的值**拒绝**(禁 service 互依)。
171
+ */
172
+ export type ServicesShape<S> = {
173
+ [K in keyof S]: S[K] extends string | number | boolean ? never : S[K] extends {
174
+ dependsOn: unknown;
175
+ } ? never : S[K];
176
+ };
177
+ /**
178
+ * `defineServer()` 入参:一个身份块 + 五个工厂槽位(键顺序=分层)。
179
+ *
180
+ * `S` 上的两道闸门(`ServicesShape<S>`,N2 §2.5)写在 `services` 的返回类型上:
181
+ * `S & ServicesShape<S>` —— 形状合法时恒等,非法时该值塌成 `never` → 编译失败。
182
+ */
183
+ export interface ServerConfig<R, C, S> {
184
+ app: AppIdentity;
185
+ resources: ResourcesFactory<R>;
186
+ config: ConfigFactory<NoInfer<R>, C>;
187
+ services: (ctx: ServiceContext<NoInfer<R>, NoInfer<C>>) => S & ServicesShape<S>;
188
+ middlewares: MiddlewaresFactory<NoInfer<C>, NoInfer<S>>;
189
+ routers: RoutersFactory<NoInfer<S>>;
190
+ }
191
+ /** 品牌字段值(`Server` 的 `__brand`) */
192
+ export declare const SERVER_BRAND = "taicode.server";
193
+ /** 纯定义产物:同一份定义可同时喂给「启动」与「出 spec」 */
194
+ export type Server<R, C, S> = ServerConfig<R, C, S> & {
195
+ readonly __brand: typeof SERVER_BRAND;
196
+ };
197
+ /** `startServer()` 的逃生选项 */
198
+ export interface StartServerOptions<R = unknown, C = unknown, S = unknown> {
199
+ /** 是否 listen + 装信号;默认 `NODE_ENV !== 'test'` */
200
+ listen?: boolean;
201
+ /** 整体覆盖关闭流程 */
202
+ shutdown?: (ctx: ShutdownContext<R, C, S>) => Promise<void>;
203
+ }
204
+ /** 关闭阶段视图:`services` ctx + `app` + `services` 实体 */
205
+ export interface ShutdownContext<R, C, S> extends ServiceContext<R, C> {
206
+ readonly app: AppInstance;
207
+ readonly services: Awaited<S>;
208
+ }
209
+ /** `generateOpenApi()` 的返回(OpenAPI 文档对象) */
210
+ export type OpenApiDocument = Record<string, unknown>;
149
211
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../source/app/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../source/app/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1,2 @@
1
- export {};
1
+ /** 品牌字段值(`Server` 的 `__brand`) */
2
+ export const SERVER_BRAND = 'taicode.server';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taicode/common-server",
3
- "version": "3.8.0",
3
+ "version": "4.0.0-beta.1",
4
4
  "author": "Alain",
5
5
  "license": "ISC",
6
6
  "description": "",
@@ -24,13 +24,18 @@
24
24
  "output"
25
25
  ],
26
26
  "dependencies": {
27
- "dotenv": "^17.3.1"
27
+ "@fastify/cookie": "^11",
28
+ "@fastify/cors": "^11",
29
+ "@fastify/swagger": "^9",
30
+ "@scalar/fastify-api-reference": "^1",
31
+ "dotenv": "^17.3.1",
32
+ "fastify-type-provider-zod": "^6",
33
+ "zod": "^4.3.6"
28
34
  },
29
35
  "peerDependencies": {
30
36
  "fastify": "^5.5.0",
31
37
  "redis": "^5.11.0",
32
- "zod": "^4.1.0",
33
- "@taicode/common-base": "^3.8.0"
38
+ "@taicode/common-base": "^4.0.0-beta.1"
34
39
  },
35
40
  "devDependencies": {
36
41
  "@eslint/js": "^9.39.3",
@@ -44,8 +49,7 @@
44
49
  "redis": "^5.11.0",
45
50
  "typescript-eslint": "^8.56.1",
46
51
  "vitest": "^3.2.4",
47
- "zod": "^4.3.6",
48
- "@taicode/common-base": "^3.8.0"
52
+ "@taicode/common-base": "^4.0.0-beta.1"
49
53
  },
50
54
  "scripts": {
51
55
  "test": "vitest run",
@@ -1,16 +0,0 @@
1
- import type { DatabaseModule, ModuleAssembly, ModuleName, ServerModule } from './module.js';
2
- /** 装配结果:注册顺序、按名索引、被 `false` 跳过的名字、以及数据层模块句柄 */
3
- export interface ResolvedModules {
4
- order: ModuleName[];
5
- byName: Partial<Record<ModuleName, ServerModule>>;
6
- disabled: ModuleName[];
7
- database?: DatabaseModule;
8
- }
9
- /**
10
- * 装配期校验 + 槽位解析(design §3.2)。
11
- *
12
- * 报错**发生在 `defineServer()` 装配阶段**(返回 promise resolve 之前),不拖到 `listen` 才炸。
13
- * 校验顺序:未知名 → 重复 / 键名不符 → 依赖被跳过 / 依赖环 → 未实现模块未显式 false → database 未提供。
14
- */
15
- export declare function assembleModules(assembly?: ModuleAssembly): ResolvedModules;
16
- //# sourceMappingURL=assemble.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../../source/app/assemble.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE3F,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAA;IACjD,QAAQ,EAAE,UAAU,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,cAAc,CAAA;CAC1B;AA2HD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,eAAe,CAQ1E"}
@@ -1,124 +0,0 @@
1
- import { createDefaultModules } from './default-modules.js';
2
- import { MODULE_NAMES, PENDING_MODULES } from './module.js';
3
- function isModuleName(value) {
4
- return MODULE_NAMES.includes(value);
5
- }
6
- function assertKnownNames(provided) {
7
- for (const key of Object.keys(provided)) {
8
- if (!isModuleName(key)) {
9
- throw new Error(`Unknown module "${key}". Allowed: ${MODULE_NAMES.join(', ')}`);
10
- }
11
- }
12
- }
13
- function assertNamesMatch(provided) {
14
- const seen = new Set();
15
- for (const key of Object.keys(provided)) {
16
- const value = provided[key];
17
- if (value === undefined || value === false) {
18
- continue;
19
- }
20
- if (seen.has(value.name)) {
21
- throw new Error(`Module "${value.name}" registered twice`);
22
- }
23
- if (value.name !== key) {
24
- throw new Error(`Module key "${key}" != module.name "${value.name}"`);
25
- }
26
- seen.add(value.name);
27
- }
28
- }
29
- function assertNoCycles(provided) {
30
- const visiting = new Set();
31
- const visited = new Set();
32
- function visit(name, path) {
33
- if (visited.has(name)) {
34
- return;
35
- }
36
- if (visiting.has(name)) {
37
- throw new Error(`Module dependency cycle detected: ${[...path, name].join(' -> ')}`);
38
- }
39
- visiting.add(name);
40
- const value = provided[name];
41
- const deps = value === undefined || value === false ? [] : value.dependsOn ?? [];
42
- for (const dep of deps) {
43
- if (isModuleName(dep)) {
44
- visit(dep, [...path, name]);
45
- }
46
- }
47
- visiting.delete(name);
48
- visited.add(name);
49
- }
50
- for (const key of Object.keys(provided)) {
51
- if (isModuleName(key)) {
52
- visit(key, []);
53
- }
54
- }
55
- }
56
- function assertDependencies(provided) {
57
- for (const key of Object.keys(provided)) {
58
- const value = provided[key];
59
- if (value === undefined || value === false) {
60
- continue;
61
- }
62
- for (const dep of value.dependsOn ?? []) {
63
- if (!isModuleName(dep)) {
64
- throw new Error(`Module "${value.name}" depends on unknown module "${dep}"`);
65
- }
66
- if (provided[dep] === false) {
67
- throw new Error(`Module "${value.name}" depends on "${dep}" which is disabled`);
68
- }
69
- }
70
- }
71
- assertNoCycles(provided);
72
- }
73
- function assertPendingProvided(provided) {
74
- for (const [name, stage] of Object.entries(PENDING_MODULES)) {
75
- if (provided[name] === undefined) {
76
- throw new Error(`Module "${name}" is not implemented until ${stage}; pass false to opt out`);
77
- }
78
- }
79
- }
80
- function assertDatabaseProvided(provided) {
81
- if (provided.database === undefined) {
82
- throw new Error('Module "database" requires createPrismaDatabaseModule({...}) or false');
83
- }
84
- }
85
- function resolveModules(provided) {
86
- const defaults = createDefaultModules();
87
- const byName = {};
88
- const disabled = [];
89
- for (const name of MODULE_NAMES) {
90
- const value = provided[name];
91
- if (value === false) {
92
- disabled.push(name);
93
- continue;
94
- }
95
- if (value) {
96
- byName[name] = value;
97
- continue;
98
- }
99
- const fallback = defaults[name];
100
- if (fallback) {
101
- byName[name] = fallback;
102
- }
103
- }
104
- const order = MODULE_NAMES.filter((name) => byName[name] !== undefined);
105
- const candidate = byName.database;
106
- // `database` 已由 `assertDatabaseProvided` 强制显式:走到这里要么是 `DatabaseModule`,要么是 `false`
107
- const database = typeof candidate?.createClient === 'function' ? candidate : undefined;
108
- return { order, byName, disabled, database };
109
- }
110
- /**
111
- * 装配期校验 + 槽位解析(design §3.2)。
112
- *
113
- * 报错**发生在 `defineServer()` 装配阶段**(返回 promise resolve 之前),不拖到 `listen` 才炸。
114
- * 校验顺序:未知名 → 重复 / 键名不符 → 依赖被跳过 / 依赖环 → 未实现模块未显式 false → database 未提供。
115
- */
116
- export function assembleModules(assembly) {
117
- const provided = (assembly ?? {});
118
- assertKnownNames(provided);
119
- assertNamesMatch(provided);
120
- assertDependencies(provided);
121
- assertPendingProvided(provided);
122
- assertDatabaseProvided(provided);
123
- return resolveModules(provided);
124
- }
@@ -1,36 +0,0 @@
1
- import type { DatabaseClientParams, DatabaseModule, PrismaErrorConstructors, PrismaOperationLabels } from './module.js';
2
- export interface PrismaDatabaseModuleParams<Ctor extends new (...args: never[]) => unknown> {
3
- /**
4
- * 各仓生成的 client 构造函数(`@prisma/generated/*`)——**只能由各仓经参数注入**,
5
- * common 不引用任何具体生成产物(决策 #8)。
6
- */
7
- PrismaClient: Ctor;
8
- /**
9
- * 各仓生成的命名空间(`instanceof` 判定用;跨包 `instanceof` 不可靠,决策 #9)。
10
- */
11
- PrismaNamespace: PrismaErrorConstructors;
12
- /** 可选:覆盖 operation 标签;不传则用 common 默认集 */
13
- operationLabels?: PrismaOperationLabels;
14
- /**
15
- * 可选:构造 Prisma client 的参数工厂。
16
- *
17
- * common **不依赖** `@prisma/client` 与其驱动适配器(如 `@prisma/adapter-pg`),
18
- * 由调用方注入构造参数,例如:
19
- *
20
- * ```ts
21
- * createClientArgs: (params) => [
22
- * { adapter: new PrismaPg(params.postgresConfig, { schema: (params.postgresConfig as { schema: string }).schema }) },
23
- * ]
24
- * ```
25
- *
26
- * 省略时等价于 `new PrismaClient()`(要求传入的 `PrismaClient` 自身可完成连接)。
27
- */
28
- createClientArgs?: (params: DatabaseClientParams) => unknown[];
29
- }
30
- /**
31
- * `database` 模块的默认实现:Prisma(design §3.3 / 调研 D)。
32
- *
33
- * 返回类型即 `defineServer<Db>` 的 `Db`,调用方据此**推断**类型、无需强转(决策 10-2)。
34
- */
35
- export declare function createPrismaDatabaseModule<Ctor extends new (...args: never[]) => unknown>(params: PrismaDatabaseModuleParams<Ctor>): DatabaseModule<InstanceType<Ctor>>;
36
- //# sourceMappingURL=database.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../source/app/database.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAevH,MAAM,WAAW,0BAA0B,CAAC,IAAI,SAAS,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO;IACxF;;;OAGG;IACH,YAAY,EAAE,IAAI,CAAA;IAClB;;OAEG;IACH,eAAe,EAAE,uBAAuB,CAAA;IACxC,yCAAyC;IACzC,eAAe,CAAC,EAAE,qBAAqB,CAAA;IACvC;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,OAAO,EAAE,CAAA;CAC/D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,SAAS,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EACvF,MAAM,EAAE,0BAA0B,CAAC,IAAI,CAAC,GACvC,cAAc,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CA2BpC"}
@@ -1,40 +0,0 @@
1
- import { SystemError } from '@taicode/common-base';
2
- /** common 默认的统一 operation 标签(design §2.3:抽进 common 时统一口径) */
3
- const DEFAULT_OPERATION_LABELS = {
4
- known: '已知请求错误',
5
- unknown: '未知请求错误',
6
- validation: '参数校验错误',
7
- initialization: '初始化错误',
8
- rustPanic: '引擎崩溃',
9
- };
10
- /**
11
- * `database` 模块的默认实现:Prisma(design §3.3 / 调研 D)。
12
- *
13
- * 返回类型即 `defineServer<Db>` 的 `Db`,调用方据此**推断**类型、无需强转(决策 10-2)。
14
- */
15
- export function createPrismaDatabaseModule(params) {
16
- const labels = { ...DEFAULT_OPERATION_LABELS, ...params.operationLabels };
17
- return {
18
- name: 'database',
19
- createClient: (clientParams) => {
20
- const args = params.createClientArgs ? params.createClientArgs(clientParams) : [];
21
- return Reflect.construct(params.PrismaClient, args);
22
- },
23
- classifyError: (error) => {
24
- const hit = (Ctor, label) => (error instanceof Ctor ? label : null);
25
- const namespace = params.PrismaNamespace;
26
- const label = hit(namespace.PrismaClientKnownRequestError, labels.known) ??
27
- hit(namespace.PrismaClientUnknownRequestError, labels.unknown) ??
28
- hit(namespace.PrismaClientValidationError, labels.validation) ??
29
- hit(namespace.PrismaClientInitializationError, labels.initialization) ??
30
- hit(namespace.PrismaClientRustPanicError, labels.rustPanic);
31
- return label ? new SystemError('DATABASE_ERROR', { operation: label }, label) : null;
32
- },
33
- dispose: async (db) => {
34
- const target = db;
35
- if (typeof target.$disconnect === 'function') {
36
- await target.$disconnect();
37
- }
38
- },
39
- };
40
- }