-
Notifications
You must be signed in to change notification settings - Fork 59
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 support for typescript with jsdoc #568
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 | ||
\`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) | ||
} | ||
} |
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, | ||
Gozala marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"noEmit": true, | ||
"esModuleInterop": true, | ||
"declaration": true, | ||
"removeComments": false, | ||
"skipLibCheck": true, | ||
"lib": [ | ||
"ES2018", | ||
"DOM" | ||
] | ||
} | ||
} |
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') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to fail if there is no |
||
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')) | ||
} | ||
} |
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') | ||
} | ||
} | ||
}) | ||
} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.