@plotday/twister 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +5 -5
  2. package/bin/templates/AGENTS.template.md +5 -5
  3. package/bin/templates/README.template.md +1 -1
  4. package/cli/templates/AGENTS.template.md +5 -5
  5. package/cli/templates/README.template.md +1 -1
  6. package/dist/common/calendar.d.ts +1 -1
  7. package/dist/docs/assets/search.js +1 -1
  8. package/dist/docs/documents/Advanced.html +6 -6
  9. package/dist/docs/documents/Building_Custom_Tools.html +3 -3
  10. package/dist/docs/documents/Built-in_Tools.html +3 -3
  11. package/dist/docs/documents/Core_Concepts.html +3 -3
  12. package/dist/docs/documents/Getting_Started.html +1 -1
  13. package/dist/docs/documents/Runtime_Environment.html +2 -2
  14. package/dist/docs/enums/plot.ActivityType.html +3 -3
  15. package/dist/docs/interfaces/common_calendar.CalendarTool.html +1 -1
  16. package/dist/docs/types/plot.Activity.html +1 -1
  17. package/dist/docs/types/plot.NewActivity.html +1 -1
  18. package/dist/llm-docs/common/calendar.d.ts +1 -1
  19. package/dist/llm-docs/common/calendar.d.ts.map +1 -1
  20. package/dist/llm-docs/common/calendar.js +1 -1
  21. package/dist/llm-docs/common/calendar.js.map +1 -1
  22. package/dist/llm-docs/plot.d.ts +1 -1
  23. package/dist/llm-docs/plot.d.ts.map +1 -1
  24. package/dist/llm-docs/plot.js +1 -1
  25. package/dist/llm-docs/plot.js.map +1 -1
  26. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  27. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  28. package/dist/llm-docs/twist-guide-template.js +1 -1
  29. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  30. package/dist/plot.d.ts +5 -5
  31. package/dist/plot.d.ts.map +1 -1
  32. package/dist/plot.js +1 -1
  33. package/dist/plot.js.map +1 -1
  34. package/dist/twist-guide.d.ts +1 -1
  35. package/dist/twist-guide.d.ts.map +1 -1
  36. package/package.json +1 -1
@@ -9,11 +9,11 @@
9
9
  </ul>
10
10
  <hr>
11
11
  <h2 id="complex-twist-architectures" class="tsd-anchor-link">Complex twist Architectures<a href="#complex-twist-architectures" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="multi-service-integration" class="tsd-anchor-link">Multi-Service Integration<a href="#multi-service-integration" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Coordinate multiple external services:</p>
12
- <pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">GitHubTool</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@mycompany/plot-github-tool&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">JiraTool</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@mycompany/plot-jira-tool&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">SlackTool</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@mycompany/plot-slack-tool&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">twist</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">Priority</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">ToolBuilder</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Plot</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister/tools/plot&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-0">default</span><span class="hl-1"> </span><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">DevOpsTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">twist</span><span class="hl-1">&lt;</span><span class="hl-5">DevOpsTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">build</span><span class="hl-1">: </span><span class="hl-5">ToolBuilder</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">plot:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Plot</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-2">github:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">GitHubTool</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">owner:</span><span class="hl-1"> </span><span class="hl-3">&quot;mycompany&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">repo:</span><span class="hl-1"> </span><span class="hl-3">&quot;myapp&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">token:</span><span class="hl-1"> </span><span class="hl-2">process</span><span class="hl-1">.</span><span class="hl-2">env</span><span class="hl-1">.</span><span class="hl-8">GITHUB_TOKEN</span><span class="hl-1">!,</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> </span><span class="hl-2">slack:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">SlackTool</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">webhookUrl:</span><span class="hl-1"> </span><span class="hl-2">process</span><span class="hl-1">.</span><span class="hl-2">env</span><span class="hl-1">.</span><span class="hl-8">SLACK_WEBHOOK_URL</span><span class="hl-1">!,</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> </span><span class="hl-2">jira:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">JiraTool</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">domain:</span><span class="hl-1"> </span><span class="hl-3">&quot;mycompany.atlassian.net&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">apiToken:</span><span class="hl-1"> </span><span class="hl-2">process</span><span class="hl-1">.</span><span class="hl-2">env</span><span class="hl-1">.</span><span class="hl-8">JIRA_TOKEN</span><span class="hl-1">!,</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> };</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">activate</span><span class="hl-1">(</span><span class="hl-2">priority</span><span class="hl-1">: </span><span class="hl-5">Pick</span><span class="hl-1">&lt;</span><span class="hl-5">Priority</span><span class="hl-1">, </span><span class="hl-3">&quot;id&quot;</span><span class="hl-1">&gt;) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Set up cross-service workflow</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">setupIssueSync</span><span class="hl-1">();</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">setupIssueSync</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-7">// When GitHub issue is created, create Jira ticket and post to Slack</span><br/><span class="hl-1"> </span><span class="hl-7">// When Jira ticket is updated, update GitHub issue</span><br/><span class="hl-1"> </span><span class="hl-7">// When PR is merged, update both and notify Slack</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
12
+ <pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">GitHubTool</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@mycompany/plot-github-tool&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">JiraTool</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@mycompany/plot-jira-tool&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">SlackTool</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@mycompany/plot-slack-tool&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">twist</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">Priority</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">ToolBuilder</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Plot</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister/tools/plot&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-0">default</span><span class="hl-1"> </span><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">DevOpsTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Twist</span><span class="hl-1">&lt;</span><span class="hl-5">DevOpsTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">build</span><span class="hl-1">: </span><span class="hl-5">ToolBuilder</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">plot:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Plot</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-2">github:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">GitHubTool</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">owner:</span><span class="hl-1"> </span><span class="hl-3">&quot;mycompany&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">repo:</span><span class="hl-1"> </span><span class="hl-3">&quot;myapp&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">token:</span><span class="hl-1"> </span><span class="hl-2">process</span><span class="hl-1">.</span><span class="hl-2">env</span><span class="hl-1">.</span><span class="hl-8">GITHUB_TOKEN</span><span class="hl-1">!,</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> </span><span class="hl-2">slack:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">SlackTool</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">webhookUrl:</span><span class="hl-1"> </span><span class="hl-2">process</span><span class="hl-1">.</span><span class="hl-2">env</span><span class="hl-1">.</span><span class="hl-8">SLACK_WEBHOOK_URL</span><span class="hl-1">!,</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> </span><span class="hl-2">jira:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">JiraTool</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">domain:</span><span class="hl-1"> </span><span class="hl-3">&quot;mycompany.atlassian.net&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">apiToken:</span><span class="hl-1"> </span><span class="hl-2">process</span><span class="hl-1">.</span><span class="hl-2">env</span><span class="hl-1">.</span><span class="hl-8">JIRA_TOKEN</span><span class="hl-1">!,</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> };</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">activate</span><span class="hl-1">(</span><span class="hl-2">priority</span><span class="hl-1">: </span><span class="hl-5">Pick</span><span class="hl-1">&lt;</span><span class="hl-5">Priority</span><span class="hl-1">, </span><span class="hl-3">&quot;id&quot;</span><span class="hl-1">&gt;) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Set up cross-service workflow</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">setupIssueSync</span><span class="hl-1">();</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">setupIssueSync</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-7">// When GitHub issue is created, create Jira ticket and post to Slack</span><br/><span class="hl-1"> </span><span class="hl-7">// When Jira ticket is updated, update GitHub issue</span><br/><span class="hl-1"> </span><span class="hl-7">// When PR is merged, update both and notify Slack</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
13
13
  </code><button type="button">Copy</button></pre>
14
14
 
15
15
  <h3 id="state-machine-pattern" class="tsd-anchor-link">State Machine Pattern<a href="#state-machine-pattern" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Implement complex workflows with state machines:</p>
