@cloudcare/hvigor-ohos-plugin 0.1.0-alpha.3 → 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,14 @@
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
+
7
+ ## [0.1.0] - 2026-09-14
8
+
9
+ - Added compiler instrumentation for automatic console/HiLog collection.
10
+ - Added compiler instrumentation for cold-launch tracking.
11
+
3
12
  ## [0.1.0-alpha.3] - 2026-09-11
4
13
 
5
14
  - Added build-time registration of the installed plugin version in SDK `sdk_pkg_info.track`.
@@ -13,8 +22,3 @@
13
22
 
14
23
  - Prepared the initial npm prerelease of the console/HiLog and cold-launch instrumentation plugin.
15
24
 
16
- ## [0.1.0] - 2026-09-05
17
-
18
- - Added compiler instrumentation for automatic console/HiLog collection.
19
- - Added compiler instrumentation for cold-launch tracking.
20
- - Fixed cold-launch instrumentation to retry first-frame observation after `WindowStage.loadContent(...)` completes successfully.
package/README.md CHANGED
@@ -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.0-alpha.3"
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
- The `0.1.0-alpha.3` prerelease 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.
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 rewriteSource(ts: TypeScriptApi, id: string, code: string): string {
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 rewriteSource(ts: TypeScriptApi, id: string, code: string): string {
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 consoleLogTransformPath = path.join(__dirname, 'hvigorCompile', 'ft-console-log-transform.ts');
19
- const coldLaunchTransformPath = path.join(__dirname, 'hvigorCompile', 'ft-cold-launch-transform.ts');
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.0-alpha.3",
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",