mcpField
F
fix-library-init

fix-library-init

github.com/ui5开发44141 次安装1 周前更新
代码仓库

关于 fix-library-init

用于修复 UI5 库初始化代码的开发技能,面向处理 UI5 Linter 弃用提示的开发者。它补充正确的 apiVersion: 2,并指导将枚举改为 DataType.registerEnum。

主要功能

  1. 01修正 Library.init() 调用
  2. 02补充数值型 apiVersion: 2
  3. 03处理多种初始化参数形式
  4. 04指导枚举注册现代化

适用场景

  1. 01修复 UI5 Linter 初始化错误
  2. 02现代化 UI5 库的初始化代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ui5/plugins-coding-agents --skill fix-library-init

安装后在 Claude Code 中输入/fix-library-init确认已加载。

详细介绍

Library.init() 现代化改造

此技能用于修复 UI5 linter 检测到的缺少 apiVersion: 2 的 Library.init() / Lib.init() 调用,并将枚举定义现代化为使用 DataType.registerEnum——使用 apiVersion: 2 时必须这样做。

处理的 Linter 规则

规则 ID消息模式此技能的操作
no-deprecated-api对 Library.init() 的调用已弃用。请改用 {apiVersion: 2} 参数在 init 调用中添加 apiVersion: 2
no-deprecated-api对 Lib.init() 的调用已弃用。请改用 {apiVersion: 2} 参数在 init 调用中添加 apiVersion: 2
no-deprecated-api对 init() 的调用已弃用。请改用 {apiVersion: 2} 参数添加 apiVersion: 2(解构的 init)

适用场景

当你看到类似以下的 linter 输出时,请应用此技能:

library.js:9:2 error Deprecated call to Library.init(). Use the {apiVersion: 2} parameter instead  no-deprecated-api
library.js:11:2 error Deprecated call to Lib.init(). Use the {apiVersion: 2} parameter instead  no-deprecated-api
library.js:51:2 error Deprecated call to init(). Use the {apiVersion: 2} parameter instead  no-deprecated-api

背景:Library.init() 的作用

sap/ui/core/Lib.init() 会向框架注册一个 UI5 库,并声明其元数据:名称、依赖项、控件、元素、类型(枚举)和接口。apiVersion: 2 参数表示该库采用现代初始化模式。

重要:Lib.init() 只接受 apiVersion: 2。与也接受 apiVersion: 4 的控件渲染器不同,库初始化只接受 2。

修复策略

1. 无参数

问题:调用 Lib.init() 时完全没有传入参数。

// Before — triggers no-deprecated-api
sap.ui.define([
    "sap/ui/core/Lib"
], function(Library) {
    "use strict";

    Library.init();
});

修复:添加一个包含 apiVersion: 2 的对象参数。

// After
sap.ui.define([
    "sap/ui/core/Lib"
], function(Library) {
    "use strict";

    Library.init({
        apiVersion: 2
    });
});
2. 对象参数中没有 apiVersion

问题:Lib.init() 接收了一个对象,但其中没有 apiVersion 属性。

// Before — triggers no-deprecated-api
Library.init({
    name: "my.lib",
    dependencies: ["sap.ui.core", "sap.m"]
});

修复:将 apiVersion: 2 作为对象的第一个属性添加。

// After
Library.init({
    apiVersion: 2,
    name: "my.lib",
    dependencies: ["sap.ui.core", "sap.m"]
});
3. apiVersion 不是数字

问题:apiVersion 是字符串,而不是数字字面量。

// Before — triggers no-deprecated-api
Library.init({
    apiVersion: "2"
});

修复:改为数字字面量 2。

// After
Library.init({
    apiVersion: 2
});
4. apiVersion 数字错误

问题:apiVersion 是数字,但不是 2。

// Before — triggers no-deprecated-api
Library.init({
    apiVersion: 1
});

修复:改为 2。

// After
Library.init({
    apiVersion: 2
});
5. 元素访问语法

通过方括号表示法调用 init 时,也适用相同的模式:

// Before
Library["init"]({
    apiVersion: 1,
    dependencies: ["sap.ui.core"]
});

// After
Library["init"]({
    apiVersion: 2,
    dependencies: ["sap.ui.core"]
});
6. 解构或赋值的 init

Linter 也会检测以下模式:

// Assignment
const LibInit = Library.init;
LibInit({ apiVersion: 1 });

// Destructuring
const {init} = Library;
init({ apiVersion: 1 });

// Destructuring with rename
const {init: libInit} = Library;
libInit({ apiVersion: 1 });

修复:同样,将每次调用中的 apiVersion 改为 2。

将枚举现代化为 DataType.registerEnum

将 Lib.init() 升级为 apiVersion: 2 时,在全局命名空间中定义枚举的旧方法将不再有效。若未显式注册,框架就无法解析控件元数据中使用的类型字符串,这可能导致 XSS 漏洞,因为类型检查会被静默跳过。

此技能必须在 library.js 中查找现有的枚举定义,并将其现代化为使用 DataType.registerEnum。

如何查找枚举
  1. 检查 Lib.init() 调用中的 types 数组——其中列出了该库定义的所有类型(枚举)的完全限定名称
  2. 搜索全局命名空间赋值——例如 my.lib.ValueColor = { ... },其中 my.lib 是库命名空间
  3. 查找现有的枚举对象——以包含字符串键值对的普通对象形式定义