16
- <pre><code class="typescript"><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-5">WorkflowState</span><span class="hl-1"> = </span><span class="hl-3">&quot;pending&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;review&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;complete&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-5">WorkflowData</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">state</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">activityId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">metadata</span><span class="hl-1">: </span><span class="hl-5">Record</span><span class="hl-1">&lt;</span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-5">any</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">WorkflowTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">twist</span><span class="hl-1">&lt;</span><span class="hl-5">WorkflowTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">transitionTo</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">newState</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">workflow</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;</span><span class="hl-5">WorkflowData</span><span class="hl-1">&gt;(</span><span class="hl-3">`workflow:</span><span class="hl-4">${</span><span class="hl-2">workflowId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-2">workflow</span><span class="hl-1">) </span><span class="hl-0">throw</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Error</span><span class="hl-1">(</span><span class="hl-3">&quot;Workflow not found&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">oldState</span><span class="hl-1"> = </span><span class="hl-2">workflow</span><span class="hl-1">.</span><span class="hl-2">state</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Validate transition</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">isValidTransition</span><span class="hl-1">(</span><span class="hl-2">oldState</span><span class="hl-1">, </span><span class="hl-2">newState</span><span class="hl-1">)) {</span><br/><span class="hl-1"> </span><span class="hl-0">throw</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Error</span><span class="hl-1">(</span><span class="hl-3">`Invalid transition: </span><span class="hl-4">${</span><span class="hl-2">oldState</span><span class="hl-4">}</span><span class="hl-3"> -&gt; </span><span class="hl-4">${</span><span class="hl-2">newState</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Execute transition logic</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">onExit</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">, </span><span class="hl-2">oldState</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-2">workflow</span><span class="hl-1">.</span><span class="hl-2">state</span><span class="hl-1"> = </span><span class="hl-2">newState</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">`workflow:</span><span class="hl-4">${</span><span class="hl-2">workflowId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">workflow</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">onEnter</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">, </span><span class="hl-2">newState</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-6">isValidTransition</span><span class="hl-1">(</span><span class="hl-2">from</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">, </span><span class="hl-2">to</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">): </span><span class="hl-5">boolean</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">transitions</span><span class="hl-1">: </span><span class="hl-5">Record</span><span class="hl-1">&lt;</span><span class="hl-5">WorkflowState</span><span class="hl-1">, </span><span class="hl-5">WorkflowState</span><span class="hl-1">[]&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-2">pending:</span><span class="hl-1"> [</span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-2">in_progress:</span><span class="hl-1"> [</span><span class="hl-3">&quot;review&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;pending&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-2">review:</span><span class="hl-1"> [</span><span class="hl-3">&quot;complete&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-2">complete:</span><span class="hl-1"> [],</span><br/><span class="hl-1"> };</span><br/><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-2">transitions</span><span class="hl-1">[</span><span class="hl-2">from</span><span class="hl-1">]?.</span><span class="hl-6">includes</span><span class="hl-1">(</span><span class="hl-2">to</span><span class="hl-1">) ?? </span><span class="hl-4">false</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onEnter</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">state</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">switch</span><span class="hl-1"> (</span><span class="hl-2">state</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">case</span><span class="hl-1"> </span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">notifyAssigned</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">break</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">case</span><span class="hl-1"> </span><span class="hl-3">&quot;review&quot;</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">requestReview</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">break</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">case</span><span class="hl-1"> </span><span class="hl-3">&quot;complete&quot;</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">markComplete</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">break</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onExit</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">state</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Cleanup for previous state</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
16
+ <pre><code class="typescript"><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-5">WorkflowState</span><span class="hl-1"> = </span><span class="hl-3">&quot;pending&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;review&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;complete&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-5">WorkflowData</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">state</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">activityId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">metadata</span><span class="hl-1">: </span><span class="hl-5">Record</span><span class="hl-1">&lt;</span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-5">any</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">WorkflowTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Twist</span><span class="hl-1">&lt;</span><span class="hl-5">WorkflowTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">transitionTo</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">newState</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">workflow</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;</span><span class="hl-5">WorkflowData</span><span class="hl-1">&gt;(</span><span class="hl-3">`workflow:</span><span class="hl-4">${</span><span class="hl-2">workflowId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-2">workflow</span><span class="hl-1">) </span><span class="hl-0">throw</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Error</span><span class="hl-1">(</span><span class="hl-3">&quot;Workflow not found&quot;</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">oldState</span><span class="hl-1"> = </span><span class="hl-2">workflow</span><span class="hl-1">.</span><span class="hl-2">state</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Validate transition</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">isValidTransition</span><span class="hl-1">(</span><span class="hl-2">oldState</span><span class="hl-1">, </span><span class="hl-2">newState</span><span class="hl-1">)) {</span><br/><span class="hl-1"> </span><span class="hl-0">throw</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Error</span><span class="hl-1">(</span><span class="hl-3">`Invalid transition: </span><span class="hl-4">${</span><span class="hl-2">oldState</span><span class="hl-4">}</span><span class="hl-3"> -&gt; </span><span class="hl-4">${</span><span class="hl-2">newState</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Execute transition logic</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">onExit</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">, </span><span class="hl-2">oldState</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-2">workflow</span><span class="hl-1">.</span><span class="hl-2">state</span><span class="hl-1"> = </span><span class="hl-2">newState</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">`workflow:</span><span class="hl-4">${</span><span class="hl-2">workflowId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">workflow</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">onEnter</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">, </span><span class="hl-2">newState</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-6">isValidTransition</span><span class="hl-1">(</span><span class="hl-2">from</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">, </span><span class="hl-2">to</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">): </span><span class="hl-5">boolean</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">transitions</span><span class="hl-1">: </span><span class="hl-5">Record</span><span class="hl-1">&lt;</span><span class="hl-5">WorkflowState</span><span class="hl-1">, </span><span class="hl-5">WorkflowState</span><span class="hl-1">[]&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-2">pending:</span><span class="hl-1"> [</span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-2">in_progress:</span><span class="hl-1"> [</span><span class="hl-3">&quot;review&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;pending&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-2">review:</span><span class="hl-1"> [</span><span class="hl-3">&quot;complete&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> </span><span class="hl-2">complete:</span><span class="hl-1"> [],</span><br/><span class="hl-1"> };</span><br/><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-2">transitions</span><span class="hl-1">[</span><span class="hl-2">from</span><span class="hl-1">]?.</span><span class="hl-6">includes</span><span class="hl-1">(</span><span class="hl-2">to</span><span class="hl-1">) ?? </span><span class="hl-4">false</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onEnter</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">state</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">switch</span><span class="hl-1"> (</span><span class="hl-2">state</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">case</span><span class="hl-1"> </span><span class="hl-3">&quot;in_progress&quot;</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">notifyAssigned</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">break</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">case</span><span class="hl-1"> </span><span class="hl-3">&quot;review&quot;</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">requestReview</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">break</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-0">case</span><span class="hl-1"> </span><span class="hl-3">&quot;complete&quot;</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">markComplete</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">break</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onExit</span><span class="hl-1">(</span><span class="hl-2">workflowId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">state</span><span class="hl-1">: </span><span class="hl-5">WorkflowState</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Cleanup for previous state</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
17
17
  </code><button type="button">Copy</button></pre>
18
18
 
19
19
  <hr>
@@ -31,11 +31,11 @@
31
31
 
32
32
  <hr>
33
33
  <h2 id="debugging-and-logging" class="tsd-anchor-link">Debugging and Logging<a href="#debugging-and-logging" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="structured-logging" class="tsd-anchor-link">Structured Logging<a href="#structured-logging" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Use consistent log formats:</p>
34
- <pre><code class="typescript"><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-5">LogContext</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">twistId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">priorityId</span><span class="hl-1">?: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">operation</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> [</span><span class="hl-2">key</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">]: </span><span class="hl-5">any</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">twist</span><span class="hl-1">&lt;</span><span class="hl-5">MyTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-6">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">level</span><span class="hl-1">: </span><span class="hl-3">&quot;info&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;warn&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;error&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">context</span><span class="hl-1">?: </span><span class="hl-5">Partial</span><span class="hl-1">&lt;</span><span class="hl-5">LogContext</span><span class="hl-1">&gt;</span><br/><span class="hl-1"> ) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">logEntry</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-2">timestamp:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">().</span><span class="hl-6">toISOString</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-2">level</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">twist:</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">,</span><br/><span class="hl-1"> ...</span><span class="hl-2">context</span><span class="hl-1">,</span><br/><span class="hl-1"> };</span><br/><br/><span class="hl-1"> </span><span class="hl-2">console</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-8">JSON</span><span class="hl-1">.</span><span class="hl-6">stringify</span><span class="hl-1">(</span><span class="hl-2">logEntry</span><span class="hl-1">));</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">activate</span><span class="hl-1">(</span><span class="hl-2">priority</span><span class="hl-1">: </span><span class="hl-5">Pick</span><span class="hl-1">&lt;</span><span class="hl-5">Priority</span><span class="hl-1">, </span><span class="hl-3">&quot;id&quot;</span><span class="hl-1">&gt;) {</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">&quot;info&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;twist activating&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">priorityId:</span><span class="hl-1"> </span><span class="hl-2">priority</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">operation:</span><span class="hl-1"> </span><span class="hl-3">&quot;activate&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">try</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">setupWebhooks</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">&quot;info&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;Webhooks configured successfully&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-0">catch</span><span class="hl-1"> (</span><span class="hl-2">error</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">&quot;error&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;Failed to setup webhooks&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">error:</span><span class="hl-1"> </span><span class="hl-2">error</span><span class="hl-1">.</span><span class="hl-2">message</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">stack:</span><span class="hl-1"> </span><span class="hl-2">error</span><span class="hl-1">.</span><span class="hl-2">stack</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
34
+ <pre><code class="typescript"><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-5">LogContext</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">twistId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">priorityId</span><span class="hl-1">?: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-2">operation</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">;</span><br/><span class="hl-1"> [</span><span class="hl-2">key</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">]: </span><span class="hl-5">any</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Twist</span><span class="hl-1">&lt;</span><span class="hl-5">MyTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-6">log</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">level</span><span class="hl-1">: </span><span class="hl-3">&quot;info&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;warn&quot;</span><span class="hl-1"> | </span><span class="hl-3">&quot;error&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">context</span><span class="hl-1">?: </span><span class="hl-5">Partial</span><span class="hl-1">&lt;</span><span class="hl-5">LogContext</span><span class="hl-1">&gt;</span><br/><span class="hl-1"> ) {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">logEntry</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-2">timestamp:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">().</span><span class="hl-6">toISOString</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-2">level</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">twist:</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">,</span><br/><span class="hl-1"> ...</span><span class="hl-2">context</span><span class="hl-1">,</span><br/><span class="hl-1"> };</span><br/><br/><span class="hl-1"> </span><span class="hl-2">console</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-8">JSON</span><span class="hl-1">.</span><span class="hl-6">stringify</span><span class="hl-1">(</span><span class="hl-2">logEntry</span><span class="hl-1">));</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">activate</span><span class="hl-1">(</span><span class="hl-2">priority</span><span class="hl-1">: </span><span class="hl-5">Pick</span><span class="hl-1">&lt;</span><span class="hl-5">Priority</span><span class="hl-1">, </span><span class="hl-3">&quot;id&quot;</span><span class="hl-1">&gt;) {</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">&quot;info&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;twist activating&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">priorityId:</span><span class="hl-1"> </span><span class="hl-2">priority</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">operation:</span><span class="hl-1"> </span><span class="hl-3">&quot;activate&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">try</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">setupWebhooks</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">&quot;info&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;Webhooks configured successfully&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-0">catch</span><span class="hl-1"> (</span><span class="hl-2">error</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">&quot;error&quot;</span><span class="hl-1">, </span><span class="hl-3">&quot;Failed to setup webhooks&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">error:</span><span class="hl-1"> </span><span class="hl-2">error</span><span class="hl-1">.</span><span class="hl-2">message</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">stack:</span><span class="hl-1"> </span><span class="hl-2">error</span><span class="hl-1">.</span><span class="hl-2">stack</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
35
35
  </code><button type="button">Copy</button></pre>
36
36
 
37
37
  <h3 id="debug-mode" class="tsd-anchor-link">Debug Mode<a href="#debug-mode" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Add debug flag for verbose logging:</p>
38
- <pre><code class="typescript"><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">twist</span><span class="hl-1">&lt;</span><span class="hl-5">MyTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">get</span><span class="hl-1"> </span><span class="hl-6">debugMode</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">boolean</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;</span><span class="hl-5">boolean</span><span class="hl-1">&gt;(</span><span class="hl-3">&quot;debug_mode&quot;</span><span class="hl-1">).</span><span class="hl-6">then</span><span class="hl-1">((</span><span class="hl-2">v</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">v</span><span class="hl-1"> ?? </span><span class="hl-4">false</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">debug</span><span class="hl-1">(</span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">data</span><span class="hl-1">?: </span><span class="hl-5">any</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">debugMode</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-2">console</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">`[DEBUG] </span><span class="hl-4">${</span><span class="hl-2">message</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">data</span><span class="hl-1"> || </span><span class="hl-3">&quot;&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">processData</span><span class="hl-1">(</span><span class="hl-2">data</span><span class="hl-1">: </span><span class="hl-5">any</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">debug</span><span class="hl-1">(</span><span class="hl-3">&quot;Processing data&quot;</span><span class="hl-1">, { </span><span class="hl-2">itemCount:</span><span class="hl-1"> </span><span class="hl-2">data</span><span class="hl-1">.</span><span class="hl-2">length</span><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">for</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">item</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-2">data</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">debug</span><span class="hl-1">(</span><span class="hl-3">&quot;Processing item&quot;</span><span class="hl-1">, </span><span class="hl-2">item</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processItem</span><span class="hl-1">(</span><span class="hl-2">item</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
38
+ <pre><code class="typescript"><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Twist</span><span class="hl-1">&lt;</span><span class="hl-5">MyTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">get</span><span class="hl-1"> </span><span class="hl-6">debugMode</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">boolean</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;</span><span class="hl-5">boolean</span><span class="hl-1">&gt;(</span><span class="hl-3">&quot;debug_mode&quot;</span><span class="hl-1">).</span><span class="hl-6">then</span><span class="hl-1">((</span><span class="hl-2">v</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-2">v</span><span class="hl-1"> ?? </span><span class="hl-4">false</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">debug</span><span class="hl-1">(</span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">, </span><span class="hl-2">data</span><span class="hl-1">?: </span><span class="hl-5">any</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">debugMode</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-2">console</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">`[DEBUG] </span><span class="hl-4">${</span><span class="hl-2">message</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">data</span><span class="hl-1"> || </span><span class="hl-3">&quot;&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">processData</span><span class="hl-1">(</span><span class="hl-2">data</span><span class="hl-1">: </span><span class="hl-5">any</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">debug</span><span class="hl-1">(</span><span class="hl-3">&quot;Processing data&quot;</span><span class="hl-1">, { </span><span class="hl-2">itemCount:</span><span class="hl-1"> </span><span class="hl-2">data</span><span class="hl-1">.</span><span class="hl-2">length</span><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">for</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">item</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-2">data</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">debug</span><span class="hl-1">(</span><span class="hl-3">&quot;Processing item&quot;</span><span class="hl-1">, </span><span class="hl-2">item</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processItem</span><span class="hl-1">(</span><span class="hl-2">item</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
39
39
  </code><button type="button">Copy</button></pre>
40
40
 
41
41
  <h3 id="performance-monitoring" class="tsd-anchor-link">Performance Monitoring<a href="#performance-monitoring" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Track operation durations:</p>
@@ -70,7 +70,7 @@
70
70
 
71
71
  <hr>
72
72
  <h2 id="performance-patterns" class="tsd-anchor-link">Performance Patterns<a href="#performance-patterns" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="lazy-loading" class="tsd-anchor-link">Lazy Loading<a href="#lazy-loading" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Load data only when needed:</p>
73
- <pre><code class="typescript"><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">twist</span><span class="hl-1">&lt;</span><span class="hl-5">MyTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-2">_config</span><span class="hl-1">: </span><span class="hl-5">Config</span><span class="hl-1"> | </span><span class="hl-5">null</span><span class="hl-1"> = </span><span class="hl-4">null</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">getConfig</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">Config</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">_config</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">_config</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;</span><span class="hl-5">Config</span><span class="hl-1">&gt;(</span><span class="hl-3">&quot;config&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">_config</span><span class="hl-1">!;</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">someMethod</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">config</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">getConfig</span><span class="hl-1">(); </span><span class="hl-7">// Loaded once</span><br/><span class="hl-1"> </span><span class="hl-7">// Use config...</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
73
+ <pre><code class="typescript"><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Twist</span><span class="hl-1">&lt;</span><span class="hl-5">MyTwist</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-2">_config</span><span class="hl-1">: </span><span class="hl-5">Config</span><span class="hl-1"> | </span><span class="hl-5">null</span><span class="hl-1"> = </span><span class="hl-4">null</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">getConfig</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">Config</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">_config</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">_config</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;</span><span class="hl-5">Config</span><span class="hl-1">&gt;(</span><span class="hl-3">&quot;config&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">_config</span><span class="hl-1">!;</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">someMethod</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">config</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">getConfig</span><span class="hl-1">(); </span><span class="hl-7">// Loaded once</span><br/><span class="hl-1"> </span><span class="hl-7">// Use config...</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
74
74
  </code><button type="button">Copy</button></pre>
75
75
 
76
76
  <h3 id="request-coalescing" class="tsd-anchor-link">Request Coalescing<a href="#request-coalescing" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Combine multiple similar requests:</p>
@@ -78,7 +78,7 @@
78
78
  </code><button type="button">Copy</button></pre>
79
79
 
80
80
  <h3 id="bulk-operations" class="tsd-anchor-link">Bulk Operations<a href="#bulk-operations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Batch database operations:</p>
81
- <pre><code class="typescript"><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">syncAllItems</span><span class="hl-1">(</span><span class="hl-2">items</span><span class="hl-1">: </span><span class="hl-2">Item</span><span class="hl-1">[]) {</span><br/><span class="hl-1"> </span><span class="hl-7">// ❌ SLOW - One at a time</span><br/><span class="hl-1"> </span><span class="hl-7">// for (const item of items) {</span><br/><span class="hl-1"> </span><span class="hl-7">// await this.tools.plot.createActivity({...});</span><br/><span class="hl-1"> </span><span class="hl-7">// }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// ✅ FAST - Bulk create</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivities</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">items</span><span class="hl-1">.</span><span class="hl-6">map</span><span class="hl-1">(</span><span class="hl-2">item</span><span class="hl-1"> </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Task</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">description</span><br/><span class="hl-1"> }))</span><br/><span class="hl-1"> );</span><br/><span class="hl-1">}</span>
81
+ <pre><code class="typescript"><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">syncAllItems</span><span class="hl-1">(</span><span class="hl-2">items</span><span class="hl-1">: </span><span class="hl-2">Item</span><span class="hl-1">[]) {</span><br/><span class="hl-1"> </span><span class="hl-7">// ❌ SLOW - One at a time</span><br/><span class="hl-1"> </span><span class="hl-7">// for (const item of items) {</span><br/><span class="hl-1"> </span><span class="hl-7">// await this.tools.plot.createActivity({...});</span><br/><span class="hl-1"> </span><span class="hl-7">// }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// ✅ FAST - Bulk create</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivities</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">items</span><span class="hl-1">.</span><span class="hl-6">map</span><span class="hl-1">(</span><span class="hl-2">item</span><span class="hl-1"> </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Action</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">description</span><br/><span class="hl-1"> }))</span><br/><span class="hl-1"> );</span><br/><span class="hl-1">}</span>
82
82
  </code><button type="button">Copy</button></pre>
83
83
 
84
84
  <hr>