mirror of
https://github.com/langgenius/dify.git
synced 2026-11-13 14:51:39 +08:00
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
106 lines
4.0 KiB
TypeScript
106 lines
4.0 KiB
TypeScript
import { existsSync, globSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { basename, dirname, relative, resolve } from 'node:path'
|
|
import { format } from 'vite-plus/fmt'
|
|
|
|
const declarationHeader = '// Generated by @dify/contracts gen-compatibility-sources.\n'
|
|
|
|
function writeIfChanged(file: string, content: string) {
|
|
mkdirSync(dirname(file), { recursive: true })
|
|
const existing = existsSync(file) ? readFileSync(file, 'utf8') : undefined
|
|
// No-op generation must not restart the language server.
|
|
if (existing !== content) writeFileSync(file, content)
|
|
}
|
|
|
|
async function writeDescriptor(file: string, value: unknown) {
|
|
let content = `${JSON.stringify(value, null, 2)}\n`
|
|
if (file.endsWith('.json')) {
|
|
const formatted = await format(file, content)
|
|
if (formatted.errors.length) throw new Error(`Failed to format ${file}`)
|
|
content = formatted.code
|
|
}
|
|
writeIfChanged(file, content)
|
|
}
|
|
|
|
/** Thin mapper subpaths share one exporter configuration per backend source. */
|
|
export async function generateCompatibilitySources(
|
|
root = resolve(import.meta.dirname, '..'),
|
|
output = resolve(root, '../openapi-content-mapper/contracts'),
|
|
) {
|
|
const repo = resolve(root, '../..')
|
|
const sharedSources = {
|
|
community: resolve(output, 'community.source.json'),
|
|
enterprise: resolve(output, 'enterprise.source.json'),
|
|
}
|
|
for (const [name, file] of Object.entries(sharedSources)) {
|
|
const enterprise = name === 'enterprise'
|
|
await writeDescriptor(file, {
|
|
command: ['node', 'packages/contracts/scripts/export-compatibility-types.ts'],
|
|
cwd: relative(output, repo),
|
|
inputs: [
|
|
'packages/contracts/api-documents.ts',
|
|
'packages/contracts/typescript-generation.ts',
|
|
'packages/contracts/scripts/export-compatibility-types.ts',
|
|
'packages/contracts/package.json',
|
|
'pnpm-lock.yaml',
|
|
...(enterprise
|
|
? [
|
|
'packages/contracts/generated/enterprise*/types.gen.ts',
|
|
'packages/contracts/generated/enterprise*/openapi.gen.json',
|
|
]
|
|
: [
|
|
'packages/contracts/generated/api/**/types.gen.ts',
|
|
'api/**/*.py',
|
|
'dify-agent/src/**/*.py',
|
|
'dify-agent/pyproject.toml',
|
|
'api/pyproject.toml',
|
|
'api/uv.lock',
|
|
]),
|
|
],
|
|
...(enterprise
|
|
? {}
|
|
: {
|
|
env: ['UV_PROJECT_ENVIRONMENT'],
|
|
exclude: ['api/tests/**'],
|
|
optionalInputs: ['.env'],
|
|
}),
|
|
timeoutMs: 120000,
|
|
})
|
|
}
|
|
const modules = globSync('generated/**/types.gen.ts', { cwd: root }).sort()
|
|
const expected = new Set<string>()
|
|
for (const entry of modules) {
|
|
const module = entry.slice('generated/'.length, -'/types.gen.ts'.length)
|
|
const subpath = module.replace(/^api\//, '')
|
|
const file = resolve(output, `${subpath}.openapi-types`)
|
|
expected.add(file)
|
|
const declaration = resolve(output, `${subpath}.d.ts`)
|
|
expected.add(declaration)
|
|
// A native declaration entry avoids TS 7's missing-declaration hint for
|
|
// package exports targeting custom extensions. Types still come from the mapper.
|
|
writeIfChanged(declaration, `${declarationHeader}export type * from './${basename(file)}'\n`)
|
|
await writeDescriptor(file, {
|
|
extends: relative(
|
|
dirname(file),
|
|
sharedSources[module.startsWith('enterprise') ? 'enterprise' : 'community'],
|
|
),
|
|
args: [module],
|
|
})
|
|
}
|
|
for (const entry of globSync('**/*.openapi-types', { cwd: output })) {
|
|
const file = resolve(output, entry)
|
|
if (!expected.has(file)) {
|
|
const descriptor = JSON.parse(readFileSync(file, 'utf8'))
|
|
if (Object.values(sharedSources).includes(resolve(dirname(file), descriptor.extends ?? '')))
|
|
rmSync(file)
|
|
}
|
|
}
|
|
for (const entry of globSync('**/*.d.ts', { cwd: output })) {
|
|
const file = resolve(output, entry)
|
|
if (!expected.has(file) && readFileSync(file, 'utf8').startsWith(declarationHeader))
|
|
rmSync(file)
|
|
}
|
|
return modules
|
|
}
|
|
|
|
if (import.meta.main) await generateCompatibilitySources()
|