This repository has been archived by the owner on Feb 5, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2
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
Showing
17 changed files
with
5,967 additions
and
21 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,9 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
indent_size = 2 | ||
indent_style = space | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
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 @@ | ||
ko_fi: ffflorian |
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,61 @@ | ||
workflow "Build, lint and test" { | ||
on = "push" | ||
resolves = [ | ||
"Build project", | ||
"Lint project", | ||
"Publish project" | ||
] | ||
} | ||
|
||
action "Don't skip CI" { | ||
uses = "ffflorian/actions/skip-ci-check@v1.0.0" | ||
} | ||
|
||
action "Install dependencies" { | ||
uses = "ffflorian/actions/git-node@v1.0.0" | ||
needs = "Don't skip CI" | ||
runs = "yarn" | ||
} | ||
|
||
action "Lint project" { | ||
uses = "ffflorian/actions/git-node@v1.0.0" | ||
needs = "Install dependencies" | ||
runs = "yarn" | ||
args = "lint" | ||
} | ||
|
||
action "Build project" { | ||
uses = "ffflorian/actions/git-node@v1.0.0" | ||
needs = "Install dependencies" | ||
runs = "yarn" | ||
args = "dist" | ||
} | ||
|
||
action "Check for master branch" { | ||
uses = "actions/bin/filter@master" | ||
needs = [ | ||
"Build project", | ||
"Lint project", | ||
] | ||
args = "branch master" | ||
} | ||
|
||
action "Don't publish dependency updates" { | ||
uses = "ffflorian/actions/last_commit@v1.0.0" | ||
needs = "Check for master branch" | ||
args = "^(?!chore\\(deps)" | ||
} | ||
|
||
action "Publish project" { | ||
uses = "ffflorian/actions/git-node@v1.0.0" | ||
needs = "Don't publish dependency updates" | ||
env = { | ||
GIT_AUTHOR_NAME = "ffflobot" | ||
GIT_AUTHOR_EMAIL = "ffflobot@users.noreply.github.com" | ||
GIT_COMMITTER_NAME = "ffflobot" | ||
GIT_COMMITTER_EMAIL = "ffflobot@users.noreply.github.com" | ||
} | ||
runs = "yarn" | ||
args = "release" | ||
secrets = ["GH_TOKEN", "NPM_TOKEN"] | ||
} |
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 @@ | ||
node_modules/ | ||
dist/ | ||
*.log | ||
spec/.temp |
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,2 @@ | ||
registry=https://registry.npmjs.org/ | ||
save-exact=true |
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,3 @@ | ||
dist | ||
node_modules | ||
package.json |
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,22 @@ | ||
{ | ||
"plugins": [ | ||
"@semantic-release/commit-analyzer", | ||
"@semantic-release/release-notes-generator", | ||
"@semantic-release/changelog", | ||
"@semantic-release/npm", | ||
[ | ||
"@semantic-release/github", | ||
{ | ||
"releasedLabels": false, | ||
"successComment": false | ||
} | ||
], | ||
[ | ||
"@semantic-release/git", | ||
{ | ||
"assets": ["package.json", "CHANGELOG.md"], | ||
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" | ||
} | ||
] | ||
] | ||
} |
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,36 @@ | ||
# publisher [](https://github.com/ffflorian/publisher/actions/) [](https://www.npmjs.com/package/@ffflorian/publisher) [](https://dependabot.com) | ||
|
||
Publish your project without the dist directory. | ||
|
||
## Description | ||
|
||
Here is what it does: | ||
|
||
1. Re-build your project | ||
2. Copy your dist files into a temporary directory | ||
3. Publish your project from the temporary directory | ||
|
||
## Installation | ||
|
||
``` | ||
yarn add @ffflorian/publisher | ||
``` | ||
|
||
### CLI Usage | ||
|
||
``` | ||
Usage: cli.ts [options] <dir> | ||
Publish your project without the dist directory | ||
Options: | ||
-V, --version output the version number | ||
-c, --yarn Use yarn for publishing (default: false) | ||
-o, --omit <dir> Which directory to omit (default: "dist") | ||
-n, --no-publish Do not publish (default: false) | ||
-h, --help output usage information | ||
``` | ||
|
||
### API Usage | ||
|
||
See [`cli.ts`](./src/cli.ts). |
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,79 @@ | ||
{ | ||
"author": "Florian Keller <github@floriankeller.de>", | ||
"bin": { | ||
"publisher": "dist/cli.js" | ||
}, | ||
"dependencies": { | ||
"commander": "2.20.0", | ||
"commander-remaining-args": "1.2.0", | ||
"fs-extra": "8.0.1", | ||
"logdown": "3.2.8", | ||
"npm-packlist": "1.4.1" | ||
}, | ||
"description": "Publish your project without the dist directory", | ||
"devDependencies": { | ||
"@ffflorian/prettier-config": "0.0.5", | ||
"@ffflorian/tslint-config": "0.2.2", | ||
"@semantic-release/changelog": "3.0.2", | ||
"@semantic-release/git": "7.0.8", | ||
"@types/fs-extra": "7.0.0", | ||
"@types/jasmine": "3.3.13", | ||
"@types/node": "~12", | ||
"@types/npm-packlist": "1.1.1", | ||
"husky": "2.4.1", | ||
"jasmine": "3.4.0", | ||
"lint-staged": "8.2.0", | ||
"prettier": "1.18.2", | ||
"rimraf": "2.6.3", | ||
"semantic-release": "15.13.12", | ||
"ts-node": "8.2.0", | ||
"tslint": "5.17.0", | ||
"tslint-config-prettier": "1.18.0", | ||
"tslint-plugin-prettier": "2.0.1", | ||
"typescript": "3.5.1" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"keywords": [ | ||
"cli", | ||
"typescript" | ||
], | ||
"license": "MIT", | ||
"lint-staged": { | ||
"*.{json,md}": [ | ||
"prettier --write", | ||
"git add" | ||
], | ||
"*.ts": [ | ||
"tslint --project tsconfig.json --fix", | ||
"git add" | ||
] | ||
}, | ||
"main": "dist/index.js", | ||
"name": "publisher", | ||
"prettier": "@ffflorian/prettier-config", | ||
"repository": "https://github.com/ffflorian/publisher.git", | ||
"scripts": { | ||
"build": "tsc", | ||
"clean": "rimraf dist", | ||
"dist": "yarn clean && yarn build", | ||
"fix": "yarn fix:other && yarn fix:ts", | ||
"fix:other": "yarn prettier --write", | ||
"fix:ts": "yarn lint:ts --fix", | ||
"lint": "yarn lint:ts && yarn lint:other", | ||
"lint:other": "yarn prettier --list-different", | ||
"lint:ts": "tslint --project tsconfig.json", | ||
"prettier": "prettier \"*.{json,md}\"", | ||
"publish": "node dist/cli.js", | ||
"release": "semantic-release", | ||
"start": "ts-node src/cli.ts", | ||
"test": "exit 0" | ||
}, | ||
"version": "0.0.1" | ||
} |
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,147 @@ | ||
import {exec} from 'child_process'; | ||
import * as os from 'os'; | ||
import * as path from 'path'; | ||
import {promisify} from 'util'; | ||
|
||
import * as fs from 'fs-extra'; | ||
import * as logdown from 'logdown'; | ||
import * as packlist from 'npm-packlist'; | ||
|
||
const execAsync = promisify(exec); | ||
|
||
export interface PublishOptions { | ||
/** Which directory to omit (e.g. to move dist/main.js => main.js, use `dist`) */ | ||
dirToOmit: string; | ||
packageDir: string; | ||
/** Arguments to forward to npm or yarn */ | ||
publishArguments?: string[]; | ||
/** Use yarn for publishing */ | ||
useYarn?: boolean; | ||
} | ||
|
||
type FilesInOmittedDir = Array<{fileName: string; replacedFilename: string}>; | ||
|
||
interface Categorized { | ||
filesInOmittedDir: FilesInOmittedDir; | ||
normalFiles: string[]; | ||
} | ||
|
||
export class Publisher { | ||
private readonly options: PublishOptions; | ||
private readonly logger: logdown.Logger; | ||
private readonly packageDir: string; | ||
private readonly dirToOmit: string; | ||
private readonly dirToOmitRegex: RegExp; | ||
|
||
constructor(options: PublishOptions) { | ||
this.options = options; | ||
this.logger = logdown('publisher', { | ||
logger: console, | ||
markdown: false, | ||
}); | ||
this.logger.state.isEnabled = true; | ||
|
||
this.packageDir = path.resolve(this.options.packageDir); | ||
this.dirToOmit = this.cleanDirName(this.options.dirToOmit); | ||
this.dirToOmitRegex = new RegExp(`${this.dirToOmit}[\\/]`); | ||
} | ||
|
||
private cleanDirName(dirName: string): string { | ||
const separatorRegex = new RegExp('[\\/]*([^\\/]+)[\\/]*', 'g'); | ||
const cleanName = dirName.trim().replace(separatorRegex, '$1'); | ||
if (!cleanName) { | ||
throw new Error(`Invalid omit dir "${dirName}" specified`); | ||
} | ||
return cleanName; | ||
} | ||
|
||
private createTempDir(): Promise<string> { | ||
return fs.mkdtemp(path.join(os.tmpdir(), 'publisher-')); | ||
} | ||
|
||
private async cleanPackageJson(filePath: string, filesInOmittedDir: FilesInOmittedDir): Promise<void> { | ||
const packageJson = await fs.readJSON(filePath); | ||
packageJson.files = packageJson.files.map((fileName: string) => fileName.replace(this.dirToOmitRegex, '')); | ||
packageJson.files = packageJson.files.concat(filesInOmittedDir.map(({replacedFilename}) => replacedFilename)); | ||
packageJson.files = packageJson.files.filter((fileName: string) => fileName !== this.dirToOmit); | ||
|
||
if (typeof packageJson.bin === 'string') { | ||
packageJson.bin = packageJson.bin.replace(this.dirToOmitRegex, ''); | ||
} else if (typeof packageJson.bin === 'object') { | ||
for (const binName of Object.keys(packageJson.bin)) { | ||
packageJson.bin[binName] = packageJson.bin[binName].replace(this.dirToOmitRegex, ''); | ||
} | ||
} | ||
|
||
if (packageJson.main) { | ||
packageJson.main = packageJson.main.replace(this.dirToOmitRegex, ''); | ||
} | ||
|
||
const packageJsonString = `${JSON.stringify(packageJson, null, 2)}\n`; | ||
await fs.writeFile(filePath, packageJsonString, 'utf-8'); | ||
} | ||
|
||
async publish(tempDir: string): Promise<void> { | ||
this.logger.info(`Publishing package in "${this.packageDir}" ...`); | ||
|
||
const executor = this.options.useYarn ? 'yarn' : 'npm'; | ||
const command = `${executor} publish "${tempDir}" ${this.options.publishArguments}`.trim(); | ||
|
||
this.logger.info(`Running "${command}" ...`); | ||
|
||
const {stderr, stdout} = await execAsync(command); | ||
|
||
if (stderr) { | ||
throw new Error(stderr); | ||
} | ||
|
||
this.logger.info(stdout); | ||
|
||
await fs.remove(tempDir); | ||
} | ||
|
||
async build(): Promise<string | void> { | ||
const files = await packlist({path: this.packageDir}); | ||
|
||
this.logger.info('Got files', files); | ||
|
||
if (!files.length) { | ||
this.logger.info('No files to publish'); | ||
return; | ||
} | ||
|
||
if (!files.includes('package.json')) { | ||
throw new Error(`Files don't include a "package.json" file`); | ||
} | ||
|
||
const {normalFiles, filesInOmittedDir} = files.reduce( | ||
(result: Categorized, fileName: string) => { | ||
if (this.dirToOmitRegex.test(fileName)) { | ||
const replacedFilename = fileName.replace(this.dirToOmitRegex, ''); | ||
result.filesInOmittedDir.push({fileName, replacedFilename}); | ||
} else { | ||
result.normalFiles.push(fileName); | ||
} | ||
return result; | ||
}, | ||
{normalFiles: [], filesInOmittedDir: []} | ||
); | ||
|
||
const tempDir = await this.createTempDir(); | ||
|
||
for (const file of normalFiles) { | ||
await fs.copy(path.join(this.packageDir, file), path.join(tempDir, file), {overwrite: true, recursive: true}); | ||
} | ||
|
||
for (const {fileName, replacedFilename} of filesInOmittedDir) { | ||
await fs.copy(path.join(this.packageDir, fileName), path.join(tempDir, replacedFilename), { | ||
overwrite: true, | ||
recursive: true, | ||
}); | ||
} | ||
|
||
await this.cleanPackageJson(path.join(tempDir, 'package.json'), filesInOmittedDir); | ||
|
||
return tempDir; | ||
} | ||
} |
Oops, something went wrong.