Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ts cmd #671

Merged
merged 10 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
# AEgir
# AEgir <!-- omit in toc -->

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/ipfs/aegir/ci/master?style=flat-square)
[![Dependency Status](https://david-dm.org/ipfs/aegir.svg?style=flat-square)](https://david-dm.org/ipfs/aegir)

> Automated JavaScript project management.

## Lead Maintainer
## Lead Maintainer <!-- omit in toc -->

[Hugo Dias](https://github.com/hugomrdias)

## ToC <!-- omit in toc -->
- [Project Structure](#project-structure)
- [CI](#ci)
- [Travis Setup](#travis-setup)
- [Github Action Setup](#github-action-setup)
- [Stack Requirements](#stack-requirements)
- [Testing helpers](#testing-helpers)
- [Fixtures](#fixtures)
- [Echo Server](#echo-server)
- [Get Port](#get-port)
- [Tasks](#tasks)
- [Linting](#linting)
- [Testing](#testing)
- [Coverage](#coverage)
- [Node](#node)
- [Browser](#browser)
- [Building](#building)
- [Generating Webpack stats.json](#generating-webpack-statsjson)
- [Typescript](#typescript)
- [JSDoc Typescript support](#jsdoc-typescript-support)
- [Releasing](#releasing)
- [Scoped Github Token](#scoped-github-token)
- [Documentation](#documentation)
- [License](#license)

## Project Structure

Expand Down Expand Up @@ -39,10 +62,12 @@ Your `package.json` should have the following entries and should pass `aegir lin
"test:browser": "aegir test --target browser"
}
```
## Travis Setup

## CI
### Travis Setup
Check this tutorial https://github.com/ipfs/aegir/wiki/Travis-Setup

## Github Action Setup
### Github Action Setup
Check this tutorial https://github.com/ipfs/aegir/wiki/Github-Actions-Setup

## Stack Requirements
Expand Down Expand Up @@ -200,18 +225,15 @@ after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codeco
```

### Building


You can run it using
The build command builds a browser bundle and TS type declarations from the `src` folder.

```bash
$ aegir build
$ aegir build --help
```
This will build a browser ready version into `dist`, so after publishing the results will be available under

```
https://unpkg.com/<module-name>/dist/index.js
https://unpkg.com/<module-name>/dist/index.min.js
```

**Specifying a custom entry file for Webpack**
Expand All @@ -235,6 +257,16 @@ Pass the `--analyze` option to have Webpack generate a `stats.json` file for the
```bash
aegir build --analyze
```
### Typescript

#### JSDoc Typescript support
```bash
aegir ts --help
```
The `ts` command adds support for JSDoc types in native javascript code.
hugomrdias marked this conversation as resolved.
Show resolved Hide resolved

> Check [ts-jsdoc](./md/ts-jsdoc.md) for more documentation.


### Releasing

Expand Down Expand Up @@ -290,12 +322,12 @@ Be aware that by storing it in `~/.profile` or similar you will make it availabl

### Documentation

You can use `aegir docs` to generate documentation. This uses [documentation.js](http://documentation.js.org/) with the theme [clean-documentation-theme](https://github.com/dignifiedquire/clean-documentation-theme).
You can use `aegir docs` to generate documentation, this command uses `aegir ts --preset docs` internally.

To publish the documentation automatically to the `gh-pages` branch you can run

```bash
$ aegir docs --publish
$ aegir docs --help
hugomrdias marked this conversation as resolved.
Show resolved Hide resolved
```

## License
Expand Down
4 changes: 2 additions & 2 deletions cmds/build.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict'
const EPILOG = `
This command outputs two bundles, one in development mode (index.js) and another in production mode (index.min.js) plus respective source-maps, files are written to ./dist folder.
Output files will go into a "./dist" folder.
Supports options forwarding with '--' for more info check https://webpack.js.org/api/cli/
`
module.exports = {
command: 'build',
desc: 'Builds browser bundles with Webpack.',
desc: 'Builds a browser bundle and TS type declarations from the `src` folder.',
builder: (yargs) => {
yargs
.epilog(EPILOG)
Expand Down
10 changes: 5 additions & 5 deletions cmds/docs.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
'use strict'

const EPILOG = `
Supports options forwarding with '--' for more info check https://github.com/documentationjs/documentation/blob/master/docs/USAGE.md
Typescript config file is required to generated docs. Try \`aegir ts --preset config > tsconfig.json\`
`

module.exports = {
command: 'docs',
desc: 'Generate documentation from JSDoc.',
desc: 'Generate documentation from TS type declarations.',
builder: yargs => {
yargs
.epilog(EPILOG)
.example('aegir docs -- --format md -o docs.md', 'Build markdown documentation.')
.example('aegir docs', 'Build HTML documentation.')
.example('aegir docs -p', 'Build HTML documentation and publish to Github Pages.')
.options(
{
publish: {
Expand All @@ -24,7 +25,6 @@ module.exports = {
},
handler (argv) {
const docs = require('../src/docs')
const onError = require('../src/error-handler')
docs.run(argv).catch(onError)
return docs.run(argv)
}
}
42 changes: 42 additions & 0 deletions cmds/ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict'

const EPILOG = `
Presets:
\`check\` Runs the type checker with your local config and doesn't not emit output.
hugomrdias marked this conversation as resolved.
Show resolved Hide resolved
hugomrdias marked this conversation as resolved.
Show resolved Hide resolved
\`types\` Emits type declarations for \`['src/**/*', 'package.json']\` to \`dist\` folder.
\`docs\` Generates documentation based on type declarations to the \`docs\` folder.
\`config\` Prints base config to stdout.

Note:
To enable types declarations to be used add this to your package.json:
hugomrdias marked this conversation as resolved.
Show resolved Hide resolved

\`\`\`json
"types": "./dist/src/index.d.ts",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓Why both typeVersions and types ? Could having both cause some problems ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types works for the default package export
typeVersions works for atomic internal package exports

"typesVersions": {
"*": { "src/*": ["dist/src/*"] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨We have discovered couple of issues microsoft/TypeScript#41284, microsoft/TypeScript#41281 with this setup and a workaround by doing following:

Suggested change
"*": { "src/*": ["dist/src/*"] }
"*": { "src/*": ["dist/src/*", "dist/src/*/index"] }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓Is limiting everything to src deliberate ? And does that not cause problem with package.json that will be falling outside of src ? Also I think I remember seeing some packages that did not have src, but might be conflating with some of the newer IPLD stuff that doesn't use aegir.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using src is an aegir convention

i can't understand the problem with

"types": "./dist/src/index.d.ts",
"typesVersions": {
  "*": { "src/*": ["dist/src/*"] }
}

in the issues above

},
\`\`\`

Supports options forwarding with '--' for more info check https://www.typescriptlang.org/docs/handbook/compiler-options.html
`
module.exports = {
command: 'ts',
desc: 'Typescript command with presets for specific tasks.',
builder: (yargs) => {
yargs
.epilog(EPILOG)
.example('aegir ts --preset config > tsconfig.json', 'Add a base tsconfig.json to the current repo.')
.options({
preset: {
type: 'string',
choices: ['config', 'check', 'types', 'docs'],
describe: 'Preset to run',
alias: 'p'
}
})
},
handler (argv) {
const ts = require('../src/ts')
return ts(argv)
}
}
106 changes: 106 additions & 0 deletions md/ts-jsdoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Documentation for JSDoc based TS types

## Getting Started

Add a `tsconfig.json` to your repo:
```bash
aegir ts -p config > tsconfig.json
```

Add types configuration to your package.json:
```json
"types": "./dist/src/index.d.ts",
"typesVersions": {
"*": { "src/*": ["dist/src/*"] }
},
```
`types` will tell `tsc` where to look for the entry point type declarations and `typeVersions` for every other files inside the `src` folder.

> The `ts` command follows aegir folder conventions, source code inside `./src`, test inside `./test` and documentation inside `./docs`.


## CLI `ts` command

Run `aegir ts --help` and check the help text. There's presets for common TS use cases.

```md
Presets:
`check` Runs the type checker with your local config and doesn't not emit output.
`types` Emits type declarations for `['src/**/*', 'package.json']` to `dist` folder.
`docs` Generates documentation based on type declarations to the `docs` folder.
`config` Prints base config to stdout.
```


## Adding types with JSDoc

Typescript can infered lots of types without any help, but you can improve your code types by using just JSDoc for that follow the official TS documentation https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html.
hugomrdias marked this conversation as resolved.
Show resolved Hide resolved

### Rules for optimal type declarations and documentation

This list is a WIP, more rules will be added as we identify them.

#### 1. Commonjs default exports
When using `commonjs` modules, only use default exports when exporting a single `class`.

```js
// GOOD

class IPFS {}

module.exports = IPFS

// GOOD
IPFS.hash = ()=>{}

module.exports = IPFS

// BAD
function hash() {}

module.exports = hash

// REALLY BAD

function hash() {}
function hash2() {}

module.exports = hash
exports.hash2 = hash2


```

#### 2. Commons js named exports
When using `commonjs` modules, always use named exports if you want to export multiple references.
```js
// GOOD
function hash() {}
function hash2() {}
class IPFS {}
module.exports = {
IPFS
hash,
hash2,
...
}

// BAD
exports.hash2 = hash2() {}
exports.hash = hash() {}
exports.IPFS = IPFS
```

#### 3. Use a `types.ts` file
When writing types sometimes JSDoc can be cumbersome, impossible, it can output weird type declarations or even broken documentation. Most of these problems can be solved by defining some complex types in typescript in a `types.ts` file.

```ts
// types.ts
export type IntersectionType = Type1 & Type2
```

```js
// index.js
/** @type { import('./types').IntersectionType } */
const list
```
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
"@commitlint/travis-cli": "^11.0.0",
"@electron/get": "^1.10.0",
"@polka/send-type": "^0.5.2",
"@types/mocha": "^8.0.4",
"@types/node": "^14.14.7",
"aegir-typedoc-theme": "^0.1.0",
"babel-loader": "^8.0.5",
"buffer": "^5.6.0",
"bytes": "^3.1.0",
Expand Down Expand Up @@ -106,13 +109,17 @@
"pascalcase": "^1.0.0",
"pify": "^5.0.0",
"polka": "^0.5.2",
"premove": "^3.0.1",
"prompt-promise": "^1.0.3",
"read-pkg-up": "^7.0.1",
"rimraf": "^3.0.1",
"semver": "^7.3.2",
"simple-git": "^2.7.0",
"strip-bom": "^4.0.0",
"strip-json-comments": "^3.1.1",
"terser-webpack-plugin": "^3.0.5",
"typescript": "^4.0.3",
"typedoc": "^0.19.2",
"typescript": "^4.0.5",
"update-notifier": "^5.0.0",
"webpack": "^4.43.0",
"webpack-bundle-analyzer": "^3.7.0",
Expand Down
14 changes: 4 additions & 10 deletions src/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ const fs = require('fs')
const bytes = require('bytes')
const execa = require('execa')
const rimraf = require('rimraf')
const { fromAegir, gzipSize, pkg } = require('./../utils')
const { fromAegir, gzipSize, pkg, hasTsconfig } = require('./../utils')
const userConfig = require('../config/user')
const tsCmd = require('../ts')

const config = userConfig()

Expand Down Expand Up @@ -41,15 +42,8 @@ module.exports = async (argv) => {
stdio: 'inherit'
})

if (argv.ts) {
await execa('tsc', [
'--outDir', './dist/src',
'--declaration'
], {
localDir: path.join(__dirname, '../..'),
preferLocal: true,
stdio: 'inherit'
})
if (hasTsconfig) {
await tsCmd({ preset: 'types' })
}

if (argv.bundlesize) {
Expand Down
17 changes: 0 additions & 17 deletions src/clean.js

This file was deleted.

Loading