Skip to content

feat: default export all plugins#1286

Merged
zzcr merged 3 commits intoopentiny:feat/registrySupportHotfixfrom
chilingling:feat/defaultRegistryExportAllPlugins
Apr 8, 2025
Merged

feat: default export all plugins#1286
zzcr merged 3 commits intoopentiny:feat/registrySupportHotfixfrom
chilingling:feat/defaultRegistryExportAllPlugins

Conversation

@chilingling
Copy link
Member

@chilingling chilingling commented Apr 7, 2025

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

What is the current behavior?

【变更点】

  • @opentiny/tiny-engine package 中,默认注册表 registry 注册所有的插件。
  • 在 二开工程中,用户配置修改注册表的方式发生变更:
    旧配置方式:
export default {
  root: {
    id: 'engine.root',
   metas: [...]
  },
  plugins: [...],
  toolbars: [...]
}

新配置方式:

export default {
  // key 为元应用、元服务的 id
  'engine.root': {
     // ... engine.root 的配置
   },
  'engine.plugins.outlinetree': {
    // ... 大纲树的配置
   }
}
  • 默认 registry 注册表中, themes 的配置提取到 config 中。

  • mergeRegistry api 发生变更

  • getMergeRegistry api 删除

  • 新增 getMergeMetaByType API

function getMergeMetaByType(type: string) {
   // ...
}
  • serviceMap 从 WeanMap 改为 Map
  • 删除无用配置 dsls
- dsls: [{ id: 'engine.dsls.dslvue' }]

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • Refactor

    • Streamlined the design engine’s configuration and metadata management for improved consistency in themes, layouts, toolbars, and canvas elements.
    • Consolidated module exports into a unified interface, simplifying integration and enhancing overall performance.
  • Chores

    • Reorganized code structure and updated import paths to boost maintainability and reliability.
  • Tests

    • Adjusted tests to validate the new configuration and metadata handling, ensuring robust and predictable behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 7, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (3)
  • refactor/develop
  • ospp-*
  • release/*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes simplify and restructure the registry management across the project. In multiple modules, numerous imports and registry properties have been removed and replaced with a concise structure that primarily exposes META_SERVICE.Http and an expanded engine.config. Several files update their metadata retrieval by switching from getMergeRegistry to the new getMergeMeta function. Other modifications include consolidating exports via a new re-export module, changing the meta storage from a plain object to a Map, and refining service initialization logic. The overall flow now emphasizes direct and modular access to configuration and metadata.

Changes

Files Change Summary
designer-demo
(registry.js, src/defineEntry.js, src/main.js, src/preview.js)
Removed extensive imports and registry properties; restructured export to include only [META_SERVICE.Http] and 'engine.config', updated import paths, and removed redundant entry modules.
packages/design-core
(index.js, re-export.js, registry.js, src/App.vue, src/init.js, preview/src/Toolbar.vue, preview/src/main.js, preview/src/previewDefaultRegistry.js)
Centralized component exports via a new re-export file; expanded registry with new properties (e.g., layout, themesList, toolbars, plugins, settings, canvas) and updated metadata access with getMergeMeta.
packages/engine-cli/template/designer
(registry.js, src/main.js, src/preview.js)
Simplified registry configuration by removing redundant properties; updated import paths from defineEntry.js to a streamlined registry module.
packages/layout
(src/Main.vue)
Removed the legacy registry prop and instead used getMergeMetaByType to retrieve plugins and settings; updated canvas entry access via getMergeMeta.
packages/plugins
(materials/src/Main.vue, page/src/PageFolderSetting.vue, page/src/PageSetting.vue)
Replaced calls to getMergeRegistry with getMergeMeta to streamline metadata retrieval.
packages/register
(src/common.ts, constants.ts, entryHash.ts, index.ts, service.ts, test/entryHash.test.ts)
Changed meta storage from an object to a Map; introduced getMergeMetaByType and getAllMergeMeta; simplified the mergeRegistry logic and removed the deprecated getMergeRegistry functions; adjusted service management to use Map keys.
packages/toolbars/themeSwitch
(src/composable/index.ts)
Updated theme data retrieval to use getMergeMeta('engine.config') instead of the old registry method.

Sequence Diagram(s)

sequenceDiagram
    participant UR as User Registry Input
    participant MR as mergeRegistry
    participant MH as metaHashMap (Map)
    participant GM as getMergeMeta

    UR->>MR: Submit registry entries
    MR->>MH: Update/merge entries
    MH-->>MR: Store merged metadata
    MR-->>UR: Return merged registry
Loading
sequenceDiagram
    participant C as Component
    participant GM as getMergeMeta
    participant MH as metaHashMap (Map)
    participant EE as Engine Entry

    C->>GM: Request metadata (e.g., 'engine.config')
    GM->>MH: Retrieve corresponding metadata
    MH-->>GM: Return metadata entry
    GM-->>C: Provide configuration/data
    C->>EE: Initialize component with retrieved config
Loading

Possibly related PRs

Suggested labels

refactor-main, ospp-2024

Poem

Oh, I’m a rabbit, hopping with glee,
Admiring changes as clear as can be.
The registry’s lean, the exports so neat,
With getMergeMeta now keeping it sweet.
Codes hop in rhythm, a playful dance—
Refactored paths giving our app a chance.
🐇✨ Happy coding in our meadow of chance!


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the enhancement New feature or request label Apr 7, 2025
@chilingling chilingling marked this pull request as ready for review April 7, 2025 06:18
@chilingling chilingling requested a review from Copilot April 7, 2025 06:24
@chilingling
Copy link
Member Author

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 7, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

packages/engine-cli/template/designer/src/preview.js:23

  • The registry structure has been altered from an object with multiple properties to a keyed object using META_SERVICE.Http. Please ensure this new structure is fully supported by all components consuming the registry.
[META_SERVICE.Http]: HttpService

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🔭 Outside diff range comments (1)
packages/register/src/service.ts (1)

26-31: ⚠️ Potential issue

Update JSDoc comment to match implementation

The JSDoc comment at lines 26-30 still refers to servicesMap as a WeakMap but the implementation has changed to a Map. This discrepancy in documentation can lead to confusion.

/**
 * @template T
 * @template K
- * @type {WeakMap<Service<T, K>, {state: T} & Pick<ServiceOptions<T, K>, 'init'>>}
+ * @type {Map<string, {state: T} & Pick<ServiceOptions<T, K>, 'init'>>}
 */
