Skip to content

Commit

Permalink
feat: support committing package.json at the project level
Browse files Browse the repository at this point in the history
for project like projen itself.
  • Loading branch information
Elad Ben-Israel committed May 12, 2020
1 parent fcc9fcc commit 3ff069c
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 78 deletions.
15 changes: 12 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Generated by projen. To modify, edit "projen.js" and run "projen"
/package.json
# synthesized by projen
/.npmignore
# Logs
logs
Expand Down Expand Up @@ -37,16 +37,25 @@ jspm_packages/
.yarn-integrity
# parcel-bundler cache (https://parceljs.org/)
.cache
# synthesized by projen
/LICENSE
# synthesized by projen
/.versionrc.json
/.versionrc.json
# synthesized by projen
/.eslintrc.json
# exclude jsii outputs
dist
tsconfig.json
.jsii
tsconfig.json
# exclude typescript compiler outputs
*.d.ts
*.js
!# synthesized by projen, but committed to git
!/package.json
!projen.js
!# always commit version file
!version.json
!# synthesized by projen, but committed to git
!/.github/workflows/release.yml
!# synthesized by projen, but committed to git
!/.github/workflows/build.yml
102 changes: 52 additions & 50 deletions lib/eslint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,59 +20,61 @@ export class Eslint extends Construct {
project.addTestCommands('yarn eslint');

new JsonFile(project, '.eslintrc.json', {
env: {
jest: true,
node: true,
},
plugins: [
'@typescript-eslint',
'import',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: '2018',
sourceType: 'module',
project: './tsconfig.json',
},
extends: [
'plugin:import/typescript',
],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
obj: {
env: {
jest: true,
node: true,
},
'import/resolver': {
node: {},
typescript: {
directory: './tsconfig.json',
},
plugins: [
'@typescript-eslint',
'import',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: '2018',
sourceType: 'module',
project: './tsconfig.json',
},
},
ignorePatterns: [ '*.js', '*.d.ts', 'node_modules/', '*.generated.ts' ],
rules: {
// Require use of the `import { foo } from 'bar';` form instead of `import foo = require('bar');`
'@typescript-eslint/no-require-imports': [ 'error' ],
'@typescript-eslint/indent': [ 'error', 2 ],

// Style
'quotes': [ 'error', 'single', { avoidEscape: true } ],
'comma-dangle': [ 'error', 'always-multiline' ], // ensures clean diffs, see https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8

// Require all imported dependencies are actually declared in package.json
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [ // Only allow importing devDependencies from:
'**/build-tools/**', // --> Build tools
'**/test/**', // --> Unit tests
],
optionalDependencies: false, // Disallow importing optional dependencies (those shouldn't be in use in the project)
peerDependencies: true, // Allow importing peer dependencies (that aren't also direct dependencies)
},
extends: [
'plugin:import/typescript',
],

// Require all imported libraries actually resolve (!!required for import/no-extraneous-dependencies to work!!)
'import/no-unresolved': [ 'error' ],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
node: {},
typescript: {
directory: './tsconfig.json',
},
},
},
ignorePatterns: [ '*.js', '*.d.ts', 'node_modules/', '*.generated.ts' ],
rules: {
// Require use of the `import { foo } from 'bar';` form instead of `import foo = require('bar');`
'@typescript-eslint/no-require-imports': [ 'error' ],
'@typescript-eslint/indent': [ 'error', 2 ],

// Style
'quotes': [ 'error', 'single', { avoidEscape: true } ],
'comma-dangle': [ 'error', 'always-multiline' ], // ensures clean diffs, see https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8

// Require all imported dependencies are actually declared in package.json
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [ // Only allow importing devDependencies from:
'**/build-tools/**', // --> Build tools
'**/test/**', // --> Unit tests
],
optionalDependencies: false, // Disallow importing optional dependencies (those shouldn't be in use in the project)
peerDependencies: true, // Allow importing peer dependencies (that aren't also direct dependencies)
},
],

// Require all imported libraries actually resolve (!!required for import/no-extraneous-dependencies to work!!)
'import/no-unresolved': [ 'error' ],
},
},
});

