RunJS Plugin Extension Points (ctx Documentation / Snippets / Scene Mapping)
When a plugin adds or extends RunJS capabilities, it is recommended to register the "context mapping / ctx documentation / example code" through official extension points. This ensures:
- CodeEditor can provide auto-completion for
ctx.xxx.yyy. - AI coding can obtain structured
ctxAPI references and examples.
This chapter introduces two extension points:
registerRunJSContextContribution(...)registerRunJSSnippet(...)
1. registerRunJSContextContribution
Used to register RunJS "contributions." Typical use cases include:
- Adding/overriding
RunJSContextRegistrymappings (modelClass->RunJSContext, includingscenes). - Extending
RunJSDocMeta(descriptions/examples/completion templates for thectxAPI) forFlowRunJSContextor customRunJSContext.
Behavior Description
- Contributions are executed collectively during the
setupRunJSContexts()phase. - If
setupRunJSContexts()has already completed, late registrations will be executed immediately (no need to re-run setup). - Each contribution will be executed at most once for each
RunJSVersion.
Example: Adding a JS-writable Model Context
2. registerRunJSSnippet
Used to register example code snippets for RunJS, which are used for:
- CodeEditor snippet completion.
- Serving as examples/reference materials for AI coding (can be filtered by scene/version/locale).
Recommended ref Naming
It is suggested to use: plugin/<pluginName>/<topic>, for example:
plugin/plugin-my/fooplugin/plugin-my/api-request-example
Avoid conflicts with core global/* or scene/* namespaces.
Conflict Strategy
- By default, existing
refentries are not overwritten (returnsfalsewithout throwing an error). - To explicitly overwrite, pass
{ override: true }.
Example: Registering a Snippet
3. Best Practices
- Layered Maintenance of Documentation + Snippets:
RunJSDocMeta: Descriptions/completion templates (short, structured).- Snippets: Long examples (reusable, filterable by scene/version).
- Avoid Excessive Prompt Length: Examples should be concise; prioritize "minimal runnable templates."
- Scene Priority: If your JS code primarily runs in scenarios like forms or tables, ensure the
scenesfield is filled correctly to improve the relevance of completions and examples.
4. Hiding Completions Based on Actual ctx: hidden(ctx)
Certain ctx APIs are highly context-specific (e.g., ctx.popup is only available when a popup or drawer is open). If you want to hide these unavailable APIs during completion, you can define hidden(ctx) for the corresponding entry in RunJSDocMeta:
- Returns
true: Hides the current node and its subtree. - Returns
string[]: Hides specific sub-paths under the current node (supports returning multiple paths; paths are relative; subtrees are hidden based on prefix matching).
hidden(ctx) supports async: You can use await ctx.getVar('ctx.xxx') to determine visibility (at the user's discretion). It is recommended to keep this logic fast and side-effect-free (e.g., avoid network requests).
Example: Show ctx.popup.* completions only when popup.uid exists.
Example: Popup is available but some sub-paths are hidden (relative paths only; e.g., hiding record and parent.record).
Note: CodeEditor always enables completion filtering based on the actual ctx (fail-open, does not throw errors).
5. Runtime info/meta and Context Information API (for Completions and LLMs)
In addition to maintaining ctx documentation statically via FlowRunJSContext.define(), you can also inject info/meta at runtime via FlowContext.defineProperty/defineMethod. You can then output serializable context information for CodeEditor or LLMs using the following APIs:
await ctx.getApiInfos(options?): Static API information.await ctx.getVarInfos(options?): Variable structure information (sourced frommeta, supports path/maxDepth expansion).await ctx.getEnvInfos(): Runtime environment snapshot.
5.1 defineMethod(name, fn, info?)
info supports (all optional):
description/detail/examplesref: string | { url: string; title?: string }params/returns(JSDoc-like)
Note:
getApiInfos()outputs static API documentation and will not include fields likedeprecated,disabled, ordisabledReason.
Example: Providing documentation links for ctx.refreshTargets().
5.2 defineProperty(key, { meta?, info? })
meta: Used for the variable selector UI (getPropertyMetaTree/FlowContextSelector). It determines visibility, tree structure, disabling, etc. (supports functions/async).- Common fields:
title/type/properties/sort/hidden/disabled/disabledReason/buildVariablesParams
- Common fields:
info: Used for static API documentation (getApiInfos) and descriptions for LLMs. It does not affect the variable selector UI (supports functions/async).- Common fields:
title/type/interface/description/examples/ref/params/returns
- Common fields:
When only meta is provided (without info):
getApiInfos()will not return this key (as static API docs are not inferred frommeta).getVarInfos()will build the variable structure based onmeta(used for variable selectors/dynamic variable trees).
5.3 Context Information API
Used to output "available context capability information."
Common parameters:
getApiInfos({ version }): RunJS documentation version (defaults tov1).getVarInfos({ path, maxDepth }): Trimming and maximum expansion depth (defaults to 3).
Note: The results returned by the above APIs do not contain functions and are suitable for direct serialization to LLMs.
5.4 await ctx.getVar(path)
When you have a "variable path string" (e.g., from configuration or user input) and want to retrieve the runtime value of that variable directly, use getVar:
- Example:
const v = await ctx.getVar('ctx.record.roles.id') pathis an expression path starting withctx.(e.g.,ctx.record.id/ctx.record.roles[0].id).
Additionally: Methods or properties starting with an underscore _ are treated as private members and will not appear in the output of getApiInfos() or getVarInfos().

