@supacloud/compiler 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -3
- package/dist/analyze.d.ts +2 -2
- package/dist/cli.js +1958 -561
- package/dist/generate.d.ts +2 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1950 -556
- package/dist/program.d.ts +30 -0
- package/dist/traits.d.ts +32 -0
- package/dist/type-safety.d.ts +9 -0
- package/dist/types.d.ts +73 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @supacloud/compiler
|
|
2
2
|
|
|
3
|
-
SupaCloud 应用静态编译器:读取 `@supacloud/app`
|
|
3
|
+
SupaCloud 应用静态编译器:读取 `@supacloud/app` 装饰器元数据的原生 TypeScript AST,构建 ApplicationGraph,做静态校验,并生成**无反射、无容器**的工厂代码与 manifest。
|
|
4
4
|
|
|
5
5
|
本包不依赖 `@supacloud/app`:AST 只按装饰器名匹配(`Module`/`Injectable`/`Inject`/`Command`/`Query`/`Controller`/`Get`/`Post`/`Put`/`Patch`/`Delete`/`defineModule`/`InjectionToken`),不校验 import 来源。
|
|
6
6
|
|
|
@@ -20,7 +20,12 @@ const result = await compileProject({
|
|
|
20
20
|
rootDir: "/path/to/app", // 项目根(含 tsconfig)
|
|
21
21
|
include: ["**/*.ts"], // 可选,默认 ['**/*.module.ts', '**/*.ts']
|
|
22
22
|
outDir: "/path/to/app/generated", // 生成目录
|
|
23
|
-
strict:
|
|
23
|
+
strict: true, // 同时启用类型安全门,并将 warn 升级为 error
|
|
24
|
+
typeSafety: {
|
|
25
|
+
noAnyInGenerated: true, // 生成的 TS 产物禁止 any
|
|
26
|
+
scanProductionSource: true, // 扫描生产源码的 any/断言/隐式宽化
|
|
27
|
+
exclude: ["src/legacy/**"], // 额外排除的相对 glob
|
|
28
|
+
},
|
|
24
29
|
});
|
|
25
30
|
result.diagnostics; // Diagnostic[]
|
|
26
31
|
result.graph; // ApplicationGraph
|
|
@@ -45,7 +50,7 @@ const diagnostics = validateGraph(graph, /* strict */ false);
|
|
|
45
50
|
|
|
46
51
|
```ts
|
|
47
52
|
interface ApplicationGraph {
|
|
48
|
-
modules: ModuleNode[]; // 模块:providers/controllers/commands/queries/exports/imports
|
|
53
|
+
modules: ModuleNode[]; // 模块:providers/controllers/commands/jobs/queries/aspects/exports/imports
|
|
49
54
|
externalTokens: string[]; // 被依赖但无任何模块提供的 token(平台注入,如 DB_CLIENT、REQUEST_CONTEXT)
|
|
50
55
|
}
|
|
51
56
|
```
|
|
@@ -58,10 +63,16 @@ interface ApplicationGraph {
|
|
|
58
63
|
|
|
59
64
|
- 文件顶部本地声明 `CompiledRoute` / `CompiledController` / `CompiledModule` 接口,不 import 任何外部包。
|
|
60
65
|
- `createCompiledModules()` 按 imports 拓扑序返回模块描述:`{ name, createServices, createRequestScope?, createJobScope?, controllers, commands }`。平台依赖统一由 `createApplication({ deps })` 传入生成工厂。
|
|
66
|
+
- `makeEnvironmentProviders`、`provideToken`、`provideAppInitializer`、`provideEnvironmentInitializer`、`provideRouter` 和 `provideHttpClient` 的可静态展开部分会在 AST 分析阶段展开为普通 provider;不支持静态安全展开的动态参数会产生诊断,不会被静默丢弃。
|
|
61
67
|
- 每个模块一个 `create<Name>Services(deps, imported)`:实例化 application 级 provider;dep 解析顺序为本模块 services > imports 模块导出的 services(`imported.<module>.<key>`)> 平台注入(`deps.<camelName>`)。
|
|
62
68
|
- 含 request 级 provider/controller 的模块额外生成 `create<Name>RequestScope(services, ctx)`:依赖 `REQUEST_CONTEXT`(或 token name `supacloud.request-context`)的参数传 `ctx`,其余经 `services` 解析(运行期负责把 imports 模块导出的 application 服务合并进 `services`);job 级同理生成 `create<Name>JobScope`。
|
|
69
|
+
- 含 request/job 级 provider 或 controller 的模块同时生成异步静态 `create<Name>RequestScope` / `create<Name>JobScope` 与 `destroy<Name>RequestScope(scope)` / `destroy<Name>JobScope(scope)`;factory 在构造中途失败时按编译期确定的逆创建顺序回滚已知 `onDestroy` 方法,不会运行时扫描或解析 Token。
|
|
70
|
+
- `@Host()` 在 EnvironmentInjector 作用域中保留元数据但不改变解析,因为 SupaCloud 没有 Angular 元素注入器树;`@Self()` / `@SkipSelf()` 由静态 factory 按当前 scope 与模块可见性执行。
|
|
71
|
+
- AOP 只支持静态边界:`ModuleOptions.aspects`、`RouteOptions.aspects`、`CommandOptions.aspects` 和 `JobOptions.aspects` 必须是显式数组字面量,元素必须是可解析的函数标识符。生成器会直接 import aspect 并生成固定顺序的 onion chain,不使用 Proxy、Reflect 扫描、动态 pointcut 或运行时注册。
|
|
72
|
+
- 执行顺序为 `module -> route -> command -> commandGovernance -> handler`;Job 使用 `module -> job -> executor -> run/execute`,并在 finally 中销毁 job scope。
|
|
63
73
|
- services 对象的 key 为 token 名的 camelCase:`CaseService → caseService`、`CASE_REPOSITORY → caseRepository`、`LOGGER → logger`。
|
|
64
74
|
- controller 描述静态给出:`{ path, serviceKey, scope, routes: [{ method, path, handler, body?, params?, query?, response? }] }`,schema 直接引用 import 进来的对象。
|
|
75
|
+
- 严格生成模式会对 `application.ts`、可选的 `client.ts` 和 `permissions.ts` 做 AST 扫描,禁止生成 `any`。
|
|
65
76
|
|
|
66
77
|
`<outDir>/app.manifest.json`:`{ version: 1, modules, externalTokens }`,供 CLI graph/explain 使用。
|
|
67
78
|
|
|
@@ -79,10 +90,30 @@ interface ApplicationGraph {
|
|
|
79
90
|
| `duplicate-route` | error | 规范化后 HTTP method + path 冲突 |
|
|
80
91
|
| `route-command-unresolved` | error | 路由绑定了本模块未声明的 command 类 |
|
|
81
92
|
| `command-missing-permission` | error | `@Command` 未声明 permission |
|
|
93
|
+
| `invalid-job-scope` | error | `@Job` 使用了不支持的 `request` scope |
|
|
94
|
+
| `provider-type-mismatch` | error | Provider 的 useClass/useValue/useFactory/useExisting 不满足 InjectionToken 的静态类型契约 |
|
|
95
|
+
| `unsupported-provider-helper` | warn(strict 时 error) | functional provider 的动态参数无法安全展开为静态 factory |
|
|
96
|
+
| `dynamic-aspect-reference` | error | aspects 不是显式数组字面量,或包含 spread/表达式/字符串 pointcut |
|
|
97
|
+
| `invalid-aspect-reference` | error | aspect 不是可静态解析的函数声明、箭头函数或函数表达式 |
|
|
82
98
|
| `missing-deps` | warn(strict 时 error) | 构造/工厂依赖无法静态解析 |
|
|
99
|
+
| `generated-any` | warn(strict 时 error) | 生成的 TypeScript 产物包含 `any` |
|
|
100
|
+
| `source-any` | warn(strict 时 error) | 未被排除的生产源码包含显式 `any` |
|
|
101
|
+
| `source-type-assertion` | warn(strict 时 error) | 生产源码使用 `as T` 或 `<T>value` 类型断言 |
|
|
102
|
+
| `source-non-null-assertion` | warn(strict 时 error) | 生产源码使用非空断言 `value!` |
|
|
103
|
+
| `source-implicit-widening` | warn(strict 时 error) | 可静态判定的字面量类型隐式宽化 |
|
|
83
104
|
|
|
84
105
|
依赖的 token 全图都无 provider 时不报错,记入 `externalTokens`(平台注入)。
|
|
85
106
|
|
|
107
|
+
## 类型安全扫描
|
|
108
|
+
|
|
109
|
+
`strict: true` 默认开启两道类型安全门;也可以单独配置 `typeSafety`。生产源码扫描默认排除测试、fixture、声明文件、`generated` 和 `dist`,并支持 `typeSafety.exclude` 增加项目自定义排除规则。
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
supacloud-compiler check --root ./app --out ./app/generated --strict
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
程序化调用可直接使用 `scanGeneratedArtifacts()` 和 `scanProductionSource()` 获取结构化诊断。
|
|
116
|
+
|
|
86
117
|
## 开发模式
|
|
87
118
|
|
|
88
119
|
```bash
|
package/dist/analyze.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ApplicationGraph, DependencyGraphCache } from "./types";
|
|
2
2
|
/**
|
|
3
|
-
* Analyzes source code under rootDir
|
|
3
|
+
* Analyzes source code under rootDir via the native TypeScript Program API.
|
|
4
4
|
* Decorators are matched by name only (Module/Injectable/Inject/Command/Query/Controller/Get/...),
|
|
5
5
|
* without checking import origins, so this package does not need to depend on @supacloud/app.
|
|
6
6
|
*/
|
|
7
|
-
export declare function analyzeProject(rootDir: string, include?: string[], cache?: DependencyGraphCache): Promise<ApplicationGraph>;
|
|
7
|
+
export declare function analyzeProject(rootDir: string, include?: string[], cache?: DependencyGraphCache, changedPaths?: string[]): Promise<ApplicationGraph>;
|