|
| 1 | +import fs from 'fs' |
| 2 | +import path from 'path' |
| 3 | +import { fileURLToPath, pathToFileURL } from 'url' |
| 4 | +import { __dirname } from '../common' |
| 5 | + |
| 6 | +function getScriptLangByFileName(fileName: string) { |
| 7 | + const extension = fileName.split('.').pop()?.toLowerCase() |
| 8 | + switch (extension) { |
| 9 | + case 'js': |
| 10 | + case 'mjs': |
| 11 | + case 'cjs': |
| 12 | + return 'JavaScript' |
| 13 | + case 'ts': |
| 14 | + return 'TypeScript' |
| 15 | + case 'jsx': |
| 16 | + return 'JSX' |
| 17 | + case 'tsx': |
| 18 | + return 'TSX' |
| 19 | + case 'html': |
| 20 | + case 'htm': |
| 21 | + return 'HTML' |
| 22 | + case 'css': |
| 23 | + return 'CSS' |
| 24 | + case 'vue': |
| 25 | + return 'Vue' |
| 26 | + case 'json': |
| 27 | + return 'JSON' |
| 28 | + case 'yaml': |
| 29 | + case 'yml': |
| 30 | + return 'YAML' |
| 31 | + case 'xml': |
| 32 | + return 'XML' |
| 33 | + default: |
| 34 | + return 'Unknown' |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +export class ScriptMap { |
| 39 | + private urlToScriptId: Map<string, string> |
| 40 | + private scriptIdToUrl: Map<string, string> |
| 41 | + |
| 42 | + constructor() { |
| 43 | + this.urlToScriptId = new Map<string, string>() |
| 44 | + this.scriptIdToUrl = new Map<string, string>() |
| 45 | + } |
| 46 | + |
| 47 | + public addMapping(filePath: string, scriptId: string) { |
| 48 | + this.urlToScriptId.set(filePath, scriptId) |
| 49 | + this.scriptIdToUrl.set(scriptId, filePath) |
| 50 | + } |
| 51 | + |
| 52 | + public getUrlByScriptId(scriptId: string) { |
| 53 | + return this.scriptIdToUrl.get(scriptId) |
| 54 | + } |
| 55 | + |
| 56 | + public getScriptIdByUrl(url: string) { |
| 57 | + return this.urlToScriptId.get(url) |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +export class ResourceService { |
| 62 | + private scriptMap: ScriptMap |
| 63 | + private scriptIdCounter: number |
| 64 | + |
| 65 | + constructor() { |
| 66 | + this.scriptMap = new ScriptMap() |
| 67 | + this.scriptIdCounter = 0 |
| 68 | + } |
| 69 | + |
| 70 | + public getScriptIdByUrl(url: string) { |
| 71 | + return this.scriptMap.getScriptIdByUrl(url) |
| 72 | + } |
| 73 | + |
| 74 | + public getUrlByScriptId(scriptId: string) { |
| 75 | + return this.scriptMap.getUrlByScriptId(scriptId) |
| 76 | + } |
| 77 | + |
| 78 | + public getScriptSource(scriptId: string) { |
| 79 | + const fileUrl = this.scriptMap.getUrlByScriptId(scriptId) |
| 80 | + if (!fileUrl) { |
| 81 | + console.error(`No file path found for script ID: ${scriptId}`) |
| 82 | + return null |
| 83 | + } |
| 84 | + |
| 85 | + const filePath = fileURLToPath(fileUrl) |
| 86 | + try { |
| 87 | + return fs.readFileSync(filePath, 'utf-8') |
| 88 | + } catch (err) { |
| 89 | + console.error('Error reading file:', err) |
| 90 | + return null |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + private traverseDirToMap(directoryPath: string, ignoreList: string[] = ['node_modules']) { |
| 95 | + const scriptList = [] |
| 96 | + const stack = [directoryPath] |
| 97 | + let scriptId = this.scriptIdCounter |
| 98 | + |
| 99 | + while (stack.length > 0) { |
| 100 | + const currentPath = stack.pop()! |
| 101 | + const items = fs.readdirSync(currentPath) |
| 102 | + |
| 103 | + for (const item of items) { |
| 104 | + if (ignoreList.includes(item)) { |
| 105 | + continue |
| 106 | + } |
| 107 | + |
| 108 | + const fullPath = path.join(currentPath, item) |
| 109 | + const stats = fs.statSync(fullPath) |
| 110 | + |
| 111 | + if (stats.isDirectory()) { |
| 112 | + stack.push(fullPath) |
| 113 | + } else { |
| 114 | + const resolvedPath = path.resolve(fullPath) |
| 115 | + const fileUrl = pathToFileURL(resolvedPath) |
| 116 | + const scriptIdStr = `${++scriptId}` |
| 117 | + scriptList.push({ |
| 118 | + url: fileUrl.href, |
| 119 | + scriptLanguage: getScriptLangByFileName(fileUrl.href), |
| 120 | + embedderName: fileUrl.href, |
| 121 | + scriptId: scriptIdStr, |
| 122 | + // TODO: SourceMap? |
| 123 | + sourceMapURL: '', |
| 124 | + hasSourceURL: false |
| 125 | + // TODO: is useful? |
| 126 | + // startColumn: 0, |
| 127 | + // startLine: 0, |
| 128 | + // endColumn: 231, |
| 129 | + // endLine: 145, |
| 130 | + // isModule: false, |
| 131 | + // length: 63559, |
| 132 | + // isLiveEdit: false |
| 133 | + }) |
| 134 | + this.scriptMap.addMapping(fileUrl.href, scriptIdStr) |
| 135 | + } |
| 136 | + } |
| 137 | + } |
| 138 | + this.scriptIdCounter += scriptList.length |
| 139 | + return scriptList |
| 140 | + } |
| 141 | + |
| 142 | + public getLocalScriptList() { |
| 143 | + const projectScripts = this.traverseDirToMap(process.cwd()) |
| 144 | + const coreScripts = this.traverseDirToMap(__dirname) |
| 145 | + |
| 146 | + return [...projectScripts, ...coreScripts] |
| 147 | + } |
| 148 | +} |
0 commit comments