Skip to content

Conversation

@drawcoder
Copy link
Contributor

@drawcoder drawcoder commented Jul 11, 2025

新增inula-adapter模块适配vue api,供转换工具使用

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive Vue adapter package with support for Pinia and Vuex state management, lifecycle hooks, directives, conditional rendering, dynamic components, and teleport functionality.
    • Added extensive documentation covering global API usage, Pinia and Vuex integration, and lifecycle details.
    • Provided numerous usage examples demonstrating features such as refs, parent/child communication, force updates, nextTick, custom plugins, event emitters, and internationalization.
    • Implemented helper utilities for styles, scoped attributes, and semi-controlled components.
  • Bug Fixes

    • Not applicable.
  • Documentation

    • Added detailed guides and API references for all major features and adapters.
  • Tests

    • Introduced comprehensive test suites for Pinia, Vuex, lifecycle hooks, directives, conditional rendering, props, and global APIs to ensure reliability and correctness.
  • Chores

    • Added configuration files for TypeScript, Babel, Prettier, Vitest, and Rollup to streamline development, building, and testing workflows.
    • Included scripts for building, testing, and generating type declarations.

@changeset-bot
Copy link

changeset-bot bot commented Jul 11, 2025

⚠️ No Changeset found

Latest commit: e8c30dd

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Jul 11, 2025

Walkthrough

This change introduces a new inula-adapter package, providing a comprehensive Vue compatibility layer built on top of the OpenInula framework. It includes source code for Vue, Pinia, and Vuex adapters, extensive documentation, configuration files, build/test scripts, and a robust suite of tests and usage examples. The design enables Vue-like APIs, lifecycle hooks, directives, state management, and component patterns to function in an OpenInula environment.

Changes

File(s) / Group Change Summary
package.json, packages/inula-adapter/package.json, .../npm/*/package.json Added package metadata, scripts, dependencies, and module/type entry points for adapter packages.
packages/inula-adapter/.gitignore, .prettierrc.js, babel.config.js Added ignore rules, Prettier, and Babel configuration for code formatting and transpilation.
packages/inula-adapter/tsconfig*.json Added TypeScript configs for main, Vue, Pinia, and Vuex packages, focusing on declaration output.
packages/inula-adapter/vitest.config.ts Added Vitest config with React plugin, jsdom environment, and React-to-OpenInula module aliases.
packages/inula-adapter/scripts/* Added Rollup build configs and type bundling scripts for multi-package output and cleanup.
packages/inula-adapter/src/vue/, .../src/pinia/, .../src/vuex/* Implemented Vue, Pinia, and Vuex adapters, including APIs, lifecycle hooks, directives, and helpers.
packages/inula-adapter/src/vue/keepAlive/* Added KeepAlive/KeepAlivePro components and lifecycle management for component caching.
packages/inula-adapter/src/vuex/maps.ts, types.ts, vuex.ts Implemented Vuex helpers, types, and a Vuex-like store system atop OpenInula's reactive store.
packages/inula-adapter/src/pinia/pinia.ts, types.ts Implemented Pinia-compatible store definition, mapping, and utility helpers.
packages/inula-adapter/examples/**/* Added numerous usage examples comparing Vue SFCs and OpenInula/JSX equivalents.
packages/inula-adapter/docs/* Added documentation on global API, Pinia, Vuex, and lifecycle differences and migration guidance.
packages/inula-adapter/tests/**/* Added comprehensive test suites for Pinia, Vuex, Vue adapter features, lifecycle, and reactivity.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant Adapter
    participant OpenInula
    participant Store

    User->>App: createApp(rootComponent)
    App->>Adapter: Initializes AppContext, config, global properties
    App->>Adapter: Registers components, directives, plugins
    App->>OpenInula: Renders rootComponent via OpenInula
    User->>App: app.use(plugin) / app.component() / app.directive()
    App->>Adapter: Registers plugin/component/directive globally
    User->>App: app.mount(container)
    App->>OpenInula: Mounts to DOM container

    User->>Adapter: defineStore(options) (Pinia)
    Adapter->>Store: Creates or retrieves singleton store instance
    Store->>OpenInula: Uses reactive state, actions, getters

    User->>Adapter: createStore(options) (Vuex)
    Adapter->>Store: Initializes root/module stores, proxies state/getters
    Store->>OpenInula: Uses reactive state, mutations, actions, modules
Loading

Poem

🐇
A new adapter hops to view,
Vue and Inula, joined anew!
With scripts and tests and docs so bright,
State and hooks now work just right.
From lifecycles to stores,
And directives galore—
This rabbit’s code leaps out the door!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 77

♻️ Duplicate comments (3)
packages/inula-adapter/examples/$el/TypewriterInput.vue (1)

11-17: Verify the addListener API consistency.

Similar to the JSX version, this component uses addListener which is non-standard for DOM elements. Please verify this is the correct API for the Vue adapter and ensure consistency across both implementations.

The same addListener API issue exists in both component versions. Standard DOM elements use addEventListener, and the event names should typically be lowercase (keydown, keyup instead of keyDown, keyUp).

packages/inula-adapter/tsconfig.vuex.json (1)

1-10: Same trailing-comma issue as in tsconfig.vue.json

Replicate the fix (or suppress the linter rule) to avoid inconsistent build behaviour.

-    "declarationDir": "./build/vuex/@types"
-  },
+    "declarationDir": "./build/vuex/@types"
+  }
packages/inula-adapter/tsconfig.pinia.json (1)

1-10: Repeat of trailing-comma / Biome parse error

For consistency, drop the trailing comma here as well.

-    "declarationDir": "./build/pinia/@types"
-  },
+    "declarationDir": "./build/pinia/@types"
+  }
🧹 Nitpick comments (71)
packages/inula-adapter/tests/utils/globalSetup.js (2)

18-22: Prefer globalThis over Node-specific global.

global is Node-specific, whereas globalThis is standards-based and works in both browser‐like and Node environments (Vitest’s JSDOM, workers, etc.).
Switching prevents subtle reference errors when a non-Node runtime is introduced.

-beforeEach(() => {
-  // 创建一个 DOM 元素作为渲染目标
-  global.container = document.createElement('div');
-  document.body.appendChild(global.container);
-});
+beforeEach(() => {
+  // 创建一个 DOM 元素作为渲染目标
+  globalThis.container = document.createElement('div');
+  document.body.appendChild(globalThis.container);
+});

24-27: Guard against missing container & detach safely.

If a test crashes before beforeEach completes, afterEach will currently throw (global.container is undefined).
Add a null-check and use globalThis consistently.

-afterEach(() => {
-  global.container.remove();
-  global.container = null;
-});
+afterEach(() => {
+  if (globalThis.container) {
+    globalThis.container.remove();
+    globalThis.container = null;
+  }
+});
packages/inula-adapter/examples/$forceUpdate/clock.jsx (1)

1-1: Remove unused props parameter.

The props parameter is defined but never used in the component.

Apply this diff to remove the unused parameter:

-export default function (props) {
+export default function Clock() {
packages/inula-adapter/examples/$el/TypewriterInput.jsx (1)

4-4: Remove unused props parameter.

The props parameter is defined but never used in the function, as correctly flagged by ESLint.

-export default function (props) {
+export default function () {
packages/inula-adapter/tsconfig.vue.json (1)

1-10: Trailing comma triggers lint error – consider JSONC‐safe but linter-hostile.

tsc accepts trailing commas in tsconfig.json (it is parsed as JSONC), yet Biome flags this as an error. If your CI / pre-commit pipeline uses Biome (or another strict JSON parser), builds might fail.

-  "compilerOptions": {
-    "emitDeclarationOnly": true,
-    "declarationDir": "./build/vue/@types"
-  },
+  "compilerOptions": {
+    "emitDeclarationOnly": true,
+    "declarationDir": "./build/vue/@types"
+  }

Confirm whether Biome (or any other JSON-validator) runs in the pipeline. If yes, the diff above silences the error; if not, feel free to keep the trailing comma.

packages/inula-adapter/src/vue/types.ts (1)

16-16: Type alias name deviates from common casing conventions

FN in all-caps reads like a constant; TypeScript community tends to use Fn, Noop, or similar for function aliases. Consider:

-export type FN = () => void;
+export type Fn = () => void;

If the alias is already consumed elsewhere, update imports accordingly.

packages/inula-adapter/src/vue/keepAlive/index.ts (1)

1-4: Expose default & named export in a single statement for better DX

Today consumers need:

import { KeepAlive } from '.../keepAlive';

but cannot do import KeepAlive from .... You can provide both with a tiny tweak:

-import KeepAlive from './keepAlive';
-import { useActivatePro, useUnActivatePro } from './lifeCycleHooks';
-
-export { KeepAlive, useActivatePro, useUnActivatePro };
+export { default as KeepAlive } from './keepAlive';
+export { useActivatePro, useUnActivatePro } from './lifeCycleHooks';

Same runtime behaviour, leaner code, and dual import style supported.

packages/inula-adapter/examples/emitter/listener.jsx (1)

1-1: Remove unused parameter.

The props parameter is defined but never used.

-export default function (props) {
+export default function () {
packages/inula-adapter/examples/$t - plugins/App.jsx (1)

3-3: Remove unused parameter.

The props parameter is defined but never used.

-export default function (props) {
+export default function () {
packages/inula-adapter/examples/$root/root.jsx (1)

3-3: Remove unused props parameter.

The props parameter is defined but never used in the component. Remove it to clean up the code.

-export default function (props) {
+export default function () {
packages/inula-adapter/examples/emitter/emitter.jsx (2)

1-1: Remove unused props parameter.

The props parameter is defined but never used.

-export default function (props) {
+export default function () {

2-4: Optimize useInstance calls for better performance.

Calling useInstance() multiple times is inefficient. Consider storing the instance reference.

+import { useInstance } from 'vue-inula';
+
 export default function () {
+  const instance = useInstance();
+  
   function clicked() {
-    useInstance().$refs.emitter.$emit('eventEmitterClicked');
+    instance.$refs.emitter.$emit('eventEmitterClicked');
   }
packages/inula-adapter/examples/$t - plugins/i18n.js (1)

8-8: Fix Spanish translation typo.

"Ola" should be "Hola" in Spanish.

-    introduction: 'Ola, yo soy Dora.',
+    introduction: 'Hola, yo soy Dora.',
packages/inula-adapter/examples/$refs/refresh.jsx (2)

3-3: Remove unused props parameter.

The props parameter is defined but never used.

-export default function (props) {
+export default function () {

4-10: Optimize useInstance calls for better performance.

Calling useInstance() multiple times is inefficient. Consider storing the instance reference.

 export default function () {
+  const instance = useInstance();
+  
   function validateAndSubmit() {
-    if (!useInstance().$refs[0].value) {
-      useInstance().$refs[0].focus();
+    if (!instance.$refs[0].value) {
+      instance.$refs[0].focus();
     } else {
       submit();
     }
   }
packages/inula-adapter/examples/$children/FruitList.jsx (1)

3-3: Remove unused props parameter.

The props parameter is defined but never used in the component.

Remove the unused parameter:

-export default function (props) {
+export default function () {
packages/inula-adapter/.prettierrc.js (1)

16-16: Remove redundant 'use strict' directive.

The 'use strict' directive is redundant in ES modules as strict mode is automatically applied.

Remove the redundant directive:

*/

-'use strict';
-
module.exports = {
packages/inula-adapter/examples/$nextTick/nextTick.jsx (1)

1-1: Remove unused props parameter.

The props parameter is defined but never used in the component.

-export default function (props) {
+export default function () {
packages/inula-adapter/tsconfig.json (2)

10-10: Consider translating Chinese comments to English.

The comment is in Chinese which may limit accessibility for international contributors.

-    "noUnusedLocals": false,  // 等大部分js代码改成ts之后再启用.
+    "noUnusedLocals": false,  // Enable after most JS code is converted to TS.

28-28: Consider translating Chinese comments to English.

The comment is in Chinese which may limit accessibility for international contributors.

-    "types": ["jest"], // 赋值为空数组使@types/node不会起作用
+    "types": ["jest"], // Setting to empty array prevents @types/node from taking effect
packages/inula-adapter/src/vue/injectProvide.tsx (1)

1-1: Remove unused import.

The useContext import is not used in this module.

-import { createContext, useContext } from 'openinula';
+import { createContext } from 'openinula';
packages/inula-adapter/docs/README_vuex.md (1)

75-75: Fix numbering inconsistency in the documentation.

There are two sections numbered "4" in the documentation. The section about store.replaceState should be numbered "5", and subsequent sections should be renumbered accordingly.

-4、不支持store.replaceState
+5、不支持store.replaceState

Also update the following sections:

  • Line 125: "5、store.registerModule不支持传入options参数" → "6、store.registerModule不支持传入options参数"
  • Line 139: "5、dispatch不支持传入options参数" → "7、dispatch不支持传入options参数"
  • Line 144: "6、不支持action中的root属性" → "8、不支持action中的root属性"
  • Line 163: "7、createStore中不支持plugins" → "9、createStore中不支持plugins"
packages/inula-adapter/examples/$set/fruits.jsx (1)

3-3: Remove unused props parameter.

The props parameter is defined but never used in the component.

-export default function (props) {
+export default function () {
packages/inula-adapter/tests/pinia/pinia.store.test.ts (1)

74-74: Address the skipped test for state replacement.

The test for replacing store state is currently skipped. This might indicate missing functionality or a known limitation in the Pinia adapter.

Would you like me to help investigate why this test is skipped and potentially implement the missing functionality for state replacement?

packages/inula-adapter/tests/pinia/pinia.state.test.ts (3)

20-20: Remove unused import.

The reactive import is not used in this test file and should be removed.

-const { watch, computed, ref, reactive, nextTick } = vueReactive;
+const { watch, computed, ref, nextTick } = vueReactive;

122-123: Add description to @ts-expect-error directive.

The @ts-expect-error directive should include a description explaining why it's necessary.

-    // @ts-expect-error
+    // @ts-expect-error: intentionally assigning ref to test reactivity behavior
     store.$state.name = nameRef;

132-133: Add description to @ts-expect-error directive.

The @ts-expect-error directive should include a description explaining why it's necessary.

-    // @ts-expect-error
+    // @ts-expect-error: intentionally assigning ref to test state synchronization
     store.$state.name = ref('Ed');
packages/inula-adapter/src/vue/dynamicComponent.tsx (2)

15-15: Remove unused import.

The Inula import is not used since JSX transformation is handled by Babel with the automatic runtime.

-import Inula, { ComponentType, InulaElement } from 'openinula';
+import { ComponentType, InulaElement } from 'openinula';

50-54: Use optional chaining for safer property access.

The code can be made more robust by using optional chaining to prevent potential runtime errors.

     // If not found, look in global components
     if (!Component) {
-      const app = getCurrentInstance().appContext.app;
-      Component = app._context.components[pascalCaseName];
+      Component = getCurrentInstance()?.appContext?.app?._context?.components?.[pascalCaseName];
     }
packages/inula-adapter/tests/utils/testingLibrary.js (3)

16-16: Remove unused import.

The Inula import is not used anywhere in the file.

-import Inula from 'openinula';

21-29: Consider adding cleanup mechanism for rendered components.

The render function creates DOM elements and appends them to document.body but doesn't provide a cleanup mechanism. This could lead to DOM pollution between tests.

Consider returning a cleanup function:

export function render(component) {
  const container = document.createElement('div');
  document.body.appendChild(container);

  const app = createApp(component);
  app.mount(container);

-  return { container, app };
+  return { 
+    container, 
+    app, 
+    cleanup: () => {
+      app.unmount();
+      document.body.removeChild(container);
+    }
+  };
}

67-79: Use optional chaining for safer property access.

The toHaveTextContent matcher can be improved with optional chaining to handle null/undefined values more safely.

  toHaveTextContent(received, expected) {
-    const pass = received && received.textContent.includes(expected);
+    const pass = received?.textContent?.includes(expected);
    if (pass) {
      return {
        message: () => `expected ${received} not to have text content "${expected}"`,
        pass: true,
      };
    } else {
      return {
        message: () => `expected ${received} to have text content "${expected}"`,
        pass: false,
      };
    }
  },
packages/inula-adapter/tests/vuex/vuex.component.test.tsx (1)

16-16: Remove unused import.

The vi import from vitest is not used in the tests.

-import { describe, expect, it, vi } from 'vitest';
+import { describe, expect, it } from 'vitest';
packages/inula-adapter/tests/pinia/pinia.storeToRefs.test.ts (1)

16-16: Remove unused import.

The vi import from vitest is not used in the tests.

-import { beforeEach, describe, it, vi, expect } from 'vitest';
+import { beforeEach, describe, it, expect } from 'vitest';
packages/inula-adapter/tests/vuex/vuex.modules.test.ts (2)

16-16: Remove unused import.

The beforeEach import is not used in the test file.

-import { describe, it, expect, beforeEach, vi } from 'vitest';
+import { describe, it, expect, vi } from 'vitest';

103-103: Fix typo in test name.

"existance" should be "existence".

-  it('dynamic module existance test', () => {
+  it('dynamic module existence test', () => {
packages/inula-adapter/tests/vue/injectProvide.test.tsx (2)

19-19: Remove unused import.

The vi import is not used in the test file.

-import { describe, expect, it, vi, beforeEach } from 'vitest';
+import { describe, expect, it, beforeEach } from 'vitest';

22-22: Remove empty beforeEach.

The empty beforeEach function serves no purpose and can be removed.

-  beforeEach(() => {});
packages/inula-adapter/tests/vue/liftcycle.test.tsx (1)

1-1: Fix filename typo.

The filename "liftcycle" should be "lifecycle".

Consider renaming the file to lifecycle.test.tsx to fix the typo.

packages/inula-adapter/tests/vue/sfcAPI.test.tsx (1)

16-16: Remove unused import.

The vi import is not used in this test file.

-import { describe, it, vi, expect } from 'vitest';
+import { describe, it, expect } from 'vitest';
packages/inula-adapter/src/vue/condition.tsx (1)

16-16: Remove unused import.

The Inula import is not used anywhere in the file and should be removed.

-import Inula, { isValidElement, Children, FC } from 'openinula';
+import { isValidElement, Children, FC } from 'openinula';
packages/inula-adapter/tests/vue/props.test.tsx (1)

16-16: Remove unused import.

The vi import from vitest is not used in this test file and should be removed.

-import { describe, it, vi, expect } from 'vitest';
+import { describe, it, expect } from 'vitest';
packages/inula-adapter/tests/pinia/pinia.getters.test.ts (3)

37-39: Add descriptive comment for @ts-expect-error directive.

The @ts-expect-error directive should include a description explaining why the error is expected.

-        // @ts-expect-error
+        // @ts-expect-error: Testing access to non-existent property
         state.nope;

54-56: Clean up unused variables.

The variables useB and useA are declared but never used in the tests.

   let useStore = createStore();
-  let useB;
-  let useA;

69-71: Add descriptive comment for @ts-expect-error directive.

The @ts-expect-error directive should include a description explaining why the error is expected.

-    // @ts-expect-error
+    // @ts-expect-error: Testing access to non-existent property
     store.nope;
packages/inula-adapter/tests/vue/condition.test.tsx (2)

19-19: Remove unused import.

The vi import from vitest is not used in this test file and should be removed.

-import { describe, expect, it, vi } from 'vitest';
+import { describe, expect, it } from 'vitest';

23-23: Remove unused variable.

The useReference variable is destructured but never used in the tests.

-const { useReactive, useReference } = vueReactive;
+const { useReactive } = vueReactive;
packages/inula-adapter/src/vue/helper.tsx (1)

94-94: Use const for variables that are never reassigned.

The variable key is never reassigned and should be declared as const.

Apply this diff:

- for (let key in styleObject) {
+ for (const key in styleObject) {
packages/inula-adapter/src/vue/semiControlledComponent.tsx (1)

16-16: Remove unused import.

The Inula import is never used in this file.

Apply this diff:

- import Inula, { useState, useEffect, useRef, ChangeEvent, FC } from 'openinula';
+ import { useState, useEffect, useRef, ChangeEvent, FC } from 'openinula';
packages/inula-adapter/tests/vue/attrs.test.tsx (5)

16-17: Remove unused imports.

Several imports are defined but never used in the test file.

Apply this diff:

- import { describe, it, vi, expect } from 'vitest';
- import { render, act, vueReactive, useState, Component, memo, forwardRef } from 'openinula';
+ import { describe, it, expect } from 'vitest';
+ import { act, useState, Component, memo, forwardRef } from 'openinula';

221-223: Remove unnecessary constructor.

The constructor doesn't add any functionality and can be removed.

Apply this diff:

class App extends Component {
- constructor(props) {
-   super(props);
- }
  render() {
    return <Parent style="background-color:yellow; width: 100%" />;
  }
}

264-266: Remove unnecessary constructor.

The constructor doesn't add any functionality and can be removed.

Apply this diff:

class App extends Component {
- constructor(props) {
-   super(props);
- }
  render() {
    return <Parent style="background-color:yellow; width: 100%" />;
  }
}

307-309: Remove unnecessary constructor.

The constructor doesn't add any functionality and can be removed.

Apply this diff:

class App extends Component {
- constructor(props) {
-   super(props);
- }
  render() {
    return <Parent style="background-color:yellow; width: 100%" />;
  }
}

329-329: Remove unused parameter.

The resolve parameter in the describe function is never used.

Apply this diff:

- describe('$attrs: $attrs object', async resolve => {
+ describe('$attrs: $attrs object', () => {
packages/inula-adapter/src/vue/props.tsx (1)

15-15: Remove unused import.

The Inula import is never used in this file.

Apply this diff:

- import Inula, { vueReactive, useRef, ReactiveRet } from 'openinula';
+ import { vueReactive, useRef, ReactiveRet } from 'openinula';
packages/inula-adapter/tests/vue/globalAPI.test.tsx (1)

27-27: Remove unused import.

The vi import is not used anywhere in this test file.

-import { describe, expect, it, vi, beforeEach } from 'vitest';
+import { describe, expect, it, beforeEach } from 'vitest';
packages/inula-adapter/tests/vue/keepAlivePro.test.tsx (2)

19-19: Remove unused import.

The vi import is not used anywhere in this test file.

-import { describe, expect, it, vi, beforeEach } from 'vitest';
+import { describe, expect, it, beforeEach } from 'vitest';

29-29: Fix incorrect test suite name.

The describe block incorrectly names the test suite as "KeepAlive" when it should be "KeepAlivePro" to match the component being tested.

-describe('component: KeepAlive', () => {
+describe('component: KeepAlivePro', () => {
packages/inula-adapter/tests/vue/keepAlive.test.tsx (1)

71-71: Remove commented out code

The commented line appears to be leftover from debugging.

-    // await wait(10);
packages/inula-adapter/src/pinia/pinia.ts (1)

196-208: Address ESLint warnings for unused parameters

The parameters app and plugin are part of the Pinia interface but intentionally unused in this stub implementation.

  const result = {
-    install: (app: any) => {},
-    use: (plugin: any) => result,
+    install: (_app: any) => {},
+    use: (_plugin: any) => result,
    state: {},
  };

Alternatively, disable the ESLint rule for these specific lines:

  const result = {
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    install: (app: any) => {},
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    use: (plugin: any) => result,
    state: {},
  };
packages/inula-adapter/src/vue/directive.tsx (2)

94-103: Use optional chaining for cleaner code

Replace the conditional checks with optional chaining as suggested by Biome.

  let directiveObj: Directive = {};
- if (registerDirectives && registerDirectives[name]) {
-   directiveObj = registerDirectives[name];
- } else {
-   directiveObj = appDirectives[name];
- }
+ directiveObj = registerDirectives?.[name] || appDirectives[name];

- if (directiveObj && directiveObj[hook]) {
-   directiveObj[hook]!(instance['$el']!, { value, oldValue, arg, modifiers });
- }
+ directiveObj?.[hook]?.(instance['$el']!, { value, oldValue, arg, modifiers });

87-89: Add type annotation for directives parameter

The directives parameter in the callback lacks type annotation.

  const prevDirectiveValues: Record<string, any> = useMemo(() => ({}), []);
- const applyDirectives = useCallback((hook: keyof Directive, directives) => {
+ const applyDirectives = useCallback((hook: keyof Directive, directives: DirectiveComponentProps['directives']) => {
    directives.forEach(directive => {
packages/inula-adapter/src/vue/useScoped.ts (2)

79-80: Consider deferring vnode traversal for better performance

The getFirstSingleDomVnode call happens on every render even when it's only needed for style updates.

Consider moving this call inside the effects that use it, or memoize the result:

- const vDomNode = getFirstSingleDomVnode(instance?.$vnode);
+ const vDomNode = useMemo(() => getFirstSingleDomVnode(instance?.$vnode), [instance?.$vnode]);

172-177: Improve readability of complex condition

Consider extracting the complex condition for better readability.

+ const shouldSkip = shouldSkipSetAttrToEl(instance.$vnode);
+ const styleUnchanged = shallowCompare(preNodeStyle.current, vDomNode?.props.style);
+
  useLayoutEffect(() => {
-   if (shouldSkipSetAttrToEl(instance.$vnode) || shallowCompare(preNodeStyle.current, vDomNode?.props.style)) {
+   if (shouldSkip || styleUnchanged) {
      return;
    }
    preNodeStyle.current = vDomNode?.props.style;
    mergeStyle();
  }, [vDomNode?.props.style]);
packages/inula-adapter/scripts/rollup.config.js (1)

95-98: Translate Chinese comments to English for consistency.

The codebase should maintain language consistency in comments.

Apply this diff:

-        // 判断目标文件夹是否存在
+        // Check if the destination directory exists
         if (!fs.existsSync(destDir)) {
-          // 目标文件夹不存在,创建它
+          // If destination directory doesn't exist, create it
           fs.mkdirSync(destDir, { recursive: true });
packages/inula-adapter/src/vue/keepAlive/keepAlive.tsx (1)

12-13: Translate Chinese comments to English for consistency.

Apply this diff:

-// 更新缓存的children节点key数组
-// 当缓存的实例超过max时,移除最久没有使用的组件缓存, 并把最新的key插到尾部
+// Update the array of cached children node keys
+// When cached instances exceed max, remove the least recently used component cache and insert the latest key at the end
packages/inula-adapter/src/vue/sfcAPI.tsx (3)

2-2: Update copyright year to match the current year.

The copyright year shows 2020, but this is a new file being added in 2025.

- * Copyright (c) 2020 Huawei Technologies Co.,Ltd.
+ * Copyright (c) 2025 Huawei Technologies Co.,Ltd.

71-72: Translate Chinese comment to English for consistency.

Apply this diff:

-    // 检查 exposed 是否是一个对象
+    // Check if exposed is an object
     if (typeof exposed === 'object' && exposed !== null) {

89-94: Consider implementing emit validation based on the emits declaration.

The defineEmits function accepts an emits parameter but doesn't use it for validation. In Vue, this parameter is used to validate emitted events.

Consider adding validation logic to ensure only declared events are emitted, similar to Vue's behavior. This would help catch typos and improve type safety.

Would you like me to generate an implementation that validates emitted events against the emits declaration?

packages/inula-adapter/src/vuex/maps.ts (1)

99-101: Simplify argument spreading in commit and dispatch wrappers.

The current implementation uses array indexing which is less readable and error-prone.

Apply this diff to improve readability:

-        commit = (...args) => {
-          store.commit(args[0], args[1], args[2], moduleName);
-        };
+        commit = (type, payload, options) => {
+          store.commit(type, payload, options, moduleName);
+        };

And similarly for dispatch:

-        dispatch = (...args) => {
-          store.dispatch(args[0], args[1], args[2], moduleName);
-        };
+        dispatch = (type, payload, options) => {
+          store.dispatch(type, payload, options, moduleName);
+        };

Also applies to: 134-136

packages/inula-adapter/src/vue/globalAPI.tsx (1)

218-225: Optimize kebabToCamelCase implementation

The current implementation creates multiple intermediate strings. Consider a more efficient approach.

 function kebabToCamelCase(str: string) {
-  return str
-    .split('-')
-    .map(sub => {
-      return sub.charAt(0).toUpperCase() + sub.substr(1);
-    })
-    .join('');
+  return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())
+    .replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83f90ba and e8c30dd.

📒 Files selected for processing (102)
  • package.json (1 hunks)
  • packages/inula-adapter/.gitignore (1 hunks)
  • packages/inula-adapter/.prettierrc.js (1 hunks)
  • packages/inula-adapter/README.md (1 hunks)
  • packages/inula-adapter/babel.config.js (1 hunks)
  • packages/inula-adapter/docs/README_global_api.md (1 hunks)
  • packages/inula-adapter/docs/README_pinia.md (1 hunks)
  • packages/inula-adapter/docs/README_vue.md (1 hunks)
  • packages/inula-adapter/docs/README_vuex.md (1 hunks)
  • packages/inula-adapter/examples/$children/FruitItem.jsx (1 hunks)
  • packages/inula-adapter/examples/$children/FruitItem.vue (1 hunks)
  • packages/inula-adapter/examples/$children/FruitList.jsx (1 hunks)
  • packages/inula-adapter/examples/$children/FruitList.vue (1 hunks)
  • packages/inula-adapter/examples/$el/TypewriterInput.jsx (1 hunks)
  • packages/inula-adapter/examples/$el/TypewriterInput.vue (1 hunks)
  • packages/inula-adapter/examples/$forceUpdate/clock.jsx (1 hunks)
  • packages/inula-adapter/examples/$forceUpdate/clock.vue (1 hunks)
  • packages/inula-adapter/examples/$nextTick/nextTick.jsx (1 hunks)
  • packages/inula-adapter/examples/$nextTick/nextTick.vue (1 hunks)
  • packages/inula-adapter/examples/$parent/list-item.jsx (1 hunks)
  • packages/inula-adapter/examples/$parent/list-item.vue (1 hunks)
  • packages/inula-adapter/examples/$parent/list.jsx (1 hunks)
  • packages/inula-adapter/examples/$parent/list.vue (1 hunks)
  • packages/inula-adapter/examples/$refs/refresh.jsx (1 hunks)
  • packages/inula-adapter/examples/$refs/refresh.vue (1 hunks)
  • packages/inula-adapter/examples/$root/root.jsx (1 hunks)
  • packages/inula-adapter/examples/$root/root.vue (1 hunks)
  • packages/inula-adapter/examples/$root/themeChanger.jsx (1 hunks)
  • packages/inula-adapter/examples/$root/themeChanger.vue (1 hunks)
  • packages/inula-adapter/examples/$set/fruits.jsx (1 hunks)
  • packages/inula-adapter/examples/$set/fruits.vue (1 hunks)
  • packages/inula-adapter/examples/$t - plugins/App.jsx (1 hunks)
  • packages/inula-adapter/examples/$t - plugins/App.vue (1 hunks)
  • packages/inula-adapter/examples/$t - plugins/i18n.js (1 hunks)
  • packages/inula-adapter/examples/$t - plugins/main.js (1 hunks)
  • packages/inula-adapter/examples/custom functions/main.js (1 hunks)
  • packages/inula-adapter/examples/emitter/emitter.jsx (1 hunks)
  • packages/inula-adapter/examples/emitter/emitter.vue (1 hunks)
  • packages/inula-adapter/examples/emitter/listener.jsx (1 hunks)
  • packages/inula-adapter/examples/emitter/listener.vue (1 hunks)
  • packages/inula-adapter/npm/pinia/package.json (1 hunks)
  • packages/inula-adapter/npm/vuex/package.json (1 hunks)
  • packages/inula-adapter/package.json (1 hunks)
  • packages/inula-adapter/scripts/build-types.js (1 hunks)
  • packages/inula-adapter/scripts/rollup.config.js (1 hunks)
  • packages/inula-adapter/src/pinia/index.ts (1 hunks)
  • packages/inula-adapter/src/pinia/pinia.ts (1 hunks)
  • packages/inula-adapter/src/pinia/types.ts (1 hunks)
  • packages/inula-adapter/src/vue/Teleport.ts (1 hunks)
  • packages/inula-adapter/src/vue/compare.ts (1 hunks)
  • packages/inula-adapter/src/vue/condition.tsx (1 hunks)
  • packages/inula-adapter/src/vue/directive.tsx (1 hunks)
  • packages/inula-adapter/src/vue/dynamicComponent.tsx (1 hunks)
  • packages/inula-adapter/src/vue/globalAPI.tsx (1 hunks)
  • packages/inula-adapter/src/vue/helper.tsx (1 hunks)
  • packages/inula-adapter/src/vue/index.ts (1 hunks)
  • packages/inula-adapter/src/vue/injectProvide.tsx (1 hunks)
  • packages/inula-adapter/src/vue/keepAlive/context.ts (1 hunks)
  • packages/inula-adapter/src/vue/keepAlive/index.ts (1 hunks)
  • packages/inula-adapter/src/vue/keepAlive/keepAlive.tsx (1 hunks)
  • packages/inula-adapter/src/vue/keepAlive/keeper.tsx (1 hunks)
  • packages/inula-adapter/src/vue/keepAlive/lifeCycleHooks.ts (1 hunks)
  • packages/inula-adapter/src/vue/keepAlivePro.tsx (1 hunks)
  • packages/inula-adapter/src/vue/lifecycle.ts (1 hunks)
  • packages/inula-adapter/src/vue/props.tsx (1 hunks)
  • packages/inula-adapter/src/vue/semiControlledComponent.tsx (1 hunks)
  • packages/inula-adapter/src/vue/sfcAPI.tsx (1 hunks)
  • packages/inula-adapter/src/vue/types.ts (1 hunks)
  • packages/inula-adapter/src/vue/useScoped.ts (1 hunks)
  • packages/inula-adapter/src/vue/vShow.ts (1 hunks)
  • packages/inula-adapter/src/vuex/index.ts (1 hunks)
  • packages/inula-adapter/src/vuex/maps.ts (1 hunks)
  • packages/inula-adapter/src/vuex/types.ts (1 hunks)
  • packages/inula-adapter/src/vuex/vuex.ts (1 hunks)
  • packages/inula-adapter/tests/pinia/pinia.actions.test.ts (1 hunks)
  • packages/inula-adapter/tests/pinia/pinia.getters.test.ts (1 hunks)
  • packages/inula-adapter/tests/pinia/pinia.state.test.ts (1 hunks)
  • packages/inula-adapter/tests/pinia/pinia.store.test.ts (1 hunks)
  • packages/inula-adapter/tests/pinia/pinia.storeSetup.test.ts (1 hunks)
  • packages/inula-adapter/tests/pinia/pinia.storeToRefs.test.ts (1 hunks)
  • packages/inula-adapter/tests/utils/globalSetup.js (1 hunks)
  • packages/inula-adapter/tests/utils/testingLibrary.js (1 hunks)
  • packages/inula-adapter/tests/vue/attrs.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/condition.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/directive.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/dynamicComponent.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/globalAPI.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/injectProvide.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/keepAlive.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/keepAlivePro.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/liftcycle.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/props.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vue/sfcAPI.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vuex/vuex.component.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vuex/vuex.maps.test.tsx (1 hunks)
  • packages/inula-adapter/tests/vuex/vuex.modules.test.ts (1 hunks)
  • packages/inula-adapter/tests/vuex/vuex.store.test.ts (1 hunks)
  • packages/inula-adapter/tsconfig.json (1 hunks)
  • packages/inula-adapter/tsconfig.pinia.json (1 hunks)
  • packages/inula-adapter/tsconfig.vue.json (1 hunks)
  • packages/inula-adapter/tsconfig.vuex.json (1 hunks)
  • packages/inula-adapter/vitest.config.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (20)
packages/inula-adapter/examples/$children/FruitList.jsx (1)
packages/inula-adapter/examples/$children/FruitItem.jsx (1)
  • isChecked (5-5)
packages/inula-adapter/examples/$root/themeChanger.jsx (1)
packages/inula-adapter/examples/$root/root.jsx (1)
  • theme (4-4)
packages/inula-adapter/examples/$children/FruitItem.jsx (2)
packages/inula-adapter/src/vue/sfcAPI.tsx (1)
  • defineExpose (67-84)
packages/inula-adapter/examples/$set/fruits.jsx (1)
  • fruitName (16-16)
packages/inula-adapter/src/vue/keepAlive/context.ts (1)
packages/inula-adapter/src/vue/keepAlive/lifeCycleHooks.ts (1)
  • LifeCycleListener (34-34)
packages/inula-adapter/examples/$t - plugins/main.js (2)
packages/inula-adapter/src/vue/globalAPI.tsx (1)
  • createApp (93-194)
packages/inula-adapter/examples/$t - plugins/i18n.js (1)
  • i18n (12-16)
packages/inula-adapter/tests/pinia/pinia.storeSetup.test.ts (2)
packages/inula-adapter/tests/pinia/pinia.state.test.ts (2)
  • increment (32-34)
  • upperCased (37-39)
packages/inula-adapter/src/pinia/pinia.ts (1)
  • defineStore (51-70)
packages/inula-adapter/examples/$root/root.jsx (1)
packages/inula-adapter/src/vue/sfcAPI.tsx (1)
  • defineExpose (67-84)
packages/inula-adapter/tests/pinia/pinia.store.test.ts (1)
packages/inula-adapter/src/pinia/pinia.ts (1)
  • defineStore (51-70)
packages/inula-adapter/src/vue/semiControlledComponent.tsx (2)
packages/inula/src/types.ts (2)
  • ChangeEvent (325-327)
  • FC (93-93)
packages/inula/src/jsx-type/baseElement.ts (1)
  • HTMLInputElement (25-25)
packages/inula-adapter/tests/pinia/pinia.state.test.ts (1)
packages/inula-adapter/src/pinia/pinia.ts (2)
  • defineStore (51-70)
  • createPinia (196-208)
packages/inula-adapter/src/vue/vShow.ts (2)
packages/inula-adapter/src/vue/directive.tsx (1)
  • Directive (37-48)
packages/inula/src/jsx-type/baseElement.ts (1)
  • HTMLElement (1-1)
packages/inula-adapter/src/vuex/types.ts (1)
packages/inula/src/inulax/types.ts (1)
  • StoreObj (67-75)
packages/inula-adapter/src/vue/condition.tsx (2)
packages/inula/src/types.ts (1)
  • FC (93-93)
packages/inula/src/index.ts (1)
  • Children (130-130)
packages/inula-adapter/src/vue/keepAlive/keeper.tsx (3)
packages/inula/src/jsx-type/baseElement.ts (1)
  • HTMLElement (1-1)
packages/inula-adapter/src/vue/keepAlive/lifeCycleHooks.ts (1)
  • LifeCycleFunc (9-9)
packages/inula-adapter/src/vue/keepAlive/context.ts (1)
  • NodeKeeperLifeCycleContext (3-3)
packages/inula-adapter/src/vue/keepAlive/lifeCycleHooks.ts (1)
packages/inula-adapter/src/vue/keepAlive/context.ts (1)
  • NodeKeeperLifeCycleContext (3-3)
packages/inula-adapter/src/vuex/maps.ts (1)
packages/inula-adapter/src/vuex/vuex.ts (1)
  • moduleGettersProxy (326-335)
packages/inula-adapter/src/vue/sfcAPI.tsx (2)
packages/inula-adapter/examples/$el/TypewriterInput.jsx (1)
  • instance (5-5)
packages/inula-adapter/src/vue/globalAPI.tsx (1)
  • emit (259-273)
packages/inula-adapter/src/vue/lifecycle.ts (1)
packages/inula-adapter/src/vue/types.ts (1)
  • FN (16-16)
packages/inula-adapter/tests/pinia/pinia.getters.test.ts (1)
packages/inula-adapter/src/pinia/pinia.ts (1)
  • defineStore (51-70)
packages/inula-adapter/src/pinia/types.ts (1)
packages/inula/src/renderer/Types.ts (1)
  • RefType (60-62)
🪛 GitHub Actions: ci
package.json

[error] 1-1: pnpm install failed due to outdated lockfile. The pnpm-lock.yaml is not up to date with package.json. Run 'pnpm install --no-frozen-lockfile' to update the lockfile.

packages/inula-adapter/package.json

[error] 1-1: pnpm install failed due to outdated lockfile. The pnpm-lock.yaml is not up to date with package.json. Run 'pnpm install --no-frozen-lockfile' to update the lockfile.

🪛 ESLint
packages/inula-adapter/examples/$t - plugins/App.jsx

[error] 3-3: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/examples/emitter/listener.jsx

[error] 1-1: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 2-2: 'useInstance' is not defined.

(no-undef)


[error] 4-4: 'ButtonEmitter' is not defined.

(no-undef)

packages/inula-adapter/examples/$children/FruitList.jsx

[error] 3-3: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 8-8: 'useInstance' is not defined.

(no-undef)

packages/inula-adapter/examples/custom functions/main.js

[error] 6-6: 'removeLoadingMsg' is not defined.

(no-undef)

packages/inula-adapter/examples/$forceUpdate/clock.jsx

[error] 1-1: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 4-4: 'useEffect' is not defined.

(no-undef)


[error] 5-5: 'useState' is not defined.

(no-undef)

packages/inula-adapter/tests/pinia/pinia.storeSetup.test.ts

[error] 22-22: '_value' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/dynamicComponent.test.tsx

[error] 30-30: Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free.

(@typescript-eslint/ban-ts-comment)


[error] 46-46: Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free.

(@typescript-eslint/ban-ts-comment)


[error] 65-65: Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free.

(@typescript-eslint/ban-ts-comment)

packages/inula-adapter/tests/vuex/vuex.component.test.tsx

[error] 16-16: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/examples/$nextTick/nextTick.jsx

[error] 1-1: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 3-3: 'useEffect' is not defined.

(no-undef)


[error] 7-7: 'useInstance' is not defined.

(no-undef)

packages/inula-adapter/src/vue/injectProvide.tsx

[error] 1-1: 'useContext' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/pinia/pinia.storeToRefs.test.ts

[error] 16-16: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vue/helper.tsx

[error] 94-94: 'key' is never reassigned. Use 'const' instead.

(prefer-const)

packages/inula-adapter/examples/$root/root.jsx

[error] 3-3: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/examples/$set/fruits.jsx

[error] 3-3: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 16-16: 'useInstance' is not defined.

(no-undef)


[error] 18-18: 'useInstance' is not defined.

(no-undef)

packages/inula-adapter/src/vue/semiControlledComponent.tsx

[error] 16-16: 'Inula' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/injectProvide.test.tsx

[error] 19-19: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/pinia/pinia.state.test.ts

[error] 20-20: 'reactive' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 122-122: Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer.

(@typescript-eslint/ban-ts-comment)


[error] 132-132: Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer.

(@typescript-eslint/ban-ts-comment)

packages/inula-adapter/examples/$parent/list.jsx

[error] 10-10: 'filteredItems' is not defined.

(no-undef)


[error] 22-22: 'item' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/condition.test.tsx

[error] 19-19: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 23-23: 'useReference' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/sfcAPI.test.tsx

[error] 16-16: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/examples/$refs/refresh.jsx

[error] 3-3: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 8-8: 'submit' is not defined.

(no-undef)

packages/inula-adapter/examples/$el/TypewriterInput.jsx

[error] 4-4: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/attrs.test.tsx

[error] 16-16: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 17-17: 'render' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 17-17: 'vueReactive' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 329-329: 'resolve' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vue/condition.tsx

[error] 16-16: 'Inula' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vue/dynamicComponent.tsx

[error] 15-15: 'Inula' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/examples/emitter/emitter.jsx

[error] 1-1: 'props' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 3-3: 'useInstance' is not defined.

(no-undef)

packages/inula-adapter/tests/vue/props.test.tsx

[error] 16-16: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/utils/testingLibrary.js

[error] 16-16: 'Inula' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vuex/vuex.modules.test.ts

[error] 16-16: 'beforeEach' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vue/props.tsx

[error] 15-15: 'Inula' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/pinia/pinia.ts

[error] 202-202: 'app' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 203-203: 'plugin' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/directive.test.tsx

[error] 77-77: 'el' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 77-77: 'binding' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 87-87: 'binding' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 123-123: 'el' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 123-123: 'binding' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 134-134: 'el' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 139-139: 'el' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 139-139: 'binding' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vue/keepAlivePro.tsx

[error] 1-1: 'Memo' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 4-4: Don't use String as a type. Use string instead

(@typescript-eslint/ban-types)


[error] 4-4: Don't use String as a type. Use string instead

(@typescript-eslint/ban-types)


[error] 94-94: 'searchComponent' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 97-97: Don't use {} as a type. {} actually means "any non-nullish value".

  • If you want a type meaning "any object", you probably want object instead.
  • If you want a type meaning "any value", you probably want unknown instead.
  • If you want a type meaning "empty object", you probably want Record<string, never> instead.
  • If you really want a type meaning "any non-nullish value", you probably want NonNullable<unknown> instead.

(@typescript-eslint/ban-types)


[error] 104-104: 'data' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 107-107: Don't use {} as a type. {} actually means "any non-nullish value".

  • If you want a type meaning "any object", you probably want object instead.
  • If you want a type meaning "any value", you probably want unknown instead.
  • If you want a type meaning "empty object", you probably want Record<string, never> instead.
  • If you really want a type meaning "any non-nullish value", you probably want NonNullable<unknown> instead.

(@typescript-eslint/ban-types)


[error] 129-129: 'key' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 129-129: 'value' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 145-145: 'activeComponent' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 154-154: Don't use {} as a type. {} actually means "any non-nullish value".

  • If you want a type meaning "any object", you probably want object instead.
  • If you want a type meaning "any value", you probably want unknown instead.
  • If you want a type meaning "empty object", you probably want Record<string, never> instead.
  • If you really want a type meaning "any non-nullish value", you probably want NonNullable<unknown> instead.

(@typescript-eslint/ban-types)

packages/inula-adapter/tests/pinia/pinia.getters.test.ts

[error] 37-37: Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer.

(@typescript-eslint/ban-ts-comment)


[error] 54-54: 'useB' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 55-55: 'useA' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 69-69: Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer.

(@typescript-eslint/ban-ts-comment)

packages/inula-adapter/tests/vue/globalAPI.test.tsx

[error] 27-27: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vuex/vuex.ts

[error] 20-20: 'useComputed' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 20-20: 'computed' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 278-278: 'state' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/src/vue/globalAPI.tsx

[error] 129-129: 'mixin' is defined but never used.

(@typescript-eslint/no-unused-vars)

packages/inula-adapter/tests/vue/keepAlivePro.test.tsx

[error] 19-19: 'vi' is defined but never used.

(@typescript-eslint/no-unused-vars)

🪛 Biome (1.9.4)
packages/inula-adapter/tsconfig.vue.json

[error] 9-10: Expected a property but instead found '}'.

Expected a property here.

(parse)

packages/inula-adapter/tsconfig.vuex.json

[error] 9-10: Expected a property but instead found '}'.

Expected a property here.

(parse)

packages/inula-adapter/tsconfig.pinia.json

[error] 9-10: Expected a property but instead found '}'.

Expected a property here.

(parse)

packages/inula-adapter/examples/$children/FruitList.jsx

[error] 18-19: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

packages/inula-adapter/examples/custom functions/main.js

[error] 18-18: Illegal use of an import declaration not at the top level

move this declaration to the top level

(parse)

packages/inula-adapter/.prettierrc.js

[error] 15-16: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)

packages/inula-adapter/src/vue/helper.tsx

[error] 84-84: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

packages/inula-adapter/examples/$set/fruits.jsx

[error] 25-25: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

packages/inula-adapter/examples/$parent/list.jsx

[error] 23-23: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

packages/inula-adapter/tests/vue/attrs.test.tsx

[error] 221-223: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)


[error] 264-266: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)


[error] 307-309: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)

packages/inula-adapter/src/vue/dynamicComponent.tsx

[error] 50-51: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/inula-adapter/src/vue/compare.ts

[error] 26-27: Comparing to itself is potentially pointless.

(lint/suspicious/noSelfCompare)


[error] 27-28: Comparing to itself is potentially pointless.

(lint/suspicious/noSelfCompare)

packages/inula-adapter/tests/utils/testingLibrary.js

[error] 68-71: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/inula-adapter/src/vue/directive.tsx

[error] 95-96: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 101-102: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/inula-adapter/src/vue/keepAlivePro.tsx

[error] 4-4: Don't use 'String' as a type.

Use lowercase primitives for consistency.
Safe fix: Use 'string' instead

(lint/complexity/noBannedTypes)


[error] 4-4: Don't use 'String' as a type.

Use lowercase primitives for consistency.
Safe fix: Use 'string' instead

(lint/complexity/noBannedTypes)


[error] 97-97: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)


[error] 107-107: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)


[error] 161-161: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 154-154: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

packages/inula-adapter/src/vue/globalAPI.tsx

[error] 175-176: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🔇 Additional comments (93)
packages/inula-adapter/tests/utils/globalSetup.js (1)

18-27: Consider per-test containers for concurrent tests.

Vitest allows test.concurrent. A single shared globalThis.container can cause race conditions or double-remove errors when tests run in parallel.
Optionally create a fresh, local container per test (returned by a helper) instead of exposing a shared global.
Not blocking, but worth evaluating if you plan to adopt concurrent tests.

packages/inula-adapter/examples/$parent/list-item.jsx (1)

1-25: Good implementation of React-style component with vue-inula.

The component correctly uses useInstance() from vue-inula to access parent methods and follows proper React functional component patterns.

packages/inula-adapter/.gitignore (1)

1-5: LGTM! Standard gitignore configuration.

The gitignore file includes appropriate exclusions for a JavaScript/TypeScript project, covering dependencies, IDE configurations, build artifacts, and lock files.

package.json (2)

22-22: LGTM! Consistent build script pattern.

The new build script follows the same pattern as other package-specific build scripts in the project.


1-95: Lockfile regeneration complete

  • The pnpm lockfile has been successfully regenerated (pnpm install --no-frozen-lockfile).
  • Please commit the updated pnpm-lock.yaml to this PR to resolve the CI pipeline failure.
packages/inula-adapter/src/pinia/index.ts (1)

1-17: LGTM! Clean module entry point structure.

The file correctly serves as a simple re-export entry point for the Pinia adapter module. The copyright header and export statement are properly formatted.

packages/inula-adapter/npm/pinia/package.json (1)

1-6: LGTM! Proper package.json configuration.

The package.json correctly defines module entry points for different formats (ESM, CJS, and TypeScript declarations), following standard Node.js package conventions.

packages/inula-adapter/src/vuex/index.ts (1)

1-18: LGTM! Comprehensive module exports.

The file correctly exports from both the core Vuex adapter and mapping helpers, providing a complete API surface for consumers. The structure follows standard practices.

packages/inula-adapter/examples/$t - plugins/App.jsx (1)

1-7: LGTM! Correct i18n integration pattern.

The component correctly demonstrates how to use the useInstance hook to access Vue's $t translation function in a React-style component.

packages/inula-adapter/examples/$t - plugins/main.js (1)

1-7: LGTM! Standard Vue app initialization pattern.

The code correctly follows Vue 3 application setup patterns with proper import from the vue-inula adapter, plugin installation, and mounting sequence.

packages/inula-adapter/src/vue/keepAlive/context.ts (1)

1-3: LGTM! Properly implemented context creation.

The context is correctly typed and initialized with appropriate default value for the keep-alive lifecycle management system.

packages/inula-adapter/npm/vuex/package.json (1)

1-5: LGTM! Package structure follows best practices.

The package.json correctly defines entry points for different module systems (ESM, CommonJS) and TypeScript declarations, following standard dual package publishing conventions.

packages/inula-adapter/examples/$root/themeChanger.jsx (1)

1-19: LGTM! Component implementation follows correct patterns.

The component correctly uses the useInstance() hook to access the root instance and implements proper event handling. The JSX structure and prop usage are appropriate for a theme changer component.

packages/inula-adapter/examples/$root/root.jsx (1)

12-12: Ignore reactive ref unwrap suggestion

The inula-adapter’s JSX runtime (via openinula.createElement) automatically unwraps reactive refs when assigning props, so passing theme directly is correct. No change to <app color={theme} /> is needed.

Likely an incorrect or invalid review comment.

packages/inula-adapter/examples/$children/FruitItem.jsx (1)

1-25: LGTM! Well-implemented Vue-style functional component.

The component correctly demonstrates Vue API compatibility with React-style JSX syntax. The use of useRef for reactive state and defineExpose for exposing internal state to parent components follows the expected pattern for the inula-adapter.

packages/inula-adapter/vitest.config.ts (2)

18-22: Well-configured alias mapping for OpenInula integration.

The alias configuration correctly redirects React imports to OpenInula equivalents, which is essential for the Vue adapter to work properly with the OpenInula framework.


24-32: Proper Vitest configuration for the adapter package.

The configuration correctly sets up the React plugin, jsdom environment, and module resolution, providing a solid foundation for testing the Vue adapter functionality.

packages/inula-adapter/.prettierrc.js (1)

18-32: Comprehensive Prettier configuration.

The configuration provides appropriate formatting rules for the project, including sensible defaults for line width, indentation, quotes, and other formatting preferences.

packages/inula-adapter/tsconfig.json (1)

1-35: Configuration looks comprehensive and well-structured.

The TypeScript configuration covers all necessary compiler options for a mixed JS/TS project with JSX support.

packages/inula-adapter/src/vue/index.ts (1)

16-28: Clean barrel export structure.

The module index properly re-exports from all submodules, providing a clean API surface for the Vue adapter package.

packages/inula-adapter/src/vue/injectProvide.tsx (1)

7-16: Ignore React-style Context.Provider advice in Vue adapter

The provide/inject pair in packages/inula-adapter/src/vue/injectProvide.tsx is a Vue-Composition-API–style implementation that simply stores values by key in a local map. It isn’t part of Inula’s React-style Context.Provider system, so pointing at <Context.Provider> here doesn’t apply. You can safely disregard this suggestion.

Likely an incorrect or invalid review comment.

packages/inula-adapter/docs/README_vuex.md (1)

1-188: Documentation provides comprehensive coverage of Vuex limitations.

The documentation clearly outlines the key differences and limitations of the Vuex adapter implementation compared to standard Vuex. The code examples effectively demonstrate each limitation, making it easy for developers to understand what features are not supported.

packages/inula-adapter/tests/vuex/vuex.store.test.ts (1)

25-343: Comprehensive test suite with excellent coverage.

The test suite provides thorough coverage of the Vuex store functionality including:

  • Mutations with both direct and object-style commits
  • Synchronous and asynchronous actions with Promise handling
  • Getters and their integration with actions
  • Subscription mechanisms for both mutations and actions
  • Watch API functionality with proper lifecycle testing
  • Error handling and edge cases

The tests are well-structured, use appropriate mocking, and properly handle asynchronous operations with nextTick.

packages/inula-adapter/src/vue/vShow.ts (1)

18-38: Correct implementation of v-show directive.

The implementation correctly replicates Vue's v-show behavior:

  • Uses a Symbol to safely store the original display value
  • Properly handles the lifecycle hooks (beforeMount, updated, beforeUnmount)
  • Correctly implements the boolean coercion check in the updated hook
  • The setDisplay helper function properly toggles between original display and 'none'

The approach of storing the original display value and restoring it when showing the element matches Vue's behavior exactly.

packages/inula-adapter/tests/vue/dynamicComponent.test.tsx (1)

21-68: Well-structured test suite for dynamic components.

The test suite effectively covers the main use cases for dynamic components:

  • Local component registration and rendering
  • Global component registration via app.component()
  • DOM element rendering with proper attributes

The test structure is clear and each test case validates the expected behavior appropriately.

packages/inula-adapter/babel.config.js (1)

16-49: LGTM! Well-configured Babel setup for OpenInula JSX transformation.

The configuration appropriately sets up TypeScript and JSX transformation with the openinula import source, includes comprehensive plugins for modern JavaScript features, and uses sensible optimization options like loose mode for better performance.

packages/inula-adapter/tests/pinia/pinia.store.test.ts (1)

36-122: LGTM! Comprehensive test coverage for Pinia store functionality.

The test suite properly covers store reuse, state initialization, and subscription mechanisms. The test structure is well-organized with proper setup and teardown.

packages/inula-adapter/tests/pinia/pinia.state.test.ts (1)

44-142: LGTM! Comprehensive test coverage for Pinia state functionality.

The test suite thoroughly covers state access, reactivity, nested state handling, and watcher functionality. The test structure is well-organized and validates the expected behavior of the Pinia adapter.

packages/inula-adapter/src/vue/dynamicComponent.tsx (1)

38-82: LGTM! Well-implemented dynamic component functionality.

The implementation correctly mimics Vue's dynamic component behavior with proper component resolution from both local and global scopes. The toPascalCase helper function properly converts Vue-style component names to React-style naming conventions.

packages/inula-adapter/tests/vuex/vuex.component.test.tsx (2)

22-67: Good test coverage for Vuex store integration.

The test properly verifies store state, mutations, and reactivity within components. The test structure is clean and assertions are comprehensive.


69-116: Excellent test coverage for Vuex helper functions.

The test effectively validates the useMapState, useMapGetters, and useMapMutations helper functions, ensuring they work correctly in component contexts.

packages/inula-adapter/tests/pinia/pinia.storeToRefs.test.ts (2)

26-32: Well-designed test helper function.

The objectOfRefs helper function is a clever utility for comparing objects containing refs by their values, making the test assertions more readable.


34-141: Comprehensive test coverage for storeToRefs.

The test suite thoroughly covers all scenarios including empty states, plain values, setup stores, and computed getters. The tests verify both reading and writing through refs, ensuring proper reactivity.

packages/inula-adapter/scripts/build-types.js (1)

54-64: Good build configuration structure.

The buildTypeConfig function and exported configurations are well-structured for bundling TypeScript declarations for the three packages.

packages/inula-adapter/tests/pinia/pinia.storeSetup.test.ts (4)

22-22: Type testing function is correctly implemented.

The expectType function is a common pattern for compile-time type checking. The unused parameter is intentional.


24-63: Excellent test coverage for setup store $state behavior.

The test thoroughly verifies that $state correctly extracts only state properties, excluding computed values and methods. The reactivity testing is comprehensive.


65-77: Good test for function storage in state.

The test properly verifies that functions can be stored as state properties and accessed correctly.


79-156: Comprehensive reactivity and ref unwrapping tests.

The tests cover direct state access, reactivity, watchers, and ref unwrapping scenarios. The mixed syntax test (setup vs options) is particularly valuable for ensuring compatibility.

packages/inula-adapter/src/vue/compare.ts (2)

19-31: LGTM! NaN comparison is intentional for Object.is polyfill.

The static analysis warnings about "self-compare" are false positives. The x !== x && y !== y comparison is the correct way to detect NaN values in the Object.is polyfill, as NaN is the only value that is not equal to itself.


48-50: Potential issue with key comparison logic.

The key comparison logic uses keysX[i] instead of key in the final comparison, which could lead to incorrect results.

     return keysX.every(
-      (key, i) => Object.prototype.hasOwnProperty.call(paramY, key) && isSame(paramX[key], paramY[keysX[i]])
+      (key) => Object.prototype.hasOwnProperty.call(paramY, key) && isSame(paramX[key], paramY[key])
     );

Likely an incorrect or invalid review comment.

packages/inula-adapter/tests/vuex/vuex.modules.test.ts (1)

21-480: LGTM! Comprehensive test coverage.

The test suite provides excellent coverage of Vuex module functionality including dynamic registration, namespacing, state management, and edge cases. The tests are well-structured and thorough.

packages/inula-adapter/tests/vue/injectProvide.test.tsx (1)

24-111: LGTM! Comprehensive inject/provide tests.

The test suite provides good coverage of the inject/provide functionality including basic usage, default values, and symbol keys. The tests are well-structured and validate the expected behavior.

packages/inula-adapter/tests/vue/liftcycle.test.tsx (1)

162-190: LGTM! Well-structured lifecycle tests.

The lifecycle tests provide good coverage of the Vue lifecycle hooks and validate their timing correctly. The test structure and assertions (except for the onUnmounted issue noted above) are appropriate.

packages/inula-adapter/tests/vue/sfcAPI.test.tsx (2)

23-72: Well-structured test for defineExpose functionality.

The test correctly verifies that:

  1. Methods exposed via defineExpose are accessible from parent components
  2. The reactive state updates properly when exposed methods are called
  3. The ref mechanism works correctly with useInstance

74-128: Comprehensive test for multiple exposed properties.

This test effectively validates that both reactive references and methods can be exposed simultaneously and accessed correctly from parent components.

packages/inula-adapter/tests/vuex/vuex.maps.test.tsx (1)

22-639: Excellent comprehensive test coverage for Vuex mapping utilities.

This test suite provides thorough coverage of all Vuex mapping utilities with multiple scenarios:

  • Array mapping: Tests simple array-based mapping for all utilities
  • Object mapping: Tests object-based mapping with custom names
  • Function mapping: Tests function-based mapping with custom logic
  • Namespace support: Validates namespaced module functionality
  • Integration: Tests all utilities working together

The test patterns correctly validate:

  1. Reactive state updates for useMapState and useMapGetters
  2. Proper mutation commits for useMapMutations
  3. Action dispatching for useMapActions
  4. Mock function usage for action verification
packages/inula-adapter/src/vue/keepAlive/keeper.tsx (4)

10-16: Well-structured component interface and state management.

The component properly initializes refs for DOM elements, child nodes, and lifecycle callbacks. The structure is clean and follows React patterns.


18-27: Proper cleanup on component unmount.

The cleanup effect correctly removes DOM nodes and triggers deactivation callbacks when the component unmounts, preventing memory leaks.


48-57: Context provider implementation is correct.

The component properly provides the lifecycle context to descendant components, enabling them to register activation/deactivation callbacks.


29-46: Verify wrapper existence and add comprehensive keep-alive tests

Before manipulating DOM, it’s safest to guard against missing refs—and without existing tests covering rapid toggle or nested‐component scenarios, we can’t be confident there aren’t subtle race conditions or event-listener losses. Please:

• Add a null check at the top of the effect
• Only move a child if its current parentElement matches your expectation
• Expand your test suite under packages/inula-adapter/tests/ to cover:
– Rapid toggling of active
– Nested keep-alive components
– Preservation of event listeners after activation/unactivation

Suggested diff:

 useEffect(() => {
+  if (!wrapper.current) return;
+
   if (active) {
     childrenNode.current = Array.from(wrapper.current.children);
     childrenNode.current.forEach(child => {
-      wrapper.current?.parentElement?.insertBefore(child, wrapper.current);
+      if (child.parentElement === wrapper.current && wrapper.current.parentElement) {
+        wrapper.current.parentElement.insertBefore(child, wrapper.current);
+      }
     });
     nodeKeeperLifeCycleValue.current[KEEP_ALIVE_LIFECYCLE.ACTIVATE]
       .forEach(callback => callback());
   } else {
     childrenNode.current.forEach(child => {
-      wrapper.current?.appendChild(child);
+      if (wrapper.current && child.parentElement !== wrapper.current) {
+        wrapper.current.appendChild(child);
+      }
     });
     nodeKeeperLifeCycleValue.current[KEEP_ALIVE_LIFECYCLE.UNACTIVATE]
       .forEach(callback => callback());
   }
 }, [active]);
packages/inula-adapter/src/vue/condition.tsx (2)

18-31: LGTM: Clean interface definitions and component implementations.

The conditional props interface and component implementations are well-structured. The If component correctly renders children based on condition, and the Else component uses proper TypeScript typing with Omit.


37-52: LGTM: Solid ConditionalRenderer implementation.

The ConditionalRenderer correctly implements the logic to find the first matching condition among children, handling both If/ElseIf components with true conditions and Else components. The use of Children.toArray and isValidElement ensures safe child element handling.

packages/inula-adapter/tests/vue/props.test.tsx (3)

22-69: LGTM: Comprehensive reactive props testing.

The first test properly validates that reactive props work with numeric values, including state updates and computed values. The test structure is well-organized with proper setup and assertions.


71-159: LGTM: Thorough array reactivity testing.

The second test comprehensively covers array prop reactivity, including:

  • Array replacement operations
  • Array mutation operations (push)
  • Default prop values with functions
  • Proper use of nextTick for async reactivity

161-194: LGTM: Edge case testing for empty arrays.

The third test validates the specific edge case of setting empty arrays and subsequent mutations, ensuring reactivity works correctly in these scenarios.

packages/inula-adapter/tests/pinia/pinia.getters.test.ts (1)

65-97: LGTM: Comprehensive getter testing.

The test suite effectively validates:

  • Getter computation and reactivity
  • State updates triggering getter recalculation
  • Getter composition (using other getters)
  • Reactivity preservation during state hydration
packages/inula-adapter/tests/pinia/pinia.actions.test.ts (4)

19-69: LGTM: Well-structured store factory function.

The createStore function provides a comprehensive test store with state, getters, and actions covering various scenarios including async operations, error handling, and nested state mutations.


77-101: LGTM: Comprehensive action testing.

The tests effectively validate:

  • Correct this context binding in actions
  • State mutations through actions
  • Action composition and inter-action calls
  • Proper handling of forced context

102-121: LGTM: Thorough error handling testing.

The tests properly validate both synchronous and asynchronous error handling, including error catching and propagation.


122-139: LGTM: Robust destructuring and context testing.

The test validates that destructured actions work correctly even with altered this context, which is important for developer experience and debugging scenarios.

packages/inula-adapter/tests/vue/condition.test.tsx (3)

26-73: LGTM: Comprehensive conditional rendering testing.

The first test effectively validates the ConditionalRenderer logic with different conditions, ensuring correct branch selection and rendering updates.


75-168: LGTM: Thorough reactive data testing.

The second test comprehensively validates conditional rendering with reactive data, covering multiple conditions and state transitions. The test scenarios closely mirror real-world usage patterns.


170-208: LGTM: Edge case testing with ref arrays.

The third test validates conditional rendering with object properties and provides good coverage of edge cases where formatters might be undefined.

packages/inula-adapter/src/vue/helper.tsx (2)

22-69: LGTM! Function correctly handles multiple input types.

The setToInstance function properly handles objects, arrays, and functions with appropriate error handling and warnings for invalid inputs.


77-120: LGTM! Helper functions are well-implemented.

The helper functions handle camelCase conversion and style processing correctly, with proper handling of numeric values and special CSS properties.

packages/inula-adapter/src/vue/semiControlledComponent.tsx (4)

45-57: LGTM! Props handling and state initialization are correct.

The component properly handles default values and initializes internal state from props.


70-70: Verify synthetic event structure matches OpenInula expectations.

The synthetic event creation should match OpenInula's ChangeEvent interface structure. Ensure the event object has all required properties.

Consider adding more properties to the synthetic event object to match the full ChangeEvent interface:

- onChange({ target: { value: newValue } } as ChangeEvent<HTMLInputElement>);
+ onChange({ 
+   target: { value: newValue, ...input }, 
+   currentTarget: input,
+   type: 'change'
+ } as ChangeEvent<HTMLInputElement>);

98-104: LGTM! Standard event handling is correct.

The onChange handler properly manages state updates and event propagation.


60-95: Please validate cross-browser compatibility of the value setter override

Overriding the native value property on an <input> is clever but can behave differently across environments. Before merging, manually verify:

• Chrome, Firefox, Safari (including mobile browsers)
• Common input types (text, number, email, password, etc.)
• Programmatic updates from external libraries or frameworks

No other instances of this pattern were found in the codebase, so ensure this change doesn’t introduce regressions.

packages/inula-adapter/docs/README_global_api.md (2)

1-268: Comprehensive documentation with clear examples.

The documentation provides thorough coverage of the global API features with practical examples and migration guidance. The distinction between supported and unsupported features is clearly communicated.


59-210: Excellent migration example from Vue mixins to hooks.

The detailed example showing how to convert Vue mixins to OpenInula hooks is particularly valuable for developers migrating from Vue. The side-by-side comparison makes the migration path clear.

packages/inula-adapter/tests/vue/attrs.test.tsx (1)

21-370: Comprehensive test coverage for $attrs behavior.

The test suite thoroughly covers:

  • CSS class inheritance and merging
  • Style object merging with precedence rules
  • Deep merging across component hierarchies
  • Scoped attribute inheritance
  • Different component types (functional, class, memo, forwardRef)

The tests validate the correct behavior of attribute inheritance in the Vue adapter.

packages/inula-adapter/src/vue/props.tsx (4)

39-54: LGTM! Reactive props hook is well-implemented.

The useReactiveProps hook correctly manages reactive props with proper initialization and updates. The use of useRef ensures reference stability across renders.


77-94: Robust default value handling.

The setFullProps function properly handles both raw props and default values with appropriate precedence rules. The use of hasOwnProperty checks ensures proper property ownership validation.


116-130: Smart default value resolution.

The resolvePropValue function correctly distinguishes between function defaults and Function-type props, ensuring proper default value application.


51-51: Good integration with scoped attributes.

The call to useScoped() ensures that scoped attributes are properly handled alongside reactive props, maintaining the Vue component model.

packages/inula-adapter/tests/vue/globalAPI.test.tsx (1)

16-368: Comprehensive test coverage is excellent.

The test suite provides thorough coverage of the global API functionality including app creation, mounting, plugins, dependency injection, component registration, and async components. The tests are well-structured and cover both success and edge cases.

packages/inula-adapter/tests/vue/keepAlivePro.test.tsx (1)

54-262: Comprehensive KeepAlivePro testing.

The test suite provides excellent coverage of KeepAlivePro functionality including:

  • Basic caching and state preservation
  • Maximum instance limits with proper eviction
  • Component filtering with include/exclude patterns
  • Lifecycle hook integration (onActivated/onDeactivated)

The async handling and DOM assertions are well-implemented.

packages/inula-adapter/src/vue/lifecycle.ts (1)

37-69: Lifecycle hook implementations look correct.

The remaining lifecycle hooks (onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted) are properly implemented using the appropriate openinula hooks with correct timing and cleanup.

packages/inula-adapter/tests/vue/directive.test.tsx (2)

77-77: Ignore ESLint warnings for directive callback parameters.

The ESLint warnings about unused el and binding parameters are false positives. These parameters are part of the Vue directive API contract and should be preserved even if not used in test mocks, as they document the expected interface.

Also applies to: 87-87, 123-123, 134-134, 139-139


23-262: Comprehensive directive testing.

The test suite provides excellent coverage of directive functionality including:

  • DOM element directives with lifecycle hooks (mounted, updated, unmounted)
  • Component directives with custom registration
  • Built-in v-show directive behavior
  • Event simulation and DOM interaction testing
  • Proper cleanup and lifecycle management

The tests effectively validate the DirectiveComponent wrapper and directive integration.

packages/inula-adapter/src/vue/keepAlive/lifeCycleHooks.ts (3)

4-7: Well-defined lifecycle events.

The enum clearly defines the activation lifecycle events with descriptive names that follow component lifecycle naming conventions.


10-28: Robust lifecycle hook implementation.

The useActivation hook properly:

  • Checks for KeepAlive context availability
  • Manages callback replacement vs addition logic
  • Uses refs to track previous callbacks
  • Handles effect dependencies correctly

The implementation ensures callbacks are properly updated when dependencies change.


30-34: Clean API design with bound hooks.

The bound hooks (useActivatePro, useUnActivatePro) provide a clean API for consumers while the type definition properly documents the expected context structure.

packages/inula-adapter/tests/vue/keepAlive.test.tsx (2)

52-89: Well-structured test for basic KeepAlive functionality

The test comprehensively covers state preservation and DOM caching behavior.


91-270: Comprehensive test coverage for KeepAlive features

The test suite thoroughly covers:

  • Cache size limiting with max prop
  • Include/exclude filtering with string and regex patterns
  • Activation/deactivation lifecycle hooks

All tests properly use act() for state updates and verify DOM structure correctly.

packages/inula-adapter/src/pinia/pinia.ts (1)

72-93: Correct implementation of action parameter adjustment

The function properly removes the first store parameter that openinula injects but Pinia doesn't require, ensuring compatibility between the two APIs.

packages/inula-adapter/src/vuex/types.ts (1)

1-108: Well-designed type system for Vuex adapter

The type definitions provide comprehensive type safety with:

  • Proper generic constraints for state, mutations, actions, and getters
  • Utility types that correctly transform function signatures
  • Support for nested modules with namespacing
  • Integration with openinula's StoreObj type
packages/inula-adapter/src/vuex/vuex.ts (2)

82-114: Well-structured mutation and action dispatching

The implementation correctly handles:

  • Root-level mutations/actions with options.root
  • Namespaced module syntax with / delimiter
  • Broadcasting to non-namespaced modules
  • Promise aggregation for action results

Also applies to: 115-153


313-324: Proper cleanup implementation for dynamic module unregistration

The deleteGetters function correctly resets property descriptors before deletion, ensuring clean removal of dynamically registered getters.

packages/inula-adapter/src/pinia/types.ts (1)

23-103: Well-designed type definitions for Pinia adapter

The type definitions are comprehensive and properly handle:

  • Generic constraints for store state, actions, and getters
  • Proper this context binding using ThisType
  • Complex conditional types for filtering properties
  • Type-safe store-to-refs conversion
packages/inula-adapter/src/vue/globalAPI.tsx (2)

259-273: Well-implemented event emission with Vue compatibility

The emit function properly handles:

  • Direct event names and Vue-style 'on' prefixed handlers
  • Proper argument forwarding
  • Helpful warnings for missing handlers

292-328: Robust window size tracking implementation

The useWindowSize hook provides:

  • Proper event listener cleanup
  • Configurable scrollbar inclusion
  • Optional orientation change listening
  • Safe initial value handling

Comment on lines +5 to +9
<script>
setInterval(()=>{
this.$forceUpdate();
},1000)
</script> No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Vue component structure and lifecycle management.

The current implementation has several critical issues:

  1. Missing proper Vue component export structure
  2. The setInterval runs immediately when the script loads, not within component lifecycle
  3. No cleanup mechanism, which will cause memory leaks
  4. Multiple intervals may be created if the component is re-instantiated

Apply this diff to fix the component structure and lifecycle management:

-<script>
-    setInterval(()=>{
-        this.$forceUpdate();
-    },1000)
-</script>
+<script>
+export default {
+    name: 'Clock',
+    data() {
+        return {
+            intervalId: null
+        }
+    },
+    mounted() {
+        this.intervalId = setInterval(() => {
+            this.$forceUpdate();
+        }, 1000);
+    },
+    beforeDestroy() {
+        if (this.intervalId) {
+            clearInterval(this.intervalId);
+        }
+    }
+}
+</script>
🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$forceUpdate/clock.vue around lines 5 to 9,
the script incorrectly runs setInterval immediately without proper Vue component
structure or lifecycle management, causing potential memory leaks and multiple
intervals on re-instantiation. Refactor the code to define and export a Vue
component properly, move the setInterval call inside the mounted lifecycle hook,
and clear the interval in the beforeUnmount hook to ensure cleanup.

Comment on lines +4 to +13
useEffect(() => {
const [b, r] = useState(false); // by toggling this state object, force update is triggered
const interval = setInterval(() => {
r(!b);
}, 1000);

return () => {
clearInterval(interval);
};
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix critical React hooks usage and missing imports.

The current implementation has several critical issues:

  1. useEffect and useState are used but not imported
  2. useState is incorrectly called inside useEffect (hooks must be called at the top level)
  3. The force update logic is flawed

Apply this diff to fix the implementation:

+import { useState, useEffect } from 'react';
+
 export default function Clock() {
+  const [, forceUpdate] = useState(false);
+
-  // useeffect and clearInterval operation mas no sense, but this is necessary
+  // useEffect and clearInterval operation may not make sense, but this is necessary
   // to prevent problems between persistent vue components and temporary inula function components
   useEffect(() => {
-    const [b, r] = useState(false); // by toggling this state object, force update is triggered
     const interval = setInterval(() => {
-      r(!b);
+      forceUpdate(prev => !prev);
     }, 1000);
 
     return () => {
       clearInterval(interval);
     };
-  });
+  }, []);
   return <span>{Date.now()}</span>;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
const [b, r] = useState(false); // by toggling this state object, force update is triggered
const interval = setInterval(() => {
r(!b);
}, 1000);
return () => {
clearInterval(interval);
};
});
import { useState, useEffect } from 'react';
export default function Clock() {
const [, forceUpdate] = useState(false);
// useEffect and clearInterval operation may not make sense, but this is necessary
// to prevent problems between persistent vue components and temporary inula function components
useEffect(() => {
const interval = setInterval(() => {
forceUpdate(prev => !prev);
}, 1000);
return () => {
clearInterval(interval);
};
}, []);
return <span>{Date.now()}</span>;
}
🧰 Tools
🪛 ESLint

[error] 4-4: 'useEffect' is not defined.

(no-undef)


[error] 5-5: 'useState' is not defined.

(no-undef)

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$forceUpdate/clock.jsx around lines 4 to 13,
fix the React hooks usage by importing useEffect and useState at the top of the
file, move the useState call outside of useEffect to the top level of the
component, and update the force update logic by toggling the state correctly
inside the setInterval callback. Also, add an empty dependency array to
useEffect to ensure the interval is set up only once and cleaned up properly.

Comment on lines +13 to +19
<script>
const { productId,productName,productType } = defineProps([ 'productId', 'productName', 'productType' ]);

function filterType(type){
this.$parent.setFilterType(type);
}
</script> No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Vue Composition API syntax and missing imports.

Several issues with the Vue component implementation:

  1. defineProps is used outside of <script setup> context
  2. The filterType function is not accessible in the template
  3. Missing required imports for Vue composition functions
  4. this.$parent access won't work in this context

Apply this diff to fix the component:

-<script>
+<script setup>
+import { inject } from 'vue';
+
-    const { productId,productName,productType } = defineProps([ 'productId', 'productName', 'productType' ]);
+    const { productId, productName, productType } = defineProps(['productId', 'productName', 'productType']);
+    
+    // Use inject to get parent methods instead of this.$parent
+    const parentMethods = inject('parentMethods', {});

-    function filterType(type){
-        this.$parent.setFilterType(type);
-    }
+    function filterType(type) {
+        parentMethods.setFilterType?.(type);
+    }
</script>
🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$parent/list-item.vue around lines 13 to 19,
the script uses defineProps outside of <script setup>, the filterType function
is not exposed to the template, required Vue composition imports are missing,
and this.$parent access is invalid. To fix, convert the script to use <script
setup> syntax, import necessary Vue functions, define filterType as a function
within the setup context, and replace this.$parent with an appropriate emit or
provide/inject pattern to communicate with the parent component.

Product type
</td>
</tr>
<table-item v-for="item in filteredIdems" productId="item.id" productName="item.name" productType="item.type"></table-item>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix prop binding in v-for directive.

The props are passed as string literals instead of expressions, which will render the literal text "item.id" instead of the actual values.

Apply this diff to fix the prop binding:

-        <table-item v-for="item in filteredIdems" productId="item.id" productName="item.name" productType="item.type"></table-item>
+        <table-item v-for="item in filteredIdems" :key="item.id" :productId="item.id" :productName="item.name" :productType="item.type"></table-item>
🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$parent/list.vue at line 14, the props
productId, productName, and productType are incorrectly passed as string
literals instead of dynamic expressions. Fix this by binding the props using
v-bind syntax or shorthand, for example :productId="item.id",
:productName="item.name", and :productType="item.type" to pass the actual values
from each item in filteredIdems.

Comment on lines +17 to +27
<script>
const {items} = defineProps(['items']);

const filteredIdems = ref(items);

function setFilterType(type){
filteredItems.value = items.filter(item => item.type===type);
}

defineExpose({setFilterType})
</script> No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix variable naming inconsistency and missing imports.

Multiple issues with the script section:

  1. Variable name typo: filteredIdems vs filteredItems
  2. Missing required imports for Vue composition functions
  3. Should use <script setup> syntax

Apply this diff to fix the issues:

-<script>
+<script setup>
+import { ref, defineProps, defineExpose } from 'vue';
+
     const {items} = defineProps(['items']);

-    const filteredIdems = ref(items);
+    const filteredItems = ref(items);

     function setFilterType(type){
         filteredItems.value = items.filter(item => item.type===type);
     }

     defineExpose({setFilterType})
</script>

Also update the template to use the correct variable name:

-        <table-item v-for="item in filteredIdems" :key="item.id" :productId="item.id" :productName="item.name" :productType="item.type"></table-item>
+        <table-item v-for="item in filteredItems" :key="item.id" :productId="item.id" :productName="item.name" :productType="item.type"></table-item>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$parent/list.vue around lines 17 to 27, fix
the typo by renaming the variable from filteredIdems to filteredItems for
consistency. Add the missing imports for ref, defineProps, and defineExpose from
'vue' at the top of the script. Change the script tag to use the <script setup>
syntax to align with Vue 3 composition API best practices. Also, update any
template references to use the corrected filteredItems variable name.

Comment on lines +10 to +11
if(!this.$refs[0].value){
this.$refs[0].focus();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix $refs access to use the named reference.

The code accesses $refs[0] but should use $refs.myInput to match the ref attribute in the template.

-        if(!this.$refs[0].value){
-            this.$refs[0].focus();
+        if(!this.$refs.myInput.value){
+            this.$refs.myInput.focus();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(!this.$refs[0].value){
this.$refs[0].focus();
if(!this.$refs.myInput.value){
this.$refs.myInput.focus();
🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$refs/refresh.vue around lines 10 to 11, the
code incorrectly accesses this.$refs using an index (this.$refs[0]) instead of
the named reference. Update the code to use this.$refs.myInput to correctly
reference the element by its ref attribute name.

<template>
<iv>
<input ref="myInput" type="text" />
<button @click="validateAndSubmit">submit</button>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Define the missing validateAndSubmit method.

The template references validateAndSubmit but this method is not defined in the script section.

<script>
+    function validateAndSubmit() {
+        validate();
+    }
+
     function validate(){

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$refs/refresh.vue at line 4, the template
uses a method called validateAndSubmit on the button click event, but this
method is not defined in the script section. To fix this, define a
validateAndSubmit method inside the script section of the Vue component that
handles the form validation and submission logic as intended.

@@ -0,0 +1,16 @@
<template>
<iv>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the HTML tag typo.

The <iv> tag appears to be a typo and should be <div>.

-    <iv>
+    <div>
-    </iv>
+    </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<iv>
<div>
</div>
🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$refs/refresh.vue at line 2, the HTML tag
<iv> is a typo and should be corrected to <div>. Replace the <iv> tag with <div>
to fix the markup.

if(!this.$refs[0].value){
this.$refs[0].focus();
} else {
submit()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Define the missing submit function.

The submit() function is called but not defined or imported.

+    function submit() {
+        // TODO: Implement submit logic
+        console.log('Form submitted');
+    }
+
     function validate(){
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
submit()
function submit() {
// TODO: Implement submit logic
console.log('Form submitted');
}
function validate(){
// existing validate logic…
}
🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$refs/refresh.vue at line 13, the submit()
function is called but not defined or imported. Define the submit function
within the component's script section or import it if it exists externally.
Ensure the function is properly declared before it is called to avoid runtime
errors.

Comment on lines +4 to +10
// this timeout should be wrapped as an adapter that way you can call only $nextClick( ... ) as usual
const timeout = setTimeout(() => {
// this must be wrapped, because at the time of render, this element does not exist yet
useInstance().$refs.inp.$el.attachEventListener('keyUp', e => {
console.log(e);
});
}, 1);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider abstracting the timeout logic into a proper adapter.

As suggested by the comments, this setTimeout workaround should be wrapped in an adapter to provide a cleaner $nextTick API.

Consider creating a $nextTick adapter function that encapsulates this logic for better reusability and cleaner API usage.

🧰 Tools
🪛 ESLint

[error] 7-7: 'useInstance' is not defined.

(no-undef)

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$nextTick/nextTick.jsx around lines 4 to 10,
the setTimeout logic used to delay attaching the event listener should be
refactored into a dedicated $nextTick adapter function. Create a reusable
$nextTick adapter that wraps this timeout and callback logic, so callers can
simply invoke $nextTick(callback) to run code after the next DOM update,
improving code clarity and reusability.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review continued from previous batch...

@@ -0,0 +1,18 @@
export default function (props) {
// inula rendering is synchronous, so this timeout appends this function at next asynchronous position to execute after render
useEffect(() => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing import for useEffect.

The useEffect hook is used but not imported.

+import { useEffect } from 'openinula';
+
 export default function (props) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
import { useEffect } from 'openinula';
export default function (props) {
useEffect(() => {
// ...
});
// rest of component
}
🧰 Tools
🪛 ESLint

[error] 3-3: 'useEffect' is not defined.

(no-undef)

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$nextTick/nextTick.jsx at line 3, the
useEffect hook is used but not imported. Add an import statement for useEffect
from 'react' at the top of the file along with other React imports to ensure the
hook is available.

// this timeout should be wrapped as an adapter that way you can call only $nextClick( ... ) as usual
const timeout = setTimeout(() => {
// this must be wrapped, because at the time of render, this element does not exist yet
useInstance().$refs.inp.$el.attachEventListener('keyUp', e => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing import for useInstance.

The useInstance hook is used but not imported.

+import { useInstance } from 'vue-inula';
+
 export default function (props) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useInstance().$refs.inp.$el.attachEventListener('keyUp', e => {
import { useInstance } from 'vue-inula';
export default function (props) {
useInstance().$refs.inp.$el.attachEventListener('keyUp', e => {
🧰 Tools
🪛 ESLint

[error] 7-7: 'useInstance' is not defined.

(no-undef)

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$nextTick/nextTick.jsx at line 7, the
useInstance hook is used but not imported. Add an import statement for
useInstance from its appropriate module at the top of the file to ensure it is
properly referenced.

Comment on lines +18 to +29
export function inject(name, defaultValue?) {
// If variable exists, local value is returned
if (contextMap.has(name)) {
const ctx = contextMap.get(name);
return ctx.value;
}
// If there is no fallback value, error is thrown
if (!defaultValue) {
throw Error('Injected value is not provided. Make sure to provide it before use or add default value');
}
return defaultValue;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the inject function logic and context usage.

There are several issues with the current implementation:

  1. The default value check !defaultValue will fail for falsy values like 0, false, or empty string
  2. The context is not being used properly - ctx.value should be accessed via useContext(ctx)
  3. The provide/inject pattern needs to work within the React component tree
-export function inject(name, defaultValue?) {
+export function inject(name, defaultValue?) {
   // If variable exists, local value is returned
   if (contextMap.has(name)) {
     const ctx = contextMap.get(name);
-    return ctx.value;
+    return useContext(ctx);
   }
   // If there is no fallback value, error is thrown
-  if (!defaultValue) {
+  if (defaultValue === undefined) {
     throw Error('Injected value is not provided. Make sure to provide it before use or add default value');
   }
   return defaultValue;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function inject(name, defaultValue?) {
// If variable exists, local value is returned
if (contextMap.has(name)) {
const ctx = contextMap.get(name);
return ctx.value;
}
// If there is no fallback value, error is thrown
if (!defaultValue) {
throw Error('Injected value is not provided. Make sure to provide it before use or add default value');
}
return defaultValue;
}
export function inject(name, defaultValue?) {
// If variable exists, local value is returned
if (contextMap.has(name)) {
const ctx = contextMap.get(name);
return useContext(ctx);
}
// If there is no fallback value, error is thrown
if (defaultValue === undefined) {
throw Error('Injected value is not provided. Make sure to provide it before use or add default value');
}
return defaultValue;
}
🤖 Prompt for AI Agents
In packages/inula-adapter/src/vue/injectProvide.tsx around lines 18 to 29, the
inject function incorrectly checks for defaultValue using a falsy check which
fails for valid falsy values like 0 or false. Also, it accesses contextMap
values directly instead of using useContext to retrieve the current context
value. To fix this, change the defaultValue check to explicitly check for
undefined, use useContext with the retrieved context from contextMap, and ensure
the function integrates properly with React's provide/inject pattern by
returning the context value from useContext or the defaultValue if provided.

Comment on lines +24 to +46
{fruits.map(fruit => (
<li>
<p>Fruit: {fruit.name}</p>
<p>
Amount:{' '}
<button
onClick={() => {
decrement(fruit);
}}
>
-
</button>{' '}
{fruit.amount}{' '}
<button
onClick={() => {
increment(fruit);
}}
>
+
</button>
</p>
</li>
))}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add missing key prop for list items.

React requires a key prop for each item in a list to help with efficient re-rendering.

-        {fruits.map(fruit => (
-          <li>
+        {fruits.map((fruit, index) => (
+          <li key={index}>

Better yet, if fruits have unique names, use the name as the key:

-        {fruits.map(fruit => (
-          <li>
+        {fruits.map(fruit => (
+          <li key={fruit.name}>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{fruits.map(fruit => (
<li>
<p>Fruit: {fruit.name}</p>
<p>
Amount:{' '}
<button
onClick={() => {
decrement(fruit);
}}
>
-
</button>{' '}
{fruit.amount}{' '}
<button
onClick={() => {
increment(fruit);
}}
>
+
</button>
</p>
</li>
))}
{fruits.map(fruit => (
<li key={fruit.name}>
<p>Fruit: {fruit.name}</p>
<p>
Amount:{' '}
<button
onClick={() => {
decrement(fruit);
}}
>
-
</button>{' '}
{fruit.amount}{' '}
<button
onClick={() => {
increment(fruit);
}}
>
+
</button>
</p>
</li>
))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 25-25: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$set/fruits.jsx between lines 24 and 46, the
list items rendered inside the fruits.map() call are missing a key prop. To fix
this, add a unique key prop to each <li> element, preferably using fruit.name if
it is unique, like key={fruit.name}, to help React efficiently identify and
update list items during re-renders.

Comment on lines +15 to +19
function addFruit() {
const fruitName = useInstance().$refs.newFruit.value;
this.$set(fruits, fruits.length, { name: fruitName, amount: 0 }); // how should we do this? Will use of reactive handle this case automaticaly?
useInstance().$refs.newFruit.value = '';
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix critical issues in addFruit function.

The function has several critical issues:

  1. useInstance is not imported
  2. Mixing this.$set with useInstance() is incorrect for functional components
  3. With reactive arrays, direct manipulation should work without $set
+import { useInstance } from 'vue-inula';
+
 export default function () {
   // ... existing code ...
   
   function addFruit() {
-    const fruitName = useInstance().$refs.newFruit.value;
-    this.$set(fruits, fruits.length, { name: fruitName, amount: 0 }); // how should we do this? Will use of reactive  handle this case automaticaly?
-    useInstance().$refs.newFruit.value = '';
+    const instance = useInstance();
+    const fruitName = instance.$refs.newFruit.value;
+    fruits.push({ name: fruitName, amount: 0 }); // reactive arrays handle this automatically
+    instance.$refs.newFruit.value = '';
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function addFruit() {
const fruitName = useInstance().$refs.newFruit.value;
this.$set(fruits, fruits.length, { name: fruitName, amount: 0 }); // how should we do this? Will use of reactive handle this case automaticaly?
useInstance().$refs.newFruit.value = '';
}
import { useInstance } from 'vue-inula';
export default function () {
// ... existing code ...
function addFruit() {
const instance = useInstance();
const fruitName = instance.$refs.newFruit.value;
fruits.push({ name: fruitName, amount: 0 }); // reactive arrays handle this automatically
instance.$refs.newFruit.value = '';
}
}
🧰 Tools
🪛 ESLint

[error] 16-16: 'useInstance' is not defined.

(no-undef)


[error] 18-18: 'useInstance' is not defined.

(no-undef)

🤖 Prompt for AI Agents
In packages/inula-adapter/examples/$set/fruits.jsx around lines 15 to 19, fix
the addFruit function by first importing useInstance if needed, then remove the
incorrect use of this.$set since this is a functional component. Instead,
directly push the new fruit object into the reactive fruits array to update it
properly. Also, ensure you access the input value via
useInstance().$refs.newFruit.value and clear it afterward as done currently.

// 给getters的key增加一个前缀,避免和actions, mutations的key冲突
`${GETTER_PREFIX}${key}`,
// 重新定义getter的方法,绑定this,修改参数: state, getters, rootState, rootGetters
function (state: Record<string, unknown>) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused parameter in getter wrapper

The state parameter in the getter wrapper function is not used.

-            function (state: Record<string, unknown>) {
+            function () {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function (state: Record<string, unknown>) {
function () {
🧰 Tools
🪛 ESLint

[error] 278-278: 'state' is defined but never used.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
In packages/inula-adapter/src/vuex/vuex.ts at line 278, the getter wrapper
function has an unused parameter named 'state'. Remove this 'state' parameter
from the function definition to clean up the code and avoid unused parameter
warnings.

import { VuexStore, VuexStoreOptions } from './types';
import { AnyFunction } from '../vuex/types';

const { watch, useComputed, computed } = vueReactive;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused destructured variables

The variables useComputed and computed are destructured from vueReactive but never used in the code.

-const { watch, useComputed, computed } = vueReactive;
+const { watch } = vueReactive;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { watch, useComputed, computed } = vueReactive;
- const { watch, useComputed, computed } = vueReactive;
+ const { watch } = vueReactive;
🧰 Tools
🪛 ESLint

[error] 20-20: 'useComputed' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 20-20: 'computed' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
In packages/inula-adapter/src/vuex/vuex.ts at line 20, the variables useComputed
and computed are destructured from vueReactive but never used. Remove
useComputed and computed from the destructuring assignment, keeping only watch
if it is used elsewhere in the code.

Comment on lines +339 to +342
export function useStore(key = storeKey) {
getStoreXCache!();
return storeMap.get(key);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check for getStoreXCache

The useStore function uses a non-null assertion on getStoreXCache without validation. This could throw if createStore hasn't been called yet.

 export function useStore(key = storeKey) {
-  getStoreXCache!();
+  if (!getStoreXCache) {
+    throw new Error('Store has not been created. Call createStore() first.');
+  }
+  getStoreXCache();
   return storeMap.get(key);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function useStore(key = storeKey) {
getStoreXCache!();
return storeMap.get(key);
}
export function useStore(key = storeKey) {
if (!getStoreXCache) {
throw new Error('Store has not been created. Call createStore() first.');
}
getStoreXCache();
return storeMap.get(key);
}
🤖 Prompt for AI Agents
In packages/inula-adapter/src/vuex/vuex.ts around lines 339 to 342, the useStore
function calls getStoreXCache with a non-null assertion but does not check if
getStoreXCache is defined, which can cause a runtime error if createStore hasn't
been called. Add a null or undefined check before calling getStoreXCache to
ensure it is initialized, and handle the case where it is not set, such as
throwing a clear error or returning a fallback value.

Comment on lines +129 to +133
mixin(mixin) {
// 不支持
console.log('Inula中暂时不支持mixin,请用Hook方式进行改造代码。');
return app;
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused parameter from mixin method

The mixin parameter is not used since the feature is unsupported.

-    mixin(mixin) {
+    mixin() {
       // 不支持
       console.log('Inula中暂时不支持mixin,请用Hook方式进行改造代码。');
       return app;
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mixin(mixin) {
// 不支持
console.log('Inula中暂时不支持mixin,请用Hook方式进行改造代码。');
return app;
},
mixin() {
// 不支持
console.log('Inula中暂时不支持mixin,请用Hook方式进行改造代码。');
return app;
},
🧰 Tools
🪛 ESLint

[error] 129-129: 'mixin' is defined but never used.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
In packages/inula-adapter/src/vue/globalAPI.tsx around lines 129 to 133, the
mixin method has an unused parameter named mixin because the feature is not
supported. Remove the mixin parameter from the method signature to clean up the
code and avoid unused parameter warnings, while keeping the method body
unchanged.

Comment on lines +167 to +173
unmount() {
if (isMounted) {
unmountComponentAtNode(app._container);

delete app._container;
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace delete operator with undefined assignment

Using the delete operator can impact performance. Assign undefined instead.

     unmount() {
       if (isMounted) {
         unmountComponentAtNode(app._container);
 
-        delete app._container;
+        app._container = null;
+        isMounted = false;
       }
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
unmount() {
if (isMounted) {
unmountComponentAtNode(app._container);
delete app._container;
}
},
unmount() {
if (isMounted) {
unmountComponentAtNode(app._container);
app._container = null;
isMounted = false;
}
},
🤖 Prompt for AI Agents
In packages/inula-adapter/src/vue/globalAPI.tsx around lines 167 to 173, replace
the use of the delete operator on app._container with an assignment of undefined
to app._container to avoid performance issues. Change "delete app._container;"
to "app._container = undefined;" within the unmount method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant