feat(material): add material package#537
feat(material): add material package#537chilingling wants to merge 11 commits intoopentiny:developfrom
Conversation
WalkthroughReplaced a static materials JSON in the designer-demo engine config with an imported Changes
Sequence Diagram(s)sequenceDiagram
participant DevCLI as CLI
participant Builder as MaterialsBuilder
participant FS as FileSystem
participant HTTP as StaticServer
rect rgb(230,248,255)
DevCLI->>Builder: run build / build:split / serve
opt build or build:split
Builder->>FS: read materials/*/*.json, meta.json
Builder->>Builder: validate & generate bundles
Builder->>FS: write dist/entry.json, entry.compsMap.json
alt build (combine)
Builder->>FS: write dist/index.json, index.compsMap.json
end
end
opt serve
Builder->>FS: initial build
Builder->>FS: watch files (add/change/unlink)
FS->>Builder: file change events
Builder->>FS: rebuild affected entries
DevCLI->>HTTP: start static server (serve dist)
HTTP->>DevCLI: serve on auto-detected port
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (8)
- packages/materials/README.md (1 hunks)
- packages/materials/buildMaterials.mjs (1 hunks)
- packages/materials/package.json (1 hunks)
- packages/materials/src/ElementPlus/ElButton.json (1 hunks)
- packages/materials/src/ElementPlus/ElInput.json (1 hunks)
- packages/materials/src/TinyVue/TinyButton.json (1 hunks)
- packages/materials/src/TinyVue/TinyInput.json (1 hunks)
- packages/materials/src/html/Input.json (1 hunks)
Files skipped from review due to trivial changes (5)
- packages/materials/package.json
- packages/materials/src/ElementPlus/ElButton.json
- packages/materials/src/TinyVue/TinyButton.json
- packages/materials/src/TinyVue/TinyInput.json
- packages/materials/src/html/Input.json
Additional context used
Markdownlint
packages/materials/README.md
12-12: null (MD032, blanks-around-lists)
Lists should be surrounded by blank lines
33-33: null (MD034, no-bare-urls)
Bare URL used
Additional comments not posted (4)
packages/materials/buildMaterials.mjs (3)
24-42: Ensure all required fields are checked invalidateComponent.This function correctly checks for missing required fields and logs appropriate errors. Good use of array operations for validation.
118-154: Ensure error handling inbuildComponentsis robust.Good use of try-catch for error handling. Consider adding more specific error messages or handling different types of exceptions if applicable.
156-190: Review the implementation of theservefunction.The function sets up a watcher and a static server correctly. Good use of asynchronous programming and logging.
packages/materials/src/ElementPlus/ElInput.json (1)
1-292: Review the schema definition forElInput.The JSON schema is well-structured and includes comprehensive details about the component, its properties, events, and slots. Good use of nested structures and data types.
|
|
||
| function start() { | ||
| const commandsMap = { | ||
| serve: serve, | ||
| build: build, | ||
| 'build:split': buildSplit | ||
| } | ||
|
|
||
| const command = process.argv.slice(2) | ||
|
|
||
| if (!commandsMap[command]) { | ||
| logger.error(`[@opentiny/tiny-engine-materials] 不支持${command}命令`) | ||
|
|
||
| return | ||
| } | ||
|
|
||
| commandsMap[command]() | ||
| } |
There was a problem hiding this comment.
Tip
Codebase Verification
The start function in packages/materials/buildMaterials.mjs does include a basic validation check to ensure the command is in the commandsMap. However, it only checks if the command exists in the map and does not handle other potential issues such as invalid command formats or additional arguments.
- Location in codebase:
packages/materials/buildMaterials.mjs(lines 202-219)
To improve the validation, consider adding more comprehensive checks, such as verifying the format of the command and handling unexpected additional arguments.
Analysis chain
Validate command input in start function.
Ensure that the command validation is comprehensive and covers all expected scenarios.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify command validation in the start function.
# Test: Search for command validation logic. Expect: Comprehensive validation logic.
rg --type javascript $'commandsMap[command]'
Length of output: 80
Script:
#!/bin/bash
# Description: Verify command validation in the start function.
# Test: Search for command validation logic. Expect: Comprehensive validation logic.
rg --type js $'commandsMap[command]'
Length of output: 37
Script:
#!/bin/bash
# Description: Locate the start function and review its implementation.
# Search for the start function definition in JavaScript files.
rg --type js 'function start'
Length of output: 31
Script:
#!/bin/bash
# Description: Locate the start function and review its implementation.
# Search for the start function definition in JavaScript and ES module files.
rg --type-add 'mjs:*.mjs' --type js --type mjs 'function start'
Length of output: 122
Script:
#!/bin/bash
# Description: Extract and display the start function implementation from buildMaterials.mjs.
# Extract the start function implementation.
rg --type-add 'mjs:*.mjs' --type mjs --context 10 'function start' packages/materials/buildMaterials.mjs
Length of output: 495
| "test": "echo \"Error: no test specified\" && exit 1", | ||
| "serve": "node buildMaterials.mjs serve", | ||
| "build": "node buildMaterials.mjs build", | ||
| "build:split": "node buildMaterials.mjs build:split" |
f43f9dd to
ac2bdc2
Compare
ac2bdc2 to
7b429a2
Compare
0aeda52 to
2a33088
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
designer-demo/package.json (1)
13-13: Use consistent version specifier for workspace dependencies.The new dependency uses
workspace:*while@opentiny/tiny-engineusesworkspace:^. Consider using consistent version specifiers across workspace dependencies.- "@opentiny/tiny-engine-materials": "workspace:*", + "@opentiny/tiny-engine-materials": "workspace:^",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
designer-demo/engine.config.js(1 hunks)designer-demo/package.json(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (3)
designer-demo/engine.config.js (2)
1-10: Document the breaking changes and provide a migration guide.This change introduces a breaking change by modifying how materials are configured. Please:
- Document the new material module structure
- Provide a migration guide for users moving from the JSON file format
- Update the README with the new configuration details
1-1: Verify the material module's structure and add error handling.The change from a static JSON file to a dynamic module is a breaking change. Consider:
- Adding error handling for module loading failures
- Documenting the expected shape of the material module
- Providing type information
Also applies to: 6-6
designer-demo/package.json (1)
1-34: Add tests for the material package.The PR checklist indicates that tests are missing. Please add tests to verify:
- Material module loading
- Integration with the engine configuration
- Error handling for invalid material configurations
Would you like me to help generate test cases for the material package?
7c7bc09 to
79adeb4
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
designer-demo/engine.config.js(1 hunks)designer-demo/package.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- designer-demo/package.json
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: chilingling
PR: opentiny/tiny-engine#837
File: packages/vue-generator/src/plugins/genDependenciesPlugin.js:66-66
Timestamp: 2024-09-30T07:51:10.036Z
Learning: In the `tiny-engine` project, `opentiny/tiny-engine-dsl-vue` refers to the current package itself, and importing types from it may cause circular dependencies.
🧬 Code Graph Analysis (1)
designer-demo/engine.config.js (1)
packages/materials/buildMaterials.mjs (1)
material(77-77)
| @@ -1,7 +1,9 @@ | |||
| import material from '@opentiny/tiny-engine-materials' | |||
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Default import may not match the package’s export shape — consider interop-safe import.
If @opentiny/tiny-engine-materials does not export a default (e.g., CommonJS export or named export), this will break at runtime. Use a namespace import and normalize to a material object for robustness.
Apply this diff:
-import material from '@opentiny/tiny-engine-materials'
+import * as materials from '@opentiny/tiny-engine-materials'
+const material = materials.default ?? materials.material ?? materialsTo verify the export shape of the materials package and the dependency wiring, run:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) Check demo dependency is declared"
rg -n -C2 '"@opentiny/tiny-engine-materials"\s*:\s*' designer-demo/package.json || {
echo "Dependency not found in designer-demo/package.json"; exit 1; }
echo
echo "2) Locate the materials package and inspect export style"
# Path inferred from context (packages/materials/…)
if [ -d packages/materials ]; then
echo "- package.json name:"
rg -n -C1 '"name"\s*:\s*' packages/materials/package.json || true
echo
echo "- Look for default or CJS exports under packages/materials:"
rg -n -C2 -S 'export\s+default|module\.exports\s*=|exports\.' packages/materials || true
else
echo "packages/materials not found; adjust the path if the package lives elsewhere."
fiLength of output: 1001
Ensure interop-safe import of @opentiny/tiny-engine-materials
The @opentiny/tiny-engine-materials package has no default export, so this will break at runtime:
designer-demo/engine.config.js:1
-import material from '@opentiny/tiny-engine-materials'
+import * as materials from '@opentiny/tiny-engine-materials'
+const material = materials.default ?? materials.material ?? materials;This normalizes the import to work with both ESM and CJS export shapes.
📝 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.
| import material from '@opentiny/tiny-engine-materials' | |
| import * as materials from '@opentiny/tiny-engine-materials' | |
| const material = materials.default ?? materials.material ?? materials; |
🤖 Prompt for AI Agents
In designer-demo/engine.config.js at line 1, the current statement imports a
package that has no default export; change the import to be interop-safe by
either importing the module namespace (import * as material from
'@opentiny/tiny-engine-materials') or normalizing a default import (import
materialImport from '@opentiny/tiny-engine-materials' then const material =
materialImport?.default ?? materialImport); update the file to use one of these
patterns so the code works with both ESM and CJS export shapes.
| id: 'engine.config', | ||
| theme: 'light', | ||
| material: ['/mock/bundle.json'], | ||
| material: [material], |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Switching from a mock JSON URL to the materials package looks good — confirm engine compatibility and document the migration.
Nice move away from hardcoded /mock/bundle.json to a shareable materials package; this should improve consistency across demos. Please confirm the engine accepts inlined material objects (not just URLs) in the material array and add a short migration note since the PR is marked “breaking.”
Optional (to ease migration/backward-compat): allow a fallback/toggle to the legacy bundle for now. Example:
-import * as materials from '@opentiny/tiny-engine-materials'
-const material = materials.default ?? materials.material ?? materials
+import * as materials from '@opentiny/tiny-engine-materials'
+const material = materials.default ?? materials.material ?? materials
+const usePkg = !!(import.meta?.env?.VITE_USE_MATERIAL_PKG ?? true)
export default {
id: 'engine.config',
theme: 'light',
- material: [material],
+ material: [usePkg ? material : '/mock/bundle.json'],
scripts: [],
styles: []
}Quick checks you can run:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) Ensure no stale references to the old mock bundle remain"
rg -n -C2 '/mock/bundle\.json' || echo "No references found."
echo
echo "2) Grep for material array handling to ensure objects are supported (heuristic)"
rg -n -C3 -S '\bmaterial\b' packages | head -n 100 || trueLength of output: 14235
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Context around material in designer-demo/src/preview.js:"
rg -n -C3 'material' designer-demo/src/preview.js || true
echo
echo "Import statements in designer-demo/src/preview.js:"
rg -n 'import ' designer-demo/src/preview.jsLength of output: 608
Confirm inline material support & document breaking change migration
Engine already accepts in‐memory material objects (see “也可以传入 JSON 对象” examples in docs/api/frontend-api/preview-api.md and docs/extension-capabilities-overview/registry.md). To finish this breaking change:
• Update documentation
- docs/api/frontend-api/preview-api.md: show both URL and inlined object usage, and add a “Migration” note for replacing
/mock/bundle.jsonwith the new package import. - docs/extension-capabilities-overview/registry.md: mirror the inline-object example and call out the breaking change.
• (Optional) provide a runtime toggle/fallback to the legacy mock bundle in designer-demo/engine.config.js:
import * as materials from '@opentiny/tiny-engine-materials'
const material = materials.default ?? materials.material ?? materials
+ const usePkg = Boolean(import.meta.env.VITE_USE_MATERIAL_PKG ?? true)
export default {
id: 'engine.config',
theme: 'light',
- material: [material],
+ material: [usePkg ? material : '/mock/bundle.json'],
scripts: [],
styles: []
}• (Out-of-scope for this PR) schedule follow-up to clean up stale /mock/bundle.json references in CLI templates, scripts, and other demos.
📝 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.
| material: [material], | |
| import * as materials from '@opentiny/tiny-engine-materials' | |
| const material = materials.default ?? materials.material ?? materials | |
| const usePkg = Boolean(import.meta.env.VITE_USE_MATERIAL_PKG ?? true) | |
| export default { | |
| id: 'engine.config', | |
| theme: 'light', | |
| material: [usePkg ? material : '/mock/bundle.json'], | |
| scripts: [], | |
| styles: [] | |
| } |
🤖 Prompt for AI Agents
In designer-demo/engine.config.js around line 6 (material: [material]), confirm
and support inline in-memory material objects and add a runtime fallback to
preserve legacy /mock/bundle.json behavior: update engine.config.js to accept
either an imported object or a URL/string — if material is a string treat it as
a URL and load the legacy bundle, otherwise treat it as the inlined object; also
update docs/api/frontend-api/preview-api.md to show both URL and inline-object
usage and add a “Migration” note explaining replacing /mock/bundle.json with the
new package import, and mirror the inline-object example and breaking-change
callout in docs/extension-capabilities-overview/registry.md.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
packages/materials/buildMaterials.mjs (3)
121-123: Use consistent variable reference.Line 122 accesses
componentInfo.npm.destructuring, butnpmInfowas already extracted at line 112 for this purpose. UsenpmInfo.destructuringfor consistency.Apply this diff:
if (typeof npmInfo.destructuring === 'boolean') { - mapItem.destructuring = componentInfo.npm.destructuring + mapItem.destructuring = npmInfo.destructuring }
223-223: Fix typo in comment.Line 223 contains a typo: "手动出发" should be "手动触发".
- // 第一次需要手动出发构建一遍 + // 第一次需要手动触发构建一遍
207-221: Consider debouncing file change events.The watcher triggers a full rebuild on every file change without debouncing. If multiple files change simultaneously (e.g., during a git checkout), this could trigger multiple concurrent builds, potentially causing race conditions or wasted resources.
Consider adding a debounce mechanism to batch multiple changes:
let rebuildTimer = null watcher.on('all', (event, file) => { const eventMap = { add: '新增', change: '更新', unlink: '删除' } const fileFullPath = path.join(process.cwd(), file) logger.info(`${eventMap[event]}组件文件 (${fileFullPath})`) // Debounce rebuilds clearTimeout(rebuildTimer) rebuildTimer = setTimeout(() => { buildComponents() }, 300) // 300ms debounce })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/materials/buildMaterials.mjs(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/materials/buildMaterials.mjs (2)
scripts/splitMaterials.mjs (1)
fileName(56-56)scripts/buildMaterials.mjs (1)
componentInfo(157-157)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: push-check
🔇 Additional comments (2)
packages/materials/buildMaterials.mjs (2)
1-16: LGTM!The imports and initial setup are appropriate for the build orchestration functionality.
143-202: LGTM!The build logic correctly processes entries, aggregates bundles, and writes both per-entry and combined output files. Error handling is appropriate.
| if (!component.npm) { | ||
| logger.warn(`组件文件 ${file} 缺少 npm 字段,出码时将不能通过import语句导入组件。`) | ||
|
|
||
| return false | ||
| } |
There was a problem hiding this comment.
Inconsistent validation behavior: warning with failure.
The function logs a warning when the npm field is missing (line 36) but returns false (line 38), causing the component to be skipped. This is inconsistent—warnings typically shouldn't fail validation. Either return true to allow components without npm fields, or change the log level to error to match the failure behavior.
Apply this diff to align the log level with the behavior:
if (!component.npm) {
- logger.warn(`组件文件 ${file} 缺少 npm 字段,出码时将不能通过import语句导入组件。`)
+ logger.error(`组件文件 ${file} 缺少 npm 字段,出码时将不能通过import语句导入组件。`)
return false
}Alternatively, if components without npm should be allowed:
if (!component.npm) {
logger.warn(`组件文件 ${file} 缺少 npm 字段,出码时将不能通过import语句导入组件。`)
- return false
+ // Allow components without npm field
}📝 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.
| if (!component.npm) { | |
| logger.warn(`组件文件 ${file} 缺少 npm 字段,出码时将不能通过import语句导入组件。`) | |
| return false | |
| } | |
| if (!component.npm) { | |
| logger.error(`组件文件 ${file} 缺少 npm 字段,出码时将不能通过import语句导入组件。`) | |
| return false | |
| } |
🤖 Prompt for AI Agents
In packages/materials/buildMaterials.mjs around lines 35 to 39, the code logs a
warning when component.npm is missing but then returns false (failing the
component); change the log level to logger.error so the log matches the failure
behavior (keep the return false), i.e., replace logger.warn with logger.error
and keep the existing message so that missing npm is treated as an error and
clearly recorded.
| componentFiles.forEach((file) => { | ||
| const material = fsExtra.readJsonSync(path.resolve(entry, file), { throws: false }) | ||
|
|
||
| if (!material) { | ||
| const fileFullPath = path.join(process.cwd(), file) | ||
|
|
||
| logger.error(`文件格式有误 (${fileFullPath})`) | ||
|
|
||
| return | ||
| } |
There was a problem hiding this comment.
Incorrect path construction in error message.
Line 80 constructs the error path using path.join(process.cwd(), file), but file is a filename relative to entry, not relative to process.cwd(). This produces an incorrect path in the error message.
Apply this diff to fix the path construction:
if (!material) {
- const fileFullPath = path.join(process.cwd(), file)
+ const fileFullPath = path.resolve(entry, file)
logger.error(`文件格式有误 (${fileFullPath})`)📝 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.
| componentFiles.forEach((file) => { | |
| const material = fsExtra.readJsonSync(path.resolve(entry, file), { throws: false }) | |
| if (!material) { | |
| const fileFullPath = path.join(process.cwd(), file) | |
| logger.error(`文件格式有误 (${fileFullPath})`) | |
| return | |
| } | |
| componentFiles.forEach((file) => { | |
| const material = fsExtra.readJsonSync(path.resolve(entry, file), { throws: false }) | |
| if (!material) { | |
| const fileFullPath = path.resolve(entry, file) | |
| logger.error(`文件格式有误 (${fileFullPath})`) | |
| return | |
| } |
🤖 Prompt for AI Agents
In packages/materials/buildMaterials.mjs around lines 76 to 85, the error path
is built with path.join(process.cwd(), file) but `file` is relative to `entry`;
change the construction to resolve using the entry directory (e.g.
path.resolve(entry, file) or path.join(entry, file)) so the error message shows
the correct full path, and update the logger.error call to use that resolved
path variable.
| function start() { | ||
| const commandsMap = { | ||
| serve: serve, | ||
| build: build, | ||
| 'build:split': buildSplit | ||
| } | ||
|
|
||
| const command = process.argv.slice(2) | ||
|
|
||
| if (!commandsMap[command]) { | ||
| logger.error(`[@opentiny/tiny-engine-materials] 不支持${command}命令`) | ||
|
|
||
| return | ||
| } | ||
|
|
||
| commandsMap[command]() | ||
| } |
There was a problem hiding this comment.
Critical: Command argument extracted incorrectly.
Line 256 uses process.argv.slice(2), which returns an array, but line 258 uses command as if it were a string when accessing commandsMap[command]. This means commandsMap[command] will always be undefined, and the script will never execute any command.
Apply this diff to fix the bug:
- const command = process.argv.slice(2)
+ const command = process.argv[2]
if (!commandsMap[command]) {Alternatively, extract the first element explicitly:
- const command = process.argv.slice(2)
+ const [command] = process.argv.slice(2)
if (!commandsMap[command]) {🤖 Prompt for AI Agents
In packages/materials/buildMaterials.mjs around lines 249 to 265, the code uses
process.argv.slice(2) which returns an array but treats it as a string key when
looking up commandsMap, causing commandsMap[command] to always be undefined;
change the extraction to get the first argument (e.g., const command =
process.argv[2] or const [command] = process.argv.slice(2)) and then use that
string to check and invoke commandsMap[command], keeping the existing error
handling and return behavior if the command is not found.
English | 简体中文
PR
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
Background and solution
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
New Features
Chores