Skip to content
This repository has been archived by the owner on Feb 5, 2023. It is now read-only.

Commit

Permalink
feat: Rename to publish-flat
Browse files Browse the repository at this point in the history
  • Loading branch information
ffflorian committed Jun 12, 2019
1 parent 1aca6be commit 30d6dba
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 76 deletions.
9 changes: 8 additions & 1 deletion .github/main.workflow
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,16 @@ action "Don't publish dependency updates" {
args = "^(?!chore\\(deps)"
}

action "Publish project" {
action "Flatten project" {
uses = "ffflorian/actions/git-node@v1.0.0"
needs = "Don't publish dependency updates"
runs = "yarn"
args = "flatten"
}

action "Publish project" {
uses = "ffflorian/actions/git-node@v1.0.0"
needs = "Flatten project"
env = {
GIT_AUTHOR_NAME = "ffflobot"
GIT_AUTHOR_EMAIL = "ffflobot@users.noreply.github.com"
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
node_modules/
dist/
*.log
spec/.temp
flattened
7 changes: 6 additions & 1 deletion .releaserc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/npm",
{
"pkgRoot": "flattened"
}
],
[
"@semantic-release/github",
{
Expand Down
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## [1.0.1](https://github.com/ffflorian/publisher/compare/v1.0.0...v1.0.1) (2019-06-12)
## [1.0.1](https://github.com/ffflorian/publish-flat/compare/v1.0.0...v1.0.1) (2019-06-12)

### Bug Fixes

- Package name ([be6de45](https://github.com/ffflorian/publisher/commit/be6de45))
- Package name ([be6de45](https://github.com/ffflorian/publish-flat/commit/be6de45))

# 1.0.0 (2019-06-12)

### Features

- Add base files ([9e613f2](https://github.com/ffflorian/publisher/commit/9e613f2))
- Add base files ([9e613f2](https://github.com/ffflorian/publish-flat/commit/9e613f2))
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# publisher [![Build Status](https://action-badges.now.sh/ffflorian/publisher)](https://github.com/ffflorian/publisher/actions/) [![npm version](https://img.shields.io/npm/v/@ffflorian/publisher.svg?style=flat)](https://www.npmjs.com/package/@ffflorian/publisher) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=ffflorian/publisher)](https://dependabot.com)
# publish-flat [![Build Status](https://action-badges.now.sh/ffflorian/publish-flat)](https://github.com/ffflorian/publish-flat/actions/) [![npm version](https://img.shields.io/npm/v/publish-flat.svg?style=flat)](https://www.npmjs.com/package/publish-flat) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=ffflorian/publish-flat)](https://dependabot.com)

Publish your project without the dist directory.
Publish your project flattened.

## Description

Expand All @@ -13,22 +13,23 @@ Here is what it does:
## Installation

```
yarn add @ffflorian/publisher
yarn add publish-flat
```

### CLI Usage

```
Usage: cli.ts [options] <dir>
Usage: publish-flat [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
-V, --version output the version number
-c, --yarn Use yarn for publishing (default: false)
-f, --flatten <dir> Which directory to flatten (default: "dist")
-o, --output <dir> Set the output directory (default: temp directory)
-n, --no-publish Do not publish (default: false)
-h, --help output usage information
```

### API Usage
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"author": "Florian Keller <github@floriankeller.de>",
"bin": {
"publisher": "dist/cli.js"
"publish-flat": "dist/cli.js"
},
"dependencies": {
"@expo/spawn-async": "1.4.2",
"commander": "2.20.0",
"commander-remaining-args": "1.2.0",
"fs-extra": "8.0.1",
Expand All @@ -16,6 +17,7 @@
"@ffflorian/tslint-config": "0.2.2",
"@semantic-release/changelog": "3.0.2",
"@semantic-release/git": "7.0.8",
"@semantic-release/npm": "5.1.7",
"@types/fs-extra": "7.0.0",
"@types/jasmine": "3.3.13",
"@types/node": "~12",
Expand Down Expand Up @@ -56,9 +58,9 @@
]
},
"main": "dist/index.js",
"name": "@ffflorian/publisher",
"name": "publish-flat",
"prettier": "@ffflorian/prettier-config",
"repository": "https://github.com/ffflorian/publisher.git",
"repository": "https://github.com/ffflorian/publish-flat.git",
"scripts": {
"build": "tsc",
"clean": "rimraf dist",
Expand All @@ -69,8 +71,8 @@
"lint": "yarn lint:ts && yarn lint:other",
"lint:other": "yarn prettier --list-different",
"lint:ts": "tslint --project tsconfig.json",
"flatten": "yarn start -n -o flattened",
"prettier": "prettier \"*.{json,md}\"",
"publish": "node dist/cli.js",
"release": "semantic-release",
"start": "ts-node src/cli.ts",
"test": "exit 0"
Expand Down
84 changes: 40 additions & 44 deletions src/Publisher.ts → src/FlatPublisher.ts
Original file line number Diff line number Diff line change
@@ -1,110 +1,104 @@
import {exec} from 'child_process';
import * as os from 'os';
import * as path from 'path';
import {promisify} from 'util';

import spawnAsync = require('@expo/spawn-async');
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;
/** Which directory to flatten (e.g. to move dist/main.js => main.js, use `dist`) */
dirToFlatten: string;
outputDir?: 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}>;
type FilesInFlattenedDir = Array<{fileName: string; replacedFilename: string}>;

interface Categorized {
filesInOmittedDir: FilesInOmittedDir;
filesInFlattenedDir: FilesInFlattenedDir;
normalFiles: string[];
}

export class Publisher {
export class FlatPublisher {
private readonly options: PublishOptions;
private readonly logger: logdown.Logger;
private readonly packageDir: string;
private readonly dirToOmit: string;
private readonly dirToOmitRegex: RegExp;
private readonly dirToFlatten: string;
private readonly dirToFlattenRegex: RegExp;

constructor(options: PublishOptions) {
this.options = options;
this.logger = logdown('publisher', {
this.logger = logdown('flat-publish', {
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}[\\/]`);
this.dirToFlatten = this.cleanDirName(this.options.dirToFlatten);
this.dirToFlattenRegex = new RegExp(`${this.dirToFlatten}[\\/]`);
}

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`);
throw new Error(`Invalid flatten dir "${dirName}" specified`);
}
return cleanName;
}

private createTempDir(): Promise<string> {
return fs.mkdtemp(path.join(os.tmpdir(), 'publisher-'));
return fs.mkdtemp(path.join(os.tmpdir(), 'flat-publish-'));
}

private async cleanPackageJson(filePath: string, filesInOmittedDir: FilesInOmittedDir): Promise<void> {
private async cleanPackageJson(filePath: string, filesInFlattenedDir: FilesInFlattenedDir): 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);
packageJson.files = packageJson.files.map((fileName: string) => fileName.replace(this.dirToFlattenRegex, ''));
packageJson.files = packageJson.files.concat(filesInFlattenedDir.map(({replacedFilename}) => replacedFilename));
packageJson.files = packageJson.files.filter((fileName: string) => fileName !== this.dirToFlatten);

if (typeof packageJson.bin === 'string') {
packageJson.bin = packageJson.bin.replace(this.dirToOmitRegex, '');
packageJson.bin = packageJson.bin.replace(this.dirToFlattenRegex, '');
} else if (typeof packageJson.bin === 'object') {
for (const binName of Object.keys(packageJson.bin)) {
packageJson.bin[binName] = packageJson.bin[binName].replace(this.dirToOmitRegex, '');
packageJson.bin[binName] = packageJson.bin[binName].replace(this.dirToFlattenRegex, '');
}
}

if (packageJson.main) {
packageJson.main = packageJson.main.replace(this.dirToOmitRegex, '');
packageJson.main = packageJson.main.replace(this.dirToFlattenRegex, '');
}

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}" ...`);
this.logger.info(`Publishing "${this.packageDir}" ...`);

const executor = this.options.useYarn ? 'yarn' : 'npm';
const command = `${executor} publish "${tempDir}" ${this.options.publishArguments}`.trim();
const args = ['publish', `"${tempDir}"`].concat(this.options.publishArguments || []);

this.logger.info(`Running "${command}" ...`);
this.logger.info(`Running "${executor} ${args.join(' ')}" ...`);

const {stderr, stdout} = await execAsync(command);
const {stdout} = await spawnAsync(executor, args, {shell: true, windowsHide: true});

if (stderr) {
throw new Error(stderr);
if (stdout) {
this.logger.info(stdout);
}

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;
Expand All @@ -114,34 +108,36 @@ export class Publisher {
throw new Error(`Files don't include a "package.json" file`);
}

const {normalFiles, filesInOmittedDir} = files.reduce(
const {normalFiles, filesInFlattenedDir: filesInFlattenedDir} = files.reduce(
(result: Categorized, fileName: string) => {
if (this.dirToOmitRegex.test(fileName)) {
const replacedFilename = fileName.replace(this.dirToOmitRegex, '');
result.filesInOmittedDir.push({fileName, replacedFilename});
if (this.dirToFlattenRegex.test(fileName)) {
const replacedFilename = fileName.replace(this.dirToFlattenRegex, '');
result.filesInFlattenedDir.push({fileName, replacedFilename});
} else {
result.normalFiles.push(fileName);
}
return result;
},
{normalFiles: [], filesInOmittedDir: []}
{normalFiles: [], filesInFlattenedDir: []}
);

const tempDir = await this.createTempDir();
const outputDir = this.options.outputDir ? path.resolve(this.options.outputDir) : await this.createTempDir();

for (const file of normalFiles) {
await fs.copy(path.join(this.packageDir, file), path.join(tempDir, file), {overwrite: true, recursive: true});
await fs.copy(path.join(this.packageDir, file), path.join(outputDir, file), {overwrite: true, recursive: true});
}

for (const {fileName, replacedFilename} of filesInOmittedDir) {
await fs.copy(path.join(this.packageDir, fileName), path.join(tempDir, replacedFilename), {
for (const {fileName, replacedFilename} of filesInFlattenedDir) {
await fs.copy(path.join(this.packageDir, fileName), path.join(outputDir, replacedFilename), {
overwrite: true,
recursive: true,
});
}

await this.cleanPackageJson(path.join(tempDir, 'package.json'), filesInOmittedDir);
this.logger.info(`Flattened ${filesInFlattenedDir.length} files`);

await this.cleanPackageJson(path.join(outputDir, 'package.json'), filesInFlattenedDir);

return tempDir;
return outputDir;
}
}
20 changes: 11 additions & 9 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node

import * as program from 'commander';
import {Publisher} from './Publisher';
import {FlatPublisher} from './FlatPublisher';

const getRemainingArgs = require('commander-remaining-args');

Expand All @@ -12,28 +12,30 @@ program
.version(version)
.description(description)
.option('-c, --yarn', 'Use yarn for publishing (default: false)')
.option('-o, --omit <dir>', 'Which directory to omit', 'dist')
.option('-f, --flatten <dir>', 'Which directory to flatten', 'dist')
.option('-o, --output <dir>', 'Set the output directory (default: temp directory)')
.option('-n, --no-publish', 'Do not publish (default: false)')
.arguments('[dir]')
.allowUnknownOption()
.parse(process.argv);

const remainingArgs = getRemainingArgs(program);

const publisher = new Publisher({
dirToOmit: program.omit,
const flatPublisher = new FlatPublisher({
dirToFlatten: program.flatten,
outputDir: program.output,
packageDir: program.dir || '.',
publishArguments: remainingArgs,
useYarn: program.yarn || false,
});

publisher
flatPublisher
.build()
.then(tempDir => {
if (program.publish && tempDir) {
return publisher.publish(tempDir);
.then(outputDir => {
if (program.publish && outputDir) {
return flatPublisher.publish(outputDir);
}
console.log(tempDir);
console.log(outputDir);
return;
})
.catch(error => {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './Publisher';
export * from './FlatPublisher';
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"sourceMap": true,
"strict": true,
"strictFunctionTypes": true,
"target": "es5"
"target": "es6"
},
"exclude": ["dist", "node_modules", "spec"]
}
Loading

0 comments on commit 30d6dba

Please sign in to comment.