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(cli,cli-service,cli-test-utils): add ts declaration #5356

Merged
merged 14 commits into from Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/@vue/cli-service/package.json
Expand Up @@ -26,6 +26,9 @@
"@intervolga/optimize-cssnano-plugin": "^1.0.5",
"@soda/friendly-errors-webpack-plugin": "^1.7.1",
"@soda/get-current-script": "^1.0.0",
"@types/minimist": "^1.2.0",
"@types/webpack": "^4.0.0",
"@types/webpack-dev-server": "^3.11.0",
"@vue/cli-overlay": "^4.4.6",
"@vue/cli-plugin-router": "^4.4.6",
"@vue/cli-plugin-vuex": "^4.4.6",
Expand Down
10 changes: 6 additions & 4 deletions packages/@vue/cli-service/types/ProjectOptions.d.ts
@@ -1,5 +1,5 @@
import ChainableWebpackConfig from 'webpack-chain'
import { WebpackOptions } from 'webpack/declarations/WebpackOptions'
import ChainableWebpackConfig = require('webpack-chain')
import { Configuration as WebpackOptions } from 'webpack'

type PageEntry = string | string[];

Expand Down Expand Up @@ -29,7 +29,7 @@ interface CSSOptions {
loaderOptions?: LoaderOptions;
}

export interface ProjectOptions {
interface ProjectOptions {
publicPath?: string;
outputDir?: string;
assetsDir?: string;
Expand Down Expand Up @@ -57,4 +57,6 @@ export interface ProjectOptions {
pluginOptions?: object;
}

export type ConfigFunction = () => ProjectOptions
type ConfigFunction = () => ProjectOptions

export { ProjectOptions, ConfigFunction }
64 changes: 64 additions & 0 deletions packages/@vue/cli-service/types/cli-service-test.ts
@@ -0,0 +1,64 @@
import { ServicePlugin } from '@vue/cli-service'

const servicePlugin: ServicePlugin = (api, options) => {
const version = api.version
api.assertVersion(4)
api.assertVersion('^100')
api.getCwd()
api.resolve('src/main.js')
api.hasPlugin('eslint')
api.registerCommand(
'lint',
{
description: 'lint and fix source files',
usage: 'vue-cli-service lint [options] [...files]',
options: {
'--format [formatter]': 'specify formatter (default: codeframe)'
},
details: 'For more options, see https://eslint.org/docs/user-guide/command-line-interface#options'
},
args => {
require('./lint')(args, api)
}
)
api.registerCommand('lint', args => {})

api.chainWebpack(webpackConfig => {
if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
webpackConfig.devtool('cheap-module-eval-source-map')

webpackConfig.plugin('hmr').use(require('webpack/lib/HotModuleReplacementPlugin'))

webpackConfig.output.globalObject(`(typeof self !== 'undefined' ? self : this)`)
}
})

api.configureWebpack(config => {
config.output = {
path: 'test-dist-2'
}
})

api.configureWebpack(config => {
return {
devtool: config.devtool || 'source-map'
}
})

api.resolveWebpackConfig()

api.resolveWebpackConfig(api.resolveChainableWebpackConfig())

const { cacheIdentifier, cacheDirectory } = api.genCacheConfig(
'babel-loader',
{
'@babel/core': require('@babel/core/package.json').version,
'@vue/babel-preset-app': require('@vue/babel-preset-app/package.json').version,
'babel-loader': require('babel-loader/package.json').version,
modern: !!process.env.VUE_CLI_MODERN_BUILD,
browserslist: api.service.pkg.browserslist
},
['babel.config.js', '.browserslistrc']
)
}
export = servicePlugin
138 changes: 137 additions & 1 deletion packages/@vue/cli-service/types/index.d.ts
@@ -1 +1,137 @@
export { ProjectOptions, ConfigFunction } from './ProjectOptions'
import minimist = require('minimist')
import ChainableConfig = require('webpack-chain')
import webpack = require('webpack')
import WebpackDevServer = require('webpack-dev-server')
import express = require('express') // @types/webpack-dev-server depends on @types/express
import { ProjectOptions } from './ProjectOptions'

type RegisterCommandFn = (args: minimist.ParsedArgs, rawArgv: string[]) => any

type RegisterCommandOpts = Partial<{
description: string
usage: string
options: {
[flags: string]: string
}
details: string
}>

type WebpackChainFn = (chainableConfig: ChainableConfig) => void

type webpackRawConfigFn = ((config: webpack.Configuration) => webpack.Configuration | void) | webpack.Configuration

type DevServerConfigFn = (app: express.Application, server: WebpackDevServer) => void

interface CacheConfig {
cacheDirectory: string
cacheIdentifier: string
}
declare class PluginAPI {
id: string

service: any

readonly version: string

assertVersion(range: number | string): void

/**
* Current working directory.
*/
getCwd(): string

/**
* Resolve path for a project.
*
* @param _path - Relative path from project root
* @return The resolved absolute path.
*/
resolve(_path: string): string

/**
* Check if the project has a given plugin.
*
* @param id - Plugin id, can omit the (@vue/|vue-|@scope/vue)-cli-plugin- prefix
* @return `boolean`
*/
hasPlugin(id: string): boolean

/**
* Register a command that will become available as `vue-cli-service [name]`.
*
* @param name
* @param [opts]
* @param fn
*/
registerCommand(name: string, fn: RegisterCommandFn): void
registerCommand(name: string, opts: RegisterCommandOpts, fn: RegisterCommandFn): void

/**
* Register a function that will receive a chainable webpack config
* the function is lazy and won't be called until `resolveWebpackConfig` is
* called
*
* @param fn
*/
chainWebpack(fn: WebpackChainFn): void

/**
* Register
* - a webpack configuration object that will be merged into the config
* OR
* - a function that will receive the raw webpack config.
* the function can either mutate the config directly or return an object
* that will be merged into the config.
*
* @param fn
*/
configureWebpack(fn: webpackRawConfigFn): void

/**
* Register a dev serve config function. It will receive the express `app`
* instance of the dev server.
*
* @param fn
*/
configureDevServer(fn: DevServerConfigFn): void

/**
* Resolve the final raw webpack config, that will be passed to webpack.
*
* @param [chainableConfig]
* @return Raw webpack config.
*/
resolveWebpackConfig(chainableConfig?: ChainableConfig): webpack.Configuration

/**
* Resolve an intermediate chainable webpack config instance, which can be
* further tweaked before generating the final raw webpack config.
* You can call this multiple times to generate different branches of the
* base webpack config.
* See https://github.com/mozilla-neutrino/webpack-chain
*
* @return ChainableWebpackConfig
*/
resolveChainableWebpackConfig(): ChainableConfig

/**
* Generate a cache identifier from a number of variables
*/
genCacheConfig(id: string, partialIdentifier: any, configFiles?: string | string[]): CacheConfig
}

/**
* Service plugin serves for modifying webpack config,
* creating new vue-cli service commands or changing existing commands
*
* @param api - A PluginAPI instance
* @param options - An object containing project local options specified in vue.config.js,
* or in the "vue" field in package.json.
*/
type ServicePlugin = (
api: PluginAPI,
options: ProjectOptions
) => any

export { ProjectOptions, ServicePlugin, PluginAPI }
export { ConfigFunction } from './ProjectOptions'
22 changes: 22 additions & 0 deletions packages/@vue/cli-service/types/tsconfig.json
@@ -0,0 +1,22 @@
{
"files": [
"cli-service-test.ts",
"index.d.ts",
"ProjectOptions.d.ts"
],
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"esModuleInterop": true,
"strictFunctionTypes": true,
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": "."
}
}
16 changes: 16 additions & 0 deletions packages/@vue/cli-test-utils/assertPromptModule.d.ts
@@ -0,0 +1,16 @@
import { PromptModuleAPI } from '@vue/cli'

