Skip to content

Commit 44d0858

Browse files
committed
feat: integrate knitwork-x for code generation and typings, update pnpm workspace and package dependencies
1 parent f8758cc commit 44d0858

9 files changed

Lines changed: 108 additions & 236 deletions

File tree

packages/pipeline/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,9 @@
3434
"@genapi/shared": "workspace:*",
3535
"fs-extra": "catalog:runtime",
3636
"got": "catalog:runtime",
37+
"knitwork-x": "catalog:runtime",
3738
"p-pipe": "catalog:runtime",
38-
"prettier": "catalog:runtime",
39-
"ts-factory-extra": "catalog:runtime",
40-
"typescript": "catalog:cli"
39+
"prettier": "catalog:runtime"
4140
},
4241
"devDependencies": {
4342
"@types/fs-extra": "catalog:types",

packages/pipeline/src/compiler/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import { compilerTsRequestDeclaration } from './request'
33
import { compilerTsTypingsDeclaration } from './typings'
44

55
/**
6-
* Compiles graphs to AST: request code and typings for each output.
6+
* Compiles graphs to code string: request and typings for each output.
77
*
88
* @param configRead - ConfigRead with graphs and outputs
9-
* @returns Same configRead with output.ast set
9+
* @returns Same configRead with output.code set
1010
* @group Pipeline
1111
*/
1212
export function compiler(configRead: ApiPipeline.ConfigRead) {
1313
for (const output of configRead.outputs) {
1414
if (output.type === 'request' && !configRead.config.onlyDeclaration)
15-
output.ast = compilerTsRequestDeclaration(configRead)
15+
output.code = compilerTsRequestDeclaration(configRead)
1616
if (output.type === 'typings')
17-
output.ast = compilerTsTypingsDeclaration(configRead)
17+
output.code = compilerTsTypingsDeclaration(configRead)
1818
}
1919

2020
return configRead
Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import type { ApiPipeline } from '@genapi/shared'
2-
import { codeToAstNode, createComment, createFunction, createImport, createVariable } from 'ts-factory-extra'
2+
import {
3+
genComment,
4+
genFunction,
5+
genImport,
6+
genVariable,
7+
} from 'knitwork-x'
38

4-
import { factory, NodeFlags } from 'typescript'
59
import { compilerTsTypingsDeclaration } from './typings'
610

7-
const varFlags = {
8-
let: NodeFlags.Let,
9-
const: NodeFlags.Const,
10-
var: NodeFlags.None,
11-
}
12-
// @ts-check
13-
export function compilerTsRequestDeclaration(configRead: ApiPipeline.ConfigRead) {
11+
/**
12+
* Compiles configRead graphs to request code string using knitwork-x.
13+
*/
14+
export function compilerTsRequestDeclaration(configRead: ApiPipeline.ConfigRead): string {
1415
configRead.graphs.imports = configRead.graphs.imports || []
1516
configRead.graphs.comments = configRead.graphs.comments || []
1617
configRead.graphs.variables = configRead.graphs.variables || []
@@ -19,46 +20,64 @@ export function compilerTsRequestDeclaration(configRead: ApiPipeline.ConfigRead)
1920
const isGenerateType = configRead.outputs.some(v => v.type === 'typings')
2021
const isTypescript = configRead.outputs.some(v => v.type === 'request' && v.path.endsWith('.ts'))
2122

22-
const comments = [
23-
createComment('multi', configRead.graphs.comments),
24-
]
25-
const imports = configRead.graphs.imports?.map((item) => {
26-
return createImport(item.name, item.names, item.value, item.namespace)
23+
const sections: string[] = []
24+
25+
// Comments
26+
if (configRead.graphs.comments.length > 0) {
27+
sections.push(genComment(configRead.graphs.comments.join('\n'), { block: true }))
28+
}
29+
30+
// Imports
31+
const importLines = configRead.graphs.imports.map((item) => {
32+
if (item.namespace)
33+
return genImport(item.value, { name: '*', as: item.name! }, { type: !!item.type })
34+
if (item.name && !item.names)
35+
return genImport(item.value, item.name, { type: !!item.type })
36+
if (item.name && item.names?.length) {
37+
const imports = [{ name: 'default', as: item.name }, ...item.names.map(n => ({ name: n }))]
38+
return genImport(item.value, imports, { type: !!item.type })
39+
}
40+
return genImport(item.value, item.names || [], { type: !!item.type })
2741
})
28-
const variables = configRead.graphs.variables.map((item) => {
29-
// eslint-disable-next-line ts/ban-ts-comment
30-
// @ts-expect-error
31-
return createVariable(item.export, varFlags[item.flag], item.name, item.value)
42+
if (importLines.length > 0)
43+
sections.push(importLines.join('\n'))
44+
45+
// Variables
46+
const variableLines = configRead.graphs.variables.map((item) => {
47+
return genVariable(item.name, item.value ?? '', {
48+
export: !!item.export,
49+
kind: item.flag,
50+
})
3251
})
33-
const functions = configRead.graphs.functions.flatMap((item) => {
34-
return createFunction({
52+
if (variableLines.length > 0)
53+
sections.push(variableLines.join('\n'))
54+
55+
// Functions
56+
const functionLines = configRead.graphs.functions.map((item) => {
57+
return genFunction({
3558
export: true,
36-
comment: item.description,
3759
name: item.name,
38-
parameters: item.parameters,
39-
body: item.body?.map(codeToAstNode),
60+
parameters: (item.parameters || []).map(p => ({
61+
name: p.name,
62+
type: p.type,
63+
optional: !p.required,
64+
})),
65+
body: item.body || [],
4066
async: item.async,
4167
returnType: item.returnType,
4268
generics: item.generics,
4369
generator: item.generator,
70+
jsdoc: item.description,
4471
})
4572
})
73+
if (functionLines.length > 0)
74+
sections.push(functionLines.join('\n\n'))
4675

47-
const nodes = [
48-
...comments,
49-
factory.createIdentifier(''),
50-
...imports,
51-
factory.createIdentifier(''),
52-
...variables,
53-
factory.createIdentifier(''),
54-
...functions,
55-
]
56-
76+
// Inline typings for TS request files when not generating separate typings
5777
if (!isGenerateType && isTypescript) {
58-
nodes.push(factory.createIdentifier(''))
59-
nodes.push(factory.createIdentifier(''))
60-
nodes.push(...compilerTsTypingsDeclaration(configRead, false))
78+
sections.push('')
79+
sections.push(compilerTsTypingsDeclaration(configRead, false))
6180
}
6281

63-
return nodes
82+
return sections.filter(Boolean).join('\n\n')
6483
}
Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
11
import type { ApiPipeline } from '@genapi/shared'
2-
import { createComment, createInterface, createTypeAlias } from 'ts-factory-extra'
3-
import { factory } from 'typescript'
2+
import { genComment, genInterface, genTypeAlias } from 'knitwork-x'
43

5-
export function compilerTsTypingsDeclaration(configRead: ApiPipeline.ConfigRead, comment = true) {
4+
/**
5+
* Compiles configRead graphs to typings code string using knitwork-x.
6+
*/
7+
export function compilerTsTypingsDeclaration(configRead: ApiPipeline.ConfigRead, comment = true): string {
68
configRead.graphs.comments = configRead.graphs.comments || []
79
configRead.graphs.typings = configRead.graphs.typings || []
810
configRead.graphs.interfaces = configRead.graphs.interfaces || []
911

12+
const sections: string[] = []
13+
14+
if (comment && configRead.graphs.comments.length > 0) {
15+
sections.push(genComment(configRead.graphs.comments.join('\n'), { block: true }))
16+
}
17+
1018
const typings = configRead.graphs.typings.map((item) => {
11-
return createTypeAlias(item.export, item.name, item.value)
19+
return genTypeAlias(item.name, item.value, { export: !!item.export })
1220
})
21+
if (typings.length > 0)
22+
sections.push(typings.join('\n'))
23+
1324
const interfaces = configRead.graphs.interfaces.map((item) => {
14-
return createInterface({
15-
export: item.export,
16-
name: item.name,
17-
properties: item.properties || [],
18-
})
25+
const properties = (item.properties || []).map(p => ({
26+
name: p.name,
27+
type: p.type ?? 'any',
28+
optional: !p.required,
29+
jsdoc: p.description,
30+
}))
31+
return genInterface(item.name, properties, { export: !!item.export })
1932
})
33+
if (interfaces.length > 0)
34+
sections.push(interfaces.join('\n'))
2035

21-
const nodes = [
22-
factory.createIdentifier(''),
23-
...typings,
24-
factory.createIdentifier(''),
25-
...interfaces,
26-
]
27-
28-
if (comment)
29-
nodes.unshift(createComment('multi', configRead.graphs.comments))
30-
31-
return nodes as any[]
36+
return sections.filter(Boolean).join('\n\n')
3237
}

packages/pipeline/src/generate/index.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import type { ApiPipeline } from '@genapi/shared'
22
import { format } from 'prettier'
3-
import { astNodeToCode } from 'ts-factory-extra'
43

54
/**
6-
* Generates code string from AST for each output and formats with Prettier.
5+
* Formats code for each output with Prettier.
76
*
8-
* @param configRead - ConfigRead with outputs[].ast
9-
* @returns Same configRead with outputs[].code set
7+
* @param configRead - ConfigRead with outputs[].code
8+
* @returns Same configRead with outputs[].code formatted
109
* @group Pipeline
1110
*/
1211
export function generate(configRead: ApiPipeline.ConfigRead) {
1312
for (const output of configRead.outputs || []) {
14-
if (output.ast)
15-
output.code = astNodeToCode(output.ast)
1613
if (output.code)
1714
output.code = formatTypescript(output.code)
1815
}

playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"type": "module",
44
"private": true,
55
"scripts": {
6-
"start": "genapi"
6+
"build": "genapi"
77
},
88
"dependencies": {
99
"@genapi/core": "workspace:*",

0 commit comments

Comments
 (0)