@hadss/turbo-trans-json-plugin 1.0.0-rc.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/LICENSE +177 -0
- package/README.md +253 -0
- package/dist/core/Types.d.ts +196 -0
- package/dist/core/Types.js +47 -0
- package/dist/core/analyzers/ClassAnalyzer.d.ts +23 -0
- package/dist/core/analyzers/ClassAnalyzer.js +480 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +21 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.js +243 -0
- package/dist/core/analyzers/SendableMergeChecker.d.ts +9 -0
- package/dist/core/analyzers/SendableMergeChecker.js +100 -0
- package/dist/core/analyzers/SendableMergeabilityRegistry.d.ts +7 -0
- package/dist/core/analyzers/SendableMergeabilityRegistry.js +23 -0
- package/dist/core/constants/DecoratorConstants.d.ts +7 -0
- package/dist/core/constants/DecoratorConstants.js +13 -0
- package/dist/core/constants/PathConstants.d.ts +6 -0
- package/dist/core/constants/PathConstants.js +10 -0
- package/dist/core/constants/StringConstants.d.ts +83 -0
- package/dist/core/constants/StringConstants.js +87 -0
- package/dist/core/constants/index.d.ts +3 -0
- package/dist/core/constants/index.js +19 -0
- package/dist/core/handlers/BaseTypeHandler.d.ts +23 -0
- package/dist/core/handlers/BaseTypeHandler.js +57 -0
- package/dist/core/handlers/CustomClassHandler.d.ts +21 -0
- package/dist/core/handlers/CustomClassHandler.js +191 -0
- package/dist/core/handlers/DateHandler.d.ts +2 -0
- package/dist/core/handlers/DateHandler.js +60 -0
- package/dist/core/handlers/DecimalHandler.d.ts +2 -0
- package/dist/core/handlers/DecimalHandler.js +60 -0
- package/dist/core/handlers/EnumHandler.d.ts +2 -0
- package/dist/core/handlers/EnumHandler.js +89 -0
- package/dist/core/handlers/GenericContainerHandler.d.ts +2 -0
- package/dist/core/handlers/GenericContainerHandler.js +440 -0
- package/dist/core/handlers/GenericHandler.d.ts +18 -0
- package/dist/core/handlers/GenericHandler.js +92 -0
- package/dist/core/handlers/HandlerBootstrap.d.ts +2 -0
- package/dist/core/handlers/HandlerBootstrap.js +28 -0
- package/dist/core/handlers/ITypeHandler.d.ts +23 -0
- package/dist/core/handlers/ITypeHandler.js +8 -0
- package/dist/core/handlers/PrimitiveHandler.d.ts +2 -0
- package/dist/core/handlers/PrimitiveHandler.js +127 -0
- package/dist/core/handlers/TupleHandler.d.ts +2 -0
- package/dist/core/handlers/TupleHandler.js +98 -0
- package/dist/core/handlers/TypeHandlerRegistry.d.ts +20 -0
- package/dist/core/handlers/TypeHandlerRegistry.js +113 -0
- package/dist/core/handlers/UnionTypeHandler.d.ts +2 -0
- package/dist/core/handlers/UnionTypeHandler.js +263 -0
- package/dist/core/handlers/index.d.ts +2 -0
- package/dist/core/handlers/index.js +5 -0
- package/dist/core/import-rewrite/services/BuildProfileUpdater.d.ts +8 -0
- package/dist/core/import-rewrite/services/BuildProfileUpdater.js +92 -0
- package/dist/core/import-rewrite/services/ImportRewriteService.d.ts +9 -0
- package/dist/core/import-rewrite/services/ImportRewriteService.js +61 -0
- package/dist/core/import-rewrite/services/ImportTransformService.d.ts +15 -0
- package/dist/core/import-rewrite/services/ImportTransformService.js +109 -0
- package/dist/core/import-rewrite/strategies/ImportScanStrategy.d.ts +17 -0
- package/dist/core/import-rewrite/strategies/ImportScanStrategy.js +137 -0
- package/dist/core/import-rewrite/types/ImportRewriteTypes.d.ts +17 -0
- package/dist/core/import-rewrite/types/ImportRewriteTypes.js +2 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +27 -0
- package/dist/core/interfaces/ITask.d.ts +7 -0
- package/dist/core/interfaces/ITask.js +2 -0
- package/dist/core/interfaces/ITaskContext.d.ts +11 -0
- package/dist/core/interfaces/ITaskContext.js +2 -0
- package/dist/core/interfaces/index.d.ts +2 -0
- package/dist/core/interfaces/index.js +2 -0
- package/dist/core/logger/Logger.d.ts +13 -0
- package/dist/core/logger/Logger.js +78 -0
- package/dist/core/services/CodeAnalysisService.d.ts +7 -0
- package/dist/core/services/CodeAnalysisService.js +43 -0
- package/dist/core/services/CodeGenerationEngine.d.ts +12 -0
- package/dist/core/services/CodeGenerationEngine.js +102 -0
- package/dist/core/services/CodeGenerationService/CodeGenerationService.d.ts +13 -0
- package/dist/core/services/CodeGenerationService/CodeGenerationService.js +110 -0
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +13 -0
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +119 -0
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +21 -0
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +224 -0
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +24 -0
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +307 -0
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.d.ts +28 -0
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +259 -0
- package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.d.ts +19 -0
- package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +178 -0
- package/dist/core/services/CodeGenerationService/index.d.ts +1 -0
- package/dist/core/services/CodeGenerationService/index.js +5 -0
- package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +27 -0
- package/dist/core/services/CodeGenerationService/shared/ImportManager.js +127 -0
- package/dist/core/template/HandlebarsTemplateEngine.d.ts +26 -0
- package/dist/core/template/HandlebarsTemplateEngine.js +226 -0
- package/dist/core/utils/ConfigManager.d.ts +10 -0
- package/dist/core/utils/ConfigManager.js +32 -0
- package/dist/core/utils/CustomError.d.ts +30 -0
- package/dist/core/utils/CustomError.js +37 -0
- package/dist/core/utils/DeepCopyUtil.d.ts +15 -0
- package/dist/core/utils/DeepCopyUtil.js +138 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +9 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.js +68 -0
- package/dist/core/utils/SerializationPathUtil.d.ts +18 -0
- package/dist/core/utils/SerializationPathUtil.js +107 -0
- package/dist/core/utils/TsMorphUtil.d.ts +8 -0
- package/dist/core/utils/TsMorphUtil.js +34 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +57 -0
- package/dist/json-plugin/JSONExecuteController.d.ts +13 -0
- package/dist/json-plugin/JSONExecuteController.js +103 -0
- package/dist/json-plugin/constants/TaskConstants.d.ts +7 -0
- package/dist/json-plugin/constants/TaskConstants.js +11 -0
- package/dist/json-plugin/interfaces/IModuleContext.d.ts +10 -0
- package/dist/json-plugin/interfaces/IModuleContext.js +2 -0
- package/dist/json-plugin/interfaces/ITargetContext.d.ts +8 -0
- package/dist/json-plugin/interfaces/ITargetContext.js +2 -0
- package/dist/json-plugin/interfaces/impl/ModuleContext.d.ts +12 -0
- package/dist/json-plugin/interfaces/impl/ModuleContext.js +24 -0
- package/dist/json-plugin/interfaces/impl/TargetContext.d.ts +23 -0
- package/dist/json-plugin/interfaces/impl/TargetContext.js +113 -0
- package/dist/json-plugin/tasks/BaseTask.d.ts +14 -0
- package/dist/json-plugin/tasks/BaseTask.js +53 -0
- package/dist/json-plugin/tasks/CleanTask.d.ts +8 -0
- package/dist/json-plugin/tasks/CleanTask.js +25 -0
- package/dist/json-plugin/tasks/CodeProcessingTask.d.ts +8 -0
- package/dist/json-plugin/tasks/CodeProcessingTask.js +26 -0
- package/dist/json-plugin/tasks/SyncTask.d.ts +8 -0
- package/dist/json-plugin/tasks/SyncTask.js +21 -0
- package/dist/json-plugin/tasks/WatchTask.d.ts +11 -0
- package/dist/json-plugin/tasks/WatchTask.js +102 -0
- package/package.json +46 -0
- package/src/core/Types.ts +356 -0
- package/src/core/analyzers/ClassAnalyzer.ts +824 -0
- package/src/core/analyzers/CustomTypeAnalyzer.ts +337 -0
- package/src/core/analyzers/SendableMergeChecker.ts +195 -0
- package/src/core/analyzers/SendableMergeabilityRegistry.ts +72 -0
- package/src/core/constants/DecoratorConstants.ts +27 -0
- package/src/core/constants/PathConstants.ts +31 -0
- package/src/core/constants/StringConstants.ts +152 -0
- package/src/core/constants/index.ts +21 -0
- package/src/core/handlers/BaseTypeHandler.ts +121 -0
- package/src/core/handlers/CustomClassHandler.ts +278 -0
- package/src/core/handlers/DateHandler.ts +75 -0
- package/src/core/handlers/DecimalHandler.ts +75 -0
- package/src/core/handlers/EnumHandler.ts +142 -0
- package/src/core/handlers/GenericContainerHandler.ts +621 -0
- package/src/core/handlers/GenericHandler.ts +130 -0
- package/src/core/handlers/HandlerBootstrap.ts +64 -0
- package/src/core/handlers/ITypeHandler.ts +133 -0
- package/src/core/handlers/PrimitiveHandler.ts +159 -0
- package/src/core/handlers/TupleHandler.ts +145 -0
- package/src/core/handlers/TypeHandlerRegistry.ts +236 -0
- package/src/core/handlers/UnionTypeHandler.ts +400 -0
- package/src/core/handlers/index.ts +18 -0
- package/src/core/import-rewrite/services/BuildProfileUpdater.ts +145 -0
- package/src/core/import-rewrite/services/ImportRewriteService.ts +129 -0
- package/src/core/import-rewrite/services/ImportTransformService.ts +200 -0
- package/src/core/import-rewrite/strategies/ImportScanStrategy.ts +303 -0
- package/src/core/import-rewrite/types/ImportRewriteTypes.ts +100 -0
- package/src/core/index.ts +31 -0
- package/src/core/interfaces/ITask.ts +23 -0
- package/src/core/interfaces/ITaskContext.ts +94 -0
- package/src/core/interfaces/index.ts +17 -0
- package/src/core/logger/Logger.ts +149 -0
- package/src/core/services/CodeAnalysisService.ts +67 -0
- package/src/core/services/CodeGenerationEngine.ts +181 -0
- package/src/core/services/CodeGenerationService/CodeGenerationService.ts +159 -0
- package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +189 -0
- package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +314 -0
- package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +421 -0
- package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +392 -0
- package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +277 -0
- package/src/core/services/CodeGenerationService/index.ts +16 -0
- package/src/core/services/CodeGenerationService/shared/ImportManager.ts +191 -0
- package/src/core/template/HandlebarsTemplateEngine.ts +282 -0
- package/src/core/utils/ConfigManager.ts +49 -0
- package/src/core/utils/CustomError.ts +51 -0
- package/src/core/utils/DeepCopyUtil.ts +185 -0
- package/src/core/utils/GenericTypeSubstitutionUtil.ts +136 -0
- package/src/core/utils/SerializationPathUtil.ts +142 -0
- package/src/core/utils/TsMorphUtil.ts +50 -0
- package/src/index.ts +81 -0
- package/src/json-plugin/JSONExecuteController.ts +134 -0
- package/src/json-plugin/constants/TaskConstants.ts +22 -0
- package/src/json-plugin/interfaces/IModuleContext.ts +27 -0
- package/src/json-plugin/interfaces/ITargetContext.ts +25 -0
- package/src/json-plugin/interfaces/impl/ModuleContext.ts +45 -0
- package/src/json-plugin/interfaces/impl/TargetContext.ts +196 -0
- package/src/json-plugin/tasks/BaseTask.ts +94 -0
- package/src/json-plugin/tasks/CleanTask.ts +36 -0
- package/src/json-plugin/tasks/CodeProcessingTask.ts +41 -0
- package/src/json-plugin/tasks/SyncTask.ts +33 -0
- package/src/json-plugin/tasks/WatchTask.ts +99 -0
- package/template/SerializerPerformanceTemplate.hbs +35 -0
- package/template/SerializerRegisterTemplate.hbs +10 -0
- package/template/SerializerStrictTemplate.hbs +89 -0
- package/template/SerializerTemplate.hbs +176 -0
- package/tsconfig.json +17 -0
- package/tslint.json +3 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import * as chokidar from 'chokidar';
|
|
17
|
+
import { Logger } from '../../core';
|
|
18
|
+
import { TaskConstants } from '../constants/TaskConstants';
|
|
19
|
+
import { ITargetContext } from '../interfaces/ITargetContext';
|
|
20
|
+
import { BaseTask } from './BaseTask';
|
|
21
|
+
|
|
22
|
+
export class WatchTask extends BaseTask {
|
|
23
|
+
readonly taskName: string = TaskConstants.WATCH_TASK;
|
|
24
|
+
readonly dependencies: string[] = []; // CLI任务无依赖
|
|
25
|
+
readonly postDependencies: string[] = []; // CLI任务无依赖
|
|
26
|
+
|
|
27
|
+
private watcher?: chokidar.FSWatcher;
|
|
28
|
+
|
|
29
|
+
async run(context: ITargetContext): Promise<void> {
|
|
30
|
+
Logger.info('Start the file listening task');
|
|
31
|
+
|
|
32
|
+
const watchPaths = this.getScanFiles(context);
|
|
33
|
+
if (watchPaths.length === 0) {
|
|
34
|
+
Logger.info('There are no files to listen to');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Logger.info(`Start listening for file changes: ${watchPaths.join(', ')}`);
|
|
39
|
+
|
|
40
|
+
// 创建文件监听器
|
|
41
|
+
this.watcher = chokidar.watch(watchPaths, {
|
|
42
|
+
persistent: true,
|
|
43
|
+
ignoreInitial: false // 初始时也触发一次
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// 设置事件监听器
|
|
47
|
+
this.setupWatchEvents(context);
|
|
48
|
+
|
|
49
|
+
Logger.info('File monitoring has been started. Press Ctrl+C to stop the monitoring');
|
|
50
|
+
|
|
51
|
+
return new Promise(_resolve => {
|
|
52
|
+
// 进程会一直运行,直到用户手动停止
|
|
53
|
+
// resolve永远不会被调用,除非出现错误或用户停止
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private setupWatchEvents(context: ITargetContext): void {
|
|
58
|
+
if (!this.watcher) return
|
|
59
|
+
|
|
60
|
+
let debounceTimer: NodeJS.Timeout | null = null
|
|
61
|
+
|
|
62
|
+
// 防抖处理,避免频繁触发
|
|
63
|
+
const debouncedGenerate = (filePath: string) => {
|
|
64
|
+
if (debounceTimer) {
|
|
65
|
+
clearTimeout(debounceTimer)
|
|
66
|
+
}
|
|
67
|
+
debounceTimer = setTimeout(() => {
|
|
68
|
+
this.generateCode(filePath, context)
|
|
69
|
+
}, 500) // 500ms 防抖
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.watcher
|
|
73
|
+
.on('add', (filePath: string) => {
|
|
74
|
+
Logger.info(`New file detected: ${filePath}`)
|
|
75
|
+
debouncedGenerate(filePath)
|
|
76
|
+
})
|
|
77
|
+
.on('change', (filePath: string) => {
|
|
78
|
+
Logger.info(`File change detected: ${filePath}`)
|
|
79
|
+
debouncedGenerate(filePath)
|
|
80
|
+
})
|
|
81
|
+
.on('unlink', (filePath: string) => {
|
|
82
|
+
Logger.info(`File deletion detected: ${filePath}`)
|
|
83
|
+
debouncedGenerate(filePath)
|
|
84
|
+
})
|
|
85
|
+
.on('error', (error: unknown) => {
|
|
86
|
+
Logger.error(`File monitoring error: ${error}`)
|
|
87
|
+
})
|
|
88
|
+
.on('ready', () => {
|
|
89
|
+
Logger.info('The initial file scan is complete. Start listening for file changes...')
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private generateCode(scanFile: string, context: ITargetContext): void {
|
|
94
|
+
// 统一处理:逐文件分析 → 直接生成
|
|
95
|
+
const processingResult = this.engine.processFileUnified(scanFile, context)
|
|
96
|
+
|
|
97
|
+
Logger.info(`The code generation is complete, and the output path is ${processingResult?.outputPath}`)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{{! 反序列化方法:简化的默认值处理 }}
|
|
2
|
+
deserialize(decoder: Decoder, plain: ESObject): {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}} {
|
|
3
|
+
const keys = this.serialDescriptor.elementDecodingNames;
|
|
4
|
+
|
|
5
|
+
{{#if (isClassType class)}}
|
|
6
|
+
{{! 解码构造函数属性(直接反序列化)}}
|
|
7
|
+
const result = new {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}}(
|
|
8
|
+
{{#each (getCtorProperties class.constructorParams properties)}}
|
|
9
|
+
{{#unless analysis.decorators.isTransient}}
|
|
10
|
+
{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{#unless @last}},{{/unless}}
|
|
11
|
+
{{/unless}}
|
|
12
|
+
{{/each}});
|
|
13
|
+
{{else}}
|
|
14
|
+
const result: ESObject = {};
|
|
15
|
+
{{/if}}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
{{! 可选属性赋值(构造函数外的属性)}}
|
|
19
|
+
{{#each (postConstructorAssignments class.constructorParams properties)}}
|
|
20
|
+
{{#unless analysis.decorators.isTransient}}
|
|
21
|
+
const {{analysis.name}}PlainValue: ESObject = plain[keys[{{getPropertyIndex this ../properties}}]];
|
|
22
|
+
{{#if analysis.defaultValue}}
|
|
23
|
+
{{! 有默认值的属性 }}
|
|
24
|
+
result.{{analysis.name}} = {{analysis.name}}PlainValue === undefined ? {{analysis.defaultValue}} :
|
|
25
|
+
{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
|
|
26
|
+
{{else}}
|
|
27
|
+
{{! 无默认值的属性 }}
|
|
28
|
+
result.{{analysis.name}} = {{analysis.name}}PlainValue === undefined ? undefined :
|
|
29
|
+
{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{/unless}}
|
|
32
|
+
{{/each}}
|
|
33
|
+
|
|
34
|
+
return result as {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}};
|
|
35
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{{! 类型的需要注册, 接口类型class.className无法作为参数注册 }}
|
|
2
|
+
{{#if (isClassType class)}}
|
|
3
|
+
{{#if class.generics.isGeneric}}
|
|
4
|
+
{{! 工厂注册 }}
|
|
5
|
+
registerAutoGeneratedSerializerEntry({{class.className}}, new {{class.className}}SerializerFactory());
|
|
6
|
+
{{else}}
|
|
7
|
+
{{! 单例注册 }}
|
|
8
|
+
registerAutoGeneratedSerializerEntry({{class.className}}, {{class.className}}Serializer.INSTANCE);
|
|
9
|
+
{{/if}}
|
|
10
|
+
{{/if}}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{{! 反序列化方法:精确验证和错误处理 }}
|
|
2
|
+
deserialize(decoder: Decoder, plain: ESObject): {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}} {
|
|
3
|
+
{{! 类型验证 }}
|
|
4
|
+
if (!TypeUtils.isObject(plain)) {
|
|
5
|
+
TurboTransLogger.error('Cannot deserialize `{{class.className}}` from non-object serialized data in strict deserialization.')
|
|
6
|
+
throw new SerializationError(
|
|
7
|
+
SerializationErrorCodes.CANNOT_BEGIN_STRUCTURE_ON_NON_STRUCTURE_KIND,
|
|
8
|
+
'Cannot deserialize `{{class.className}}` from non-object serialized data in strict deserialization.'
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
{{! 属性状态跟踪变量 }}
|
|
13
|
+
{{#each properties}}
|
|
14
|
+
let {{analysis.name}}Seen = false;
|
|
15
|
+
let {{analysis.name}}Value: {{serializer.decoderType}} = undefined;
|
|
16
|
+
{{/each}}
|
|
17
|
+
|
|
18
|
+
{{! Object.entries 遍历 }}
|
|
19
|
+
const entries: [string, ESObject][] = Object.entries(plain);
|
|
20
|
+
for (let i = 0; i < entries.length; i++) {
|
|
21
|
+
const entry: [string, ESObject] = entries[i];
|
|
22
|
+
const key = entry[0];
|
|
23
|
+
const value: ESObject = entry[1];
|
|
24
|
+
const elementIndex = decoder.decodeElementIndex(this.serialDescriptor, key, value);
|
|
25
|
+
|
|
26
|
+
switch (elementIndex) {
|
|
27
|
+
{{#each properties}}
|
|
28
|
+
case {{@index}}:
|
|
29
|
+
{{analysis.name}}Seen = true;
|
|
30
|
+
{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}
|
|
31
|
+
{{analysis.name}}Value = decoder.{{serializer.decodeMethod}}(value);
|
|
32
|
+
{{else}}
|
|
33
|
+
{{analysis.name}}Value = this.{{analysis.name}}Serializer.deserialize(decoder, value){{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
|
|
34
|
+
{{/if}}
|
|
35
|
+
break;
|
|
36
|
+
{{/each}}
|
|
37
|
+
case DecodedElementIndex.UNKNOWN_NAME:
|
|
38
|
+
TurboTransLogger.error(`Encounter unknown property \`${key}\` when deserialize \`{{class.className}}\`.`)
|
|
39
|
+
throw new SerializationError(
|
|
40
|
+
SerializationErrorCodes.ENCOUNTER_UNKNOWN_KEY,
|
|
41
|
+
`Encounter unknown property \`${key}\` when deserialize \`{{class.className}}\`.`
|
|
42
|
+
);
|
|
43
|
+
case DecodedElementIndex.IGNORED_NAME:
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
{{! 必填属性验证 }}
|
|
49
|
+
const missingProperties: string[] = [];
|
|
50
|
+
{{#each properties}}
|
|
51
|
+
{{#if analysis.isMust}}
|
|
52
|
+
if (!{{analysis.name}}Seen) {
|
|
53
|
+
missingProperties.push('{{formatPropertyName analysis}}');
|
|
54
|
+
}
|
|
55
|
+
{{/if}}
|
|
56
|
+
{{/each}}
|
|
57
|
+
|
|
58
|
+
if (missingProperties.length > 0) {
|
|
59
|
+
TurboTransLogger.error(`Missing required properties [${missingProperties.map(item => `\`${item}\``).join(', ')}] when deserialize \`{{class.className}}\`.`)
|
|
60
|
+
throw new SerializationError(
|
|
61
|
+
SerializationErrorCodes.MISSING_REQUIRED_PROPERTY,
|
|
62
|
+
`Missing required properties [${missingProperties.map(item => `\`${item}\``).join(', ')}] when deserialize \`{{class.className}}\`.`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
{{#if (isClassType class)}}
|
|
67
|
+
{{! 解码构造函数属性(直接反序列化)}}
|
|
68
|
+
{{! 构造函数参数(形参名和属性名一致)}}
|
|
69
|
+
const result = new {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}}(
|
|
70
|
+
{{#each (getCtorProperties class.constructorParams properties)}}
|
|
71
|
+
{{#unless analysis.decorators.isTransient}}
|
|
72
|
+
{{analysis.name}}Value!{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}},
|
|
73
|
+
{{/unless}}
|
|
74
|
+
{{/each}});
|
|
75
|
+
{{else}}
|
|
76
|
+
const result: ESObject = {};
|
|
77
|
+
{{/if}}
|
|
78
|
+
|
|
79
|
+
{{! 可选属性赋值(构造函数外的属性)}}
|
|
80
|
+
{{#each (postConstructorAssignments class.constructorParams properties)}}
|
|
81
|
+
{{#unless analysis.decorators.isTransient}}
|
|
82
|
+
if ({{analysis.name}}Seen) {
|
|
83
|
+
result.{{analysis.name}} = {{analysis.name}}Value!{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
|
|
84
|
+
}
|
|
85
|
+
{{/unless}}
|
|
86
|
+
{{/each}}
|
|
87
|
+
|
|
88
|
+
return result as {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}};
|
|
89
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
{{! ===================================================== }}
|
|
2
|
+
{{! 序列化器模板 (CoarseSerializer) }}
|
|
3
|
+
{{! 特点:性能优先,直接对象访问,简化默认值处理 }}
|
|
4
|
+
{{! ===================================================== }}
|
|
5
|
+
|
|
6
|
+
{{! 序列化名称常量 }}
|
|
7
|
+
const {{class.className}}_SERIAL_NAME = '{{serialNameConstant}}';
|
|
8
|
+
|
|
9
|
+
{{#if class.generics.isGeneric}}
|
|
10
|
+
{{! 泛型类:工厂模式 }}
|
|
11
|
+
export class {{class.className}}Serializer<{{genericParametersString class.generics.parameters}}> extends Serializer<{{class.className}}<{{genericParametersString class.generics.parameters}}>> {
|
|
12
|
+
readonly serialName: string = {{class.className}}_SERIAL_NAME;
|
|
13
|
+
|
|
14
|
+
{{! 属性序列化器声明 }}
|
|
15
|
+
{{#each properties}}
|
|
16
|
+
{{#unless (eqPrimitiveType analysis.type.kind)}}
|
|
17
|
+
private readonly {{analysis.name}}Serializer: {{serializer.typeDeclaration}};
|
|
18
|
+
{{/unless}}
|
|
19
|
+
{{/each}}
|
|
20
|
+
|
|
21
|
+
readonly serialDescriptor: SerialDescriptor;
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
{{#each class.generics.parameters}}
|
|
25
|
+
{{toLowerCase this}}Serializer: Serializer<{{this}}>{{#unless @last}},{{/unless}}
|
|
26
|
+
{{/each}}
|
|
27
|
+
) {
|
|
28
|
+
super();
|
|
29
|
+
{{! 初始化属性序列化器 }}
|
|
30
|
+
{{#each properties}}
|
|
31
|
+
{{#unless (eqPrimitiveType analysis.type.kind)}}
|
|
32
|
+
this.{{analysis.name}}Serializer = {{serializer.instantiationTemplate}};
|
|
33
|
+
{{/unless}}
|
|
34
|
+
{{/each}}
|
|
35
|
+
|
|
36
|
+
this.serialDescriptor = buildClassSerialDescriptor(
|
|
37
|
+
{{class.className}}_SERIAL_NAME,
|
|
38
|
+
builder => {
|
|
39
|
+
{{#each properties}}
|
|
40
|
+
{{! 处理数字属性名的特殊情况 }}
|
|
41
|
+
{{#if (isNumericPropertyName (formatPropertyName analysis))}}
|
|
42
|
+
builder.element({
|
|
43
|
+
elementName: '{{formatPropertyName analysis}}',
|
|
44
|
+
elementDecodingName: this.fixNonNegativeIntegerElementName('{{formatPropertyName analysis}}'),
|
|
45
|
+
descriptor:
|
|
46
|
+
{{#if (eqPrimitiveType analysis.type.kind)}}
|
|
47
|
+
{{serializer.name}}.INSTANCE.serialDescriptor
|
|
48
|
+
{{else}}
|
|
49
|
+
this.{{analysis.name}}Serializer.serialDescriptor
|
|
50
|
+
{{/if}}
|
|
51
|
+
});
|
|
52
|
+
{{else}}
|
|
53
|
+
builder.element({
|
|
54
|
+
elementName: '{{formatPropertyName analysis}}',
|
|
55
|
+
descriptor:
|
|
56
|
+
{{#if (eqPrimitiveType analysis.type.kind)}}
|
|
57
|
+
{{serializer.name}}.INSTANCE.serialDescriptor
|
|
58
|
+
{{else}}
|
|
59
|
+
this.{{analysis.name}}Serializer.serialDescriptor
|
|
60
|
+
{{/if}}
|
|
61
|
+
});
|
|
62
|
+
{{/if}}
|
|
63
|
+
{{/each}}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
{{else}}
|
|
67
|
+
{{! 非泛型类:单例模式 }}
|
|
68
|
+
export class {{class.className}}Serializer extends Serializer<{{class.className}}> {
|
|
69
|
+
private static _INSTANCE?: {{class.className}}Serializer;
|
|
70
|
+
readonly serialName: string = {{class.className}}_SERIAL_NAME;
|
|
71
|
+
|
|
72
|
+
static get INSTANCE(): {{class.className}}Serializer {
|
|
73
|
+
if (!{{class.className}}Serializer._INSTANCE) {
|
|
74
|
+
{{class.className}}Serializer._INSTANCE = new {{class.className}}Serializer();
|
|
75
|
+
}
|
|
76
|
+
return {{class.className}}Serializer._INSTANCE;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
{{! 属性序列化器声明 }}
|
|
80
|
+
{{#each properties}}
|
|
81
|
+
private readonly {{analysis.name}}Serializer: {{serializer.typeDeclaration}} = {{serializer.instantiationTemplate}};
|
|
82
|
+
{{/each}}
|
|
83
|
+
|
|
84
|
+
{{! 序列描述符构建 }}
|
|
85
|
+
readonly serialDescriptor: SerialDescriptor = buildClassSerialDescriptor(
|
|
86
|
+
{{class.className}}_SERIAL_NAME,
|
|
87
|
+
builder => {
|
|
88
|
+
{{#each properties}}
|
|
89
|
+
{{! 处理数字属性名的特殊情况 }}
|
|
90
|
+
{{#if (isNumericPropertyName (formatPropertyName analysis))}}
|
|
91
|
+
builder.element({
|
|
92
|
+
elementName: '{{formatPropertyName analysis}}',
|
|
93
|
+
elementDecodingName: this.fixNonNegativeIntegerElementName('{{formatPropertyName analysis}}'),
|
|
94
|
+
descriptor: this.{{analysis.name}}Serializer.serialDescriptor
|
|
95
|
+
});
|
|
96
|
+
{{else}}
|
|
97
|
+
builder.element({
|
|
98
|
+
elementName: '{{formatPropertyName analysis}}',
|
|
99
|
+
descriptor: this.{{analysis.name}}Serializer.serialDescriptor
|
|
100
|
+
});
|
|
101
|
+
{{/if}}
|
|
102
|
+
{{/each}}
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
private constructor() {
|
|
107
|
+
super();
|
|
108
|
+
}
|
|
109
|
+
{{/if}}
|
|
110
|
+
|
|
111
|
+
{{! 序列化方法:返回ESObject }}
|
|
112
|
+
serialize(encoder: Encoder, value: {{#if class.generics.isGeneric}}{{class.className}}<{{genericParametersString class.generics.parameters}}>{{else}}{{class.className}}{{/if}}): ESObject {
|
|
113
|
+
{{#if (canReturnDirectly class)}}
|
|
114
|
+
{{! 性能优化:只包含基础类型时直接返回对象 }}
|
|
115
|
+
if (encoder.allowSourceReuse()) {
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
return this.innerSerialize(encoder, value);
|
|
119
|
+
{{else}}
|
|
120
|
+
return this.innerSerialize(encoder, value);
|
|
121
|
+
{{/if}}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private innerSerialize(encoder: Encoder, value: {{#if class.generics.isGeneric}}{{class.className}}<{{genericParametersString class.generics.parameters}}>{{else}}{{class.className}}{{/if}}): ESObject {
|
|
125
|
+
const keys = this.serialDescriptor.elementNames;
|
|
126
|
+
const result = encoder.newObject();
|
|
127
|
+
{{#each properties}}
|
|
128
|
+
{{! 根据类型选择编码方法 }}
|
|
129
|
+
{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}
|
|
130
|
+
encoder.{{serializer.encodeMethod}}(result, keys[{{@index}}], value.{{analysis.name}});
|
|
131
|
+
{{else}}
|
|
132
|
+
encoder.encodeSerializableElement(result, keys[{{@index}}], this.{{analysis.name}}Serializer, value.{{analysis.name}});
|
|
133
|
+
{{/if}}
|
|
134
|
+
{{/each}}
|
|
135
|
+
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
{{! 动态包含反序列化模板 - 使用从上下文传递的deserializeTemplate参数 }}
|
|
140
|
+
{{> (lookup . "deserializeTemplate")}}
|
|
141
|
+
}
|
|
142
|
+
{{#if class.generics.isGeneric}}
|
|
143
|
+
{{! 基于 BaseSerializerFactory 的工厂类 }}
|
|
144
|
+
export class {{class.className}}SerializerFactory extends BaseSerializerFactory<{{class.className}}<{{genericParametersESObjString class.generics.parameters}}>> {
|
|
145
|
+
|
|
146
|
+
protected getSerialName(): string {
|
|
147
|
+
return {{class.className}}_SERIAL_NAME;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
protected getRequiredSerializersCount(): number {
|
|
151
|
+
return {{class.generics.parameters.length}};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
protected newSerializer(genericArgumentsSerializers: Serializer<ESObject>[]): Serializer<{{class.className}}<{{genericParametersESObjString class.generics.parameters}}>> {
|
|
155
|
+
return new {{class.className}}Serializer<{{genericParametersESObjString class.generics.parameters}}>(
|
|
156
|
+
{{#each class.generics.parameters}}
|
|
157
|
+
genericArgumentsSerializers[{{@index}}]{{#unless @last}},{{/unless}}
|
|
158
|
+
{{/each}}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
protected getSerializerName(): string {
|
|
163
|
+
return {{class.className}}Serializer.name;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
{{/if}}
|
|
167
|
+
|
|
168
|
+
{{#if (isClassType class)}}
|
|
169
|
+
{{#if class.generics.isGeneric}}
|
|
170
|
+
{{! 工厂注册 }}
|
|
171
|
+
registerAutoGeneratedSerializerEntryProviderForSupplementary({{class.className}}_SERIAL_NAME, () => [{{class.className}}, new {{class.className}}SerializerFactory()]);
|
|
172
|
+
{{else}}
|
|
173
|
+
{{! 单例注册 }}
|
|
174
|
+
registerAutoGeneratedSerializerEntryProviderForSupplementary({{class.className}}_SERIAL_NAME, () => [{{class.className}}, {{class.className}}Serializer.INSTANCE]);
|
|
175
|
+
{{/if}}
|
|
176
|
+
{{/if}}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2021",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"sourceMap": false,
|
|
10
|
+
"removeComments": true,
|
|
11
|
+
"outDir": "./dist",
|
|
12
|
+
"rootDir": "./src",
|
|
13
|
+
"declaration": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["./src/**/*"],
|
|
16
|
+
"exclude": ["./node_modules/", "./dist/", "./tests/"]
|
|
17
|
+
}
|
package/tslint.json
ADDED