-
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.
feat(project-files): project files tool (#39)
- Loading branch information
Showing
15 changed files
with
1,116 additions
and
452 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 @@ | ||
strict-peer-dependencies=false |
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
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
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,6 @@ | ||
{ | ||
"extends": [ | ||
"@trigen/eslint-config/esm", | ||
"@trigen/eslint-config/jest" | ||
] | ||
} |
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,41 @@ | ||
# GitHub | ||
.github/ISSUE_TEMPLATE/config.yml | ||
.github/ISSUE_TEMPLATE/bug-report.yml | ||
.github/ISSUE_TEMPLATE/feature-request.yml | ||
.github/ISSUE_TEMPLATE/question.yml | ||
# GitHub Actions | ||
.github/workflows/ci.yml | ||
.github/workflows/commit.yml | ||
.github/workflows/checks.yml | ||
.github/workflows/release.yml | ||
.github/workflows/update-snapshots.yml | ||
.github/workflows/website.yml | ||
# CI | ||
.github/renovate.json | ||
.clean-publish | ||
.eslintrc.json | ||
test/.eslintrc.json | ||
.size-limit.json | ||
.npmpackagejsonlintrc.json | ||
jest.config.json | ||
# TypeScript | ||
test/tsconfig.json | ||
tsconfig.json | ||
# Build | ||
env.d.ts | ||
.browserslistrc | ||
rollup.config.js | ||
# Monorepo | ||
lerna.json | ||
pnpm-workspace.yaml | ||
# Git Flow | ||
.gitignore | ||
.nano-staged.json | ||
.simple-git-hooks.json | ||
.commitlintrc.json | ||
.czrc | ||
# Basics | ||
.npmrc | ||
.editorconfig | ||
LICENSE | ||
README.md |
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,38 @@ | ||
{ | ||
"name": "@trigen/project-files", | ||
"type": "module", | ||
"version": "8.0.0-alpha.9", | ||
"description": "CLI tool for download snippets files.", | ||
"author": "dangreen", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/TrigenSoftware/scripts.git", | ||
"directory": "packages/project-files" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/TrigenSoftware/scripts/issues" | ||
}, | ||
"keywords": [ | ||
"files", | ||
"snippets" | ||
], | ||
"engines": { | ||
"node": ">=14" | ||
}, | ||
"bin": "./src/bin.js", | ||
"exports": "./src/index.js", | ||
"publishConfig": { | ||
"access": "public", | ||
"directory": "package" | ||
}, | ||
"scripts": { | ||
"prepublishOnly": "del ./package && clean-publish", | ||
"postpublish": "del ./package" | ||
}, | ||
"dependencies": { | ||
"@octokit/rest": "^19.0.4", | ||
"inquirer": "^8.2.0" | ||
}, | ||
"readme": "" | ||
} |
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,7 @@ | ||
TrigenSoftware/scripts | ||
TrigenSoftware/simple-github-release | ||
TrigenSoftware/Argue | ||
canvg/canvg | ||
reactchartjs/react-chartjs-2 | ||
chartist-js/chartist | ||
TrigenSoftware/flexis-srcset |
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,129 @@ | ||
import { dirname, join } from 'path' | ||
import { Octokit } from '@octokit/rest' | ||
import { writeFile } from './fs.js' | ||
|
||
/** | ||
* @typedef {import('./parse.js').SourceItem} Repo | ||
*/ | ||
|
||
const OK = 200 | ||
const { GITHUB_TOKEN } = process.env | ||
const client = new Octokit({ | ||
auth: GITHUB_TOKEN ? `token ${GITHUB_TOKEN}` : '' | ||
}) | ||
|
||
/** | ||
* @typedef RepoFile | ||
* @property {string} path - File path. | ||
* @property {string} name - File name. | ||
* @property {string} sha - The SHA of the file. | ||
* @property {string} download_url - Download url. | ||
* @property {string} html_url - Html url. | ||
*/ | ||
|
||
/** | ||
* Get files list from repository. | ||
* @param {Repo} repo | ||
* @param {string} path | ||
* @returns {Promise<RepoFile[]>} File from the repository. | ||
*/ | ||
export async function getDirectory(repo, path) { | ||
let status | ||
let data | ||
|
||
try { | ||
({ | ||
status, | ||
data | ||
} = await client.request('GET /repos/{owner}/{repo}/contents/{path}', { | ||
owner: repo.owner, | ||
repo: repo.repo, | ||
path: path === '.' ? '' : path | ||
})) | ||
} catch (err) { | ||
return [] | ||
} | ||
|
||
if (status !== OK || !data) { | ||
return [] | ||
} | ||
|
||
return data | ||
} | ||
|
||
/** | ||
* Get files filtered by sha from repository. | ||
* @param {Repo[]} repos | ||
* @param {string[]} paths | ||
* @returns {Promise<Map<string, RepoFile[]>>} Files from the repository. | ||
*/ | ||
export async function getFiles(repos, paths) { | ||
const dirs = new Set() | ||
const tasks = [] | ||
const shas = [] | ||
const filesMap = new Map() | ||
let task | ||
let dir | ||
let file | ||
let sha | ||
let files | ||
|
||
paths.forEach((path) => { | ||
dirs.add(dirname(path)) | ||
}) | ||
|
||
repos.forEach((repo) => { | ||
dirs.forEach((dir) => { | ||
tasks.push(getDirectory(repo, dir)) | ||
}) | ||
}) | ||
|
||
for (task of tasks) { | ||
dir = await task | ||
|
||
for (file of dir) { | ||
if (paths.includes(file.path)) { | ||
sha = file.sha + file.path | ||
|
||
if (!shas.includes(sha)) { | ||
shas.push(sha) | ||
|
||
files = filesMap.get(file.path) | ||
|
||
if (!files) { | ||
files = [] | ||
filesMap.set(file.path, files) | ||
} | ||
|
||
files.push(file) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return filesMap | ||
} | ||
|
||
/** | ||
* Download file. | ||
* @param {RepoFile} file | ||
* @param {boolean | string} write | ||
* @returns {Promise<string>} File contents. | ||
*/ | ||
export async function downloadFile(file, write) { | ||
const { data } = await client.request(`GET ${file.download_url}`) | ||
|
||
if (write) { | ||
await writeFile( | ||
join( | ||
write === true | ||
? '.' | ||
: write, | ||
file.path | ||
), | ||
data | ||
) | ||
} | ||
|
||
return data | ||
} |
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,39 @@ | ||
#!/usr/bin/env node | ||
import { fileURLToPath } from 'url' | ||
import { dirname, join } from 'path' | ||
import { | ||
readFile, | ||
writeFile, | ||
parseFilesList, | ||
parseSourcesList, | ||
getFiles, | ||
downloadFile, | ||
askFiles, | ||
askSource | ||
} from './index.js' | ||
|
||
const { PROJECT_FILES_DIR } = process.env | ||
const cwd = PROJECT_FILES_DIR ? join(process.cwd(), PROJECT_FILES_DIR) : process.cwd() | ||
const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), '..') | ||
const parseFilesListTask = parseFilesList(readFile(join(pkgRoot, 'files.txt'), 'utf8')) | ||
const parseSourcesListTask = parseSourcesList(readFile(join(pkgRoot, 'sources.txt'), 'utf8')) | ||
const [filesList, sourcesList] = await Promise.all([parseFilesListTask, parseSourcesListTask]) | ||
const selectedFiles = await askFiles(filesList) | ||
const files = await getFiles(sourcesList, selectedFiles) | ||
let file | ||
let fileSources | ||
const tasks = [] | ||
|
||
for (file of selectedFiles) { | ||
fileSources = files.get(file) | ||
|
||
if (!fileSources) { | ||
tasks.push(writeFile(join(cwd, file), '')) | ||
} else if (fileSources.length === 1) { | ||
tasks.push(downloadFile(fileSources[0], cwd)) | ||
} else { | ||
tasks.push(downloadFile(await askSource(fileSources), cwd)) | ||
} | ||
} | ||
|
||
await Promise.all(tasks) |
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,26 @@ | ||
import { dirname } from 'path' | ||
import { promises } from 'fs' | ||
|
||
const { readFile, writeFile: wf, mkdir } = promises | ||
|
||
export { readFile } | ||
|
||
/** | ||
* Write file. | ||
* @param {string} path | ||
* @param {string} contents | ||
* @returns {Promise<void>} | ||
*/ | ||
export async function writeFile(path, contents) { | ||
const dir = dirname(path) | ||
|
||
try { | ||
await mkdir(dir, { | ||
recursive: true | ||
}) | ||
} catch (err) { | ||
/* Ignore error */ | ||
} | ||
|
||
return wf(path, contents) | ||
} |
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,4 @@ | ||
export * from './parse.js' | ||
export * from './api.js' | ||
export * from './ui.js' | ||
export * from './fs.js' |
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,59 @@ | ||
/** | ||
* @typedef FileItem | ||
* @property {string} type - File type description | ||
* @property {string} path - File path | ||
*/ | ||
|
||
/** | ||
* Parse files list file. | ||
* @param {string | Promise<string>} contents | ||
* @returns {Promise<FileItem[]>} Parsed files info. | ||
*/ | ||
export async function parseFilesList(contents) { | ||
const text = await contents | ||
const files = [] | ||
let type | ||
|
||
text.split('\n').forEach((line) => { | ||
if (line[0] === '#') { | ||
type = line.slice(2) | ||
} else if (line) { | ||
files.push({ | ||
type, | ||
path: line | ||
}) | ||
} | ||
}) | ||
|
||
return files | ||
} | ||
|
||
/** | ||
* @typedef SourceItem | ||
* @property {string} owner - Source repository owner | ||
* @property {string} repo - Source repository name | ||
*/ | ||
|
||
/** | ||
* Parse sources list file. | ||
* @param {string | Promise<string>} contents | ||
* @returns {Promise<SourceItem[]>} Parsed sources info. | ||
*/ | ||
export async function parseSourcesList(contents) { | ||
const text = await contents | ||
const sources = [] | ||
let owner | ||
let repo | ||
|
||
text.split('\n').forEach((line) => { | ||
if (line) { | ||
[owner, repo] = line.split('/') | ||
sources.push({ | ||
owner, | ||
repo | ||
}) | ||
} | ||
}) | ||
|
||
return sources | ||
} |
Oops, something went wrong.