# KBbridge — KB Editor Pattern Extensibility Documentation > Full Markdown of the KB Editor pattern-extensibility guides (the `PatternExtensionAPI`). Source of truth: https://github.com/jmblamasuy/kbbridge-editor-pattern-extensions-documentation @ main. Each guide is also served individually at https://kbbridge.com/docs/.md # Introduction ## The problem GeneXus patterns (Work With, and many third-party patterns) have rich, IDE-integrated editors in the GeneXus desktop IDE — dynamic dropdowns, computed node captions, context commands. When GeneXus pattern instances are edited inside **KB Editor** (the GeneXus visual editor for VS Code / VSCodium), those smarts are not built in: KB Editor knows the pattern **schema** (from the pattern's `*Instance.xml`) but not the **dynamic behavior**, which in the IDE is implemented in .NET. ## The solution KB Editor exposes a **`PatternExtensionAPI`**. A small VS Code extension — written by the pattern's provider — registers **providers** that supply that dynamic behavior. KB Editor then calls those providers while the user edits, giving pattern instances the same first-class experience they have in the GeneXus IDE. A few mechanisms cover the editor behavior of essentially every pattern: 1. **Custom Types** — compute the valid values for a `custom()` property on demand. 2. **Captions** — override a node's label based on its data. 3. **Custom Actions** — add context commands to nodes. 4. **Node icons** — supply a node's icon as a bundled resource. If the provider extension is not installed, KB Editor still works (graceful degradation): dropdowns become plain text, captions fall back to defaults, and there are no extra commands. ## Who this is for - **Pattern vendors** who want their pattern to feel native in KB Editor. - **GeneXus teams** porting a pattern's editor behavior from .NET to TypeScript. ## Glossary | Term | Meaning | |---|---| | **KB Editor** | GeneXus visual editor for VS Code / VSCodium (`kbbridge.genexus-visual-editor`). | | **Pattern** | A GeneXus pattern (e.g. Work With) defined by `.Pattern` + `*Instance.xml`. | | **Pattern instance** | A `.gxPattern` file: a tree of pattern element types over a transaction/object. | | **Custom type** | A property type `custom()` whose values are computed by a provider. | | **Caption** | The label shown for a node in the editor tree. | | **Command / action** | A context action attached to a node. | | **SDK** | [`@kbbridge/genexus-sdk`](https://github.com/jmblamasuy/kbbridge-editor-genexus-sdk) — the TypeScript contract that mirrors the GeneXus .NET pattern SDK. | Next: [GeneXus pattern concepts](/docs/genexus-pattern-concepts.md). [Source: https://kbbridge.com/docs/introduction](https://kbbridge.com/docs/introduction) --- # GeneXus pattern concepts A GeneXus pattern ships a small set of definition files; KB Editor reads them to know the tree shape and property editors. Your extension supplies behavior for the dynamic parts. ``` Patterns// ├── Definitions/ │ ├── .Pattern main definition (version, generated objects, templates) │ ├── Instance.xml instance schema: element types, attributes, children │ ├── CustomTypes.xml custom type ids and their base data types │ └── Settings.xml settings schema └── Source/ … the pattern's .NET implementation (your reference) ``` ## Instance schema `*Instance.xml` defines each **ElementType** (a kind of node), its **attributes** (properties) and its allowed **child elements**. A `.gxPattern` instance is a tree of these. ```xml ``` ### Attribute types and their editors | `Type=` | Editor | |---|---| | `string` / `bool` / `int` | text / checkbox / number | | `enum{A;B;C}` | static dropdown | | `reference(KBObjectType)` | KB object picker | | `code(Events)` | embedded code editor | | **`custom()`** | **dynamic dropdown — your provider supplies the values** | ## Settings vs instance Patterns also have **settings** (`*Settings.xml`, edited as `.gxPatternSettings`). Custom types can appear in either — e.g. Work With's `GridCustomRender` custom type is used by the **settings** property `CustomRender`. The mechanism is the same: KB Editor calls your `getTypeEditor()` regardless of where the property lives. ## How it maps to your code - `ElementType Name` → `PatternInstanceElement.elementType` (branch on this). - instance node tag → `PatternInstanceElement.tag`. - `custom()` → KB Editor calls `getTypeEditor("")` on your support. - `Caption` + `CaptionParameters` → the default label; override it via `customShowElement`. > You normally **don't ship** the schema — it comes from the user's GeneXus install/KB. Your > extension provides the providers keyed by pattern type. Next: [Extensibility architecture](/docs/extensibility-architecture.md). [Source: https://kbbridge.com/docs/genexus-pattern-concepts](https://kbbridge.com/docs/genexus-pattern-concepts) --- # Extensibility architecture ``` Your extension ──codes against──▶ @kbbridge/genexus-sdk ──implemented by──▶ KB Editor (registers providers) (PatternExtensionAPI, (parses .gxPattern, IPattern* interfaces, renders tree, PatternInstanceElement) calls your providers) ``` Your extension depends only on the **SDK contract** (vendored, MIT, no runtime deps), never on KB Editor internals. KB Editor hands you the API object at runtime. ## Activation & registration 1. VS Code activates your extension. Your `package.json` declares `"extensionDependencies": ["kbbridge.genexus-visual-editor"]`, so KB Editor is present. 2. You obtain the API and register providers per pattern type: ```ts const kb = vscode.extensions.getExtension('kbbridge.genexus-visual-editor'); const api = await kb.activate(); // resolves KB Editor's exported API api.patternAPI.registerCustomTypeSupport('WorkWith', customTypes); api.patternAPI.registerEditorHelper('WorkWith', editorHelper); ``` > **Tolerate activation ordering.** `extensionDependencies` *should* make KB Editor activate > first, but on some setups it doesn't — your extension may run before KB Editor has > populated its exports, so `api.patternAPI` is momentarily missing. Don't give up on the > first try: retry acquiring it for a few seconds (the starter and Work With `activate()` > ship an `acquirePatternAPI` helper that does exactly this). 3. You dispose (unregister) on deactivate. One extension can register **several** pattern types. ## How KB Editor calls you - For a `custom()` property → `getTypeEditor(Id)` then `getValues(context)`. - When rendering a node → `customShowElement(element, context)` (caption/icon) and `getCommands(element)` (context commands). - When the user runs a command → the command's `exec()`. Context objects carry the current node, property, values, pattern type, instance name, file path, and (optionally) a KB object cache. ## Graceful degradation Missing provider ⇒ KB Editor falls back: plain text for custom types, default captions, no commands. Provider callbacks must **fail soft** (return empty / `{handled:false}`), never throw. ## One package or two? For a single pattern, **one package** is enough. If you ship **many** patterns and want to share code, you can split into a shared helper library + a patterns extension. That is an optimization, not a requirement. Deeper, build-it version: each project's [`ai/ARCHITECTURE.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/ARCHITECTURE.md) and [`ai/SDK-REFERENCE.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/SDK-REFERENCE.md). Next: [The extensibility mechanisms](/docs/extensibility-mechanisms.md). [Source: https://kbbridge.com/docs/extensibility-architecture](https://kbbridge.com/docs/extensibility-architecture) --- # The extensibility mechanisms Each mechanism is illustrated below with the GeneXus *Work With* pattern. Full, build-it guides (interfaces, invocation flow, gotchas) live in the projects' `ai/` folders. ## 1. Custom Types — dynamic dropdowns You implement `IPatternCustomTypeSupport.getTypeEditor(id)`, returning an editor whose `getValues(context)` computes the options for a `custom()` property. *Work With* example: the `GridCustomRender` custom type returns the available grid controls. ```ts class WorkWithCustomTypeSupport implements IPatternCustomTypeSupport { getTypeEditor(id: string) { return id === 'GridCustomRender' ? new GridCustomRenderEditor() : null; } } ``` → Deep dive: [`ai/EXTENSIBILITY-CUSTOM-TYPES.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/EXTENSIBILITY-CUSTOM-TYPES.md). ## 2. Captions — node labels You implement `IPatternEditorHelper.customShowElement(element, ctx)`, returning `{ handled, caption, icon }`. Return `{ handled: false }` for nodes you don't customize. (The optional `icon` lets you override a node's icon inline; for icons that ship as bundled resources use the dedicated hook in mechanism 4.) *Work With* example: the `Modes` node shows `modes (Insert, Update, ...)` listing the enabled modes. ```ts customShowElement(element) { if (element.elementType === 'Modes') return { handled: true, caption: `modes (${enabledModes(element).join(', ')})` }; return { handled: false }; } ``` → Deep dive: [`ai/EXTENSIBILITY-CAPTIONS.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/EXTENSIBILITY-CAPTIONS.md). ## 3. Custom Actions — context commands You implement `IPatternEditorHelper.getCommands(element)`, returning serializable commands (usually subclasses of `PatternEditorCommandBase`). The command's `exec()` runs on click and may mutate the instance tree. *Work With* example: **"Add Filter Variable"** on the `FilterAttributes` node. ```ts getCommands(element) { return element.elementType === 'FilterAttributes' ? [new AddFilterVariableCommand(element).toSerializable()].filter(Boolean) : []; } ``` → Deep dive: [`ai/EXTENSIBILITY-CUSTOM-ACTIONS.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/EXTENSIBILITY-CUSTOM-ACTIONS.md). ## 4. Node icons — bundled resource icons You implement `IPatternEditorHelper.getNodeIcon(element, iconName?)`, returning the node's icon as a self-contained resource (typically a `data:` URI). KB Editor resolves a node's icon in order — the caption's inline `icon` (mechanism 2), then the schema's `Icon` when it exists as a file next to the pattern, then this hook, then a built-in glyph — so returning `undefined` falls through to the next source. *Work With* example: the pattern declares its icons as .NET assembly resources (`Icon="ObjectAttribute" IconResource="…,Artech.Patterns.WorkWith"`), which don't exist as files on the client's KB. The extension bundles those images under `icons/` (named exactly like the schema `Icon` values) and returns them here, so the tree shows the real icons with no GeneXus SDK or .NET assemblies at runtime. ```ts getNodeIcon(element, iconName) { if (!iconName || !/^[A-Za-z0-9_]+$/.test(iconName)) return undefined; const file = path.join(this.iconsDir, `${iconName}.ico`); return fs.existsSync(file) ? `data:image/x-icon;base64,${fs.readFileSync(file).toString('base64')}` : undefined; } ``` → Deep dive: the *Work With* example's `WorkWithEditorHelper.getNodeIcon` and its bundled `icons/` folder. ## Optional: Variables If your pattern exposes context variables in embedded code, implement `IPatternVariableProvider` to feed KB Editor's autocomplete. → [`ai/EXTENSIBILITY-VARIABLES.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/EXTENSIBILITY-VARIABLES.md). Next: [C# → TypeScript workflow](/docs/csharp-to-typescript-workflow.md). [Source: https://kbbridge.com/docs/extensibility-mechanisms](https://kbbridge.com/docs/extensibility-mechanisms) --- # C# → TypeScript workflow If your pattern already has a GeneXus **.NET** implementation, the fastest faithful path is to **transcribe** the editor classes to TypeScript against [`@kbbridge/genexus-sdk`](https://github.com/jmblamasuy/kbbridge-editor-genexus-sdk), which mirrors the GeneXus .NET pattern SDK. ## Method 1. Put the pattern's .NET sources in a **git-ignored `reference/`** folder (never published). 2. Find the three editor classes — they are usually small even when the whole pattern is large: - the **CustomTypeSupport** (custom types), - the **EditorHelper** (`CustomShowElement` + `GetCommands`), - each **PatternEditorCommand** subclass. 3. Transcribe class-by-class, annotating each TS class with `// Equivalent to `. > Only the editor behavior matters. Code generation, build/delete processes, validators and > the instance object model are **out of scope** — KB Editor never runs them. ## The .NET → SDK mapping | GeneXus .NET (`Artech.Packages.Patterns.*`) | `@kbbridge/genexus-sdk` (TypeScript) | |---|---| | `PatternCustomTypeSupport.GetTypeEditor` | `IPatternCustomTypeSupport.getTypeEditor` | | `PatternCustomTypeEditor.GetComboValues(...)` | `IPatternCustomTypeEditor.getValues(ctx): CustomTypeValue[]` | | `PatternEditorHelper.CustomShowElement(el, ref caption, ref icon): bool` | `customShowElement(el, ctx): {handled, caption, icon}` | | `PatternEditorHelper.GetCommands(el)` | `getCommands(el): PatternEditorCommand[]` | | `PatternEditorCommand` (`Text`/`Query`/`Exec`) | `PatternEditorCommandBase` (`text`/`query`/`exec`) | | `element.Type` | `element.elementType` | | `element.Attributes.GetPropertyValue("x")` | `element.attributes['x']` | | `Children.AddNewElement(tag)` | `new PatternInstanceElement({tag,attributes,children}, parent, i, path)` + `parent.addChild(...)` | | IDE dialogs (`GenexusUIServices.*`) | VS Code APIs (`QuickPick`, `showInputBox`, …) | ## Worked example The [`kbbridge-editor-pattern-genexus-workwith`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith) project is a complete, faithful transcription of the GeneXus *Work With* editor behavior. Read its [`ai/EXAMPLES.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/EXAMPLES.md) for a file-by-file walkthrough. ## Rules - Never ship the .NET sources (or anything decompiled) — only your original TypeScript. - Transcribe from **your** pattern's sources (or a pattern you have the rights to). If porting a GeneXus-distributed pattern, add a `NOTICE` attributing GeneXus and confirm distribution terms. Next: [Getting started](/docs/getting-started.md). [Source: https://kbbridge.com/docs/csharp-to-typescript-workflow](https://kbbridge.com/docs/csharp-to-typescript-workflow) --- # Getting started ## 1. Prerequisites - **KB Editor** (`kbbridge.genexus-visual-editor`) installed in VS Code / VSCodium. - Node.js 18+ and npm. ## 2. Get a project - New pattern from scratch → clone **[`kbbridge-editor-pattern-starter`](https://github.com/jmblamasuy/kbbridge-editor-pattern-starter)**. - Learning by example → clone **[`kbbridge-editor-pattern-genexus-workwith`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith)** (the Work With port). The SDK ([`@kbbridge/genexus-sdk`](https://github.com/jmblamasuy/kbbridge-editor-genexus-sdk)) is already **vendored** in both, so there is nothing extra to install for it. ## 3. Build ```bash npm install # tooling + links the vendored SDK npm run compile # tsc → out/ npm run bundle # vendored SDK → node_modules + out/node_modules ``` ## 4. Implement (starter only) Open `src/extension.ts` → `registerProviders()` and implement the mechanisms you need ([`ai/START-HERE.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/START-HERE.md) walks you through each). Then rebuild. ## 5. Package & install ```bash npm run package # → -.vsix ``` Install the `.vsix` where KB Editor lives, **Reload Window**, and open a `.gxPattern` instance of your pattern type. ## 6. Verify - A `custom()` property shows a populated dropdown. - Your customized node captions appear. - Your context commands appear on right-click and run. Check your extension's **OutputChannel** for logs. ## Where to go next - The full build guide and exact SDK signatures: each project's **`ai/`** folder (`START-HERE.md`, [`SDK-REFERENCE.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/SDK-REFERENCE.md), `EXTENSIBILITY-*.md`, [`DEPLOY.md`](https://github.com/jmblamasuy/kbbridge-editor-pattern-genexus-workwith/blob/main/ai/DEPLOY.md)). - Publish your extension on the **[`kbbridge-editor-pattern-extensions-releases`](https://github.com/jmblamasuy/kbbridge-editor-pattern-extensions-releases)** download platform. [Source: https://kbbridge.com/docs/getting-started](https://kbbridge.com/docs/getting-started)