New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

sync-code-editor

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sync-code-editor - npm Package Compare versions

Comparing version
1.0.0
to
1.0.1
+18
-16
bin/index.js
#!/usr/bin/env node
const chalk = require('chalk').default
const ora = require('ora').default
const chalk = require('chalk').default;
const ora = require('ora').default;
const process = require('node:process');
const { detectInstalledEditors, getEditorList } = require('../lib/editors');
const { selectSourceEditor, selectConfigurationList, selectTargetEditors, confirmSync } = require('../lib/prompts');
const { syncConfigs, printSyncResults } = require('../lib/sync');
const { detectInstalledEditors, getEditorList } = require('../lib/editors');
const { renderLink } = require('../lib/utils');
const { renderLink, printf } = require('../lib/utils');
async function main() {
try {
console.log(chalk.blue('★★ 欢迎使用编辑器配置同步工具 ★★\n'));
printf(chalk.blue('★★ 欢迎使用编辑器配置同步工具 ★★\n'));

@@ -20,6 +21,6 @@ // 检测已安装的编辑器

if (installedEditors.length === 0) {
console.log(chalk.red('✗ 未检测到任何已安装的编辑器。'));
console.log('请确保至少已安装以下编辑器中的任意两个:');
getEditorList().forEach(editor => {
console.log(' - ' + renderLink(editor.homepage, editor.name));
printf(chalk.red('✗ 未检测到任何已安装的编辑器。'));
printf('请确保至少已安装以下编辑器中的任意两个:');
getEditorList().forEach((editor) => {
printf(` - ${renderLink(editor.homepage, editor.name)}`);
});

@@ -30,3 +31,3 @@ process.exit(1);

if (installedEditors.length === 1) {
console.log(chalk.yellow(`✗ 您只安装了 ${installedEditors[0].name} ,不需要进行同步操作。`));
printf(chalk.yellow(`✗ 您只安装了 ${installedEditors[0].name} ,不需要进行同步操作。`));
process.exit(1);

@@ -50,7 +51,7 @@ }

configurationKeys,
targetEditorKeys
targetEditorKeys,
);
if (!confirm) {
console.log(chalk.yellow('已取消同步操作。'));
printf(chalk.yellow('已取消同步操作。'));
process.exit(0);

@@ -66,6 +67,7 @@ }

printSyncResults(result);
} catch (error) {
console.log(chalk.red('\n✗ 发生错误:'), error.message);
}
catch (error) {
printf(chalk.red('\n✗ 发生错误:'), error.message);
if (error.stack) {
console.log(chalk.red('\n错误堆栈:'), error.stack);
printf(chalk.red('\n错误堆栈:'), error.stack);
}

@@ -76,2 +78,2 @@ process.exit(1);

main();
main();

@@ -1,2 +0,2 @@

const path = require('path');
const path = require('node:path');
const { getEditorInfo } = require('./editors');

@@ -8,21 +8,12 @@

name: '编辑器设置 (settings.json)',
files: [{ type: 'file', path: 'settings.json' }]
files: [{ type: 'file', path: 'settings.json' }],
},
keybindings: {
name: '快捷键绑定 (keybindings.json)',
files: [{ type: 'file', path: 'keybindings.json' }]
files: [{ type: 'file', path: 'keybindings.json' }],
},
snippets: {
name: '代码片段 (snippets/*)',
files: [{ type: 'dir', path: 'snippets' }]
files: [{ type: 'dir', path: 'snippets' }],
},
'project-manager': {
name: '项目管理器配置',
files: [
{
type: 'file',
path: path.join('globalStorage', 'alefragnani.project-manager', 'projects.json')
}
]
}
};

@@ -32,3 +23,3 @@

* 获取所有可用的同步项列表
* @returns {Array<{value: string, name: string}>}
* @returns {Array<{value: string, name: string}>}
*/

@@ -76,2 +67,2 @@ function getConfigurationList() {

getConfigurationFileFullPath,
};
};

@@ -6,21 +6,21 @@ const fs = require('fs-extra');

const editorMap = {
vscode: {
'vscode': {
name: 'Visual Studio Code',
path: getAppDataPathWithCache('Code'),
homepage: 'https://code.visualstudio.com/'
homepage: 'https://code.visualstudio.com/',
},
cursor: {
'cursor': {
name: 'Cursor',
path: getAppDataPathWithCache('Cursor'),
homepage: 'https://cursor.com/'
homepage: 'https://cursor.com/',
},
windsurf: {
'windsurf': {
name: 'Windsurf',
path: getAppDataPathWithCache('Windsurf'),
homepage: 'https://windsurf.com/'
homepage: 'https://windsurf.com/',
},
trae: {
'trae': {
name: 'Trae',
path: getAppDataPathWithCache('Trae'),
homepage: 'https://www.trae.ai/'
homepage: 'https://www.trae.ai/',
},

@@ -30,4 +30,4 @@ 'trae-cn': {

path: getAppDataPathWithCache('Trae CN'),
homepage: 'https://www.trae.cn/'
}
homepage: 'https://www.trae.cn/',
},
};

@@ -37,3 +37,3 @@

* 检测已安装的编辑器
* @returns {Promise<Array<import('../types').Editor>>} 已安装的编辑器列表
* @returns {Promise<Array<import('../types').Editor>>} 已安装的编辑器列表
*/

@@ -79,3 +79,3 @@ async function detectInstalledEditors() {

function getEditorList() {
return Object.keys(editorMap).map(key => {
return Object.keys(editorMap).map((key) => {
const editor = getEditorInfo(key);

@@ -86,3 +86,2 @@ return { key, ...editor };

module.exports = {

@@ -92,2 +91,2 @@ getEditorInfo,

detectInstalledEditors,
};
};
const inquirer = require('inquirer').default;
const { getEditorInfo, } = require('./editors');
const { getConfigurationList, getConfigurationInfo } = require('./configurations');
const { getEditorInfo } = require('./editors');

@@ -23,4 +23,4 @@ /**

name: editor.name,
}))
}
})),
},
]);

@@ -49,4 +49,4 @@

return true;
}
}
},
},
]);

@@ -66,4 +66,4 @@

const sourceEditorName = getEditorInfo(sourceEditorKey, 'name');
const configurationNames = configurationKeys.map(item => ' - ' + getConfigurationInfo(item, 'name')).join('\n');
const targetEditorNames = targetEditorKeys.map(editor => ' - ' + getEditorInfo(editor, 'name')).join('\n');
const configurationNames = configurationKeys.map(item => ` - ${getConfigurationInfo(item, 'name')}`).join('\n');
const targetEditorNames = targetEditorKeys.map(editor => ` - ${getEditorInfo(editor, 'name')}`).join('\n');

@@ -75,4 +75,4 @@ const { confirmed } = await inquirer.prompt([

message: `确认要将 ${sourceEditorName} 中的:\n${configurationNames} \n 同步到\n${targetEditorNames}\n`,
default: true
}
default: true,
},
]);

@@ -111,4 +111,4 @@

return true;
}
}
},
},
]);

@@ -123,3 +123,3 @@

selectTargetEditors,
confirmSync
};
confirmSync,
};

@@ -0,6 +1,7 @@

const path = require('node:path');
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk').default;
const { getEditorInfo, } = require('./editors');
const { getConfigurationInfo, getConfigurationFileFullPath } = require('./configurations');
const { getConfigurationInfo, getConfigurationFileFullPath } = require('./configurations');
const { getEditorInfo } = require('./editors');
const { printf } = require('./utils');

@@ -17,5 +18,5 @@ /**

const configurationInfo = getConfigurationInfo(configurationKey);
const sourceEditorConfigurationFiles = configurationInfo.files.map((file) => ({
const sourceEditorConfigurationFiles = configurationInfo.files.map(file => ({
...file,
path: getConfigurationFileFullPath(sourceEditorKey, file.path)
path: getConfigurationFileFullPath(sourceEditorKey, file.path),
}));

@@ -26,6 +27,6 @@

let promises = sourceEditorConfigurationFiles.map((config) => {
const promises = sourceEditorConfigurationFiles.map((config) => {
const filePath = config.path;
return fs.pathExists(filePath)
.then(exists => {
.then((exists) => {
if (!exists) {

@@ -39,6 +40,6 @@ missingFiles.push(filePath);

return false;
})
})
});
});
await Promise.all(promises)
await Promise.all(promises);

@@ -48,4 +49,4 @@ if (missingFiles.length > 0 || errorFiles.length > 0) {

success: false,
reason: { missingFiles, errorFiles }
}
reason: { missingFiles, errorFiles },
};
}

@@ -59,4 +60,4 @@

from: sourceEditorConfigurationFiles[index].path,
to: getConfigurationFileFullPath(targetEditorKey, config.path)
}
to: getConfigurationFileFullPath(targetEditorKey, config.path),
};
});

@@ -74,12 +75,13 @@

await fs.copy(task.from, task.to);
} catch (error) {
}
catch {
errorFiles.push(task.from);
return {
success: false,
reason: { errorFiles }
}
reason: { errorFiles },
};
}
}
return { success: true }
return { success: true };
}

@@ -93,3 +95,3 @@

* @param {Array<import('../types').EditorKeys>} targetEditorKeys - 目标编辑器键名数组
* @returns {Promise<import('../types').SyncResult>} 同步结果
* @returns {Promise<import('../types').SyncResult>} 同步结果
*/

@@ -112,3 +114,2 @@ async function syncConfigs(sourceEditorKey, configurationKeys, installedEditors, targetEditorKeys) {

for (const targetEditor of targetEditors) {
const targetEditorName = targetEditor.name;

@@ -123,9 +124,10 @@ const targetEditorKey = targetEditor.key;

configurationName,
...result
...result,
});
} catch (error) {
}
catch (error) {
results[targetEditorName].push({
configurationName,
success: false,
message: error.message || `${error}`
message: error.message || `${error}`,
});

@@ -143,3 +145,3 @@ }

function printSyncResults(syncResult) {
console.log('\n同步结果:');
printf('\n同步结果:');

@@ -157,12 +159,13 @@ // const list = Object.values(syncResult).flatMap(results => results);

targetEditorName,
results: results.sort((a, b) => b.success - a.success)
}
results: results.sort((a, b) => b.success - a.success),
};
}).forEach(({ targetEditorName, results }) => {
console.log(`\n${targetEditorName}:`);
printf(`\n${targetEditorName}:`);
results.forEach((result) => {
if (result.success) {
console.log(chalk.green(` ✓ ${result.configurationName}`));
printf(chalk.green(` ✓ ${result.configurationName}`));
successCount++;
} else if (!result.success) {
console.log(chalk.red(` ✗ ${result.configurationName}: ${result.message}`));
}
else if (!result.success) {
printf(chalk.red(` ✗ ${result.configurationName}: ${result.message}`));
errorCount++;

@@ -172,8 +175,8 @@ }

// TODO
console.log(chalk.yellow(` ⊘ ${result.message}`));
printf(chalk.yellow(` ⊘ ${result.message}`));
}
})
})
});
});
console.log(chalk.blue(`\n总计: ${successCount} 成功, ${errorCount} 失败\n`));
printf(chalk.blue(`\n总计: ${successCount} 成功, ${errorCount} 失败\n`));
}

