prjct-cli 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/bin/dev.js +0 -1
- package/bin/serve.js +19 -20
- package/core/agentic/agent-router.ts +79 -14
- package/core/agentic/command-executor/command-executor.ts +2 -74
- package/core/agentic/services.ts +0 -48
- package/core/agentic/template-loader.ts +35 -1
- package/core/commands/base.ts +96 -77
- package/core/commands/planning.ts +13 -2
- package/core/commands/setup.ts +3 -85
- package/core/errors.ts +209 -0
- package/core/infrastructure/config-manager.ts +22 -5
- package/core/infrastructure/setup.ts +5 -50
- package/core/storage/storage-manager.ts +42 -6
- package/core/utils/logger.ts +19 -12
- package/package.json +2 -4
- package/templates/agentic/subagent-generation.md +109 -0
- package/templates/commands/setup.md +18 -3
- package/templates/commands/sync.md +74 -13
- package/templates/mcp-config.json +20 -1
- package/templates/subagents/domain/backend.md +105 -0
- package/templates/subagents/domain/database.md +118 -0
- package/templates/subagents/domain/devops.md +148 -0
- package/templates/subagents/domain/frontend.md +99 -0
- package/templates/subagents/domain/testing.md +169 -0
- package/templates/subagents/workflow/prjct-planner.md +158 -0
- package/templates/subagents/workflow/prjct-shipper.md +179 -0
- package/templates/subagents/workflow/prjct-workflow.md +98 -0
- package/bin/generate-views.js +0 -209
- package/bin/migrate-to-json.js +0 -742
- package/core/agentic/context-filter.ts +0 -365
- package/core/agentic/parallel-tools.ts +0 -165
- package/core/agentic/response-templates.ts +0 -164
- package/core/agentic/semantic-compression.ts +0 -273
- package/core/agentic/think-blocks.ts +0 -202
- package/core/agentic/validation-rules.ts +0 -313
- package/core/domain/agent-matcher.ts +0 -130
- package/core/domain/agent-validator.ts +0 -250
- package/core/domain/architect-session.ts +0 -315
- package/core/domain/product-standards.ts +0 -106
- package/core/domain/smart-cache.ts +0 -167
- package/core/domain/task-analyzer.ts +0 -296
- package/core/infrastructure/legacy-installer-detector/cleanup.ts +0 -216
- package/core/infrastructure/legacy-installer-detector/detection.ts +0 -95
- package/core/infrastructure/legacy-installer-detector/index.ts +0 -171
- package/core/infrastructure/legacy-installer-detector/migration.ts +0 -87
- package/core/infrastructure/legacy-installer-detector/types.ts +0 -42
- package/core/infrastructure/legacy-installer-detector.ts +0 -7
- package/core/infrastructure/migrator/file-operations.ts +0 -125
- package/core/infrastructure/migrator/index.ts +0 -288
- package/core/infrastructure/migrator/project-scanner.ts +0 -90
- package/core/infrastructure/migrator/reports.ts +0 -117
- package/core/infrastructure/migrator/types.ts +0 -124
- package/core/infrastructure/migrator/validation.ts +0 -94
- package/core/infrastructure/migrator/version-migration.ts +0 -117
- package/core/infrastructure/migrator.ts +0 -10
- package/core/infrastructure/uuid-migration.ts +0 -750
- package/templates/commands/migrate-all.md +0 -96
- package/templates/commands/migrate.md +0 -140
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Legacy Installer Detector
|
|
3
|
-
*
|
|
4
|
-
* Detects and cleans up legacy curl-based installations from ~/.prjct-cli/
|
|
5
|
-
*
|
|
6
|
-
* @version 0.8.8
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
legacyInstallDir,
|
|
11
|
-
npmGlobalProjectsDir,
|
|
12
|
-
isWindows,
|
|
13
|
-
hasLegacyInstallation,
|
|
14
|
-
getNpmGlobalPath,
|
|
15
|
-
hasNpmInstallation,
|
|
16
|
-
getLegacyVersion,
|
|
17
|
-
needsCleanup,
|
|
18
|
-
} from './detection'
|
|
19
|
-
|
|
20
|
-
import { migrateProjectsData } from './migration'
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
cleanupLegacyInstallation,
|
|
24
|
-
cleanupLegacyPATH,
|
|
25
|
-
cleanupLegacySymlinks,
|
|
26
|
-
getShellConfigFiles,
|
|
27
|
-
} from './cleanup'
|
|
28
|
-
|
|
29
|
-
import type { CleanupReport, CleanupOptions } from './types'
|
|
30
|
-
import { CYAN, GREEN, YELLOW, RED, DIM, NC } from './types'
|
|
31
|
-
|
|
32
|
-
class LegacyInstallerDetector {
|
|
33
|
-
legacyInstallDir = legacyInstallDir
|
|
34
|
-
npmGlobalProjectsDir = npmGlobalProjectsDir
|
|
35
|
-
isWindows = isWindows
|
|
36
|
-
|
|
37
|
-
hasLegacyInstallation = hasLegacyInstallation
|
|
38
|
-
getNpmGlobalPath = getNpmGlobalPath
|
|
39
|
-
hasNpmInstallation = hasNpmInstallation
|
|
40
|
-
getLegacyVersion = getLegacyVersion
|
|
41
|
-
needsCleanup = needsCleanup
|
|
42
|
-
migrateProjectsData = migrateProjectsData
|
|
43
|
-
cleanupLegacyInstallation = cleanupLegacyInstallation
|
|
44
|
-
cleanupLegacyPATH = cleanupLegacyPATH
|
|
45
|
-
cleanupLegacySymlinks = cleanupLegacySymlinks
|
|
46
|
-
getShellConfigFiles = getShellConfigFiles
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Perform complete legacy cleanup
|
|
50
|
-
*/
|
|
51
|
-
async performCleanup(options: CleanupOptions = {}): Promise<CleanupReport> {
|
|
52
|
-
const { verbose = true } = options
|
|
53
|
-
|
|
54
|
-
const report: CleanupReport = {
|
|
55
|
-
success: false,
|
|
56
|
-
legacyVersion: null,
|
|
57
|
-
hasNpm: false,
|
|
58
|
-
steps: {
|
|
59
|
-
projectsMigrated: 0,
|
|
60
|
-
installationCleaned: false,
|
|
61
|
-
pathCleaned: false,
|
|
62
|
-
symlinksCleaned: false,
|
|
63
|
-
},
|
|
64
|
-
messages: [],
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const hasLegacy = await hasLegacyInstallation()
|
|
69
|
-
|
|
70
|
-
if (!hasLegacy) {
|
|
71
|
-
report.success = true
|
|
72
|
-
report.messages.push('No legacy installation found')
|
|
73
|
-
return report
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
report.legacyVersion = await getLegacyVersion()
|
|
77
|
-
report.hasNpm = await hasNpmInstallation()
|
|
78
|
-
|
|
79
|
-
if (verbose) {
|
|
80
|
-
console.log('')
|
|
81
|
-
console.log(`${YELLOW}----------------------------------------${NC}`)
|
|
82
|
-
console.log(`${YELLOW}Legacy curl installation detected${NC}`)
|
|
83
|
-
console.log(`${YELLOW}----------------------------------------${NC}`)
|
|
84
|
-
console.log('')
|
|
85
|
-
console.log(` ${DIM}Version: ${report.legacyVersion || 'unknown'}${NC}`)
|
|
86
|
-
console.log(` ${DIM}Location: ~/.prjct-cli/${NC}`)
|
|
87
|
-
console.log('')
|
|
88
|
-
|
|
89
|
-
if (!report.hasNpm) {
|
|
90
|
-
console.log(`${RED}npm global installation not found${NC}`)
|
|
91
|
-
console.log('')
|
|
92
|
-
console.log(`${CYAN}Install prjct-cli via npm first:${NC}`)
|
|
93
|
-
console.log(` ${GREEN}npm install -g prjct-cli${NC}`)
|
|
94
|
-
console.log('')
|
|
95
|
-
return report
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
console.log(`${CYAN}Migrating to npm installation...${NC}`)
|
|
99
|
-
console.log('')
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Step 1: Migrate projects data
|
|
103
|
-
if (verbose) console.log(` ${DIM}Migrating projects data...${NC}`)
|
|
104
|
-
const projectsMigration = await migrateProjectsData()
|
|
105
|
-
report.steps.projectsMigrated = projectsMigration.projectsMigrated
|
|
106
|
-
report.messages.push(projectsMigration.message)
|
|
107
|
-
if (verbose) {
|
|
108
|
-
const icon = projectsMigration.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
|
|
109
|
-
console.log(` ${icon} ${projectsMigration.message}`)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Step 2: Clean legacy installation
|
|
113
|
-
if (verbose) console.log(` ${DIM}Removing legacy files...${NC}`)
|
|
114
|
-
const installCleanup = await cleanupLegacyInstallation()
|
|
115
|
-
report.steps.installationCleaned = installCleanup.success
|
|
116
|
-
report.messages.push(installCleanup.message)
|
|
117
|
-
if (verbose) {
|
|
118
|
-
const icon = installCleanup.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
|
|
119
|
-
console.log(` ${icon} ${installCleanup.message}`)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Step 3: Clean PATH entries
|
|
123
|
-
if (verbose) console.log(` ${DIM}Cleaning shell PATH...${NC}`)
|
|
124
|
-
const pathCleanup = await cleanupLegacyPATH()
|
|
125
|
-
report.steps.pathCleaned = pathCleanup.success
|
|
126
|
-
report.messages.push(pathCleanup.message)
|
|
127
|
-
if (verbose) {
|
|
128
|
-
const icon = pathCleanup.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
|
|
129
|
-
console.log(` ${icon} ${pathCleanup.message}`)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Step 4: Clean symlinks
|
|
133
|
-
if (verbose) console.log(` ${DIM}Cleaning symlinks...${NC}`)
|
|
134
|
-
const symlinkCleanup = await cleanupLegacySymlinks()
|
|
135
|
-
report.steps.symlinksCleaned = symlinkCleanup.success
|
|
136
|
-
report.messages.push(symlinkCleanup.message)
|
|
137
|
-
if (verbose) {
|
|
138
|
-
const icon = symlinkCleanup.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
|
|
139
|
-
console.log(` ${icon} ${symlinkCleanup.message}`)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (verbose) {
|
|
143
|
-
console.log('')
|
|
144
|
-
console.log(`${GREEN}Migration complete!${NC}`)
|
|
145
|
-
console.log('')
|
|
146
|
-
console.log(`${DIM}Next steps:${NC}`)
|
|
147
|
-
if (pathCleanup.filesModified && pathCleanup.filesModified > 0) {
|
|
148
|
-
console.log(` ${CYAN}1. Reload your shell:${NC}`)
|
|
149
|
-
console.log(` source ~/.zshrc ${DIM}(or ~/.bashrc)${NC}`)
|
|
150
|
-
console.log('')
|
|
151
|
-
}
|
|
152
|
-
const stepNum = pathCleanup.filesModified && pathCleanup.filesModified > 0 ? '2' : '1'
|
|
153
|
-
console.log(` ${CYAN}${stepNum}. Verify installation:${NC}`)
|
|
154
|
-
console.log(` which prjct ${DIM}(should show npm path)${NC}`)
|
|
155
|
-
console.log(` prjct --version`)
|
|
156
|
-
console.log('')
|
|
157
|
-
console.log(`${YELLOW}----------------------------------------${NC}`)
|
|
158
|
-
console.log('')
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
report.success = true
|
|
162
|
-
return report
|
|
163
|
-
} catch (error) {
|
|
164
|
-
report.messages.push(`Cleanup failed: ${(error as Error).message}`)
|
|
165
|
-
return report
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const legacyInstallerDetector = new LegacyInstallerDetector()
|
|
171
|
-
export default legacyInstallerDetector
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migration - Project Data Migration
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import fs from 'fs/promises'
|
|
6
|
-
import path from 'path'
|
|
7
|
-
import { legacyInstallDir, npmGlobalProjectsDir } from './detection'
|
|
8
|
-
import type { MigrationResult } from './types'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Copy directory recursively
|
|
12
|
-
*/
|
|
13
|
-
async function copyDirectory(source: string, destination: string): Promise<void> {
|
|
14
|
-
await fs.mkdir(destination, { recursive: true })
|
|
15
|
-
|
|
16
|
-
const entries = await fs.readdir(source, { withFileTypes: true })
|
|
17
|
-
|
|
18
|
-
for (const entry of entries) {
|
|
19
|
-
const sourcePath = path.join(source, entry.name)
|
|
20
|
-
const destPath = path.join(destination, entry.name)
|
|
21
|
-
|
|
22
|
-
if (entry.isDirectory()) {
|
|
23
|
-
await copyDirectory(sourcePath, destPath)
|
|
24
|
-
} else {
|
|
25
|
-
await fs.copyFile(sourcePath, destPath)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Migrate projects data from legacy location to npm location
|
|
32
|
-
*/
|
|
33
|
-
export async function migrateProjectsData(): Promise<MigrationResult> {
|
|
34
|
-
const result: MigrationResult = {
|
|
35
|
-
success: false,
|
|
36
|
-
projectsMigrated: 0,
|
|
37
|
-
message: '',
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const legacyProjectsDir = path.join(legacyInstallDir, 'projects')
|
|
42
|
-
|
|
43
|
-
// Check if legacy projects directory exists
|
|
44
|
-
try {
|
|
45
|
-
await fs.access(legacyProjectsDir)
|
|
46
|
-
} catch {
|
|
47
|
-
result.success = true
|
|
48
|
-
result.message = 'No projects data to migrate'
|
|
49
|
-
return result
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Ensure npm global projects directory exists
|
|
53
|
-
await fs.mkdir(npmGlobalProjectsDir, { recursive: true })
|
|
54
|
-
|
|
55
|
-
// Read all project directories
|
|
56
|
-
const projectDirs = await fs.readdir(legacyProjectsDir, { withFileTypes: true })
|
|
57
|
-
|
|
58
|
-
for (const entry of projectDirs) {
|
|
59
|
-
if (!entry.isDirectory()) continue
|
|
60
|
-
|
|
61
|
-
const legacyProjectPath = path.join(legacyProjectsDir, entry.name)
|
|
62
|
-
const npmProjectPath = path.join(npmGlobalProjectsDir, entry.name)
|
|
63
|
-
|
|
64
|
-
// Check if project already exists in npm location
|
|
65
|
-
try {
|
|
66
|
-
await fs.access(npmProjectPath)
|
|
67
|
-
// Already exists, skip
|
|
68
|
-
continue
|
|
69
|
-
} catch {
|
|
70
|
-
// Doesn't exist, copy it
|
|
71
|
-
await copyDirectory(legacyProjectPath, npmProjectPath)
|
|
72
|
-
result.projectsMigrated++
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
result.success = true
|
|
77
|
-
result.message =
|
|
78
|
-
result.projectsMigrated > 0
|
|
79
|
-
? `Migrated ${result.projectsMigrated} project(s) to npm global location`
|
|
80
|
-
: 'All projects already in npm location'
|
|
81
|
-
|
|
82
|
-
return result
|
|
83
|
-
} catch (error) {
|
|
84
|
-
result.message = `Migration failed: ${(error as Error).message}`
|
|
85
|
-
return result
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Legacy Installer Detector Types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// Colors
|
|
6
|
-
export const CYAN = '\x1b[36m'
|
|
7
|
-
export const GREEN = '\x1b[32m'
|
|
8
|
-
export const YELLOW = '\x1b[33m'
|
|
9
|
-
export const RED = '\x1b[31m'
|
|
10
|
-
export const DIM = '\x1b[2m'
|
|
11
|
-
export const NC = '\x1b[0m'
|
|
12
|
-
|
|
13
|
-
export interface CleanupSteps {
|
|
14
|
-
projectsMigrated: number
|
|
15
|
-
installationCleaned: boolean
|
|
16
|
-
pathCleaned: boolean
|
|
17
|
-
symlinksCleaned: boolean
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface CleanupReport {
|
|
21
|
-
success: boolean
|
|
22
|
-
legacyVersion: string | null
|
|
23
|
-
hasNpm: boolean
|
|
24
|
-
steps: CleanupSteps
|
|
25
|
-
messages: string[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface MigrationResult {
|
|
29
|
-
success: boolean
|
|
30
|
-
projectsMigrated: number
|
|
31
|
-
message: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface CleanupResult {
|
|
35
|
-
success: boolean
|
|
36
|
-
message: string
|
|
37
|
-
filesModified?: number
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface CleanupOptions {
|
|
41
|
-
verbose?: boolean
|
|
42
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File Operations
|
|
3
|
-
* Handles file copying and mapping for migrations.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import fs from 'fs/promises'
|
|
7
|
-
import path from 'path'
|
|
8
|
-
import type { FileMapping, MigrationStats, LayerCounts } from './types'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Copy a directory recursively
|
|
12
|
-
*/
|
|
13
|
-
export async function copyDirectory(source: string, destination: string): Promise<number> {
|
|
14
|
-
let fileCount = 0
|
|
15
|
-
|
|
16
|
-
await fs.mkdir(destination, { recursive: true })
|
|
17
|
-
|
|
18
|
-
const entries = await fs.readdir(source, { withFileTypes: true })
|
|
19
|
-
|
|
20
|
-
for (const entry of entries) {
|
|
21
|
-
const sourcePath = path.join(source, entry.name)
|
|
22
|
-
const destPath = path.join(destination, entry.name)
|
|
23
|
-
|
|
24
|
-
if (entry.isDirectory()) {
|
|
25
|
-
fileCount += await copyDirectory(sourcePath, destPath)
|
|
26
|
-
} else {
|
|
27
|
-
await fs.copyFile(sourcePath, destPath)
|
|
28
|
-
fileCount++
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return fileCount
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Map legacy flat structure to new layered structure
|
|
37
|
-
*/
|
|
38
|
-
export function mapLegacyFile(filename: string): FileMapping {
|
|
39
|
-
if (filename === 'now.md' || filename === 'next.md' || filename === 'context.md') {
|
|
40
|
-
return { layer: 'core', filename }
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (filename === 'shipped.md' || filename === 'metrics.md') {
|
|
44
|
-
return { layer: 'progress', filename }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (filename === 'ideas.md' || filename === 'roadmap.md') {
|
|
48
|
-
return { layer: 'planning', filename }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
filename === 'memory.jsonl' ||
|
|
53
|
-
filename === 'context.jsonl' ||
|
|
54
|
-
filename === 'decisions.jsonl'
|
|
55
|
-
) {
|
|
56
|
-
return { layer: 'memory', filename }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (filename === 'repo-summary.md') {
|
|
60
|
-
return { layer: 'analysis', filename }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return { layer: '.', filename }
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Migrate files from legacy structure to new layered structure
|
|
68
|
-
*/
|
|
69
|
-
export async function migrateFiles(legacyPath: string, globalPath: string): Promise<MigrationStats> {
|
|
70
|
-
let fileCount = 0
|
|
71
|
-
const layerCounts: LayerCounts = {
|
|
72
|
-
core: 0,
|
|
73
|
-
progress: 0,
|
|
74
|
-
planning: 0,
|
|
75
|
-
analysis: 0,
|
|
76
|
-
memory: 0,
|
|
77
|
-
other: 0,
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const validLayers = ['core', 'progress', 'planning', 'analysis', 'memory', 'sessions']
|
|
81
|
-
const entries = await fs.readdir(legacyPath, { withFileTypes: true })
|
|
82
|
-
|
|
83
|
-
for (const entry of entries) {
|
|
84
|
-
const sourcePath = path.join(legacyPath, entry.name)
|
|
85
|
-
|
|
86
|
-
if (entry.name === 'prjct.config.json' || entry.name.endsWith('.old')) {
|
|
87
|
-
continue
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (entry.isDirectory()) {
|
|
91
|
-
if (validLayers.includes(entry.name)) {
|
|
92
|
-
const destPath = path.join(globalPath, entry.name)
|
|
93
|
-
const count = await copyDirectory(sourcePath, destPath)
|
|
94
|
-
fileCount += count
|
|
95
|
-
if (Object.prototype.hasOwnProperty.call(layerCounts, entry.name)) {
|
|
96
|
-
layerCounts[entry.name as keyof LayerCounts] += count
|
|
97
|
-
} else {
|
|
98
|
-
layerCounts.other += count
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
const destPath = path.join(globalPath, 'planning', entry.name)
|
|
102
|
-
const count = await copyDirectory(sourcePath, destPath)
|
|
103
|
-
fileCount += count
|
|
104
|
-
layerCounts.planning += count
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
const mapping = mapLegacyFile(entry.name)
|
|
108
|
-
const destPath = path.join(globalPath, mapping.layer, mapping.filename)
|
|
109
|
-
|
|
110
|
-
await fs.mkdir(path.dirname(destPath), { recursive: true })
|
|
111
|
-
|
|
112
|
-
await fs.copyFile(sourcePath, destPath)
|
|
113
|
-
fileCount++
|
|
114
|
-
|
|
115
|
-
if (mapping.layer === '.') {
|
|
116
|
-
layerCounts.other++
|
|
117
|
-
} else {
|
|
118
|
-
layerCounts[mapping.layer as keyof LayerCounts] =
|
|
119
|
-
(layerCounts[mapping.layer as keyof LayerCounts] || 0) + 1
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return { fileCount, layerCounts }
|
|
125
|
-
}
|