@cloudcare/hvigor-ohos-plugin 0.1.0 → 0.1.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.1] - 2026-09-14
|
|
4
|
+
|
|
5
|
+
- Fixed console/HiLog instrumentation being skipped when cold-launch instrumentation is enabled in the same Hvigor plugin.
|
|
6
|
+
|
|
3
7
|
## [0.1.0] - 2026-09-14
|
|
4
8
|
|
|
5
9
|
- Added compiler instrumentation for automatic console/HiLog collection.
|
|
@@ -18,4 +22,3 @@
|
|
|
18
22
|
|
|
19
23
|
- Prepared the initial npm prerelease of the console/HiLog and cold-launch instrumentation plugin.
|
|
20
24
|
|
|
21
|
-
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Guance HarmonyOS Hvigor Plugin
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@cloudcare/hvigor-ohos-plugin)
|
|
4
4
|
|
|
5
5
|
`@cloudcare/hvigor-ohos-plugin` is the build-time companion for `@guancecloud/ft_sdk`. It instruments direct `console.*` and `hilog.*` calls and injects cold-launch lifecycle tracking into a HAP module's `src/main/ets` sources. Runtime log collection remains controlled by `FTLoggerConfig.setEnableConsoleLog(true)` in `@guancecloud/ft_sdk`.
|
|
6
6
|
|
|
@@ -11,17 +11,7 @@ This is a Hvigor tool package, so declare it in the project-level `hvigor/hvigor
|
|
|
11
11
|
```json5
|
|
12
12
|
{
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@cloudcare/hvigor-ohos-plugin": "0.1.
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
For local development, a filesystem dependency is also supported:
|
|
20
|
-
|
|
21
|
-
```json5
|
|
22
|
-
{
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"@cloudcare/hvigor-ohos-plugin": "file:../ft_hvigor_plugin"
|
|
14
|
+
"@cloudcare/hvigor-ohos-plugin": "^0.1.1"
|
|
25
15
|
}
|
|
26
16
|
}
|
|
27
17
|
```
|
|
@@ -42,6 +32,6 @@ The plugin preserves the original console/HiLog output and does not modify appli
|
|
|
42
32
|
|
|
43
33
|
## Compatibility
|
|
44
34
|
|
|
45
|
-
|
|
35
|
+
The plugin is verified with Node.js 18 or newer, Hvigor and `@ohos/hvigor-ohos-plugin` 6.23.5, and HarmonyOS SDK 6.0.2 (API 22). It supports `@guancecloud/ft_sdk` `0.1.17` and later releases.
|
|
46
36
|
|
|
47
37
|
`@ohos/hvigor-ohos-plugin` is supplied by DevEco Studio's Hvigor runtime. `@guancecloud/ft_sdk` must still be declared as the application's runtime HAR dependency because the generated imports target that package.
|
|
@@ -15,20 +15,6 @@ declare const __dirname: string;
|
|
|
15
15
|
type TypeScriptApi = any;
|
|
16
16
|
type AbilityClassKind = 'stage' | 'ui' | 'other';
|
|
17
17
|
|
|
18
|
-
interface CompilePluginContext {
|
|
19
|
-
share: {
|
|
20
|
-
projectConfig: {
|
|
21
|
-
etsLoaderPath: string;
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface SharedSourceTransformRegistry {
|
|
27
|
-
originalReadFile: (fileName: string, options?: any) => any;
|
|
28
|
-
buffer: any;
|
|
29
|
-
transforms: Map<string, (fileName: string, code: string) => string>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
18
|
interface ColdLaunchInjection {
|
|
33
19
|
position: number;
|
|
34
20
|
content: string;
|
|
@@ -36,10 +22,6 @@ interface ColdLaunchInjection {
|
|
|
36
22
|
|
|
37
23
|
const COLD_LAUNCH_BRIDGE_IMPORT = '@guancecloud/ft_sdk/Index';
|
|
38
24
|
const COLD_LAUNCH_TRANSFORM_MARKER = '/* guance-cold-launch-transform:instrumented */';
|
|
39
|
-
const SOURCE_TRANSFORM_REGISTRY_KEY = '__guanceHvigorSourceTransformRegistry';
|
|
40
|
-
const TRANSFORM_ID = 'guance-cold-launch-transform';
|
|
41
|
-
|
|
42
|
-
let registeredFileSystem: any = null;
|
|
43
25
|
|
|
44
26
|
export function isApplicationArkTsSource(id: string): boolean {
|
|
45
27
|
const normalizedId = id.replace(/\\/g, '/');
|
|
@@ -311,7 +293,7 @@ function applyColdLaunchInjections(code: string, injections: ColdLaunchInjection
|
|
|
311
293
|
return transformedCode;
|
|
312
294
|
}
|
|
313
295
|
|
|
314
|
-
function
|
|
296
|
+
export function transformColdLaunchSource(ts: TypeScriptApi, id: string, code: string): string {
|
|
315
297
|
if (!isApplicationArkTsSource(id) || code.includes(COLD_LAUNCH_TRANSFORM_MARKER)) {
|
|
316
298
|
return code;
|
|
317
299
|
}
|
|
@@ -328,60 +310,3 @@ function rewriteSource(ts: TypeScriptApi, id: string, code: string): string {
|
|
|
328
310
|
const transformedCode = applyColdLaunchInjections(code, injections);
|
|
329
311
|
return transformedCode.slice(0, insertionOffset) + bridgeImport + transformedCode.slice(insertionOffset);
|
|
330
312
|
}
|
|
331
|
-
|
|
332
|
-
function installSourceReader(context: CompilePluginContext): void {
|
|
333
|
-
if (registeredFileSystem !== null) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const typeScriptPath = `${context.share.projectConfig.etsLoaderPath}/node_modules/typescript`;
|
|
337
|
-
const ts = require.main.require(typeScriptPath);
|
|
338
|
-
const fileSystem = require.main.require('fs');
|
|
339
|
-
let registry = fileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] as SharedSourceTransformRegistry | undefined;
|
|
340
|
-
if (!registry) {
|
|
341
|
-
registry = {
|
|
342
|
-
originalReadFile: fileSystem.readFileSync as (fileName: string, options?: any) => any,
|
|
343
|
-
buffer: require.main.require('buffer'),
|
|
344
|
-
transforms: new Map<string, (fileName: string, code: string) => string>()
|
|
345
|
-
};
|
|
346
|
-
fileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] = registry;
|
|
347
|
-
fileSystem.readFileSync = (fileName: string, options?: any): any => {
|
|
348
|
-
const content = registry!.originalReadFile(fileName, options);
|
|
349
|
-
if (typeof fileName !== 'string' || !isApplicationArkTsSource(fileName)) {
|
|
350
|
-
return content;
|
|
351
|
-
}
|
|
352
|
-
let transformedCode = typeof content === 'string' ? content : content.toString();
|
|
353
|
-
registry!.transforms.forEach((transform: (id: string, code: string) => string) => {
|
|
354
|
-
transformedCode = transform(fileName, transformedCode);
|
|
355
|
-
});
|
|
356
|
-
return typeof content === 'string' ? transformedCode : registry!.buffer.Buffer.from(transformedCode);
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
registry.transforms.set(TRANSFORM_ID, (fileName: string, code: string) => rewriteSource(ts, fileName, code));
|
|
360
|
-
registeredFileSystem = fileSystem;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
function restoreSourceReader(): void {
|
|
364
|
-
if (registeredFileSystem === null) {
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
const registry = registeredFileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] as SharedSourceTransformRegistry | undefined;
|
|
368
|
-
if (registry) {
|
|
369
|
-
registry.transforms.delete(TRANSFORM_ID);
|
|
370
|
-
if (registry.transforms.size === 0) {
|
|
371
|
-
registeredFileSystem.readFileSync = registry.originalReadFile;
|
|
372
|
-
delete registeredFileSystem[SOURCE_TRANSFORM_REGISTRY_KEY];
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
registeredFileSystem = null;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
export default {
|
|
379
|
-
name: 'guance-cold-launch-transform',
|
|
380
|
-
order: 'first',
|
|
381
|
-
buildStart(this: CompilePluginContext): void {
|
|
382
|
-
installSourceReader(this);
|
|
383
|
-
},
|
|
384
|
-
buildEnd(): void {
|
|
385
|
-
restoreSourceReader();
|
|
386
|
-
}
|
|
387
|
-
};
|
|
@@ -7,28 +7,8 @@
|
|
|
7
7
|
* never changed.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
declare const require: {
|
|
11
|
-
main: {
|
|
12
|
-
require(moduleName: string): any;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
10
|
type TypeScriptApi = any;
|
|
17
11
|
|
|
18
|
-
interface CompilePluginContext {
|
|
19
|
-
share: {
|
|
20
|
-
projectConfig: {
|
|
21
|
-
etsLoaderPath: string;
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface SharedSourceTransformRegistry {
|
|
27
|
-
originalReadFile: (fileName: string, options?: any) => any;
|
|
28
|
-
buffer: any;
|
|
29
|
-
transforms: Map<string, (fileName: string, code: string) => string>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
12
|
interface TransformCandidate {
|
|
33
13
|
start: number;
|
|
34
14
|
end: number;
|
|
@@ -52,10 +32,6 @@ const BRIDGE_IMPORT = '@guancecloud/ft_sdk/Index';
|
|
|
52
32
|
// incremental/daemon build. Keep a marker in the in-memory result so a later
|
|
53
33
|
// reader does not wrap the original console/HiLog call a second time.
|
|
54
34
|
const TRANSFORM_MARKER = '/* guance-console-log-transform:instrumented */';
|
|
55
|
-
const SOURCE_TRANSFORM_REGISTRY_KEY = '__guanceHvigorSourceTransformRegistry';
|
|
56
|
-
const TRANSFORM_ID = 'guance-console-log-transform';
|
|
57
|
-
|
|
58
|
-
let registeredFileSystem: any = null;
|
|
59
35
|
|
|
60
36
|
export function isApplicationArkTsSource(id: string): boolean {
|
|
61
37
|
const normalizedId = id.replace(/\\/g, '/');
|
|
@@ -259,7 +235,7 @@ function findImportInsertionOffset(ts: TypeScriptApi, sourceFile: any): number {
|
|
|
259
235
|
return offset;
|
|
260
236
|
}
|
|
261
237
|
|
|
262
|
-
function
|
|
238
|
+
export function transformConsoleLogSource(ts: TypeScriptApi, id: string, code: string): string {
|
|
263
239
|
if (!isApplicationArkTsSource(id) || code.includes(TRANSFORM_MARKER)) {
|
|
264
240
|
return code;
|
|
265
241
|
}
|
|
@@ -279,61 +255,3 @@ function rewriteSource(ts: TypeScriptApi, id: string, code: string): string {
|
|
|
279
255
|
return transformedCode.slice(0, transformedInsertionOffset) + bridgeImport +
|
|
280
256
|
transformedCode.slice(transformedInsertionOffset);
|
|
281
257
|
}
|
|
282
|
-
|
|
283
|
-
function installSourceReader(context: CompilePluginContext): void {
|
|
284
|
-
if (registeredFileSystem !== null) {
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const typeScriptPath = `${context.share.projectConfig.etsLoaderPath}/node_modules/typescript`;
|
|
289
|
-
const ts = require.main.require(typeScriptPath);
|
|
290
|
-
const fileSystem = require.main.require('fs');
|
|
291
|
-
let registry = fileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] as SharedSourceTransformRegistry | undefined;
|
|
292
|
-
if (!registry) {
|
|
293
|
-
registry = {
|
|
294
|
-
originalReadFile: fileSystem.readFileSync as (fileName: string, options?: any) => any,
|
|
295
|
-
buffer: require.main.require('buffer'),
|
|
296
|
-
transforms: new Map<string, (fileName: string, code: string) => string>()
|
|
297
|
-
};
|
|
298
|
-
fileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] = registry;
|
|
299
|
-
fileSystem.readFileSync = (fileName: string, options?: any): any => {
|
|
300
|
-
const content = registry!.originalReadFile(fileName, options);
|
|
301
|
-
if (typeof fileName !== 'string' || !isApplicationArkTsSource(fileName)) {
|
|
302
|
-
return content;
|
|
303
|
-
}
|
|
304
|
-
let transformedCode = typeof content === 'string' ? content : content.toString();
|
|
305
|
-
registry!.transforms.forEach((transform: (id: string, code: string) => string) => {
|
|
306
|
-
transformedCode = transform(fileName, transformedCode);
|
|
307
|
-
});
|
|
308
|
-
return typeof content === 'string' ? transformedCode : registry!.buffer.Buffer.from(transformedCode);
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
registry.transforms.set(TRANSFORM_ID, (fileName: string, code: string) => rewriteSource(ts, fileName, code));
|
|
312
|
-
registeredFileSystem = fileSystem;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function restoreSourceReader(): void {
|
|
316
|
-
if (registeredFileSystem === null) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
const registry = registeredFileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] as SharedSourceTransformRegistry | undefined;
|
|
320
|
-
if (registry) {
|
|
321
|
-
registry.transforms.delete(TRANSFORM_ID);
|
|
322
|
-
if (registry.transforms.size === 0) {
|
|
323
|
-
registeredFileSystem.readFileSync = registry.originalReadFile;
|
|
324
|
-
delete registeredFileSystem[SOURCE_TRANSFORM_REGISTRY_KEY];
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
registeredFileSystem = null;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
export default {
|
|
331
|
-
name: 'guance-console-log-transform',
|
|
332
|
-
order: 'first',
|
|
333
|
-
buildStart(this: CompilePluginContext): void {
|
|
334
|
-
installSourceReader(this);
|
|
335
|
-
},
|
|
336
|
-
buildEnd(): void {
|
|
337
|
-
restoreSourceReader();
|
|
338
|
-
}
|
|
339
|
-
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guance compiler source-transform host.
|
|
3
|
+
*
|
|
4
|
+
* Hvigor reads ArkTS source while creating its type-checking program, before
|
|
5
|
+
* normal Rollup transforms run. This host owns that single read hook and
|
|
6
|
+
* composes feature transforms in a deterministic order. Feature modules must
|
|
7
|
+
* only transform source; they must not patch the file system themselves.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
isApplicationArkTsSource,
|
|
12
|
+
transformConsoleLogSource
|
|
13
|
+
} from './ft-console-log-transform';
|
|
14
|
+
import { transformColdLaunchSource } from './ft-cold-launch-transform';
|
|
15
|
+
|
|
16
|
+
declare const require: {
|
|
17
|
+
main: {
|
|
18
|
+
require(moduleName: string): any;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type TypeScriptApi = any;
|
|
23
|
+
type SourceTransform = (ts: TypeScriptApi, fileName: string, code: string) => string;
|
|
24
|
+
|
|
25
|
+
interface CompilePluginContext {
|
|
26
|
+
share: {
|
|
27
|
+
projectConfig: {
|
|
28
|
+
etsLoaderPath: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface SourceTransformDefinition {
|
|
34
|
+
id: string;
|
|
35
|
+
transform: SourceTransform;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface SharedSourceTransformRegistry {
|
|
39
|
+
originalReadFile: (fileName: string, options?: any) => any;
|
|
40
|
+
buffer: any;
|
|
41
|
+
transforms: Map<string, (fileName: string, code: string) => string>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const SOURCE_TRANSFORM_REGISTRY_KEY = '__guanceHvigorSourceTransformRegistry';
|
|
45
|
+
const SOURCE_TRANSFORMS: SourceTransformDefinition[] = [
|
|
46
|
+
{ id: 'guance-console-log-transform', transform: transformConsoleLogSource },
|
|
47
|
+
{ id: 'guance-cold-launch-transform', transform: transformColdLaunchSource }
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
let registeredFileSystem: any = null;
|
|
51
|
+
|
|
52
|
+
function installSourceReader(context: CompilePluginContext): void {
|
|
53
|
+
if (registeredFileSystem !== null) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const typeScriptPath = `${context.share.projectConfig.etsLoaderPath}/node_modules/typescript`;
|
|
58
|
+
const ts = require.main.require(typeScriptPath);
|
|
59
|
+
const fileSystem = require.main.require('fs');
|
|
60
|
+
let registry = fileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] as SharedSourceTransformRegistry | undefined;
|
|
61
|
+
if (!registry) {
|
|
62
|
+
registry = {
|
|
63
|
+
originalReadFile: fileSystem.readFileSync as (fileName: string, options?: any) => any,
|
|
64
|
+
buffer: require.main.require('buffer'),
|
|
65
|
+
transforms: new Map<string, (fileName: string, code: string) => string>()
|
|
66
|
+
};
|
|
67
|
+
fileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] = registry;
|
|
68
|
+
fileSystem.readFileSync = (fileName: string, options?: any): any => {
|
|
69
|
+
const content = registry!.originalReadFile(fileName, options);
|
|
70
|
+
if (typeof fileName !== 'string' || !isApplicationArkTsSource(fileName)) {
|
|
71
|
+
return content;
|
|
72
|
+
}
|
|
73
|
+
let transformedCode = typeof content === 'string' ? content : content.toString();
|
|
74
|
+
registry!.transforms.forEach((transform: (id: string, code: string) => string) => {
|
|
75
|
+
transformedCode = transform(fileName, transformedCode);
|
|
76
|
+
});
|
|
77
|
+
return typeof content === 'string' ? transformedCode : registry!.buffer.Buffer.from(transformedCode);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
SOURCE_TRANSFORMS.forEach((definition: SourceTransformDefinition) => {
|
|
82
|
+
registry!.transforms.set(definition.id, (fileName: string, code: string) =>
|
|
83
|
+
definition.transform(ts, fileName, code));
|
|
84
|
+
});
|
|
85
|
+
registeredFileSystem = fileSystem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function restoreSourceReader(): void {
|
|
89
|
+
if (registeredFileSystem === null) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const registry = registeredFileSystem[SOURCE_TRANSFORM_REGISTRY_KEY] as SharedSourceTransformRegistry | undefined;
|
|
93
|
+
if (registry) {
|
|
94
|
+
SOURCE_TRANSFORMS.forEach((definition: SourceTransformDefinition) => registry!.transforms.delete(definition.id));
|
|
95
|
+
if (registry.transforms.size === 0) {
|
|
96
|
+
registeredFileSystem.readFileSync = registry.originalReadFile;
|
|
97
|
+
delete registeredFileSystem[SOURCE_TRANSFORM_REGISTRY_KEY];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
registeredFileSystem = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default {
|
|
104
|
+
name: 'guance-source-transform-host',
|
|
105
|
+
order: 'first',
|
|
106
|
+
buildStart(this: CompilePluginContext): void {
|
|
107
|
+
installSourceReader(this);
|
|
108
|
+
},
|
|
109
|
+
buildEnd(): void {
|
|
110
|
+
restoreSourceReader();
|
|
111
|
+
}
|
|
112
|
+
};
|
package/index.js
CHANGED
|
@@ -15,10 +15,8 @@ function ftConsoleLogPlugin() {
|
|
|
15
15
|
pluginId: 'guance-console-log-compiler',
|
|
16
16
|
apply(node) {
|
|
17
17
|
const hapContext = node.getContext(OhosPluginId.OHOS_HAP_PLUGIN);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
hapContext.loadCompilePlugin(consoleLogTransformPath);
|
|
21
|
-
hapContext.loadCompilePlugin(coldLaunchTransformPath);
|
|
18
|
+
const sourceTransformHostPath = path.join(__dirname, 'hvigorCompile', 'ft-source-transform-host.ts');
|
|
19
|
+
hapContext.loadCompilePlugin(sourceTransformHostPath);
|
|
22
20
|
}
|
|
23
21
|
};
|
|
24
22
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcare/hvigor-ohos-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Guance HarmonyOS Hvigor plugin for automatic console, HiLog, and cold-launch collection.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"index.js",
|
|
8
|
+
"hvigorCompile/ft-source-transform-host.ts",
|
|
8
9
|
"hvigorCompile/ft-console-log-transform.ts",
|
|
9
10
|
"hvigorCompile/ft-cold-launch-transform.ts",
|
|
10
11
|
"README.md",
|