module-definitions
GitHub管理 AG Charts 模块定义与选项贡献,处理模块注册、验证及依赖关系。用于创建模块、迁移功能或修复模块未注册的报告错误。
触发场景
安装
npx skills add ag-grid/ag-charts --skill module-definitions -g -y
SKILL.md
Frontmatter
{
"name": "module-definitions",
"targets": [
"*"
],
"description": "Add or change an AG Charts module definition: which options it owns, how community reports it when missing, how its theme defaults and validation reach the chart, and how the generated module tables stay in step. Use when creating a module, moving a feature into one, adding an option path a module owns, or when a \"required modules are not registered\" report or the module-registration lint is wrong."
}
Module Definitions and Option Contributions
A ModuleDefinition is the single place a feature declares itself. Its type decides the lifecycle
(chart, axis, series, plugin, axis:plugin, series:plugin, preset). Its option contributions decide
which locations in the options tree it owns. Everything downstream derives from these two facts:
- first-pass validation defs for module-owned locations (
composeChartOptionsDefs), - the "required modules are not registered" report and the stripping of unowned options,
- stripping options a chart type does not support (
Option \x` is not supported by `pie` series`), - theme defaults merged from
themeTemplateat the contributed path, - the runtime decision to instantiate an axis or series plugin,
- the generated placeholder table in community and the ESLint example-validation mappings.
Never add a consumer that special-cases a module by name or option key. If a consumer needs to know about a location, the owning module must declare it.
When contributes is implied
Most modules own exactly the location their type implies, and declare nothing:
| Type | Implied location | Requested when |
|---|---|---|
plugin |
<name> at the chart root |
non-null and not { enabled: false } |
axis:plugin |
axes[].<optionsKey ?? name> |
as above |
series:plugin |
series[].<name> |
any non-null value ('present') |
Chart, axis, series and preset modules own whole subtrees by identity and contribute nothing.
When to declare contributes
Declare it when the module owns options anywhere else, or owns several locations:
export const AxisInteractionModule: PluginModuleDefinition<never> = {
type: 'plugin',
name: 'axis-interaction',
chartTypes: ['cartesian'],
enterprise: true,
version: VERSION,
contributes: [
{ path: 'axes[].listeners.click', options: callback },
{ path: 'listeners.axisClick', options: callback },
],
create: (ctx) => new AxisInteraction(ctx),
};
Each contribution:
path: dotted, with[]marking a segment whose every child is a host (axes[],series[]). The first segment decides the host:axes[]is the axis host,series[]the series host, anything else the chart host.options: validation for the subtree, or one validator for a leaf such as a callback. Omit it to keep whatever the chart defs already declare there.themeTemplate: defaults merged at the path.chartTypes/axisTypes/seriesTypes: where the location applies. A contribution withoutchartTypesinherits the definition's; omitting the list applies everywhere, while an empty list applies nowhere.requested:'enabled'(default) or'present', deciding whether a supplied value counts as a request for the missing module.apiName: a public name for the report when the path alone reads badly.
A module with neither options nor a themeTemplate owns no option location at all (internal
dependencies, the community series area), so it declares nothing.
Community and enterprise pairs
An enterprise module with the same name and version as a community one replaces it on
registration (enterprise: true). Reserve this for a module whose behaviour the enterprise build
changes wholesale; the generated placeholder then names the enterprise variant.
Contributing into another module's options
A feature that lives under another module's option key is its own module, not an override of the
host. BackgroundRegionsModule declares contributes: [{ path: 'seriesArea.backgroundRegions', ... }]
and reaches the host through the seriesArea chart-context service, which every chart installs, so
ctx.seriesArea is never optional. The feature implements SeriesAreaContent and calls
ctx.seriesArea.attach(this) to render inside the series area. The host reads the keys other modules contribute below its path through contributedKeysUnder
and leaves them alone, so it validates only its own options.
Presets that users reach through an API entry point declare apiName: 'AgCharts.createGauge' so the
report names the entry point rather than the registry name.
Chart-context services
A module of any type provides chart-context services through services, a map from registry name
to factory: services: { zoomManager: (c) => new ZoomManager(c) }. The chart installs the services
of every registered module that applies to its chart type before anything reads the context; the
first provider of a name wins, so several modules may share one interchangeable provider (such as
sharedToolbar, which both the chart toolbar and annotations provide).
The context is the integration point between modules: consumers read the service from ctx and,
unless every chart module guarantees it, treat it as optional. Never add a dependencies edge or
an export only so that one module can reach a service another module provides. Keep register for
what is not a lazily built service, such as a ctx.factory or an eagerly constructed constant.
Generated tables
packages/ag-charts-enterprise/src/moduleTables.test.ts derives from the exported definitions:
packages/ag-charts-community/src/chart/factory/expectedModules.generated.tslibraries/ag-charts-eslint-rules/rules/module-mappings.generated.mjs
and asserts that the documentation module list names only exported module ids. After changing a
definition, a bundle, or a main.ts export, regenerate:
UPDATE_MODULE_TABLES=1 yarn nx test ag-charts-enterprise -- moduleTables
yarn nx format
The test fails until the files are regenerated. Do not edit the generated files. An unexported preset, or an unexported module that owns options, is reported as the exported modules that carry it: its axis and series carriers, narrowed to the types in use, else the smallest carriers.
The ESLint tables key each requirement by the owning definition's name, and list the definitions
every exported module brings in, per package. The rule treats a requirement as met when a
registered module brings in its owner, so an internal module needs no export to be recognised. The
fix imports the reported module from the package its owner's enterprise flag names.
libraries/ag-charts-eslint-rules/rules/module-mappings.mjs keeps only what definitions do not carry
(default axes per series, intrinsic defaults) and re-exports the generated tables.
Checklist for a new module
- Write the definition with
type,name,version,create, andoptions/themeTemplate. Put undocumented keys inside theoptionsliteral with...undocumentedDefs({...}), never by assigning onto it afterwards, which keeps it out of tree-shaking (see theapi-contractsrule). - Declare
contributesonly if the implied location is wrong or incomplete. It replaces the implied location, so when adding locations, list the implied one alongside them. - Export it from the package
main.tsif it is user-facing, and add it to the relevantmodule-bundles/*.ts. An internal module is registered through another module'sdependencies. - Regenerate the tables and run
yarn nx test ag-charts-community -- optionsModuleso the parametrised contract test covers the new contribution. - Add the module to
packages/ag-charts-website/src/content/module-mappings/modules.jsonif it is user-facing.
版本历史
-
902bdf1
当前 2026-11-02 22:34
移除部分捆绑包和内部模块报告;停止导出内部轴特性模块;通过 services 映射声明式提供图表上下文服务;模块注册 lint 改为检查模块内容而非 ID。
-
39cb99b
2026-10-19 05:36
核心代码改为树可摇以支持集成导出;显式 contributes 替代隐含所有权规则;新增 undocumentedDefs 模式文档及 bundle 对比工具。
-
4f5d825
2026-09-27 22:39
插件定义现支持以列表形式声明 chartTypes,允许单一定义覆盖多种图表类型,优化了运行时匹配逻辑。
- fd55d17 2026-09-22 10:50


