253 lines
6.8 KiB
JavaScript
253 lines
6.8 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import fs from 'node:fs/promises'
|
|
import http from 'node:http'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
import test from 'node:test'
|
|
|
|
import { generateApiFiles } from '../src/core/generate.js'
|
|
|
|
const createTempDir = async () => {
|
|
return fs.mkdtemp(path.join(os.tmpdir(), 'yx-generate-api-'))
|
|
}
|
|
|
|
const writeJson = async (filePath, value) => {
|
|
await fs.writeFile(filePath, JSON.stringify(value, null, 2), 'utf8')
|
|
}
|
|
|
|
const readFile = async (filePath) => {
|
|
return fs.readFile(filePath, 'utf8')
|
|
}
|
|
|
|
test('full generation cleans stale auto-generated files and keeps manual files', async () => {
|
|
const tempDir = await createTempDir()
|
|
|
|
try {
|
|
const initialSwaggerPath = path.join(tempDir, 'swagger-initial.json')
|
|
const updatedSwaggerPath = path.join(tempDir, 'swagger-updated.json')
|
|
const outputDir = path.join(tempDir, 'generated')
|
|
|
|
await writeJson(initialSwaggerPath, {
|
|
openapi: '3.0.0',
|
|
paths: {
|
|
'/api/v1/Alpha/GetThing': {
|
|
get: {
|
|
tags: ['Alpha'],
|
|
summary: 'Get alpha thing',
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
'/api/v1/Beta/GetList': {
|
|
get: {
|
|
tags: ['Beta'],
|
|
summary: 'Get beta list',
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await writeJson(updatedSwaggerPath, {
|
|
openapi: '3.0.0',
|
|
paths: {
|
|
'/api/v1/Alpha/GetThing': {
|
|
get: {
|
|
tags: ['Alpha'],
|
|
summary: 'Get alpha thing',
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await generateApiFiles({
|
|
projectRoot: tempDir,
|
|
swaggerUrl: initialSwaggerPath,
|
|
swaggerTimeoutMs: 1000,
|
|
outputDir,
|
|
requestImport: '../request',
|
|
paramStyle: 'object',
|
|
modules: [],
|
|
cleanOutput: true,
|
|
})
|
|
|
|
await fs.writeFile(path.join(outputDir, 'manual-helper.js'), 'export const keepMe = true\n', 'utf8')
|
|
|
|
await generateApiFiles({
|
|
projectRoot: tempDir,
|
|
swaggerUrl: updatedSwaggerPath,
|
|
swaggerTimeoutMs: 1000,
|
|
outputDir,
|
|
requestImport: '../request',
|
|
paramStyle: 'object',
|
|
modules: [],
|
|
cleanOutput: true,
|
|
})
|
|
|
|
await assert.doesNotReject(fs.access(path.join(outputDir, 'alpha.js')))
|
|
await assert.rejects(fs.access(path.join(outputDir, 'beta.js')))
|
|
await assert.doesNotReject(fs.access(path.join(outputDir, 'manual-helper.js')))
|
|
|
|
const sharedFile = await readFile(path.join(outputDir, 'shared.js'))
|
|
assert.doesNotMatch(sharedFile, /from 'qs'/)
|
|
assert.match(sharedFile, /appendQueryEntries/)
|
|
} finally {
|
|
await fs.rm(tempDir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
test('partial generation keeps other generated modules even when cleanOutput is enabled', async () => {
|
|
const tempDir = await createTempDir()
|
|
|
|
try {
|
|
const swaggerPath = path.join(tempDir, 'swagger.json')
|
|
const outputDir = path.join(tempDir, 'generated')
|
|
|
|
await writeJson(swaggerPath, {
|
|
openapi: '3.0.0',
|
|
paths: {
|
|
'/api/v1/Alpha/GetThing': {
|
|
get: {
|
|
tags: ['Alpha'],
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
'/api/v1/Beta/GetList': {
|
|
get: {
|
|
tags: ['Beta'],
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await generateApiFiles({
|
|
projectRoot: tempDir,
|
|
swaggerUrl: swaggerPath,
|
|
swaggerTimeoutMs: 1000,
|
|
outputDir,
|
|
requestImport: '../request',
|
|
paramStyle: 'object',
|
|
modules: [],
|
|
cleanOutput: true,
|
|
})
|
|
|
|
await generateApiFiles({
|
|
projectRoot: tempDir,
|
|
swaggerUrl: swaggerPath,
|
|
swaggerTimeoutMs: 1000,
|
|
outputDir,
|
|
requestImport: '../request',
|
|
paramStyle: 'object',
|
|
modules: ['Alpha'],
|
|
cleanOutput: true,
|
|
})
|
|
|
|
await assert.doesNotReject(fs.access(path.join(outputDir, 'beta.js')))
|
|
} finally {
|
|
await fs.rm(tempDir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
test('generated index includes namespace exports and collision-safe named exports', async () => {
|
|
const tempDir = await createTempDir()
|
|
|
|
try {
|
|
const swaggerPath = path.join(tempDir, 'swagger.json')
|
|
const outputDir = path.join(tempDir, 'generated')
|
|
|
|
await writeJson(swaggerPath, {
|
|
openapi: '3.0.0',
|
|
paths: {
|
|
'/api/v1/Alpha/GetList': {
|
|
get: {
|
|
tags: ['Alpha'],
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
'/api/v1/Beta/GetList': {
|
|
get: {
|
|
tags: ['Beta'],
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
'/api/v1/Beta/GetDetail': {
|
|
get: {
|
|
tags: ['Beta'],
|
|
responses: {
|
|
200: { description: 'OK' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await generateApiFiles({
|
|
projectRoot: tempDir,
|
|
swaggerUrl: swaggerPath,
|
|
swaggerTimeoutMs: 1000,
|
|
outputDir,
|
|
requestImport: '../request',
|
|
paramStyle: 'object',
|
|
modules: [],
|
|
cleanOutput: true,
|
|
})
|
|
|
|
const indexContent = await readFile(path.join(outputDir, 'index.js'))
|
|
|
|
assert.match(indexContent, /export \* as alphaApi from ["']\.\/alpha["']/)
|
|
assert.match(indexContent, /export \* as betaApi from ["']\.\/beta["']/)
|
|
assert.match(indexContent, /export \{ getListApi as alphaGetListApi \} from ["']\.\/alpha["']/)
|
|
assert.match(indexContent, /export \{ getListApi as betaGetListApi \} from ["']\.\/beta["']/)
|
|
assert.match(indexContent, /export \{ getDetailApi \} from ["']\.\/beta["']/)
|
|
} finally {
|
|
await fs.rm(tempDir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
test('swagger timeout surfaces a clear error message', async () => {
|
|
const tempDir = await createTempDir()
|
|
const server = http.createServer((_, response) => {
|
|
setTimeout(() => {
|
|
response.writeHead(200, { 'Content-Type': 'application/json' })
|
|
response.end(JSON.stringify({ openapi: '3.0.0', paths: {} }))
|
|
}, 100)
|
|
})
|
|
|
|
try {
|
|
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve))
|
|
const { port } = server.address()
|
|
|
|
await assert.rejects(
|
|
generateApiFiles({
|
|
projectRoot: tempDir,
|
|
swaggerUrl: `http://127.0.0.1:${port}/swagger.json`,
|
|
swaggerTimeoutMs: 10,
|
|
outputDir: path.join(tempDir, 'generated'),
|
|
requestImport: '../request',
|
|
paramStyle: 'object',
|
|
modules: [],
|
|
cleanOutput: true,
|
|
}),
|
|
/timed out/,
|
|
)
|
|
} finally {
|
|
server.close()
|
|
await fs.rm(tempDir, { recursive: true, force: true })
|
|
}
|
|
})
|