@@ -183,3 +186,3 @@

syncConfigs,
printSyncResults
};
printSyncResults,
};

@@ -1,4 +0,5 @@

const path = require('path');
const os = require('node:os');
const path = require('node:path');
const process = require('node:process');
const fs = require('fs-extra');
const os = require('os');

@@ -28,7 +29,9 @@ const platform = os.platform();

appDataPath = path.join(homeDir, 'Library', 'Application Support', appPathName, 'User');
} else if (platform === 'win32') {
}
else if (platform === 'win32') {
// Windows
const appDataDir = process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming');
appDataPath = path.join(appDataDir, appPathName, 'User');
} else {
}
else {
// Linux

@@ -47,3 +50,3 @@ appDataPath = path.join(homeDir, '.config', appPathName, 'User');

return getAppDataPathWithCache
return getAppDataPathWithCache;
}

@@ -57,5 +60,11 @@

function printf(...args) {
// eslint-disable-next-line no-console
console.log(...args);
}
module.exports = {
getAppDataPathWithCache,
renderLink
}
renderLink,
printf,
};
{
"name": "sync-code-editor",
"version": "1.0.0",
"version": "1.0.1",
"description": "同步您的设备上所有以 Visual Studio Code 为内核的编辑器配置",
"author": "onlymisaky@gmail.com",
"license": "ISC",
"homepage": "https://github.com/onlymisaky/sync-code-editor",
"repository": {
"type": "git",
"url": "git+https://github.com/onlymisaky/sync-code-editor.git"
},
"bugs": {
"url": "https://github.com/onlymisaky/sync-code-editor/issues"
},
"main": "index.js",

@@ -8,5 +19,10 @@ "bin": {

},
"author": "onlymisaky@gmail.com",
"license": "ISC",
"description": "同步您的设备上所有以 Visual Studio Code 为内核的编辑器配置",
"files": [
"bin",
"lib"
],
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"dependencies": {

@@ -18,10 +34,6 @@ "chalk": "^5.6.2",

},
"repository": {
"type": "git",
"url": "git+https://github.com/onlymisaky/sync-code-editor.git"
},
"bugs": {
"url": "https://github.com/onlymisaky/sync-code-editor/issues"
},
"homepage": "https://github.com/onlymisaky/sync-code-editor"
"devDependencies": {
"@antfu/eslint-config": "^6.2.0",
"eslint": "^9.39.1"
}
}
name: Publish NPM Package
permissions:
id-token: write
contents: write
on:
push:
branches:
- master
jobs:
publish:
# if: "${{ startsWith(github.event.head_commit.message, 'chore: release v') }}"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm publish -r --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
export type EditorKeys = 'vscode' | 'cursor' | 'windsurf' | 'trae' | 'tran-cn';
export interface Editor {
key: EditorKeys;
/** 编辑器显示名称 */
name: string;
/** 编辑器文件路径 */
path: string;
/** 编辑器首页 URL */
homepage: string;
}
export type EditorMap = Record<EditorKeys, Omit<Editor, 'key'>>;
export type ConfigurationKeys = 'settings' | 'keybindings' | 'snippets' | 'project-manager';
export interface Configuration {
key: ConfigurationKeys;
/** 同步项显示名称 */
name: string;
/** 要同步的内容数组,每个元素为文件路径或目录路径 */
files: { type: 'file' | 'dir'; path: string }[];
}
export type ConfigurationMap = Record<ConfigurationKeys, Omit<Configuration, 'key'>>;
export interface SyncResultItem {
reason?: { errorFiles?: string[]; missingFiles?: string[] };
configurationName?: string;
success: boolean;
message?: string;
}
export interface SyncResult {
[editorName: string]: Array<SyncResultItem>;
}