Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
30 changes: 30 additions & 0 deletions cmds/ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict'

const EPILOG = `
Presets:
\`check\` Checks src and test folders for Typescript errors
Copy link
Member

Choose a reason for hiding this comment

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

Will this mean we have to include TS comments on all of our tests?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, it works as is but it may output errors for some inferred types or defined types in the source code.
Checking the tests enables us to be the users of our own types and be able to identify issues in the types early.

\`types\` Generates types declarations inline with the source files
\`types-clean\` Deletes all the *.d.ts files
\`docs\` Generates documentation based on the type declarations
Supports options forwarding with '--' for more info check https://www.typescriptlang.org/v2/docs/handbook/compiler-options.html
`
module.exports = {
command: 'ts',
desc: 'Typescript command with presets for specific tasks.',
builder: (yargs) => {
yargs
.epilog(EPILOG)
.options({
preset: {
type: 'string',
choices: ['check', 'types', 'types-clean', 'docs'],
describe: 'Preset to run'
}
})
},
handler (argv) {
const ts = require('../src/ts')
return ts(argv)
}
}
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
"@commitlint/travis-cli": "^8.3.5",
"@electron/get": "^1.10.0",
"@polka/send-type": "^0.5.2",
"@types/mocha": "^7.0.2",
"@types/node": "^14.0.9",
"aegir-typedoc-theme": "~0.0.1",
"babel-loader": "^8.0.5",
"babel-plugin-transform-flow-comments": "^6.22.0",
"buffer": "^5.6.0",
Expand All @@ -76,6 +79,7 @@
"eslint": "^6.3.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jsdoc": "^25.4.2",
"eslint-plugin-no-only-tests": "^2.4.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^4.2.1",
Expand Down Expand Up @@ -120,6 +124,8 @@
"stream-array": "^1.1.2",
"terser-webpack-plugin": "^2.3.6",
"transform-loader": "~0.2.4",
"typedoc": "^0.17.7",
"typescript": "^3.9.3",
"update-notifier": "^4.0.0",
"vinyl-fs": "^3.0.3",
"webpack": "^4.43.0",
Expand All @@ -139,6 +145,9 @@
"node": ">=10.0.0",
"npm": ">=6.0.0"
},
"eslintConfig": {
"extends": "./src/config/eslintrc.js"
},
"browserslist": [
">1%",
"last 2 versions",
Expand Down
26 changes: 26 additions & 0 deletions src/config/aegir-tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"target": "es2018",
"module": "CommonJS",
"moduleResolution": "node",
"resolveJsonModule": true,
"stripInternal": true,
"strict": false,
"alwaysStrict": true,
"strictNullChecks": true,
"noFallthroughCasesInSwitch": true,
"preserveConstEnums": true,
"noEmitOnError": true,
"noEmit": true,
"esModuleInterop": true,
"declaration": true,
"removeComments": false,
"skipLibCheck": true,
"lib": [
"ES2018",
"DOM"
]
}
}
42 changes: 35 additions & 7 deletions src/config/eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ module.exports = {
parserOptions: {
sourceType: 'script'
},
settings: {
jsdoc: { mode: 'typescript' }
},
env: {
browser: true
},
globals: {
self: true
},
plugins: [
'no-only-tests'
'no-only-tests',
'jsdoc'
],
rules: {
strict: [2, 'safe'],
Expand Down Expand Up @@ -40,11 +47,32 @@ module.exports = {
'require-yield': 2,
'max-nested-callbacks': [2, 4],
'max-depth': [2, 4],
'valid-jsdoc': [2, {
requireReturn: false,
requireParamDescription: false,
requireReturnDescription: false
}],
'require-await': 2
'require-await': 2,
'jsdoc/check-alignment': 2,
'jsdoc/check-examples': 0,
'jsdoc/check-indentation': 2,
'jsdoc/check-param-names': 2,
'jsdoc/check-syntax': 2,
'jsdoc/check-tag-names': [2, { definedTags: ['internal', 'packageDocumentation'] }],
'jsdoc/check-types': 2,
'jsdoc/implements-on-classes': 2,
'jsdoc/match-description': 0,
'jsdoc/newline-after-description': 2,
'jsdoc/no-types': 0,
'jsdoc/no-undefined-types': 2,
'jsdoc/require-description': 0,
'jsdoc/require-description-complete-sentence': 0,
'jsdoc/require-example': 0,
'jsdoc/require-hyphen-before-param-description': 2,
'jsdoc/require-jsdoc': 0,
'jsdoc/require-param': 2,
'jsdoc/require-param-description': 1,
'jsdoc/require-param-name': 2,
'jsdoc/require-param-type': 2,
'jsdoc/require-returns': 2,
'jsdoc/require-returns-check': 2,
'jsdoc/require-returns-description': 1,
'jsdoc/require-returns-type': 2,
'jsdoc/valid-types': 2
}
}
4 changes: 2 additions & 2 deletions src/dependency-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const defaultInput = [
/**
* Check dependencies
*
* @param {Object} argv
* @param {ExecaOptions} execaOptions
* @param {object} argv
* @param {ExecaOptions} execaOptions - execa options
* @returns {ExecaChildProcess}
*/
const check = (argv = { _: [] }, execaOptions) => {
Expand Down
153 changes: 153 additions & 0 deletions src/ts/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
'use strict'

const path = require('path')
const execa = require('execa')
const fs = require('fs-extra')
const rimraf = require('rimraf')
const merge = require('merge-options')
const { fromRoot, fromAegir, repoDirectory, hasFile } = require('../utils')
let baseTsConfig = require('./../config/aegir-tsconfig.json')

if (hasFile('tsconfig.json')) {
baseTsConfig = require(fromRoot('tsconfig.json'))
}

module.exports = (argv) => {
const forwardOptions = argv['--'] ? argv['--'] : []

if (argv.preset === 'check') {
return check(forwardOptions)
}

if (argv.preset === 'types') {
return types(forwardOptions)
}

if (argv.preset === 'types-clean') {
return typesClean()
}

if (argv.preset === 'docs') {
return docs(forwardOptions)
}

if (!argv.preset) {
return execa('tsc', [
...forwardOptions
], {
localDir: path.join(__dirname, '../..'),
preferLocal: true,
stdio: 'inherit'
})
}
}

const check = async (forwardOptions) => {
const configPath = fromRoot('tsconfig-check.json')
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be better to fail if there is no tsconfig.json (which can include single extends directive e.g. { "extends": "aegir/src/config/aegir-tsconfig.json"}) than do this. Otherwise we introduce another instance of other tools like vscode making different assumptions than tools than aegir.

try {
fs.writeJsonSync(
configPath,
merge(baseTsConfig, {
include: ['src/**/*', 'test/**/*']
})
)
await execa('tsc', [
'-p', configPath,
...forwardOptions
], {
localDir: path.join(__dirname, '../..'),
preferLocal: true,
stdio: 'inherit'
})
} finally {
fs.removeSync(configPath)
}
}

const typesClean = () => {
rimraf.sync(path.join(repoDirectory, 'src/**/*.d.ts'))
}

const types = async (forwardOptions) => {
const configPath = fromRoot('tsconfig-types.json')
typesClean()
try {
fs.writeJsonSync(
configPath,
merge(baseTsConfig, {
compilerOptions: {
noEmit: false,
emitDeclarationOnly: true
// outDir: 'types'
},
include: [
'src/**/*'
]
})
)
await execa('tsc', [
'-p', configPath,
...forwardOptions
], {
localDir: path.join(__dirname, '../..'),
preferLocal: true,
stdio: 'inherit'
})
} finally {
fs.removeSync(configPath)
}
}

const docs = async (forwardOptions) => {
const configPath = fromRoot('tsconfig-docs.json')
try {
fs.writeJsonSync(
configPath,
merge(baseTsConfig, {
compilerOptions: {
noEmit: false,
emitDeclarationOnly: true,
outDir: 'types'
},
include: ['src/**/*']
})
)

// run tsc
await execa('tsc', [
'-p', configPath,
...forwardOptions
], {
localDir: path.join(__dirname, '../..'),
preferLocal: true,
stdio: 'inherit'
})

// run typedoc
await execa('typedoc', [
'--inputfiles', fromRoot('types'),
'--mode', 'modules',
'--out', 'docs',
'--excludeExternals',
'--excludeNotDocumented',
// '--excludeNotExported',
'--excludePrivate',
'--excludeProtected',
'--includeDeclarations',
'--hideGenerator',
'--includeVersion',
'--gitRevision', 'master',
'--disableSources',
'--tsconfig', configPath,
'--plugin', fromAegir('src/ts/typedoc-plugin.js'),
'--theme', fromAegir('./../../node_modules/aegir-typedoc-theme/bin/default')
], {
localDir: path.join(__dirname, '..'),
preferLocal: true,
stdio: 'inherit'
})
} finally {
fs.removeSync(configPath)
fs.removeSync(fromRoot('types'))
}
}
35 changes: 35 additions & 0 deletions src/ts/typedoc-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict'
const { Converter } = require('typedoc/dist/lib/converter')
const path = require('path')
const fs = require('fs')

module.exports = function (PluginHost) {
const app = PluginHost.owner
const pkg = path.join(process.cwd(), 'package.json')
let pkgJson
let main
try {
pkgJson = JSON.parse(fs.readFileSync(pkg).toString())
main = path.join(process.cwd(), pkgJson.main)
} catch (err) {
throw new Error('cant find package.json')
}

app.converter.on(Converter.EVENT_CREATE_DECLARATION, (context, reflection, node) => {
if (reflection.kind === 1 && node) {
// entry point
if (pkgJson && reflection.name === main) {
reflection.name = '\u0000' + pkgJson.name.charAt(0).toUpperCase() + pkgJson.name.slice(1)
// reflection.kind = 2
}

if (pkgJson && reflection.name.includes('types/index.d.ts')) {
reflection.name = '\u0000' + pkgJson.name.charAt(0) + pkgJson.name.slice(1)
}

if (pkgJson && reflection.name.includes('.d.ts')) {
reflection.name = reflection.name.replace('.d.ts', '.js')
}
}
})
}
Loading