现代化步骤
  1. 捕获 Lib.init() 的返回值并赋给变量(如果尚未这样做):

    // Before
    Library.init({ name: "my.lib", apiVersion: 2, types: ["my.lib.ValueColor"] });
    
    // After
    var oThisLibrary = Library.init({ name: "my.lib", apiVersion: 2, types: ["my.lib.ValueColor"] });
    
  2. 将枚举定义从全局命名空间移至库对象:

    // Before — global namespace
    my.lib.ValueColor = { Color1: "Color1", Color2: "Color2" };
    
    // After — on library object
    oThisLibrary.ValueColor = { Color1: "Color1", Color2: "Color2" };
    
  3. 在每个枚举定义后立即添加 DataType.registerEnum 调用:

    oThisLibrary.ValueColor = { Color1: "Color1", Color2: "Color2" };
    DataType.registerEnum("my.lib.ValueColor", oThisLibrary.ValueColor);
    
  4. 将 sap/ui/base/DataType 添加到 sap.ui.define 依赖列表中(如果尚未添加):

    sap.ui.define([
        "sap/ui/base/DataType",  // Add this
        "sap/ui/core/Lib"
    ], function(DataType, Library) {
    
关键规则
  • registerEnum 的第一个参数必须与控件元数据中用作 type 的字符串完全一致(例如 "my.lib.ValueColor")
  • 为确保库预加载兼容性,所有枚举定义都应保留在 library.js 中
  • types 数组中列出的每个枚举都需要各自的 registerEnum 调用

完整示例

修改前
/*!
 * ${copyright}
 */
sap.ui.define([
    "sap/ui/core/Lib"
], function(Library) {
    "use strict";

    Library.init({
        name: "my.lib",
        dependencies: ["sap.ui.core", "sap.m"],
        types: [
            "my.lib.ValueColor",
            "my.lib.StatusType"
        ],
        controls: [
            "my.lib.MyControl"
        ]
    });

    // Enums defined on global namespace
    my.lib.ValueColor = {
        Good: "Good",
        Critical: "Critical",
        Error: "Error",
        Neutral: "Neutral"
    };

    my.lib.StatusType = {
        Active: "Active",
        Inactive: "Inactive"
    };
});
修改后
/*!
 * ${copyright}
 */
sap.ui.define([
    "sap/ui/base/DataType",
    "sap/ui/core/Lib"
], function(DataType, Library) {
    "use strict";

    var oThisLibrary = Library.init({
        apiVersion: 2,
        name: "my.lib",
        dependencies: ["sap.ui.core", "sap.m"],
        types: [
            "my.lib.ValueColor",
            "my.lib.StatusType"
        ],
        controls: [
            "my.lib.MyControl"
        ]
    });

    oThisLibrary.ValueColor = {
        Good: "Good",
        Critical: "Critical",
        Error: "Error",
        Neutral: "Neutral"
    };
    DataType.registerEnum("my.lib.ValueColor", oThisLibrary.ValueColor);

    oThisLibrary.StatusType = {
        Active: "Active",
        Inactive: "Inactive"
    };
    DataType.registerEnum("my.lib.StatusType", oThisLibrary.StatusType);

    return oThisLibrary;
});

实施步骤

  1. 使用 --details 运行 linter,以获取更多上下文:

    npx @ui5/linter --details
    
  2. 阅读 library.js 文件并确认:

    • Lib.init() / Library.init() 调用及其当前参数
    • 是否将返回值赋给变量
    • 是否存在枚举定义(检查 types 数组和全局命名空间赋值)
  3. 修复 apiVersion:

    • 如果没有参数:添加 { apiVersion: 2 }
    • 如果参数是没有 apiVersion 的对象:将 apiVersion: 2 添加为第一个属性
    • 如果 apiVersion 的值或类型错误:将其改为数值 2
  4. 更新枚举(如果存在):

    • 如果尚未完成,将 Lib.init() 的返回值赋给变量
    • 将每个枚举从全局命名空间移至库对象
    • 为每个枚举添加 DataType.registerEnum 调用
    • 将 sap/ui/base/DataType 添加到依赖项列表
  5. 确保模块返回库对象(return oThisLibrary;)

  6. 重新运行 linter,验证修复结果

说明

  • 对于 Lib.init(),只有 apiVersion: 2 有效;apiVersion: 4 无效(该值仅适用于渲染器)
  • apiVersion 必须是数值字面量,不能是字符串
  • 没有枚举的库只需修复 apiVersion: 2(无需调用 DataType.registerEnum)
  • 如果库已返回 init 结果,且没有全局枚举定义,则只需修复 apiVersion
  • init 调用中的 types 数组可用于判断哪些枚举需要调用 registerEnum

相关技能

  • fix-control-renderer:用于修复渲染器 apiVersion 问题(渲染器对象中缺少 apiVersion: 2 或 4)——这与库 init apiVersion 不同
  • fix-pseudo-modules:如果使用方代码通过伪模块导入枚举(例如 sap.ui.require(["my/lib/ValueColor"])),请使用 fix-pseudo-modules 将其转换为库模块导入
  • fix-js-globals:如果 library.js 中除了枚举定义之外还存在全局访问模式(例如 sap.ui.getCore()),请使用 fix-js-globals 处理

评论

支持 Markdown