mirror of
https://github.com/langgenius/dify.git
synced 2026-04-19 18:27:27 +08:00
cli package
This commit is contained in:
25
packages/cli/bin/dify-cli.js
Executable file
25
packages/cli/bin/dify-cli.js
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const entryFile = path.join(packageRoot, 'src', 'cli.ts')
|
||||
const tsxImport = await import.meta.resolve('tsx')
|
||||
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
['--import', tsxImport, entryFile, ...process.argv.slice(2)],
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
env: process.env,
|
||||
stdio: 'inherit',
|
||||
},
|
||||
)
|
||||
|
||||
if (result.error)
|
||||
throw result.error
|
||||
|
||||
process.exit(result.status ?? 1)
|
||||
16
packages/cli/package.json
Normal file
16
packages/cli/package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@dify/cli",
|
||||
"private": true,
|
||||
"version": "0.0.0-private",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"dify-cli": "./bin/dify-cli.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"tsx": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:"
|
||||
}
|
||||
}
|
||||
57
packages/cli/src/cli.ts
Normal file
57
packages/cli/src/cli.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import process from 'node:process'
|
||||
import { runMigrationCommand } from './no-unchecked-indexed-access/migrate'
|
||||
import { runNormalizeCommand } from './no-unchecked-indexed-access/normalize'
|
||||
import { runResetCommand } from './no-unchecked-indexed-access/reset'
|
||||
import { runBatchMigrationCommand } from './no-unchecked-indexed-access/run'
|
||||
|
||||
type CommandHandler = (argv: string[]) => Promise<void>
|
||||
|
||||
const COMMANDS = new Map<string, CommandHandler>([
|
||||
['migrate', runMigrationCommand],
|
||||
['normalize', runNormalizeCommand],
|
||||
['reset', runResetCommand],
|
||||
['run', runBatchMigrationCommand],
|
||||
])
|
||||
|
||||
function printUsage() {
|
||||
console.log(`Usage:
|
||||
dify-cli no-unchecked-indexed-access migrate [options]
|
||||
dify-cli no-unchecked-indexed-access run [options]
|
||||
dify-cli no-unchecked-indexed-access normalize
|
||||
dify-cli no-unchecked-indexed-access reset`)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [group, command, ...restArgs] = process.argv.slice(2)
|
||||
|
||||
if (!group || group === 'help' || group === '--help' || group === '-h') {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
if (group !== 'no-unchecked-indexed-access') {
|
||||
printUsage()
|
||||
throw new Error(`Unknown command group: ${group}`)
|
||||
}
|
||||
|
||||
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
const handler = COMMANDS.get(command)
|
||||
if (!handler) {
|
||||
printUsage()
|
||||
throw new Error(`Unknown command: ${command}`)
|
||||
}
|
||||
|
||||
await handler(restArgs)
|
||||
}
|
||||
|
||||
try {
|
||||
await main()
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error instanceof Error ? error.message : error)
|
||||
process.exitCode = 1
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import ts from 'typescript'
|
||||
|
||||
const SUPPORTED_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts'])
|
||||
@ -44,6 +43,9 @@ export function parseArgs(argv: string[]): CliOptions {
|
||||
if (!arg)
|
||||
continue
|
||||
|
||||
if (arg === '--')
|
||||
continue
|
||||
|
||||
if (arg === '--write') {
|
||||
options.write = true
|
||||
continue
|
||||
@ -153,9 +155,6 @@ function isTargetFile(fileName: string): boolean {
|
||||
if (fileName.endsWith('.d.ts'))
|
||||
return false
|
||||
|
||||
if (fileName.endsWith(`${path.sep}scripts${path.sep}migrate-no-unchecked-indexed-access.ts`))
|
||||
return false
|
||||
|
||||
return !fileName.includes(`${path.sep}.next${path.sep}`)
|
||||
}
|
||||
|
||||
@ -1642,9 +1641,6 @@ export async function runMigration(options: CliOptions) {
|
||||
return { converged, totalEdits }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await runMigration(parseArgs(process.argv.slice(2)))
|
||||
export async function runMigrationCommand(argv: string[]) {
|
||||
await runMigration(parseArgs(argv))
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href)
|
||||
await main()
|
||||
@ -1,7 +1,7 @@
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { normalizeMalformedAssertions } from './migrate-no-unchecked-indexed-access'
|
||||
import { normalizeMalformedAssertions } from './migrate'
|
||||
|
||||
const ROOT = process.cwd()
|
||||
const EXTENSIONS = new Set(['.ts', '.tsx'])
|
||||
@ -46,4 +46,6 @@ async function main() {
|
||||
console.log(`Normalized malformed assertion syntax in ${changedFileCount} file(s).`)
|
||||
}
|
||||
|
||||
await main()
|
||||
export async function runNormalizeCommand(_argv: string[]) {
|
||||
await main()
|
||||
}
|
||||
@ -9,15 +9,29 @@ const execFileAsync = promisify(execFile)
|
||||
const PRESERVED_FILES = new Set([
|
||||
'web/package.json',
|
||||
'web/tsconfig.json',
|
||||
'web/scripts/migrate-no-unchecked-indexed-access.ts',
|
||||
'web/scripts/run-no-unchecked-indexed-access-migration.ts',
|
||||
'web/scripts/normalize-no-unchecked-indexed-access-migration.ts',
|
||||
'web/scripts/reset-no-unchecked-indexed-access-migration.ts',
|
||||
])
|
||||
|
||||
async function getTrackedChangedFiles(): Promise<string[]> {
|
||||
async function findWorkspaceRoot(startDirectory: string): Promise<string> {
|
||||
let currentDirectory = path.resolve(startDirectory)
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
await fs.access(path.join(currentDirectory, 'pnpm-workspace.yaml'))
|
||||
return currentDirectory
|
||||
}
|
||||
catch {}
|
||||
|
||||
const parentDirectory = path.dirname(currentDirectory)
|
||||
if (parentDirectory === currentDirectory)
|
||||
throw new Error('Could not find workspace root from the current directory.')
|
||||
|
||||
currentDirectory = parentDirectory
|
||||
}
|
||||
}
|
||||
|
||||
async function getTrackedChangedFiles(repoRoot: string): Promise<string[]> {
|
||||
const { stdout } = await execFileAsync('git', ['diff', '--name-only', 'HEAD', '--', 'web'], {
|
||||
cwd: path.resolve(process.cwd(), '..'),
|
||||
cwd: repoRoot,
|
||||
maxBuffer: 1024 * 1024 * 8,
|
||||
})
|
||||
|
||||
@ -27,9 +41,9 @@ async function getTrackedChangedFiles(): Promise<string[]> {
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
async function getUntrackedFiles(): Promise<string[]> {
|
||||
async function getUntrackedFiles(repoRoot: string): Promise<string[]> {
|
||||
const { stdout } = await execFileAsync('git', ['ls-files', '--others', '--exclude-standard', '--', 'web'], {
|
||||
cwd: path.resolve(process.cwd(), '..'),
|
||||
cwd: repoRoot,
|
||||
maxBuffer: 1024 * 1024 * 8,
|
||||
})
|
||||
|
||||
@ -40,9 +54,9 @@ async function getUntrackedFiles(): Promise<string[]> {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const repoRoot = path.resolve(process.cwd(), '..')
|
||||
const trackedChangedFiles = await getTrackedChangedFiles()
|
||||
const untrackedFiles = await getUntrackedFiles()
|
||||
const repoRoot = await findWorkspaceRoot(process.cwd())
|
||||
const trackedChangedFiles = await getTrackedChangedFiles(repoRoot)
|
||||
const untrackedFiles = await getUntrackedFiles(repoRoot)
|
||||
|
||||
let restoredCount = 0
|
||||
for (const relativePath of trackedChangedFiles) {
|
||||
@ -71,4 +85,6 @@ async function main() {
|
||||
console.log(`Restored ${restoredCount} tracked file(s) and removed ${removedCount} untracked file(s).`)
|
||||
}
|
||||
|
||||
await main()
|
||||
export async function runResetCommand(_argv: string[]) {
|
||||
await main()
|
||||
}
|
||||
@ -2,7 +2,7 @@ import { execFile } from 'node:child_process'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { promisify } from 'node:util'
|
||||
import { runMigration, SUPPORTED_DIAGNOSTIC_CODES } from './migrate-no-unchecked-indexed-access'
|
||||
import { runMigration, SUPPORTED_DIAGNOSTIC_CODES } from './migrate'
|
||||
|
||||
const execFileAsync = promisify(execFile)
|
||||
const DIAGNOSTIC_PATTERN = /^(.+?\.(?:ts|tsx))\((\d+),(\d+)\): error TS(\d+): (.+)$/
|
||||
@ -37,6 +37,9 @@ function parseArgs(argv: string[]): CliOptions {
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const arg = argv[i]
|
||||
|
||||
if (arg === '--')
|
||||
continue
|
||||
|
||||
if (arg === '--verbose') {
|
||||
options.verbose = true
|
||||
continue
|
||||
@ -166,9 +169,7 @@ function chunk<T>(items: T[], size: number): T[][] {
|
||||
return batches
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const options = parseArgs(process.argv.slice(2))
|
||||
|
||||
async function runBatchMigration(options: CliOptions) {
|
||||
for (let round = 1; round <= options.maxRounds; round += 1) {
|
||||
const { diagnostics, exitCode, rawOutput } = await runTypeCheck(options.project)
|
||||
if (exitCode === 0) {
|
||||
@ -226,4 +227,6 @@ async function main() {
|
||||
process.exitCode = 1
|
||||
}
|
||||
|
||||
await main()
|
||||
export async function runBatchMigrationCommand(argv: string[]) {
|
||||
await runBatchMigration(parseArgs(argv))
|
||||
}
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@ -599,6 +599,19 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.16(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.16(@types/node@25.6.0)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.1)(tsx@4.21.0)(typescript@6.0.2)(yaml@2.8.3))(happy-dom@20.9.0)(jiti@2.6.1)(sass@1.98.0)(terser@5.46.1)(tsx@4.21.0)(typescript@6.0.2)(yaml@2.8.3)
|
||||
|
||||
packages/cli:
|
||||
dependencies:
|
||||
tsx:
|
||||
specifier: 'catalog:'
|
||||
version: 4.21.0
|
||||
typescript:
|
||||
specifier: 'catalog:'
|
||||
version: 6.0.2
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: 'catalog:'
|
||||
version: 25.6.0
|
||||
|
||||
packages/iconify-collections:
|
||||
devDependencies:
|
||||
iconify-import-svg:
|
||||
@ -953,6 +966,9 @@ importers:
|
||||
'@chromatic-com/storybook':
|
||||
specifier: 'catalog:'
|
||||
version: 5.1.2(storybook@10.3.5(@testing-library/dom@10.4.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))
|
||||
'@dify/cli':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/cli
|
||||
'@dify/iconify-collections':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/iconify-collections
|
||||
|
||||
@ -39,10 +39,10 @@
|
||||
"lint:fix": "vp run lint --fix",
|
||||
"lint:quiet": "vp run lint --quiet",
|
||||
"lint:tss": "tsslint --project tsconfig.json",
|
||||
"migrate:no-unchecked-indexed-access": "tsx ./scripts/migrate-no-unchecked-indexed-access.ts",
|
||||
"migrate:no-unchecked-indexed-access:all": "tsx ./scripts/run-no-unchecked-indexed-access-migration.ts",
|
||||
"migrate:no-unchecked-indexed-access:normalize": "tsx ./scripts/normalize-no-unchecked-indexed-access-migration.ts",
|
||||
"migrate:no-unchecked-indexed-access:reset": "tsx ./scripts/reset-no-unchecked-indexed-access-migration.ts",
|
||||
"migrate:no-unchecked-indexed-access": "dify-cli no-unchecked-indexed-access migrate",
|
||||
"migrate:no-unchecked-indexed-access:all": "dify-cli no-unchecked-indexed-access run",
|
||||
"migrate:no-unchecked-indexed-access:normalize": "dify-cli no-unchecked-indexed-access normalize",
|
||||
"migrate:no-unchecked-indexed-access:reset": "dify-cli no-unchecked-indexed-access reset",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"refactor-component": "node ./scripts/refactor-component.js",
|
||||
"start": "node ./scripts/copy-and-start.mjs",
|
||||
@ -163,6 +163,7 @@
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "catalog:",
|
||||
"@chromatic-com/storybook": "catalog:",
|
||||
"@dify/cli": "workspace:*",
|
||||
"@dify/iconify-collections": "workspace:*",
|
||||
"@egoist/tailwindcss-icons": "catalog:",
|
||||
"@eslint-react/eslint-plugin": "catalog:",
|
||||
|
||||
Reference in New Issue
Block a user