Expand Down
2 changes: 2 additions & 0 deletions lib/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ export abstract class FileBase extends Construct {
const committed = options.committed ?? false;
const pattern = `/${this.path}`;
if (committed) {
project.gitignore.comment('synthesized by projen, but committed to git');
project.gitignore.include(pattern);
} else {
project.gitignore.comment('synthesized by projen');
project.gitignore.exclude(pattern);
}
} else {
Expand Down
22 changes: 21 additions & 1 deletion lib/ignore-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,28 @@ export class IgnoreFile extends FileBase {
private readonly excludes = new Array<string>();
private readonly includes = new Array<string>();

private comments = new Array<string>();

constructor(project: Project, filePath: string) {
super(project, filePath, { editGitignore: filePath !== '.gitignore' });
}

/**
* appends a comment that will be included before the next exclude/include line
* @param comment
*/
public comment(comment: string) {
this.comments.push();
this.comments.push(`# ${comment}`);
}

public exclude(...patterns: string[]) {
this.flushComments(this.excludes);
this.excludes.push(...patterns);
}

public include(...patterns: string[]) {
this.flushComments(this.includes);
this.includes.push(...patterns);
}

Expand All @@ -27,4 +40,11 @@ export class IgnoreFile extends FileBase {
...this.includes.map(x => `!${x}`),
].join('\n');
}
}

private flushComments(into: string[]) {
into.push(...this.comments);
this.comments = [];
}
}


23 changes: 11 additions & 12 deletions lib/jsii-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,25 +130,24 @@ export class JsiiProject extends NodeProject {
new Eslint(this);
}

this.gitignore.exclude(
'dist',
'tsconfig.json',
'.jsii',
'*.d.ts',
'*.js',
);

// exclude typescript source and config
this.gitignore.comment('exclude jsii outputs')
this.gitignore.exclude('dist', '.jsii', 'tsconfig.json');

this.gitignore.comment('exclude typescript compiler outputs');
this.gitignore.exclude('*.d.ts');
this.gitignore.exclude('*.js');

this.npmignore.comment('exclude typescript sources and configuration');
this.npmignore.exclude('*.ts', 'tsconfig.json');

// include javascript files and typescript declarations
this.npmignore.comment('include javascript files and typescript declarations');
this.npmignore.include('*.js');
this.npmignore.include('*.d.ts');

// exclude jsii outdir
this.npmignore.comment('exclude jsii outdir');
this.npmignore.exclude('dist');

// include .jsii manifest
this.npmignore.comment('include .jsii manifest');
this.npmignore.include('.jsii');

new JsiiBuildWorkflow(this);
Expand Down
12 changes: 8 additions & 4 deletions lib/json.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { FileBase } from './file';
import { FileBase, FileBaseOptions } from './file';
import { Project } from './project';

export interface JsonFileOptions extends FileBaseOptions {
readonly obj: any;
}

