-
Notifications
You must be signed in to change notification settings - Fork 437
chore: move upload script to template #1685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| const log = (() => { | ||
| return (...args) => { | ||
| process.stdout.write(args.map(arg => | ||
| typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg) | ||
| ).join(' ') + '\n'); | ||
| }; | ||
| })(); | ||
|
|
||
| const warn = (() => { | ||
| return (...args) => { | ||
| process.stderr.write(args.map(arg => | ||
| typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg) | ||
| ).join(' ') + '\n'); | ||
| }; | ||
| })(); | ||
|
|
||
| class Logger { | ||
| constructor(command = 'default') { | ||
| this.command = command; | ||
| this.colors = null; | ||
| this.hasColors = false; | ||
| this.initColors(); | ||
| } | ||
|
|
||
| async initColors() { | ||
| try { | ||
| const colorsModule = await import('colors'); | ||
| this.colors = colorsModule.default || colorsModule; | ||
| this.hasColors = true; | ||
| } catch (err) { | ||
| warn('colors package not found, using basic logging'); | ||
| this.hasColors = false; | ||
| } | ||
| } | ||
|
|
||
| output(type, ...args) { | ||
| const time = new Date().toLocaleTimeString(); | ||
| const prefix = `[${this.command}] [${time}]`; | ||
| const message = args.map((arg) => { | ||
| if (typeof arg === 'object') { | ||
| return JSON.stringify(arg, null, 2); | ||
| } | ||
| return String(arg); | ||
| }).join(' '); | ||
|
|
||
| const outputFn = type === 'error' || type === 'warn' ? warn : log; | ||
|
|
||
| if (this.hasColors && this.colors) { | ||
| const colorMap = { | ||
| info: this.colors.cyan, | ||
| warn: this.colors.yellow, | ||
| error: this.colors.red, | ||
| success: this.colors.green, | ||
| }; | ||
| const coloredType = colorMap[type] | ||
| ? colorMap[type](type.toUpperCase()) | ||
| : type.toUpperCase(); | ||
|
|
||
| outputFn(`${prefix} ${coloredType} ${message}`); | ||
| } else { | ||
| const emojiMap = { | ||
| info: 'ℹ️', | ||
| warn: '⚠️', | ||
| error: '❌', | ||
| success: '✅', | ||
| }; | ||
| outputFn(`${prefix} ${emojiMap[type] || ''} ${message}`); | ||
| } | ||
| } | ||
|
|
||
| success(...args) { | ||
| this.output('success', ...args); | ||
| } | ||
|
|
||
| info(...args) { | ||
| this.output('info', ...args); | ||
| } | ||
|
|
||
| warn(...args) { | ||
| this.output('warn', ...args); | ||
| } | ||
|
|
||
| error(...args) { | ||
| this.output('error', ...args); | ||
| } | ||
| } | ||
|
|
||
| export default Logger; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import dotenv from 'dotenv' | ||
| import fs from 'fs-extra' | ||
| import { Buffer } from 'node:buffer' | ||
| import path from 'node:path' | ||
| import Logger from './logger.mjs' | ||
|
|
||
|
|
||
| /** | ||
| * 同步物料资产包到后端数据库 | ||
| * 1. 读取 env/.env.local 文件,获取后端地址。需要设置地址如:backend_url=http://localhost:9090 | ||
| * 2. 读取 public/mock/bundle.json 文件,获取物料资产包数据 | ||
| * 3. 将物料资产包数据通过 POST 请求上传到后端接口 /material-center/api/component/bundle/create | ||
| * 4. 检查数据库t_component表中数据是否更新成功 | ||
| * | ||
| * 使用场景: | ||
| * 1. 本地已经将 bundle.json 文件进行修改,但是数据需要同步到后端数据库中。 | ||
| * 2. 本地已经将 bundle.json 文件进行修改,但是出码仍然不正确。 | ||
| * @returns | ||
| */ | ||
| async function main() { | ||
| const logger = new Logger('uploadMaterials') | ||
|
|
||
| // 先构造出.env*文件的绝对路径 | ||
| const appDirectory = fs.realpathSync(process.cwd()) | ||
| const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath) | ||
| const pathsDotenv = resolveApp('env') | ||
| logger.info(`Start to load .env.local file from ${pathsDotenv}/.env.local`) | ||
| dotenv.config({ path: `${pathsDotenv}/.env.local` }) | ||
| const { backend_url } = process.env | ||
|
|
||
| if (!backend_url) { | ||
| logger.error('backend_url is not set in .env.local file') | ||
| process.exit(1) | ||
| } | ||
|
|
||
| const bundlePath = path.join(process.cwd(), './public/mock/bundle.json') | ||
| logger.info(`Start to read bundle.json file from ${bundlePath}`) | ||
| const bundle = fs.readJSONSync(bundlePath) | ||
| const jsonBuffer = Buffer.from(JSON.stringify(bundle)) | ||
|
|
||
| const requestUrl = (backend_url.endsWith('/') ? backend_url.slice(0, -1) : backend_url) + '/material-center/api/component/bundle/create' | ||
| logger.info(`Start to upload bundle.json file to ${requestUrl}`) | ||
| try { | ||
| const formData = new FormData() | ||
| formData.append('file', new Blob([jsonBuffer], { type: 'application/json'}), 'bundle.json') | ||
| const response = await fetch(requestUrl, { | ||
| method: 'POST', | ||
| body: formData | ||
| }) | ||
|
|
||
| if (!response.ok) { | ||
| const errorText = await response.text() | ||
| throw new Error(`Upload failed with status ${response.status}: ${errorText}`) | ||
| } | ||
| const data = await response.json() | ||
| if (data && data.success) { | ||
| logger.success(`File uploaded successfully:${JSON.stringify(data)}`) | ||
| } else { | ||
| logger.warn(`Upload completed but success flag is false: ${JSON.stringify(data)}`) | ||
| logger.warn(`Upload completed with warnings: ${JSON.stringify(data.message)}`) | ||
| } | ||
| } catch (error) { | ||
| logger.error('Error uploading file:', error instanceof Error ? error.message : String(error)) | ||
| } | ||
| } | ||
|
|
||
| main() | ||
| .catch((e) => { | ||
| const logger = new Logger('uploadMaterials') | ||
| logger.error('Error uploading file:', e instanceof Error ? e.message : String(e)); | ||
| process.exit(1); | ||
| }) | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||||||||||||||||||||||||||||||||||||
| const log = (() => { | ||||||||||||||||||||||||||||||||||||||||
| return (...args) => { | ||||||||||||||||||||||||||||||||||||||||
| process.stdout.write( | ||||||||||||||||||||||||||||||||||||||||
| args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg))).join(' ') + '\n' | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| })() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const warn = (() => { | ||||||||||||||||||||||||||||||||||||||||
| return (...args) => { | ||||||||||||||||||||||||||||||||||||||||
| process.stderr.write( | ||||||||||||||||||||||||||||||||||||||||
| args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg))).join(' ') + '\n' | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| })() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| class Logger { | ||||||||||||||||||||||||||||||||||||||||
| constructor(command = 'default') { | ||||||||||||||||||||||||||||||||||||||||
| this.command = command | ||||||||||||||||||||||||||||||||||||||||
| this.colors = null | ||||||||||||||||||||||||||||||||||||||||
| this.hasColors = false | ||||||||||||||||||||||||||||||||||||||||
| this.initColors() | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+17
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical race condition: async initialization in constructor.
Consider one of these approaches: Option 1: Static factory method (recommended) - constructor(command = 'default') {
+ static async create(command = 'default') {
+ const logger = new Logger(command);
+ await logger.initColors();
+ return logger;
+ }
+
+ constructor(command = 'default') {
this.command = command
this.colors = null
this.hasColors = false
- this.initColors()
}Option 2: Lazy initialization on first use constructor(command = 'default') {
this.command = command
this.colors = null
this.hasColors = false
- this.initColors()
+ this.colorInitPromise = this.initColors()
}
- output(type, ...args) {
+ async output(type, ...args) {
+ await this.colorInitPromise
const time = new Date().toLocaleTimeString()
// ... rest of method
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| async initColors() { | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| const colorsModule = await import('colors') | ||||||||||||||||||||||||||||||||||||||||
| this.colors = colorsModule.default || colorsModule | ||||||||||||||||||||||||||||||||||||||||
| this.hasColors = true | ||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||
| warn('colors package not found, using basic logging') | ||||||||||||||||||||||||||||||||||||||||
| this.hasColors = false | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+34
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify correct color package is imported. Based on past review comments, the PR adds Run this script to verify which color package is actually in the dependencies: 🏁 Script executed: #!/bin/bash
# Check which color packages are in package.json files
echo "=== Template designer package.json ==="
fd -t f '^package.json$' packages/engine-cli/template/designer --exec jq -r 'select(.devDependencies) | .devDependencies | to_entries | .[] | select(.key | contains("color")) | "\(.key): \(.value)"' {}
echo -e "\n=== Designer-demo package.json ==="
fd -t f '^package.json$' designer-demo --exec jq -r 'select(.devDependencies) | .devDependencies | to_entries | .[] | select(.key | contains("color")) | "\(.key): \(.value)"' {}
echo -e "\n=== Root package.json ==="
jq -r 'select(.devDependencies) | .devDependencies | to_entries | .[] | select(.key | contains("color")) | "\(.key): \(.value)"' package.jsonLength of output: 158 Fix incorrect package import in logger.mjs. The code imports const colorsModule = await import('picocolors')🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| output(type, ...args) { | ||||||||||||||||||||||||||||||||||||||||
| const time = new Date().toLocaleTimeString() | ||||||||||||||||||||||||||||||||||||||||
| const prefix = `[${this.command}] [${time}]` | ||||||||||||||||||||||||||||||||||||||||
| const message = args | ||||||||||||||||||||||||||||||||||||||||
| .map((arg) => { | ||||||||||||||||||||||||||||||||||||||||
| if (typeof arg === 'object') { | ||||||||||||||||||||||||||||||||||||||||
| return JSON.stringify(arg, null, 2) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| return String(arg) | ||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||
| .join(' ') | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const outputFn = type === 'error' || type === 'warn' ? warn : log | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if (this.hasColors && this.colors) { | ||||||||||||||||||||||||||||||||||||||||
| const colorMap = { | ||||||||||||||||||||||||||||||||||||||||
| info: this.colors.cyan, | ||||||||||||||||||||||||||||||||||||||||
| warn: this.colors.yellow, | ||||||||||||||||||||||||||||||||||||||||
| error: this.colors.red, | ||||||||||||||||||||||||||||||||||||||||
| success: this.colors.green | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| const coloredType = colorMap[type] ? colorMap[type](type.toUpperCase()) : type.toUpperCase() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| outputFn(`${prefix} ${coloredType} ${message}`) | ||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||
| const emojiMap = { | ||||||||||||||||||||||||||||||||||||||||
| info: 'ℹ️', | ||||||||||||||||||||||||||||||||||||||||
| warn: '⚠️', | ||||||||||||||||||||||||||||||||||||||||
| error: '❌', | ||||||||||||||||||||||||||||||||||||||||
| success: '✅' | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| outputFn(`${prefix} ${emojiMap[type] || ''} ${message}`) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| success(...args) { | ||||||||||||||||||||||||||||||||||||||||
| this.output('success', ...args) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| info(...args) { | ||||||||||||||||||||||||||||||||||||||||
| this.output('info', ...args) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| warn(...args) { | ||||||||||||||||||||||||||||||||||||||||
| this.output('warn', ...args) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| error(...args) { | ||||||||||||||||||||||||||||||||||||||||
| this.output('error', ...args) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| export default Logger | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import dotenv from 'dotenv' | ||
| import fs from 'fs-extra' | ||
| import { Buffer } from 'node:buffer' | ||
| import path from 'node:path' | ||
| import Logger from './logger.mjs' | ||
|
|
||
| /** | ||
| * 同步物料资产包到后端数据库 | ||
| * 1. 读取 env/.env.local 文件,获取后端地址。需要设置地址如:backend_url=http://localhost:9090 | ||
| * 2. 读取 public/mock/bundle.json 文件,获取物料资产包数据 | ||
| * 3. 将物料资产包数据通过 POST 请求上传到后端接口 /material-center/api/component/bundle/create | ||
| * 4. 检查数据库t_component表中数据是否更新成功 | ||
| * | ||
| * 使用场景: | ||
| * 1. 本地已经将 bundle.json 文件进行修改,但是数据需要同步到后端数据库中。 | ||
| * 2. 本地已经将 bundle.json 文件进行修改,但是出码仍然不正确。 | ||
| * @returns | ||
| */ | ||
| async function main() { | ||
| const logger = new Logger('uploadMaterials') | ||
|
|
||
| // 先构造出.env*文件的绝对路径 | ||
| const appDirectory = fs.realpathSync(process.cwd()) | ||
| const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath) | ||
| const pathsDotenv = resolveApp('env') | ||
| logger.info(`Start to load .env.local file from ${pathsDotenv}/.env.local`) | ||
| dotenv.config({ path: `${pathsDotenv}/.env.local` }) | ||
| const { backend_url } = process.env | ||
|
|
||
| if (!backend_url) { | ||
| logger.error('backend_url is not set in .env.local file') | ||
| process.exit(1) | ||
| } | ||
|
|
||
| const bundlePath = path.join(process.cwd(), './public/mock/bundle.json') | ||
| logger.info(`Start to read bundle.json file from ${bundlePath}`) | ||
| const bundle = fs.readJSONSync(bundlePath) | ||
| const jsonBuffer = Buffer.from(JSON.stringify(bundle)) | ||
|
|
||
| const requestUrl = | ||
| (backend_url.endsWith('/') ? backend_url.slice(0, -1) : backend_url) + | ||
| '/material-center/api/component/bundle/create' | ||
| logger.info(`Start to upload bundle.json file to ${requestUrl}`) | ||
| try { | ||
| const formData = new FormData() | ||
| formData.append('file', new Blob([jsonBuffer], { type: 'application/json' }), 'bundle.json') | ||
| const response = await fetch(requestUrl, { | ||
| method: 'POST', | ||
| body: formData | ||
| }) | ||
|
|
||
| if (!response.ok) { | ||
| const errorText = await response.text() | ||
| throw new Error(`Upload failed with status ${response.status}: ${errorText}`) | ||
| } | ||
| const data = await response.json() | ||
| if (data && data.success) { | ||
| logger.success(`File uploaded successfully:${JSON.stringify(data)}`) | ||
| } else { | ||
| logger.warn(`Upload completed but success flag is false: ${JSON.stringify(data)}`) | ||
| logger.warn(`Upload completed with warnings: ${JSON.stringify(data.message)}`) | ||
| } | ||
| } catch (error) { | ||
| logger.error('Error uploading file:', error instanceof Error ? error.message : String(error)) | ||
| } | ||
| } | ||
|
|
||
| main().catch((e) => { | ||
| const logger = new Logger('uploadMaterials') | ||
| logger.error('Error uploading file:', e instanceof Error ? e.message : String(e)) | ||
| process.exit(1) | ||
| }) |
Uh oh!
There was an error while loading. Please reload this page.