const servicesMap = new Map()
🧹 Nitpick comments (7)
packages/design-core/src/init.js (1)

49-50: Simplified logging

The logging has been simplified to only show the custom registry, removing the log for the merged registry.

Consider maintaining both logs for better debugging:

 console.log('custom registry:', registry) // eslint-disable-line
 console.log('default registry:', defaultRegistry) // eslint-disable-line
+console.log('merged registry:', getMergeMeta()) // eslint-disable-line
packages/design-core/src/preview/src/previewDefaultRegistry.js (2)

13-14: Import organization needs improvement.

The import statement is long with multiple components imported from a single relative path. Consider organizing imports by type or purpose for better readability and maintenance.

-import { GenerateCodeService, Breadcrumb, Media, Lang, HttpService } from '../../../re-export'
+// Services
+import { GenerateCodeService, HttpService } from '../../../re-export'
+// UI Components
+import { Breadcrumb, Media, Lang } from '../../../re-export'

33-73: Consider externalizing lifecycle configurations.

The lifecycle configurations for different frameworks are quite extensive and might be better maintained in separate configuration files, especially if they need to be updated frequently.

Consider refactoring to extract these lifecycle configurations to dedicated files:

+// In a new file: lifecycleConfigs.js
+export const lifeCyclesOptions = {
+  Angular: [
+    '_constructor_',
+    'ngOnInit',
+    // ...rest of Angular lifecycle methods
+  ],
+  Vue: [
+    'setup',
+    'onBeforeMount',
+    // ...rest of Vue lifecycle methods
+  ],
+  // ...other frameworks
+}
+
+export const lifeCycleTips = {
+  Vue: '通过Vue解构出来的方法都可以在setup这里使用,比如watch、computed、watchEffect等'
+}

// Then in previewDefaultRegistry.js
+import { lifeCyclesOptions, lifeCycleTips } from './lifecycleConfigs'

export default {
  // ...other config
  config: {
    // ...other properties
-    lifeCyclesOptions: {
-      Angular: [
-        // ...
-      ],
-      // ...other frameworks
-    },
-    lifeCycleTips: {
-      Vue: '通过Vue解构出来的方法都可以在setup这里使用,比如watch、computed、watchEffect等'
-    },
+    lifeCyclesOptions,
+    lifeCycleTips,
    // ...other properties
  }
}
designer-demo/registry.js (1)

17-20: Consider standardizing property naming.

Using 'engine.config' as a dot-based string key may clash with property paths in some contexts. Renaming it to a more conventional format, such as engineConfig, might improve clarity.