export class JsonFile extends FileBase {
private readonly obj: object;

constructor(project: Project, filePath: string, obj: any) {
super(project, filePath);
this.obj = obj;
constructor(project: Project, filePath: string, options: JsonFileOptions) {
super(project, filePath, options);
this.obj = options.obj;
}

protected get data() {
Expand Down
21 changes: 19 additions & 2 deletions lib/node-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ export interface CommonOptions {
readonly peerDependencyOptions?: PeerDependencyOptions;
readonly bin?: Record<string, string>;

/**
* Should we commit `package.json` to git or ignore?
*
* @default false By default `package.json` is *not* committed. This means
* that after you check out a repository you must run `npx projen` to
* bootstrap it.
*/
readonly commitPackageJson?: boolean;

/**
* Version of projen to install.
*
Expand Down Expand Up @@ -62,7 +71,6 @@ export class NodeProject extends Project {
constructor(options: NodeProjectOptions) {
super(options);


this.manifest = {
'//': GENERATION_DISCLAIMER,
name: options.name,
Expand All @@ -84,7 +92,12 @@ export class NodeProject extends Project {
bundledDependencies: this.bundledDependencies,
};

new JsonFile(this, 'package.json', this.manifest);

const commitPackageJson = options.commitPackageJson ?? false;
new JsonFile(this, 'package.json', {
committed: commitPackageJson,
obj: this.manifest,
});

this.addDependencies(options.dependencies ?? {});
this.addPeerDependencies(options.peerDependencies ?? {});
Expand All @@ -101,7 +114,11 @@ export class NodeProject extends Project {
new License(this, license);

this.addScripts({ projen: 'node projen.js && yarn install' });

this.npmignore.comment('exclude project definition from npm module');
this.npmignore.exclude('projen.js');

this.npmignore.comment('make sure to commit projen definition');
this.gitignore.include('projen.js');

this.addBins(options.bin ?? { });
Expand Down
16 changes: 10 additions & 6 deletions lib/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ export class Version extends Construct {
'standard-version': Semver.caret('8.0.0'),
});

project.gitignore.exclude('/.versionrc.json');
project.npmignore.comment('standard-version configuration');
project.npmignore.exclude('/.versionrc.json');

project.gitignore.comment('always commit version file');
project.gitignore.include(VERSION_FILE);

new JsonFile(project, '.versionrc.json', {
packageFiles: [ { filename: VERSION_FILE, type: 'json' } ],
bumpFiles: [ { filename: VERSION_FILE, type: 'json' } ],
commitAll: true,
scripts: {
postbump: 'yarn projen && git add .',
obj: {
packageFiles: [ { filename: VERSION_FILE, type: 'json' } ],
bumpFiles: [ { filename: VERSION_FILE, type: 'json' } ],
commitAll: true,
scripts: {
postbump: 'yarn projen && git add .',
},
},
});
}
Expand Down
60 changes: 60 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"//": "Generated by projen. To modify, edit \"projen.js\" and run \"projen\"",
"name": "projen",
"description": "A new generation of project generators",
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "https://github.com/eladb/projen.git"
},
"bin": {
"projen": "bin/projen"
},
"scripts": {
"projen": "node projen.js && yarn install",
"test": "yarn eslint",
"bump": "standard-version",
"compile": "jsii",
"watch": "jsii -w",
"compat": "npx jsii-diff npm:$(node -p \"require('./package.json').name\")",
"package": "jsii-pacmak",
"build": "yarn compile && yarn test && yarn run package",
"eslint": "eslint . --ext .ts"
},
"author": {
"name": "Elad Ben-Israel",
"email": "benisrae@amazon.com"
},
"devDependencies": {
"constructs": "2.0.1",
"standard-version": "^8.0.0",
"jsii": "^1.5.0",
"jsii-diff": "^1.5.0",
"jsii-pacmak": "^1.5.0",
"jsii-release": "^0.1.5",
"@types/node": "^13.13.5",
"@typescript-eslint/eslint-plugin": "^2.31.0",
"@typescript-eslint/parser": "^2.19.2",
"eslint": "^6.8.0",
"eslint-import-resolver-node": "^0.3.3",
"eslint-import-resolver-typescript": "^2.0.0",
"eslint-plugin-import": "^2.20.2"
},
"peerDependencies": {
"constructs": "^2.0.1"
},
"dependencies": {
"yaml": "^1.9.2"
},
"bundledDependencies": [
"yaml"
],
"license": "Apache-2.0",
"version": "0.1.7",
"types": "lib/index.d.ts",
"stability": "experimental",
"jsii": {
"outdir": "dist",
"targets": {}
}
}
Loading

0 comments on commit 3ff069c

Please sign in to comment.