interface CliPromptModule {
(api: PromptModuleAPI): void
}

declare function assertPromptModule(
module: CliPromptModule | CliPromptModule[],
expectedPrompts: object[],
expectedOptions: object,
opts?: {
pluginsOnly?: boolean
},
): Promise<void>

export = assertPromptModule
21 changes: 21 additions & 0 deletions packages/@vue/cli-test-utils/createJSONServer.d.ts
@@ -0,0 +1,21 @@
import { Application } from 'express'

declare function createJSONServer(
/**
* Either a path to a json file (e.g. 'db.json') or an object in memory
*
* Default:
*{
* 'posts': [
* { 'id': 1, 'title': 'json-server', 'author': 'typicode' }
* ],
* 'comments': [
* { 'id': 1, 'body': 'some comment', 'postId': 1 }
* ],
* 'profile': { 'name': 'typicode' }
*}
*/
data?: string | object,
): Application

export = createJSONServer
11 changes: 11 additions & 0 deletions packages/@vue/cli-test-utils/createServer.d.ts
@@ -0,0 +1,11 @@
/// <reference types="node" />
import * as http from 'http'

declare function createServer(options: {
/**
* Set a sub directory to be served
*/
root: string
}): http.Server

export = createServer
46 changes: 46 additions & 0 deletions packages/@vue/cli-test-utils/createTestProject.d.ts
@@ -0,0 +1,46 @@
import execa = require('execa') // execa@1.0.0 needs @types/execa
import { Preset } from '@vue/cli'

/**
* create project at path `cwd`
*/
declare function createTestProject(
/**
* project name
*/
name: string,
/**
* manual preset used to generate project.
*
* Example:
* {
* plugins: {
* '@vue/cli-plugin-babel': {}
* }
* }
*/
preset: Preset,
/** `path.resolve(cwd, name)` will be the project's root directory */
cwd?: string | null,
/**
* if init git repo
*
* Default:`true`
*/
initGit?: boolean,
): Promise<{
/** test project's root path */
dir: string
/** test if project contains the file */
has: (file: string) => boolean
/** read the content for the file */
read: (file: string) => Promise<string>
/** write file to project */
write: (file: string, content: any) => Promise<void>
/** execa command at root path of project */
run: (command: string, args?: ReadonlyArray<string>) => execa.ExecaChildProcess
/** delete the file of project */
rm: (file: string) => Promise<void>
}>

export = createTestProject
32 changes: 32 additions & 0 deletions packages/@vue/cli-test-utils/generateWithPlugin.d.ts
@@ -0,0 +1,32 @@
import { GeneratorAPI, Preset } from '@vue/cli'

type ApplyFn = (
api: GeneratorAPI,
options: any,
rootOptions: Preset,
invoking: boolean,
) => any
interface Plugin {
/** package name from plugin */
id: string
/** generator function from plugin */
apply: ApplyFn
/** parameter passed to generator function */
options?: any
}

/**
* invoke generator function, and generate file tree in memory
*/
declare function generateWithPlugin(
plugin: Plugin | Plugin[],
): Promise<{
/** package.json Object */
pkg: Record<string, any>
/** virtual file tree, file path is the key of Object */
files: {
[filePath: string]: string | Buffer
}
}>

export = generateWithPlugin