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:
ctx.xxx.yyy.ctx API references and examples.This chapter introduces two extension points:
registerRunJSContextContribution(...)registerRunJSSnippet(...)registerRunJSContextContributionUsed to register RunJS "contributions." Typical use cases include:
RunJSContextRegistry mappings (modelClass -> RunJSContext, including scenes).RunJSDocMeta (descriptions/examples/completion templates for the ctx API) for FlowRunJSContext or custom RunJSContext.setupRunJSContexts() phase.setupRunJSContexts() has already completed, late registrations will be executed immediately (no need to re-run setup).RunJSVersion.registerRunJSSnippetUsed to register example code snippets for RunJS, which are used for:
It is suggested to use: plugin/<pluginName>/<topic>, for example:
plugin/plugin-my/fooplugin/plugin-my/api-request-exampleAvoid conflicts with core global/* or scene/* namespaces.
ref entries are not overwritten (returns false without throwing an error).{ override: true }.RunJSDocMeta: Descriptions/completion templates (short, structured).scenes field is filled correctly to improve the relevance of completions and examples.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:
true: Hides the current node and its subtree.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).
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 from meta, supports path/maxDepth expansion).await ctx.getEnvInfos(): Runtime environment snapshot.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().
defineProperty(key, { meta?, info? })meta: Used for the variable selector UI (getPropertyMetaTree / FlowContextSelector). It determines visibility, tree structure, disabling, etc. (supports functions/async).
title / type / properties / sort / hidden / disabled / disabledReason / buildVariablesParamsinfo: Used for static API documentation (getApiInfos) and descriptions for LLMs. It does not affect the variable selector UI (supports functions/async).
title / type / interface / description / examples / ref / params / returnsWhen only meta is provided (without info):
getApiInfos() will not return this key (as static API docs are not inferred from meta).getVarInfos() will build the variable structure based on meta (used for variable selectors/dynamic variable trees).Used to output "available context capability information."
Common parameters:
getApiInfos({ version }): RunJS documentation version (defaults to v1).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.
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:
const v = await ctx.getVar('ctx.record.roles.id')path is an expression path starting with ctx. (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().