generated from githuhsername/simple-template-advanced
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 30d8dd6
Showing
11 changed files
with
1,082 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,311 @@ | ||
#!/usr/bin/env node | ||
const yargs = require('yargs/yargs'); | ||
const { hideBin } = require('yargs/helpers'); | ||
const argv = yargs(hideBin(process.argv)).argv; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const child_process = require('child_process'); | ||
const { default: axios } = require('axios'); | ||
|
||
const GITHUB_TOKEN = argv.github; | ||
const OWNER_NAME = argv.owner; | ||
const CURRENT_REPO = argv.repo; | ||
const REPO_URL = argv.repourl; | ||
const PACKAGE_NAME = argv.package; | ||
|
||
function random(min, max) { | ||
return Math.floor(Math.random() * (max - min + 1) + min); | ||
} | ||
|
||
function shuffle(arr) { | ||
for (let i = arr.length - 1; i > 0; i--) { | ||
const j = Math.floor(Math.random() * (i + 1)); | ||
[arr[i], arr[j]] = [arr[j], arr[i]]; | ||
} | ||
} | ||
|
||
async function getListPackageByKeywords(keyword) { | ||
const x = await axios.get('https://registry.npmjs.org/-/v1/search', { | ||
responseType: 'json', | ||
params: { | ||
text: `keywords:${keyword} not:insecure,unstable`, | ||
quality: '0.8', | ||
popularity: '0.8', | ||
}, | ||
}); | ||
|
||
return x.data.objects; | ||
} | ||
|
||
async function getPackageInfo(packageName) { | ||
try { | ||
const x = await axios.get(`https://registry.npmjs.org/${packageName}`, { | ||
responseType: 'json', | ||
}); | ||
return x.data; | ||
} catch (err) { | ||
return null; | ||
} | ||
} | ||
|
||
const PARENT_FOLDER = path.resolve(__dirname, '../..'); | ||
const ROOT_FOLDER = path.resolve(PARENT_FOLDER, '..'); | ||
|
||
console.log('ROOT_FOLDER=%s', ROOT_FOLDER); | ||
console.log('PARENT_FOLDER=%s', PARENT_FOLDER); | ||
|
||
const SKIP_MAP = {}; | ||
|
||
async function chooseFromList(list) { | ||
for (const pkg of list) { | ||
if ( | ||
!pkg.package.links || | ||
!pkg.package.links.repository || | ||
!pkg.package.links.repository.startsWith('https://github.com/') | ||
) { | ||
continue; | ||
} | ||
|
||
const url = pkg.package.links.repository; | ||
const packageName = pkg.package.name; | ||
|
||
try { | ||
const fullPackageInfo = await getPackageInfo(packageName); | ||
|
||
const versions = Object.values(fullPackageInfo.versions || {}); | ||
|
||
if ( | ||
versions && | ||
versions[0] && | ||
versions[0].dependencies && | ||
versions[0].dependencies['node-gyp-build'] | ||
) { | ||
console.log( | ||
'Skip package %s due to the need of node-gyp-build', | ||
packageName | ||
); | ||
continue; | ||
} | ||
|
||
console.log('Try to clone package %s, url: %s', packageName, url); | ||
|
||
// clone to test-folder | ||
const folder = path.join(ROOT_FOLDER, Math.random().toString()); | ||
|
||
console.log('Try to clone to folder %s', folder); | ||
|
||
child_process.execSync(`git clone "${url}" "${folder}"`, { | ||
cwd: ROOT_FOLDER, | ||
}); | ||
|
||
const output = child_process.execSync( | ||
`rsync -av --exclude=".git" --exclude=".github" "${folder}/" "${PARENT_FOLDER}/"`, | ||
{ | ||
encoding: 'utf-8', | ||
} | ||
); | ||
|
||
console.log(output); | ||
|
||
console.log('Copied data'); | ||
|
||
child_process.execSync(`rm -rf "${folder}"`); | ||
|
||
const ORI_PACKAGE_JSON = JSON.parse( | ||
fs.readFileSync(path.join(PARENT_FOLDER, 'package.json'), { | ||
encoding: 'utf-8', | ||
}) | ||
); | ||
|
||
console.log('Original PACKAGE_JSON', ORI_PACKAGE_JSON); | ||
|
||
ORI_PACKAGE_JSON.dependencies = ORI_PACKAGE_JSON.dependencies || {}; | ||
|
||
// | ||
const { data: repos } = await axios.get( | ||
`https://api.github.com/orgs/${OWNER_NAME}/repos`, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${GITHUB_TOKEN}`, | ||
Accept: 'application/vnd.github.v3+json', | ||
}, | ||
responseType: 'json', | ||
} | ||
); | ||
|
||
for (const repo of repos) { | ||
if (repo.full_name === CURRENT_REPO) { | ||
console.log('Skip repo %s due to current repo', repo.full_name); | ||
continue; | ||
} | ||
|
||
if (SKIP_MAP[repo.full_name]) { | ||
console.log('Skip repo %s due to skip map', repo.full_name); | ||
continue; | ||
} | ||
|
||
try { | ||
const { data: packageJSON } = await axios.get( | ||
`https://raw.githubusercontent.com/${repo.full_name}/main/package.json`, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${GITHUB_TOKEN}`, | ||
}, | ||
responseType: 'json', | ||
} | ||
); | ||
|
||
if (SKIP_MAP[packageJSON.name]) { | ||
console.log('Skip repo %s due to skip map', repo.full_name); | ||
SKIP_MAP[repo.full_name] = true; | ||
continue; | ||
} | ||
|
||
if (packageJSON.name.includes('test')) { | ||
console.log('Skip repo %s due to test package', repo.full_name); | ||
SKIP_MAP[packageJSON.name] = true; | ||
SKIP_MAP[repo.full_name] = true; | ||
continue; | ||
} | ||
|
||
const info = await getPackageInfo(packageJSON.name); | ||
|
||
if (!info) { | ||
console.log( | ||
'Skip repo %s due to not found package %s', | ||
repo.full_name, | ||
packageJSON.name | ||
); | ||
SKIP_MAP[packageJSON.name] = true; | ||
SKIP_MAP[repo.full_name] = true; | ||
continue; | ||
} | ||
|
||
ORI_PACKAGE_JSON.dependencies[packageJSON.name] = | ||
'^' + packageJSON.version; | ||
} catch (err) { | ||
console.error('Skip repo %s due to error: ', repo.full_name, err); | ||
} | ||
} | ||
|
||
//remove unnecessary info | ||
const remove = [ | ||
'funding', | ||
'contributors', | ||
'authors', | ||
'donors', | ||
'maintainers', | ||
'sponsors', | ||
'bugs', | ||
'homepage', | ||
'repository', | ||
]; | ||
|
||
for (const key of remove) { | ||
if (ORI_PACKAGE_JSON[key]) { | ||
delete ORI_PACKAGE_JSON[key]; | ||
} | ||
} | ||
|
||
// dont run any scripts | ||
ORI_PACKAGE_JSON.scripts = {}; | ||
|
||
//write back | ||
fs.writeFileSync( | ||
path.join(PARENT_FOLDER, 'package.json'), | ||
JSON.stringify(ORI_PACKAGE_JSON, null, 2) | ||
); | ||
|
||
// find readme file | ||
const readmefile = fs | ||
.readdirSync(PARENT_FOLDER) | ||
.filter((file) => /^readme(\.md)?$/i.test(file)); | ||
|
||
if (readmefile.length > 1) { | ||
// remove the default | ||
fs.unlinkSync(path.join(PARENT_FOLDER, 'README.md')); | ||
} | ||
|
||
const packageRepo = new URL(url).pathname.replace(/^\/|\/$/g, ''); | ||
|
||
for (const file of readmefile) { | ||
const readmePath = path.join(PARENT_FOLDER, file); | ||
|
||
if (fs.existsSync(readmePath)) { | ||
let content = fs.readFileSync(readmePath, { encoding: 'utf-8' }); | ||
content = content.replaceAll(url, REPO_URL); | ||
content = content.replaceAll(packageName, PACKAGE_NAME); | ||
content = content.replaceAll(packageRepo, CURRENT_REPO); | ||
fs.writeFileSync(readmePath, content); | ||
} | ||
} | ||
|
||
console.log('Done!'); | ||
|
||
return true; | ||
} catch (err) { | ||
console.log('Skip package %s due to error: ', packageName, err); | ||
continue; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
async function main() { | ||
// latested packages from NPM | ||
const res = await axios.get(`https://registry.npmjs.org/-/v1/search`, { | ||
params: { | ||
text: 'not:insecure,unstable', | ||
size: '200', | ||
}, | ||
responseType: 'json', | ||
}); | ||
|
||
const packages = res.data.objects; | ||
|
||
shuffle(packages); | ||
console.log('Found packages', packages.length); | ||
|
||
for (const package of packages) { | ||
const packageName = package.package.name; | ||
const keywords = package.package.keywords || []; | ||
|
||
console.log('Try to get keywords for package %s', packageName); | ||
|
||
if (!keywords || keywords.length === 0) { | ||
console.log( | ||
'No keywords for package %s. So we choose this package', | ||
packageName | ||
); | ||
|
||
try { | ||
if (!(await chooseFromList([package]))) { | ||
continue; | ||
} | ||
} catch (err) { | ||
console.log('Skip package %s due to error: ', packageName, err); | ||
continue; | ||
} | ||
} | ||
|
||
shuffle(keywords); | ||
|
||
console.log('Keywords for package %s: ', packageName, keywords); | ||
|
||
for (const keyword of keywords) { | ||
const list = await getListPackageByKeywords(keyword); | ||
if (list.length === 0) { | ||
continue; | ||
} | ||
|
||
shuffle(list); | ||
|
||
if (await chooseFromList(list)) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
|
||
main(); |
Oops, something went wrong.