forked from umijs/umi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: api mock component generator (umijs#558)
* refactor: π¨ use template dir constant * feat: β component template files * refactor: π¨ add ensureWithQustion to helper * feat: β¨ add component generator * test: β fix windows failure case * fix: π use initial use default value * feat: β¨ mock generator * feat: β¨generate support api * fix: π mock should stay at `paths.cwd` * refactor: π₯ use only one way to demo mock defination Co-authored-by: pshu <[email protected]>
- Loading branch information
1 parent
9b04d46
commit 97b9c97
Showing
12 changed files
with
362 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { generateApiResKV } from './api'; | ||
|
||
test('api name: foo', () => { | ||
expect(generateApiResKV('foo')).toEqual({ | ||
key: '"foo"', | ||
value: '"is working"', | ||
}); | ||
}); | ||
|
||
test('api name: bar/boo', () => { | ||
expect(generateApiResKV('bar/foo')).toEqual({ | ||
key: '"foo"', | ||
value: '"is working"', | ||
}); | ||
}); | ||
|
||
test('api name: foo/[id]', () => { | ||
expect(generateApiResKV('foo/[id]')).toEqual({ | ||
key: '"fooId"', | ||
value: 'req.params["id"]', | ||
}); | ||
}); | ||
|
||
test('api name: [param]', () => { | ||
expect(generateApiResKV('[param]')).toEqual({ | ||
key: '"param"', | ||
value: 'req.params["param"]', | ||
}); | ||
}); | ||
|
||
test('api name: long/nest/foo/[param]', () => { | ||
expect(generateApiResKV('long/nest/foo/[param]')).toEqual({ | ||
key: '"fooParam"', | ||
value: 'req.params["param"]', | ||
}); | ||
}); | ||
|
||
test('api name: [ spaced ]', () => { | ||
expect(generateApiResKV('[ spaced ]')).toEqual({ | ||
key: '"spaced"', | ||
value: 'req.params["spaced"]', | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { lodash } from '@umijs/utils'; | ||
import { join, parse } from 'path'; | ||
import { TEMPLATES_DIR } from '../../constants'; | ||
import { IApi } from '../../types'; | ||
import { GeneratorHelper, trim } from './utils'; | ||
|
||
export default (api: IApi) => { | ||
api.describe({ | ||
key: 'generator:api', | ||
}); | ||
|
||
api.registerGenerator({ | ||
key: 'api', | ||
name: 'Generator api', | ||
async fn(opts) { | ||
const h = new GeneratorHelper(api); | ||
|
||
let [_, ...apiNames] = opts.args._; | ||
|
||
if (apiNames.length === 0) { | ||
let apiName = await h.ensureVariableWithQuestion(null, { | ||
type: 'text', | ||
message: 'please input your api name:', | ||
initial: 'foo', | ||
format: trim, | ||
}); | ||
|
||
apiNames = [apiName]; | ||
} | ||
|
||
for (const apiName of apiNames) { | ||
const apiFileName = `${apiName}.ts`; | ||
const base = join(api.paths.absSrcPath, 'api'); | ||
|
||
const target = join(base, apiFileName); | ||
|
||
const kv = generateApiResKV(apiName); | ||
|
||
await opts.generateFile({ | ||
target, | ||
path: API_TML, | ||
baseDir: api.paths.absSrcPath, | ||
data: kv, | ||
}); | ||
} | ||
}, | ||
}); | ||
}; | ||
|
||
const API_TML = join(TEMPLATES_DIR, 'generate/api.ts.tpl'); | ||
|
||
export function generateApiResKV(apiName: string): { | ||
key: string; | ||
value: string; | ||
} { | ||
const { name, dir } = parse(apiName); | ||
const match = name.match(/^\[\s*(\w+)\s*\]$/); | ||
|
||
const quoteStr = JSON.stringify; | ||
|
||
if (!match) { | ||
return { key: quoteStr(name), value: quoteStr('is working') }; | ||
} | ||
|
||
const paramName = match[1]; | ||
|
||
const { name: itemName } = parse(dir); | ||
|
||
const key = itemName | ||
? `${itemName}${lodash.capitalize(paramName)}` | ||
: paramName; | ||
|
||
return { key: quoteStr(key), value: `req.params[${quoteStr(paramName)}]` }; | ||
} |
60 changes: 60 additions & 0 deletions
60
packages/preset-umi/src/commands/generators/component.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { normalize } from 'path'; | ||
import { ComponentGenerator } from './component'; | ||
|
||
test('generate component with single name', async () => { | ||
const { generateFile } = await runGeneratorWith('foo'); | ||
|
||
expect(generateFile).toBeCalledTimes(2); | ||
expect(generateFile).toHaveBeenNthCalledWith( | ||
1, | ||
expect.objectContaining({ | ||
target: normalize('/my/src/path/components/Foo/index.ts'), | ||
baseDir: normalize('/my/src/path'), | ||
data: { compName: 'Foo' }, | ||
}), | ||
); | ||
expect(generateFile).toHaveBeenNthCalledWith( | ||
2, | ||
expect.objectContaining({ | ||
target: normalize('/my/src/path/components/Foo/Foo.tsx'), | ||
baseDir: normalize('/my/src/path'), | ||
data: { compName: 'Foo' }, | ||
}), | ||
); | ||
}); | ||
|
||
test('test generate nested named component foo/bar/qux', async () => { | ||
const { generateFile } = await runGeneratorWith('foo/bar/qux'); | ||
|
||
expect(generateFile).toBeCalledTimes(2); | ||
expect(generateFile).toHaveBeenNthCalledWith( | ||
1, | ||
expect.objectContaining({ | ||
target: normalize('/my/src/path/components/foo/bar/Qux/index.ts'), | ||
data: { compName: 'Qux' }, | ||
}), | ||
); | ||
expect(generateFile).toHaveBeenNthCalledWith( | ||
2, | ||
expect.objectContaining({ | ||
target: normalize('/my/src/path/components/foo/bar/Qux/Qux.tsx'), | ||
data: { compName: 'Qux' }, | ||
}), | ||
); | ||
}); | ||
|
||
async function runGeneratorWith(name: string) { | ||
const generateFile = jest.fn(); | ||
|
||
const cg = new ComponentGenerator({ | ||
componentName: name, | ||
srcPath: normalize('/my/src/path'), | ||
generateFile, | ||
}); | ||
|
||
await cg.run(); | ||
|
||
return { | ||
generateFile, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { GeneratorType } from '@umijs/core'; | ||
import { generateFile, lodash } from '@umijs/utils'; | ||
import { join, parse } from 'path'; | ||
import { TEMPLATES_DIR } from '../../constants'; | ||
import { IApi } from '../../types'; | ||
import { GeneratorHelper } from './utils'; | ||
|
||
export default (api: IApi) => { | ||
api.describe({ | ||
key: 'generator:component', | ||
}); | ||
|
||
api.registerGenerator({ | ||
key: 'component', | ||
name: 'Generate Component', | ||
type: GeneratorType.generate, | ||
|
||
fn: async (options) => { | ||
const h = new GeneratorHelper(api); | ||
options.generateFile; | ||
|
||
let componentNames = options.args._.slice(1); | ||
|
||
if (componentNames.length === 0) { | ||
let name: string = ''; | ||
name = await h.ensureVariableWithQuestion(name, { | ||
type: 'text', | ||
message: 'Please input you component Name', | ||
hint: 'foo', | ||
initial: 'foo', | ||
format: (s) => s?.trim() || '', | ||
}); | ||
componentNames = [name]; | ||
} | ||
|
||
for (const cn of componentNames) { | ||
await new ComponentGenerator({ | ||
srcPath: api.paths.absSrcPath, | ||
generateFile, | ||
componentName: cn, | ||
}).run(); | ||
} | ||
}, | ||
}); | ||
}; | ||
|
||
export class ComponentGenerator { | ||
private readonly name: string; | ||
private readonly dir: string; | ||
|
||
constructor( | ||
readonly opts: { | ||
componentName: string; | ||
srcPath: string; | ||
generateFile: typeof generateFile; | ||
}, | ||
) { | ||
const { name, dir } = parse(this.opts.componentName); | ||
this.name = name; | ||
this.dir = dir; | ||
} | ||
|
||
async run() { | ||
const { srcPath, generateFile } = this.opts; | ||
const capitalizeName = lodash.capitalize(this.name); | ||
const base = join( | ||
this.opts.srcPath, | ||
'components', | ||
this.dir, | ||
capitalizeName, | ||
); | ||
|
||
const indexFile = join(base, 'index.ts'); | ||
const compFile = join(base, `${capitalizeName}.tsx`); | ||
|
||
await generateFile({ | ||
target: indexFile, | ||
path: INDEX_TPL, | ||
baseDir: srcPath, | ||
data: { compName: capitalizeName }, | ||
}); | ||
|
||
await generateFile({ | ||
target: compFile, | ||
path: COMP_TPL, | ||
baseDir: srcPath, | ||
data: { compName: capitalizeName }, | ||
}); | ||
} | ||
} | ||
|
||
const INDEX_TPL = join(TEMPLATES_DIR, 'generate/component/index.ts.tpl'); | ||
const COMP_TPL = join(TEMPLATES_DIR, 'generate/component/component.tsx.tpl'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { GeneratorType } from '@umijs/core'; | ||
import { join } from 'path'; | ||
import { TEMPLATES_DIR } from '../../constants'; | ||
import { IApi } from '../../types'; | ||
import { GeneratorHelper, trim } from './utils'; | ||
|
||
export default (api: IApi) => { | ||
api.describe({ | ||
key: 'generator:mock', | ||
}); | ||
|
||
api.registerGenerator({ | ||
key: 'mock', | ||
type: GeneratorType.generate, | ||
name: 'Generate mock code snippet', | ||
|
||
fn: async (opts) => { | ||
let [_, mockName] = opts.args._; | ||
|
||
const h = new GeneratorHelper(api); | ||
|
||
mockName = await h.ensureVariableWithQuestion(mockName, { | ||
type: 'text', | ||
message: 'please input your mock file name', | ||
initial: 'mockName', | ||
format: trim, | ||
}); | ||
|
||
opts.generateFile({ | ||
target: join(api.paths.cwd, 'mock', `${mockName}.ts`), | ||
baseDir: api.paths.cwd, | ||
path: join(TEMPLATES_DIR, 'generate/mock.ts.tpl'), | ||
data: { mockName }, | ||
}); | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { UmiApiRequest, UmiApiResponse } from "umi"; | ||
|
||
export default async function (req: UmiApiRequest, res: UmiApiResponse) { | ||
switch (req.method) { | ||
case 'GET': | ||
res.json({ {{{key}}}: {{{value}}} }) | ||
break; | ||
default: | ||
res.status(405).json({ error: 'Method not allowed' }) | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/preset-umi/templates/generate/component/component.tsx.tpl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import React from 'react' | ||
|
||
export default function {{{compName}}}() { | ||
return <div>{{{compName}}} is a awesome component</div> | ||
} |
Oops, something went wrong.