ignore-sync
Version:
a CLI tool to build and sync *ignore files across files and repositories
104 lines (96 loc) • 3.28 kB
JavaScript
import path from 'node:path'
import * as R from 'ramda'
import { COMMENT_HEADER_ALERT } from './constants.js'
import decodeIgnoreSyncFile from './decodeIgnoreSyncFile.js'
import isIgnoreSyncFile from './isIgnoreSyncFile.js'
import formatRelativeIgnoreFile from './utils/formatRelativeIgnoreFile.js'
import { readFile } from './utils/fsHelper.js'
import { getGitHubContentFile } from './utils/github.js'
import highlightComments from './utils/highlightComments.js'
import joinLinesWithEOF from './utils/joinLinesWithEOF.js'
import { dynamicComposeP, promiseMap } from './utils/ramdaHelper.js'
const githubSourceRegex = /^([\w.-]+)\/([\w.-]+)(?:#(.+))?$/u
const prependAlert = R.concat([highlightComments(COMMENT_HEADER_ALERT), ''])
const sourceIs = (...args) => R.compose(...args, R.prop('source'))
const inlineSourceFetcher = R.compose(joinLinesWithEOF, R.prop('data'))
const githubSourceFetcher = async (block) => {
const [, owner, repo, ref] = block.source.match(githubSourceRegex)
const files = await Promise.all(
block.data.map((relativeFilePath) => {
return getGitHubContentFile({ owner, repo, ref, path: relativeFilePath })
}),
)
return joinLinesWithEOF(files)
}
const localSourceFetcher = async (block, directory) => {
const files = await Promise.all(
block.data.map(async (relativeFilePath) => {
const fileContent = await readFile(path.join(directory, relativeFilePath))
return isIgnoreSyncFile(relativeFilePath)
? generateIgnoreFile(fileContent, directory, {
isRootIgnoreSyncFile: false,
})
: fileContent
}),
)
return joinLinesWithEOF(files)
}
const relativeSourceFetcher = async (block, directory) => {
const files = await Promise.all(
block.data.map(async (relativeFilePath) => {
const fileContent = await readFile(path.join(directory, relativeFilePath))
if (isIgnoreSyncFile(relativeFilePath)) {
const ignoreFileContent = await generateIgnoreFile(
fileContent,
directory,
{
isRootIgnoreSyncFile: false,
},
)
return formatRelativeIgnoreFile(
ignoreFileContent,
path.dirname(relativeFilePath),
)
} else {
return formatRelativeIgnoreFile(
fileContent,
path.dirname(relativeFilePath),
)
}
}),
)
return joinLinesWithEOF(files)
}
const generateIgnoreFile = (
ignoreSyncFile,
directory,
{ isRootIgnoreSyncFile = true } = {},
) => {
const fetchIgnorePatternsBySource = promiseMap(
R.cond([
[sourceIs(R.equals('inline')), inlineSourceFetcher],
[
sourceIs(R.equals('local')),
(block) => localSourceFetcher(block, directory),
],
[
sourceIs(R.equals('relative')),
(block) => relativeSourceFetcher(block, directory),
],
[sourceIs(R.test(githubSourceRegex)), githubSourceFetcher],
[
R.T,
(block) => {
throw new Error(`unknown source: ${block.source}`)
},
],
]),
)
return dynamicComposeP(
joinLinesWithEOF,
isRootIgnoreSyncFile ? prependAlert : R.identity,
fetchIgnorePatternsBySource,
decodeIgnoreSyncFile,
)(ignoreSyncFile)
}
export default generateIgnoreFile