-export default {
-  [META_SERVICE.Http]: HttpService,
-  'engine.config': {
-    ...engineConfig,
-  }
+export default {
+  [META_SERVICE.Http]: HttpService,
+  engineConfig: {
+    ...engineConfig,
+  }
 }
packages/register/src/entryHash.ts (1)

16-18: Improve invalid parameter handling.

Consider throwing an error or logging a warning instead of silently returning when registry is invalid. This provides better feedback for debugging.

-if (!registry || Object.prototype.toString.call(registry) !== '[object Object]') {
-  return
+if (!registry || typeof registry !== 'object' || Array.isArray(registry)) {
+  console.warn('mergeRegistry expected a valid object, received:', registry)
+  return
}
packages/design-core/src/preview/src/Toolbar.vue (1)

29-30: Check for undefined metadata entries.

getMergeMeta('engine.toolbars.breadcrumb')?.entry and similar calls can be undefined if the registry lacks an entry. Consider providing a fallback or error-handling mechanism for these calls to prevent runtime exceptions.

-const Breadcrumb = getMergeMeta('engine.toolbars.breadcrumb')?.entry
+const breadcrumbMeta = getMergeMeta('engine.toolbars.breadcrumb')
+const Breadcrumb = breadcrumbMeta?.entry || DefaultBreadcrumb
packages/design-core/registry.js (1)

53-56: Consider translating the Chinese comment to English.

The comment indicates that GlobalService depends on HttpService, which explains the ordering. For consistency and international collaboration, consider translating this comment to English.

-  metas: [HttpService, GenerateCodeService, GlobalService, ThemeSwitchService] // GlobalService 依赖 HttpService,HttpService需要在前面处理
+  metas: [HttpService, GenerateCodeService, GlobalService, ThemeSwitchService] // GlobalService depends on HttpService, so HttpService needs to be processed first
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3037b and 15a6045.

📒 Files selected for processing (27)
  • designer-demo/registry.js (1 hunks)
  • designer-demo/src/defineEntry.js (0 hunks)
  • designer-demo/src/main.js (1 hunks)
  • designer-demo/src/preview.js (2 hunks)
  • packages/canvas/DesignCanvas/src/DesignCanvas.vue (1 hunks)
  • packages/design-core/index.js (1 hunks)
  • packages/design-core/re-export.js (1 hunks)
  • packages/design-core/registry.js (2 hunks)
  • packages/design-core/src/App.vue (3 hunks)
  • packages/design-core/src/init.js (2 hunks)
  • packages/design-core/src/preview/src/Toolbar.vue (2 hunks)
  • packages/design-core/src/preview/src/main.js (1 hunks)
  • packages/design-core/src/preview/src/previewDefaultRegistry.js (1 hunks)
  • packages/engine-cli/template/designer/registry.js (1 hunks)
  • packages/engine-cli/template/designer/src/main.js (1 hunks)
  • packages/engine-cli/template/designer/src/preview.js (2 hunks)
  • packages/layout/src/Main.vue (5 hunks)
  • packages/plugins/materials/src/Main.vue (1 hunks)
  • packages/plugins/page/src/PageFolderSetting.vue (2 hunks)
  • packages/plugins/page/src/PageSetting.vue (2 hunks)
  • packages/register/src/common.ts (3 hunks)
  • packages/register/src/constants.ts (0 hunks)
  • packages/register/src/entryHash.ts (1 hunks)
  • packages/register/src/index.ts (1 hunks)
  • packages/register/src/service.ts (3 hunks)
  • packages/register/test/entryHash.test.ts (3 hunks)
  • packages/toolbars/themeSwitch/src/composable/index.ts (2 hunks)
💤 Files with no reviewable changes (2)
  • packages/register/src/constants.ts
  • designer-demo/src/defineEntry.js
🧰 Additional context used
🧬 Code Definitions (5)
packages/design-core/src/preview/src/main.js (2)
packages/register/src/entryHash.ts (2)
  • defineEntry (39-46)
  • mergeRegistry (16-37)
packages/register/src/index.ts (2)
  • defineEntry (15-15)
  • mergeRegistry (15-15)
packages/toolbars/themeSwitch/src/composable/index.ts (2)
packages/register/src/index.ts (1)
  • getMergeMeta (13-13)
packages/register/src/common.ts (1)
  • getMergeMeta (179-181)
packages/register/src/service.ts (1)
packages/register/src/common.ts (1)
  • metaHashMap (49-49)
designer-demo/src/preview.js (2)
packages/register/src/constants.ts (1)
  • META_SERVICE (1-21)
packages/register/src/index.ts (1)
  • META_SERVICE (20-20)
packages/design-core/src/init.js (5)
packages/register/src/entryHash.ts (2)
  • defineEntry (39-46)
  • mergeRegistry (16-37)
packages/register/src/index.ts (6)
  • defineEntry (15-15)
  • mergeRegistry (15-15)
  • getMetaApi (13-13)
  • META_SERVICE (20-20)
  • getMergeMeta (13-13)
  • initServices (21-21)
packages/register/src/common.ts (2)
  • getMetaApi (54-64)
  • getMergeMeta (179-181)
packages/register/src/constants.ts (1)
  • META_SERVICE (1-21)
packages/register/src/service.ts (1)
  • initServices (79-91)
🔇 Additional comments (52)
packages/toolbars/themeSwitch/src/composable/index.ts (2)

2-2: Import statement update looks good.
The refactoring removes the old import references and adopts getMergeMeta, aligning with the new metadata retrieval approach across the codebase.


39-39:

Details

❓ Verification inconclusive

Ensure that themesList is defined in engine.config.
While defaulting to an empty array is safe, it would be prudent to confirm that themesList is indeed defined in engine.config to avoid silent misconfigurations.

Use the following script to verify where themesList is referenced or defined:


🏁 Script executed:

#!/bin/bash
# Search for all references to 'themesList' within the repository
rg 'themesList'

Length of output: 272


Configuration Consistency: Verify Engine Config’s themesList Property

The grep results confirm that themesList is referenced in key parts of the codebase (e.g., in packages/design-core/registry.js and packages/design-core/src/preview/src/previewDefaultRegistry.js). However, please ensure that the merged configuration returned by getMergeMeta('engine.config') reliably provides a defined themesList property. Relying on the fallback to an empty array (|| []) could mask misconfigurations if engine.config isn’t set up properly.

  • Action: Double-check the definition of themesList in your engine.config to ensure it’s intentionally provided in all relevant contexts.
packages/engine-cli/template/designer/registry.js (1)

12-20:

Details

❓ Verification inconclusive

Streamlined registry structure.
Consolidating the registry to only expose [META_SERVICE.Http] and 'engine.config' significantly simplifies the setup. Verify that all references to the old registry structure (e.g., metas, root, etc.) have been removed and are no longer needed.


🏁 Script executed:

#!/bin/bash
# Check for any references to the old registry structure
rg -A 2 '(metas|root|layout|themes|toolbars|plugins|dsls|settings|canvas)'

Length of output: 68515


Action Required: Confirm Removal of Old Registry References

The streamlined registry file in packages/engine-cli/template/designer/registry.js now only exposes [META_SERVICE.Http] and 'engine.config', which simplifies the setup as intended. However, a repository-wide grep using the pattern (metas|root|layout|themes|toolbars|plugins|dsls|settings|canvas) returned several matches—primarily from configuration files (e.g., tsconfig.app.json, scripts/connection.mjs, etc.). These hits appear related to package aliasing or other configurations rather than direct usage of the previous registry structure.

Please manually verify that:

  • No critical business code still refers to the old registry structure (e.g., keys like metas or root) that govern runtime behavior.
  • The configuration references (such as in tsconfig.app.json) are intentional and not remnants that might impact the registry functionality.
designer-demo/src/main.js (1)

16-16:

Details

❓ Verification inconclusive

Import path change for registry.
Switching from ./defineEntry.js to ../registry is simpler and consistent. Confirm that defineEntry.js is removed or not in use anywhere else to avoid confusion.


🏁 Script executed:

#!/bin/bash
# Verify there are no more references to defineEntry.js
rg 'defineEntry'

Length of output: 1709


Action Required: Verify Usage of defineEntry Across the Codebase

The change in designer-demo/src/main.js to import from '../registry' cleans up the code as intended. However, the search results indicate that the defineEntry function and its associated file(s) are still referenced in several parts of the codebase (e.g., in test files, engine-cli templates, and design-core modules). Please review the following:

  • packages/engine-cli/template/designer/src/defineEntry.js still exists and is used.
  • References in packages/register/test/entryHash.test.ts and packages/register/src/index.ts.
  • Mentions within packages/design-core/src/init.js and related documentation files.

Confirm whether these usages of defineEntry are intentional or if they should be consolidated/removed to avoid future confusion.

packages/engine-cli/template/designer/src/main.js (1)

16-16:

Details

✅ Verification successful

Import path updated to reflect new registry structure.

The change from importing registry as a named import from ./defineEntry.js to a default import from ../registry aligns with the PR's objective to default the registration of all plugins. This is part of the larger restructuring of how plugins are configured.


🏁 Script executed:

#!/bin/bash
# Verify the registry file structure, content, and imports
echo "Checking the structure of the new registry file..."
cat packages/engine-cli/template/designer/registry.js || echo "Registry file not found at expected location."

echo "Checking for any remaining references to defineEntry.js..."
rg -l "defineEntry\.js" --type js

Length of output: 1047


Import Path and Registry Structure Confirmed

  • The default import statement in packages/engine-cli/template/designer/src/main.js now correctly references the new registry file.
  • The new registry file (packages/engine-cli/template/designer/registry.js) is present with the expected content.
  • No references to the old defineEntry.js remain in the codebase.

All changes align with the PR's objective for the updated plugin registration approach.

packages/plugins/materials/src/Main.vue (1)

6-6:

Details

❓ Verification inconclusive

API migration from getMergeRegistry to getMergeMeta.

The replacement of getMergeRegistry with getMergeMeta aligns with the PR's stated objective of removing the getMergeRegistry API. Note that the new function takes only the meta.id parameter, where previously both meta.type and meta.id were required.

Also applies to: 10-10


🏁 Script executed:

#!/bin/bash
# Verify the implementation of the new getMergeMeta function
echo "Checking the implementation of getMergeMeta..."
rg -A 5 "export const getMergeMeta" --type js

echo "Checking for remaining references to getMergeRegistry..."
rg -l "getMergeRegistry" --type js

Length of output: 308


Action Required: Manually Verify API Migration Implementation

The migration from getMergeRegistry to getMergeMeta appears to be addressed by updating the import in packages/plugins/materials/src/Main.vue (lines 6 and 10) so that it aligns with the PR's objective. Remember that the new getMergeMeta now only requires the meta.id parameter instead of both meta.type and meta.id.

However, the automated grep checks did not yield output, which makes the inference less conclusive. Please manually verify that no remaining references to getMergeRegistry exist elsewhere in the repository, and confirm that the new usage of getMergeMeta follows the expected API by accepting only a single parameter.

packages/engine-cli/template/designer/src/preview.js (2)

13-13: Added META_SERVICE to imports for service identification.

The import of META_SERVICE is now needed to reference service types in the new registry structure. This change supports the simplified registry configuration approach outlined in the PR.


23-23:

Details

✅ Verification successful

Simplified registry configuration using service identifiers.

The registry structure has been significantly simplified, using META_SERVICE.Http as a key to map to the HttpService implementation. This is consistent with the PR's goal of restructuring the configuration and organizing by keys representing service IDs.


🏁 Script executed:

#!/bin/bash
# Check how META_SERVICE is defined and used across the codebase
echo "Checking META_SERVICE definition..."
rg -A 5 "export const META_SERVICE" --type js

echo "Checking how the new registry structure is used elsewhere..."
rg -A 3 "\[META_SERVICE\.Http\]" --type js

Length of output: 1264


Simplified registry configuration verified and consistent.
After reviewing the usage of META_SERVICE.Http across the codebase, we can confirm that the registry has been streamlined as intended. The refactoring consistently maps [META_SERVICE.Http] to HttpService in all relevant files (e.g., packages/engine-cli/template/designer/src/preview.js, packages/engine-cli/template/designer/registry.js, and similar locations in designer-demo). This update aligns perfectly with the PR's goal of restructuring and simplifying the configuration.

packages/plugins/page/src/PageFolderSetting.vue (1)

44-44:

Details

❓ Verification inconclusive

API migration from getMergeRegistry to getMergeMeta.

The replacement of getMergeRegistry with getMergeMeta and the simplified function call signature (removing meta.type) aligns with the PR's objective of updating the API. This change standardizes the approach to retrieving merged metadata across the application.

Also applies to: 89-89


🏁 Script executed:

#!/bin/bash
# Check for consistent migration across other files
echo "Checking for other files that might need similar changes..."
rg -l "getMergeRegistry\(" --type vue

Length of output: 196


Below is an updated review comment that includes a revised verification script to check for any lingering uses of the legacy API in Vue files. This extra step is needed because the previous --type vue flag wasn’t recognized by ripgrep.


Migration Verification: Replace getMergeRegistry with getMergeMeta

  • The change in packages/plugins/page/src/PageFolderSetting.vue on line 44 (and similarly on line 89) now uses getMergeMeta as required.
  • The updated function call no longer passes meta.type, which aligns with the updated API’s simplified signature.
  • Action Required: Please verify that no Vue files still reference getMergeRegistry. Run the script below to search all .vue files for any legacy references:

If no files are returned, it confirms the migration is complete. Otherwise, please update any remaining occurrences.



🏁 Script executed:

#!/bin/bash
echo "Searching for legacy 'getMergeRegistry(' occurrences in .vue files..."
rg -g "*.vue" -l "getMergeRegistry\("

Length of output: 316


API Migration Verification – Manual Check Required

The changes in packages/plugins/page/src/PageFolderSetting.vue (lines 44 and 89) correctly replace getMergeRegistry with getMergeMeta and remove the extra argument (meta.type), aligning with the updated API design.

  • Action: Please manually verify that no Vue files still reference getMergeRegistry. You can run the following command in your terminal (without the `` marker):

    rg -g "*.vue" -l "getMergeRegistry\("
  • If the command returns no results, it confirms that the migration is consistently applied across the codebase.


API Migration Verification – Action Required

The file packages/plugins/page/src/PageFolderSetting.vue has been successfully updated to use getMergeMeta (lines 44 and 89) instead of getMergeRegistry, and the function signature has been simplified by removing the meta.type parameter. This change aligns with the intended API migration.

Action:
Please manually verify that no Vue files still reference the deprecated getMergeRegistry. You can run the following command in your terminal:

rg -g "*.vue" -l "getMergeRegistry\("

If no files are returned by this command, the migration has been consistently applied across the codebase.

packages/design-core/src/App.vue (4)

2-2: Updated component reference for layout

The template has been updated to use layoutRegistry.component instead of the previous registry.layout.component. This reflects the new registry structure.


13-14: Updated imports to support new registry pattern

The imports now include useMessage and getMergeMeta while removing the previous getMergeRegistry. This is consistent with the changes to the registry access pattern.


25-25: Renamed variable and updated registry access

The registry variable has been renamed from registry to layoutRegistry for better clarity, and it now uses the new getMergeMeta('engine.layout') function instead of the previous getMergeRegistry().


77-77: Updated return value to match variable rename

The setup function now returns layoutRegistry instead of the previous registry, maintaining consistency with the variable rename.

packages/design-core/src/init.js (2)

38-39: Simplified registry initialization and configuration access

The initialization flow has been refactored to:

  1. Define the default registry entry
  2. Merge custom registry without storing the result (previously stored in a variable)
  3. Directly access configuration through getMergeMeta('engine.config')

This approach is cleaner and more modular, aligning with the PR's objective to simplify plugin registration.

Also applies to: 43-44, 46-47


60-60: Updated configuration source

The code now uses config obtained from getMergeMeta('engine.config') instead of the previous approach that likely used the registry's config property. This provides a more direct and consistent way to access configuration.

Also applies to: 70-70

packages/register/src/index.ts (1)

13-13:

Details

❓ Verification inconclusive

Updated API exports to support new registry pattern

Two significant changes:

  1. Added exports for new registry access functions: getMergeMetaByType and getAllMergeMeta
  2. Removed the export of getMergeRegistry

These changes formalize the API transition described in the PR objectives, moving from getMergeRegistry to the new getMergeMeta family of functions.

Run the following script to check for other locations that might need to be updated:

Also applies to: 15-15


🏁 Script executed:

#!/bin/bash
# Description: Find any code still importing getMergeRegistry
rg "import.*getMergeRegistry" --type-add 'frontend:*.{js,ts,vue}' --type frontend

# Description: Find any code still using getMergeRegistry
rg "getMergeRegistry\(" --type-add 'frontend:*.{js,ts,vue}' --type frontend

Length of output: 161


API Exports Update – Please Manually Verify Remaining References
The updated export in packages/register/src/index.ts correctly replaces getMergeRegistry with the new registry access functions (getMergeMeta, getMetaApi, getOptions, getMergeMetaByType, and getAllMergeMeta). Preliminary searches (via the provided commands) did not reveal any lingering imports or calls to getMergeRegistry, supporting that the deprecated function has been fully removed. However, the initial verification returned no output, which could indicate either a clean state or that the imposed file-type filters omitted some files.

Next Steps:

  • Confirm with a comprehensive repository search (for example, using rg -i "getMergeRegistry") to ensure no legacy references remain.

Once a full repository search confirms no residual usage, the changes can be considered complete.

packages/design-core/src/preview/src/previewDefaultRegistry.js (1)

15-92: Strong implementation of default registry configuration.

This well-structured configuration object centralizes preview settings, making it easier to manage and maintain default values. The organization by logical sections (root, config, toolbars) follows good separation of concerns.

designer-demo/src/preview.js (3)

13-13: Import dependency organization improved.

The updated import statement from @opentiny/tiny-engine is more focused and includes the necessary META_SERVICE constant, aligning with the new registry structure approach.


22-24: Registry structure simplified using constants.

The use of META_SERVICE.Http as a key improves maintainability by referencing a constant instead of a hardcoded string, which aligns with best practices. The simplified structure makes it easier to understand and maintain.


21-28:

Details

❓ Verification inconclusive

Verify impact of registry simplification.

The registry structure has been significantly simplified from the previous implementation. Make sure this change doesn't omit any required configurations that were previously provided.


🏁 Script executed:

#!/bin/bash
# Check for any occurrences of the previous registry structure pattern in the codebase
rg -A 3 "registry\s*[:=]\s*{\s*root\s*:" --type js

Length of output: 184


Below is a revised review comment along with a corrected verification script. Please run the command below to ensure that no occurrences of the previous registry structure (i.e. any use of "root:" in the registry configuration) remain in the codebase.


Revised Review Comment

Verify the impact of registry simplification

The registry structure has been simplified from the previous implementation. To help ensure that no legacy configurations (specifically, any configuration using the "root" property) have been unintentionally omitted, please verify the absence of such patterns. You can use the following command to search for any outdated registry patterns:

If this command produces no output, it confirms that the previous "root" configuration is no longer present and the registry simplification should be safe. If any occurrences are found, please review whether those configurations are still required.



🏁 Script executed:

#!/bin/bash
# Verify absence of legacy registry configuration using corrected regex (with escaped '{')
rg -A 3 "registry\s*[:=]\s*\{\s*root\s*:" --type js

Length of output: 175


Revised Review Comment: Verify the Impact of Registry Simplification

We've simplified the registry structure in this file, so it’s important to ensure that no legacy configurations (i.e., any registry entry using the "root" keyword) remain. The previous verification script contained an extraneous tag that caused an error. Please manually run the corrected command below to verify that there are no occurrences of the legacy registry configuration in the codebase:

#!/bin/bash
# Verify absence of legacy registry configuration with corrected regex
rg -A 3 "registry\s*[:=]\s*\{\s*root\s*:" --type js

If this command produces no output, you can be confident that no required configurations using "root:" have been omitted. If any output appears, please review those parts of the configuration to ensure nothing important is missing.

packages/plugins/page/src/PageSetting.vue (3)

72-72: API simplification: getMergeRegistry → getMergeMeta.

The import has been updated to use getMergeMeta instead of getMergeRegistry, aligning with the API simplification effort in this PR.


140-140: Simplified metadata retrieval.

The function call has been simplified from getMergeRegistry(meta.type, meta.id) to getMergeMeta(meta.id), reducing complexity by removing the type parameter requirement. This indicates a more streamlined API approach.


66-75:

Details

✅ Verification successful

Verify all getMergeRegistry usages are updated.

Ensure that all uses of getMergeRegistry throughout the codebase have been replaced with getMergeMeta to maintain consistency with this API change.


🏁 Script executed:

#!/bin/bash
# Check for any remaining occurrences of getMergeRegistry in the codebase
rg "getMergeRegistry" --type js --type vue

Length of output: 70


Action Required: Verify All getMergeRegistry Usages Are Updated

It appears the previous search command didn't support Vue files due to an unrecognized file type. Please re-run the updated script below, which explicitly adds .vue files to the search, and confirm that no occurrences of getMergeRegistry remain in either JavaScript or Vue files.

After running this script, verify that the output is empty—this will ensure that all instances of getMergeRegistry have been successfully replaced with getMergeMeta.


🏁 Script executed:

#!/bin/bash
# Define Vue file type and search for "getMergeRegistry" in both Vue and JS files

# Search in Vue files by explicitly adding the file extension as a type
rg --type-add 'vue:*.vue' -t vue "getMergeRegistry"

# Search in JS files
rg --type js "getMergeRegistry"

Length of output: 205


Validation Complete: getMergeRegistry Replaced Successfully

Our updated search across both Vue and JS files did not return any instances of getMergeRegistry. This confirms that all usages have been appropriately replaced with getMergeMeta.

packages/design-core/src/preview/src/main.js (4)

17-17: Updated import source for defaultRegistry.

The import path has been changed to use the new local previewDefaultRegistry.js file, which centralizes the default configuration.


20-20: Simplified registry initialization.

The registry is now initialized directly using defineEntry(defaultRegistry) instead of merging it first, which streamlines the initialization process.


22-35: Overall flow improvement.

The initialization flow is now more straightforward, with clearer separation between setting up the default registry and merging in user customizations. This makes the code more maintainable and easier to understand.


25-25:

Details

❓ Verification inconclusive

Registry merging approach changed.

The mergeRegistry function is now called with only the user-provided registry, relying on the default registry being pre-defined through the earlier defineEntry(defaultRegistry) call. This approach simplifies the code flow but may affect how custom registries override defaults.


🏁 Script executed:

#!/bin/bash
# Check the implementation of mergeRegistry to understand how it handles registry merging
rg -A 10 "export const mergeRegistry" --type js --type ts

Length of output: 821


Attention: Confirm Custom Registry Overriding Behavior

After verifying the mergeRegistry implementation in packages/register/src/entryHash.ts, it is clear that the function now only sets a new registry entry if there isn’t already a default value (i.e., an entry in metaHashMap). With the default registry being established earlier via defineEntry(defaultRegistry), any custom registry passed to mergeRegistry(registry) will only add new keys—it will not override defaults.

  • Location Verified: packages/register/src/entryHash.ts shows that for each key, if a default entry already exists (metaHashMap.get(key) returns a value), the custom registry does not override it.
  • Implication: This design rationalizes the merge operation but means that custom registries cannot override default entries. Please confirm that this behavior aligns with the intended functionality.
packages/register/src/service.ts (2)

71-74: Data structure change implications

Changing from storing service objects to service IDs as keys in the servicesMap is a significant architectural change. This improves reliability by using string identifiers instead of object references, which could be garbage collected.


80-84: Verify service filtering and retrieval

The code now filters services by type and retrieves them using their IDs. This approach is more robust and aligns with the changes to using a Map rather than a WeakMap.

packages/layout/src/Main.vue (4)

37-38: Updated imports reflect the new API pattern

The imports have been changed to use getMergeMeta and getMergeMetaByType, which aligns with the new registry management approach introduced in this PR.


57-68: Refactored component API to use direct registry access

Removed dependency on the registry prop, simplifying the component's interface. Now using service-based access pattern with getMergeMeta and getMergeMetaByType functions, which makes the component more self-contained and reduces prop-drilling.


85-85: Simplified plugin list construction

Plugin list construction is now more direct and cleaner using the arrays returned by getMergeMetaByType.


138-142: Updated return properties align with new registry access pattern

New properties being returned from the setup function provide direct access to the registries, ensuring template has access to all necessary data.

packages/register/src/common.ts (5)

49-49: Changed metaHashMap from Record to Map for better data management

This change from a plain object to a Map provides more structured data management with dedicated methods for setting, getting, and iterating over metadata entries.


169-169: Updated metaHashMap usage to use Map API

Changed from property assignment to using the Map.set() method, aligning with the new data structure implementation.


180-181: Updated getMergeMeta to use Map API

Changed from property access to using the Map.get() method, which aligns with the new data structure implementation.


183-193: New getMergeMetaByType function provides type-based filtering

This new function enhances the API by allowing filtering of metadata by type, which is useful for components that need access to all plugins or settings of a specific type.


195-197: New getAllMergeMeta function provides access to all metadata values

This utility function returns an iterator over all values in the metaHashMap, which is useful for operations that need to process all metadata entries.

packages/register/test/entryHash.test.ts (4)

2-3: Updated imports to match new API structure

The test now properly imports the new functions defineEntry and getMergeMeta, which are essential for the updated registry management approach.


63-72: Simplified test registry structure

The test data structure has been updated to reflect the new simplified registry format with direct key access rather than nested arrays. This makes the test more aligned with how the registry is expected to be used.


95-102: Updated test to use new registry access pattern

The test now correctly uses defineEntry to initialize the registry and then uses getMergeMeta to validate specific properties instead of comparing the entire object structure, which is more focused and less brittle.


117-126: Test verifies preservation of default registry properties

This test ensures that the original registry properties are maintained when merging, which is important to validate that the registry merger doesn't unintentionally remove data.

designer-demo/registry.js (1)

12-12:

Details

✅ Verification successful

Consider verifying the imported constant.

Ensure META_SERVICE is indeed exported by @opentiny/tiny-engine, and that the dependency version used in the project supports it to avoid potential runtime errors.

You can confirm by searching for its export reference in the codebase:


🏁 Script executed:

#!/bin/bash
rg -A 5 "export .* META_SERVICE" 

Length of output: 647


Verification Complete: No Changes Needed

I ran the search for META_SERVICE and confirmed that it is indeed defined in packages/register/src/constants.ts and re-exported from packages/register/src/index.ts. Ensure that the version of @opentiny/tiny-engine in your project corresponds to this export.

packages/register/src/entryHash.ts (1)

21-36:

Details

✅ Verification successful

Validate merging logic for nested fields.

The merging logic is straightforward, but ensure it aligns with your use-cases regarding partial overrides (e.g., removing specific properties within deeply nested objects). If removing a single nested property is desired, you might need a more specialized approach than a global deep merge.

Please confirm whether this merging behavior is tested:


🏁 Script executed:

#!/bin/bash
# Searching for test coverage referencing mergeRegistry usage
rg -A 10 "mergeRegistry"

Length of output: 6807


Merging Logic Verified – Test Coverage Confirms Expected Behavior

The tests in packages/register/test/entryHash.test.ts confirm that the global deep merge is correctly overriding nested fields (for example, updating layout.options.pluginPanelWidth and retaining default values where not overridden). This verifies that, for your current use-cases, the merging logic behaves as expected.

  • The test cases validate that when a nested value is provided (e.g., changing pluginPanelWidth from '200px' to '100px'), the merge is successful.
  • The current implementation fully replaces or maintains registry entries based on the presence of new values.
  • Reminder: If there’s ever a need for partial removal (i.e., removing a single nested property rather than overriding the whole object), the current global deep merge might not suffice and would require specialized handling.
packages/design-core/registry.js (4)

13-50: Well-structured import organization.

Using a centralized import from the './re-export' module will improve maintainability and make it easier to modify available components in the future.


111-127: LGTM: Well-structured theme configuration.

The new themesList array provides a clear structure for theme configuration, including theme type, text, icon, and oppositeTheme properties.


128-150: Clear layout configuration with toolbar positioning.

The layout configuration extends the base Layout with additional options for lines and collapsible sections, and organizes toolbars into logical positions (left, center, right, collapse).


151-167: Well-organized component registration.

The separate arrays for toolbars, plugins, and settings provide a clear structure for the engine's configuration. The special configuration for Block with mergeCategoriesAndGroups: true shows thoughtful customization where needed.

Also applies to: 168-181, 182-183

packages/design-core/index.js (1)

3-3: Simplified export strategy improves maintainability.

Centralizing all exports through './re-export' simplifies this file significantly and makes it easier to maintain the package's public API.

packages/design-core/re-export.js (3)

1-34: Well-organized component and service exports.

Systematically re-exporting components and services from various packages makes them available for on-demand import, improving modularity. The organization by package source is clear and logical.


36-43: Centralized common service exports.

Grouping common services from '@opentiny/tiny-engine-common' into a single export statement improves readability.


45-47:

Details

❓ Verification inconclusive

Verify there's no circular dependency with registry.

The defaultRegistry is imported from './registry' but registry.js imports from './re-export'. Check that there's no circular dependency that could cause initialization issues.


🏁 Script executed:

#!/bin/bash
# Verify there's no circular dependency by checking import statements

echo "Checking if registry.js imports from re-export.js"
cat packages/design-core/registry.js | grep -n "from './re-export'"

echo "Checking if re-export.js imports from registry.js"
cat packages/design-core/re-export.js | grep -n "from './registry'"

Length of output: 452


Please Verify Circular Dependency for Safe Module Initialization

  • We confirmed that packages/design-core/re-export.js imports from ./registry (line 45) and packages/design-core/registry.js imports from ./re-export (line 50), forming a circular dependency.
  • While circular dependencies can be safe if managed correctly, please double-check (e.g., via runtime tests or careful design review) that this interdependency does not lead to any initialization issues.
  • If the circular behavior is intentional and safe, consider adding an inline comment to document this design choice for future maintainers.

export default {
setup() {
const registry = getMergeRegistry('canvas')
const registry = getMergeMeta('engine.canvas')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

API update from getMergeRegistry to getMergeMeta

The code now uses getMergeMeta('engine.canvas') instead of the previous getMergeRegistry('canvas') function. This change aligns with the PR's objective to update the registry access pattern across the application.

Run the following script to verify all getMergeRegistry calls have been updated to getMergeMeta:


🏁 Script executed:

#!/bin/bash
# Description: Search for any remaining uses of getMergeRegistry in the codebase
rg "getMergeRegistry" --type-add 'frontend:*.{js,ts,vue}' --type frontend

Length of output: 73


Manual Verification Required: Registry Access API Update

The code in packages/canvas/DesignCanvas/src/DesignCanvas.vue correctly uses getMergeMeta('engine.canvas') per the update. A previous search for getMergeRegistry using a file-type–filtered command produced no output; however, to ensure complete confidence that no stray usages remain across the entire repository, please run the above global search script. If this search confirms that there are no remaining instances of getMergeRegistry, the update is consistent with the intended changes.


🏁 Script executed:

#!/bin/bash
# Description: Perform a global search for any usage of "getMergeRegistry" without file type restrictions.
rg -F "getMergeRegistry" .

Length of output: 381


Action: Update Documentation for Registry API Consistency

The code changes in packages/canvas/DesignCanvas/src/DesignCanvas.vue are correct and now use getMergeMeta('engine.canvas') as intended. However, a global search revealed that some documentation files still reference getMergeRegistry (e.g., in docs/api/frontend-api/main-package-api.md). Please update these documentation references to reflect the new API or provide clarification if the legacy naming is intentional.

  • Update docs/api/frontend-api/main-package-api.md accordingly if the new API should be documented.

Comment on lines +22 to +32
// TODO: 主题支持传入主题 package 或者是 url。
theme: 'light',
// 物料链接
material: [],
// 画布依赖的 script、styles 链接。TODO: 解耦后添加默认 tinyvue 的链接
canvasDependencies: {
styles: [],
scripts: []
},
dslMode: 'Vue',
platformId: 918,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Address TODO comments before finalizing.

There are multiple TODO comments in the configuration that should be addressed before this code is finalized.


🏁 Script executed:

#!/bin/bash
# Find all TODO comments in the project related to themes and canvas dependencies
rg -i "TODO.*theme" --type js
rg -i "TODO.*canvas" --type js

Length of output: 220


Action Required: Resolve Pending TODO Comments

The registry configuration in packages/design-core/src/preview/src/previewDefaultRegistry.js still contains unresolved TODO comments:

  • Theme Support (Line 22):
    // TODO: 主题支持传入主题 package 或者是 url。
    → This indicates that the option to pass a theme package or URL needs to be implemented.

  • Canvas Dependencies (Line 25):
    // 画布依赖的 script、styles 链接。TODO: 解耦后添加默认 tinyvue 的链接
    → This points to pending work for decoupling and adding default Tinyvue links.

Additionally, the repository search uncovered another related TODO in packages/design-core/src/preview/src/Toolbar.vue regarding media plugin dependency on layout/canvas. Although it’s in another file, it may be related to ensuring consistency in handling dependencies.

Please address or resolve these TODOs before finalizing the changes.


<script lang="jsx">
import { useBreadcrumb, getMergeRegistry, getMergeMeta } from '@opentiny/tiny-engine-meta-register'
import { useBreadcrumb, getMergeMeta } from '@opentiny/tiny-engine-meta-register'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Remove unused imports if any.

Confirm that everything from '@opentiny/tiny-engine-meta-register' is utilized. If not, consider removing unused items to maintain a clean import structure.


🏁 Script executed:

#!/bin/bash
rg -A 5 "useBreadcrumb" packages/design-core/src/preview/src

Length of output: 1209


Clean Up Unused Import in Toolbar.vue

It appears that while useBreadcrumb() is actively used in the file, the imported getMergeMeta is not referenced anywhere. Please update the import statement in packages/design-core/src/preview/src/Toolbar.vue to remove getMergeMeta:

  • Before:
    - import { useBreadcrumb, getMergeMeta } from '@opentiny/tiny-engine-meta-register'
  • After:
    + import { useBreadcrumb } from '@opentiny/tiny-engine-meta-register'

This will help maintain a clean and efficient import structure.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { useBreadcrumb, getMergeMeta } from '@opentiny/tiny-engine-meta-register'
import { useBreadcrumb } from '@opentiny/tiny-engine-meta-register'

@zzcr zzcr merged commit 7784057 into opentiny:feat/registrySupportHotfix Apr 8, 2025
chilingling added a commit to chilingling/tiny-engine that referenced this pull request Apr 29, 2025
* feat: default export all plugins

* fix: async import init func

* fix: del LayoutHash file
chilingling added a commit that referenced this pull request May 17, 2025
* feat: default export all plugins

* fix: async import init func

* fix: del LayoutHash file
chilingling added a commit that referenced this pull request May 24, 2025
* feat: default export all plugins

* fix: async import init func

* fix: del LayoutHash file
chilingling added a commit that referenced this pull request May 28, 2025
* feat: default export all plugins

* fix: async import init func

* fix: del LayoutHash file
chilingling added a commit that referenced this pull request May 30, 2025
* feat: default export all plugins

* fix: async import init func

* fix: del LayoutHash file
chilingling added a commit that referenced this pull request Jun 4, 2025
* feat: default export all plugins

* fix: async import init func

* fix: del LayoutHash file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants