| 167 | set(key: string, value: string): void; |
| 168 | delete(key: string): void; |
| 169 | }; |
| 170 | statSync(path: string): unknown; |
| 171 | inspect?(value: unknown): string; |
| 172 | }; |
| 173 | process?: { |
| 174 | cwd?(): string; |
| 175 | env?: Record<string, string | undefined>; |
| 176 | }; |
| 177 | __SHOJI_PATH_EXISTS__?: (path: string) => boolean; |
| 178 | }; |
| 179 | |
| 180 | function runtimeCwd(): string { |
| 181 | return runtimeGlobal.Deno?.cwd() ?? runtimeGlobal.process?.cwd?.() ?? "/"; |
| 182 | } |
| 183 | |
| 184 | function normalizePath(path: string): string { |
| 185 | const absolute = path.startsWith("/") ? path : `${runtimeCwd()}/${path}`; |
| 186 | const parts: string[] = []; |
| 187 | for (const part of absolute.split("/")) { |
| 188 | if (!part || part === ".") continue; |
| 189 | if (part === "..") { |
| 190 | parts.pop(); |
| 191 | continue; |
| 192 | } |
| 193 | parts.push(part); |
| 194 | } |
| 195 | return `/${parts.join("/")}`; |
| 196 | } |
| 197 | |
| 198 | function resolvePath(...paths: string[]): string { |
| 199 | return normalizePath(paths.filter(Boolean).join("/")); |
| 200 | } |
| 201 | |
| 202 | function dirnamePath(path: string): string { |
| 203 | const normalized = normalizePath(path); |
| 204 | const slash = normalized.lastIndexOf("/"); |
| 205 | return slash <= 0 ? "/" : normalized.slice(0, slash); |