@powerlines/nx 0.10.36 → 0.10.38

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{chunk-HOCK3PN2.mjs → chunk-2SK7GXYX.mjs} +1 -1
  3. package/dist/{chunk-ZGEXR2Z6.mjs → chunk-37R7Z4YA.mjs} +1 -1
  4. package/dist/{chunk-62JK5CR2.js → chunk-55HWRJFI.js} +2 -2
  5. package/dist/{chunk-D5MAY4B6.js → chunk-5IM5S57N.js} +2 -2
  6. package/dist/{chunk-6M466CL6.mjs → chunk-7Z54WTD3.mjs} +1 -1
  7. package/dist/{chunk-OBVSDJNP.mjs → chunk-BM5C4GAH.mjs} +1 -1
  8. package/dist/{chunk-76PYI2PW.js → chunk-CJE2WIZT.js} +2 -2
  9. package/dist/{chunk-V3APU4CI.js → chunk-DDZYTWHI.js} +2 -2
  10. package/dist/{chunk-FXB722G2.js → chunk-DNMCZOZX.js} +2 -2
  11. package/dist/{chunk-2PYUYDPD.js → chunk-DQI2I5KK.js} +1 -3
  12. package/dist/{chunk-LNSZHZQF.js → chunk-F7EY5OCV.js} +911 -947
  13. package/dist/{chunk-A36IQB2U.mjs → chunk-HJZ2I6NE.mjs} +11 -19
  14. package/dist/{chunk-YAQUTH2M.js → chunk-JXYA5T7X.js} +2 -2
  15. package/dist/{chunk-Q6DRZWW7.js → chunk-KBRCV5NY.js} +13 -21
  16. package/dist/{chunk-3QGFYJKW.mjs → chunk-OIL7SLIA.mjs} +1 -1
  17. package/dist/{chunk-XQ44F4OL.mjs → chunk-OS2GSBDL.mjs} +904 -939
  18. package/dist/{chunk-WGIN2BGP.mjs → chunk-OVX2CEXQ.mjs} +1 -3
  19. package/dist/{chunk-AGWVUBME.mjs → chunk-PWZ3J3N6.mjs} +1 -1
  20. package/dist/executors.js +15 -15
  21. package/dist/executors.mjs +7 -7
  22. package/dist/index.js +18 -18
  23. package/dist/index.mjs +9 -9
  24. package/dist/src/base/base-executor.js +3 -3
  25. package/dist/src/base/base-executor.mjs +2 -2
  26. package/dist/src/executors/build/executor.js +5 -5
  27. package/dist/src/executors/build/executor.mjs +3 -3
  28. package/dist/src/executors/clean/executor.js +5 -5
  29. package/dist/src/executors/clean/executor.mjs +3 -3
  30. package/dist/src/executors/docs/executor.js +5 -5
  31. package/dist/src/executors/docs/executor.mjs +3 -3
  32. package/dist/src/executors/lint/executor.js +5 -5
  33. package/dist/src/executors/lint/executor.mjs +3 -3
  34. package/dist/src/executors/prepare/executor.js +5 -5
  35. package/dist/src/executors/prepare/executor.mjs +3 -3
  36. package/dist/src/helpers/plugin-utilities.js +5 -5
  37. package/dist/src/helpers/plugin-utilities.mjs +2 -2
  38. package/dist/src/plugin/index.js +4 -4
  39. package/dist/src/plugin/index.mjs +3 -3
  40. package/dist/src/types/plugin.d.mts +1 -1
  41. package/dist/src/types/plugin.d.ts +1 -1
  42. package/package.json +8 -8
@@ -1,18 +1,19 @@
1
- import { loadWorkspaceConfig, CACHE_HASH_LENGTH, PROJECT_ROOT_HASH_LENGTH, getPrefixedProjectRootHash, loadUserConfigFile, writeMetaFile } from './chunk-WGIN2BGP.mjs';
1
+ import { loadWorkspaceConfig, CACHE_HASH_LENGTH, PROJECT_ROOT_HASH_LENGTH, getPrefixedProjectRootHash, loadUserConfigFile, writeMetaFile } from './chunk-OVX2CEXQ.mjs';
2
2
  import { __name } from './chunk-O6YSETKJ.mjs';
3
3
  import { getLogFn, getLogLevel, writeError } from '@storm-software/config-tools/logger';
4
4
  import { withRunExecutor } from '@storm-software/workspace-tools/base/base-executor';
5
5
  import { isError } from '@stryke/type-checks/is-error';
6
- import defu5, { defu } from 'defu';
6
+ import defu6, { defu } from 'defu';
7
7
  import { transformAsync } from '@babel/core';
8
8
  import { formatLogMessage } from '@storm-software/config-tools/logger/console';
9
9
  import { LogLevelLabel } from '@storm-software/config-tools/types';
10
10
  import { toArray } from '@stryke/convert/to-array';
11
11
  import { copyFiles } from '@stryke/fs/copy-file';
12
+ import { createDirectory } from '@stryke/fs/helpers';
12
13
  import { install } from '@stryke/fs/install';
13
- import { listFiles, listFilesSync } from '@stryke/fs/list-files';
14
+ import { listFilesSync, listFiles } from '@stryke/fs/list-files';
14
15
  import { isPackageExists, isPackageListed, doesPackageMatch, getPackageListing } from '@stryke/fs/package-fns';
15
- import { getResolutionCombinations, resolve, resolveSync, resolvePackage } from '@stryke/fs/resolve';
16
+ import { getResolutionCombinations, resolve as resolve$1, resolveSync, resolvePackage } from '@stryke/fs/resolve';
16
17
  import { appendPath } from '@stryke/path/append';
17
18
  import { joinPaths as joinPaths$1 } from '@stryke/path/join-paths';
18
19
  import { replacePath, replaceExtension } from '@stryke/path/replace';
@@ -26,16 +27,17 @@ import chalk5 from 'chalk';
26
27
  import Handlebars from 'handlebars';
27
28
  import { declare } from '@babel/helper-plugin-utils';
28
29
  import * as t from '@babel/types';
29
- import ts2, { flattenDiagnosticMessageText } from 'typescript';
30
+ import ts, { flattenDiagnosticMessageText } from 'typescript';
31
+ import { joinPaths } from '@stryke/path/join';
32
+ import { InMemoryFileSystemHost, Project } from 'ts-morph';
30
33
  import { getPackageName, hasPackageVersion, getPackageVersion } from '@stryke/string-format/package';
31
34
  import { getObjectDiff } from '@donedeal0/superdiff';
32
35
  import { readJsonFile, readJsonFileSync } from '@stryke/fs/json';
33
36
  import { StormJSON } from '@stryke/json/storm-json';
34
- import { findFilePath, findFileExtension, relativePath, findFileName, findFileDotExtensionSafe } from '@stryke/path/file-path-fns';
35
- import { isParentPath } from '@stryke/path/is-parent-path';
37
+ import { hasFileExtension, findFilePath, findFileName, relativePath, findFileDotExtensionSafe } from '@stryke/path/file-path-fns';
36
38
  import { titleCase } from '@stryke/string-format/title-case';
37
- import { existsSync } from '@stryke/fs/exists';
38
- import { writeFile as writeFile$1 } from '@stryke/fs/write-file';
39
+ import { existsSync, exists } from '@stryke/fs/exists';
40
+ import { writeFileSync, writeFile as writeFile$1 } from '@stryke/fs/write-file';
39
41
  import { resolveConfig, format } from 'prettier';
40
42
  import { getEnvPaths } from '@stryke/env/get-env-paths';
41
43
  import { relativeToWorkspaceRoot } from '@stryke/fs/get-workspace-root';
@@ -44,7 +46,6 @@ import { murmurhash } from '@stryke/hash/murmurhash';
44
46
  import { getUnique, getUniqueBy } from '@stryke/helpers/get-unique';
45
47
  import { omit } from '@stryke/helpers/omit';
46
48
  import { isAbsolutePath, isAbsolute } from '@stryke/path/is-type';
47
- import { joinPaths } from '@stryke/path/join';
48
49
  import { isNull } from '@stryke/type-checks/is-null';
49
50
  import { isString } from '@stryke/type-checks/is-string';
50
51
  import { uuid } from '@stryke/unique-id/uuid';
@@ -54,20 +55,19 @@ import { isUndefined } from '@stryke/type-checks/is-undefined';
54
55
  import { parseTypeDefinition } from '@stryke/convert/parse-type-definition';
55
56
  import { isFile } from '@stryke/fs/is-file';
56
57
  import * as $ from '@stryke/capnp';
57
- import { bufferToString } from '@stryke/convert/buffer-to-string';
58
58
  import { readFileBuffer, readFileBufferSync, writeFileBuffer } from '@stryke/fs/buffer';
59
- import { toAbsolutePath, correctPath } from '@stryke/path/correct-path';
59
+ import { correctPath, toAbsolutePath } from '@stryke/path/correct-path';
60
+ import { isParentPath } from '@stryke/path/is-parent-path';
60
61
  import { prettyBytes } from '@stryke/string-format/pretty-bytes';
61
- import { isBuffer } from '@stryke/type-checks/is-buffer';
62
62
  import { create } from 'flat-cache';
63
63
  import { Blob } from 'node:buffer';
64
- import _fs from 'node:fs';
65
64
  import { getColor } from '@storm-software/config-tools/utilities/colors';
66
65
  import { noop } from '@stryke/helpers/noop';
67
66
  import { slash } from '@stryke/path/slash';
68
- import { Volume } from 'memfs';
69
- import { Union } from 'unionfs';
70
- import { InMemoryFileSystemHost, Project } from 'ts-morph';
67
+ import { readFileSync, readFile } from '@stryke/fs/read-file';
68
+ import { unlinkSync } from 'node:fs';
69
+ import { unlink } from 'node:fs/promises';
70
+ import { resolve } from 'node:path';
71
71
  import { isObject } from '@stryke/type-checks/is-object';
72
72
 
73
73
  function resolveModulePath(nodePath, state) {
@@ -171,6 +171,108 @@ var moduleResolverBabelPlugin = /* @__PURE__ */ __name((context) => {
171
171
  };
172
172
  }, "builder"));
173
173
  }, "moduleResolverBabelPlugin");
174
+ var VirtualFileSystemHost = class extends InMemoryFileSystemHost {
175
+ static {
176
+ __name(this, "VirtualFileSystemHost");
177
+ }
178
+ #context;
179
+ constructor(context) {
180
+ super();
181
+ this.#context = context;
182
+ }
183
+ deleteSync(path) {
184
+ this.#context.fs.removeSync(path);
185
+ }
186
+ readDirSync(dirPath) {
187
+ return this.#context.fs.listSync(dirPath).reduce((ret, entry) => {
188
+ const fullPath = this.#context.fs.resolveSync(joinPaths(dirPath, entry));
189
+ if (fullPath) {
190
+ ret.push({
191
+ name: entry,
192
+ isDirectory: this.#context.fs.existsSync(fullPath),
193
+ isFile: this.#context.fs.existsSync(fullPath),
194
+ isSymlink: false
195
+ });
196
+ }
197
+ return ret;
198
+ }, []);
199
+ }
200
+ async readFile(filePath) {
201
+ if (!this.#context.fs.existsSync(filePath)) {
202
+ throw new Error(`File not found: '${filePath}'. Please check the path and try again.`);
203
+ }
204
+ return await this.#context.fs.read(filePath);
205
+ }
206
+ readFileSync(filePath) {
207
+ if (!this.#context.fs.existsSync(filePath)) {
208
+ throw new Error(`File not found: '${filePath}'. Please check the path and try again.`);
209
+ }
210
+ return this.#context.fs.readSync(filePath);
211
+ }
212
+ async writeFile(filePath, fileText) {
213
+ return this.#context.fs.write(filePath, fileText);
214
+ }
215
+ writeFileSync(filePath, fileText) {
216
+ this.#context.fs.writeSync(filePath, fileText);
217
+ }
218
+ async mkdir(_dirPath) {
219
+ }
220
+ mkdirSync(_dirPath) {
221
+ }
222
+ async move(srcPath, destPath) {
223
+ await this.#context.fs.move(srcPath, destPath);
224
+ }
225
+ moveSync(srcPath, destPath) {
226
+ this.#context.fs.moveSync(srcPath, destPath);
227
+ }
228
+ async copy(srcPath, destPath) {
229
+ await this.#context.fs.copy(srcPath, destPath);
230
+ }
231
+ copySync(srcPath, destPath) {
232
+ this.#context.fs.copySync(srcPath, destPath);
233
+ }
234
+ async fileExists(filePath) {
235
+ return this.#context.fs.exists(filePath);
236
+ }
237
+ fileExistsSync(filePath) {
238
+ return this.#context.fs.existsSync(filePath);
239
+ }
240
+ async directoryExists(dirPath) {
241
+ return this.#context.fs.exists(dirPath);
242
+ }
243
+ directoryExistsSync(dirPath) {
244
+ return this.#context.fs.existsSync(dirPath);
245
+ }
246
+ realpathSync(path) {
247
+ return this.#context.fs.resolveSync(path) || path;
248
+ }
249
+ getCurrentDirectory() {
250
+ return this.#context.workspaceConfig.workspaceRoot;
251
+ }
252
+ async glob(patterns) {
253
+ return this.#context.fs.glob(patterns);
254
+ }
255
+ globSync(patterns) {
256
+ return this.#context.fs.globSync(patterns);
257
+ }
258
+ };
259
+ function createProgram(context, override) {
260
+ context.log(LogLevelLabel.TRACE, `Creating ts-morph Project instance with configuration from: ${context.tsconfig.tsconfigFilePath}.`);
261
+ const project = new Project(defu6(override ?? {}, {
262
+ skipAddingFilesFromTsConfig: false,
263
+ tsConfigFilePath: context.tsconfig.tsconfigFilePath,
264
+ fileSystem: new VirtualFileSystemHost(context),
265
+ compilerOptions: defu6(context.tsconfig.options ?? {}, {
266
+ lib: [
267
+ "lib.esnext.full.d.ts"
268
+ ]
269
+ })
270
+ }));
271
+ return project;
272
+ }
273
+ __name(createProgram, "createProgram");
274
+
275
+ // ../powerlines/src/internal/helpers/generate-types.ts
174
276
  function formatTypes(code) {
175
277
  return code.replace(
176
278
  // eslint-disable-next-line regexp/no-super-linear-backtracking
@@ -181,8 +283,11 @@ function formatTypes(code) {
181
283
  __name(formatTypes, "formatTypes");
182
284
  async function emitTypes(context, files) {
183
285
  context.log(LogLevelLabel.TRACE, `Running the TypeScript compiler for ${files.length} generated runtime files.`);
184
- context.program.addSourceFilesAtPaths(files);
185
- const result = context.program.emitToMemory({
286
+ const program = createProgram(context, {
287
+ skipAddingFilesFromTsConfig: true
288
+ });
289
+ program.addSourceFilesAtPaths(files);
290
+ const result = program.emitToMemory({
186
291
  emitOnlyDtsFiles: true
187
292
  });
188
293
  let builtinModules = "";
@@ -379,13 +484,13 @@ function isIncludeMatchFound(tsconfigType, types) {
379
484
  return findIncludeMatch(tsconfigType, types) !== void 0;
380
485
  }
381
486
  __name(isIncludeMatchFound, "isIncludeMatchFound");
382
- function getParsedTypeScriptConfig(workspaceRoot, projectRoot, tsconfig, tsconfigRaw = {}, originalTsconfigJson, host = ts2.sys) {
487
+ function getParsedTypeScriptConfig(workspaceRoot, projectRoot, tsconfig, tsconfigRaw = {}, originalTsconfigJson, host = ts.sys) {
383
488
  const tsconfigFilePath = getTsconfigFilePath(workspaceRoot, projectRoot, tsconfig);
384
489
  const tsconfigJson = readJsonFileSync(tsconfigFilePath);
385
490
  if (!tsconfigJson) {
386
491
  throw new Error(`Cannot find the \`tsconfig.json\` configuration file at ${joinPaths$1(projectRoot, tsconfig ?? "tsconfig.json")}`);
387
492
  }
388
- const parsedCommandLine = ts2.parseJsonConfigFileContent(defu5(tsconfigRaw ?? {}, tsconfigJson), host, appendPath(projectRoot, workspaceRoot));
493
+ const parsedCommandLine = ts.parseJsonConfigFileContent(defu6(tsconfigRaw ?? {}, tsconfigJson), host, appendPath(projectRoot, workspaceRoot));
389
494
  if (parsedCommandLine.errors.length > 0) {
390
495
  const errorMessage = `Cannot parse the TypeScript compiler options. Please investigate the following issues:
391
496
  ${parsedCommandLine.errors.map((error) => `- ${(error.category !== void 0 && error.code ? `[${error.category}-${error.code}]: ` : "") + error.messageText.toString()}`).join("\n")}
@@ -426,15 +531,10 @@ async function resolveTsconfigChanges(context) {
426
531
  const tsconfigJson = await readJsonFile(tsconfigFilePath);
427
532
  tsconfigJson.compilerOptions ??= {};
428
533
  if (context.config.output.dts !== false) {
429
- context.config.output.dts = context.config.output.dts ? isParentPath(context.config.output.dts, context.workspaceConfig.workspaceRoot) ? context.config.output.dts : appendPath(context.config.output.dts, context.workspaceConfig.workspaceRoot) : appendPath(context.config.projectRoot, context.workspaceConfig.workspaceRoot);
430
- if (findFileExtension(context.config.output.dts) !== "d.ts" && findFileExtension(context.config.output.dts) !== "d.cts" && findFileExtension(context.config.output.dts) !== "d.mts") {
431
- context.config.output.dts = joinPaths$1(context.config.output.dts, "powerlines.d.ts");
432
- }
433
- const dtsRelativePath = joinPaths$1(relativePath(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.projectRoot), findFilePath(context.config.output.dts)), findFileName(context.config.output.dts));
534
+ const dtsRelativePath = joinPaths$1(relativePath(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.projectRoot), findFilePath(context.dtsPath)), findFileName(context.dtsPath));
434
535
  if (!tsconfigJson.include?.some((filePattern) => isIncludeMatchFound(filePattern, [
435
- String(context.config.output.dts),
436
- dtsRelativePath,
437
- "storm.d.ts"
536
+ context.dtsPath,
537
+ dtsRelativePath
438
538
  ]))) {
439
539
  tsconfigJson.include ??= [];
440
540
  tsconfigJson.include.push(dtsRelativePath.startsWith("./") ? dtsRelativePath.slice(2) : dtsRelativePath);
@@ -449,24 +549,6 @@ async function resolveTsconfigChanges(context) {
449
549
  tsconfigJson.compilerOptions.lib ??= [];
450
550
  tsconfigJson.compilerOptions.lib.push("esnext");
451
551
  }
452
- if (tsconfig.options.module !== ts2.ModuleKind.ESNext) {
453
- tsconfigJson.compilerOptions.module = "ESNext";
454
- }
455
- if (!tsconfig.options.target || ![
456
- ts2.ScriptTarget.ESNext,
457
- ts2.ScriptTarget.ES2024,
458
- ts2.ScriptTarget.ES2023,
459
- ts2.ScriptTarget.ES2022,
460
- ts2.ScriptTarget.ES2021
461
- ].includes(tsconfig.options.target)) {
462
- tsconfigJson.compilerOptions.target = "ESNext";
463
- }
464
- if (tsconfig.options.moduleResolution !== ts2.ModuleResolutionKind.Bundler) {
465
- tsconfigJson.compilerOptions.moduleResolution = "Bundler";
466
- }
467
- if (tsconfig.options.moduleDetection !== ts2.ModuleDetectionKind.Force) {
468
- tsconfigJson.compilerOptions.moduleDetection = "force";
469
- }
470
552
  if (tsconfig.options.esModuleInterop !== true) {
471
553
  tsconfigJson.compilerOptions.esModuleInterop = true;
472
554
  }
@@ -491,9 +573,7 @@ async function initializeTsconfig(context) {
491
573
  context.tsconfig.originalTsconfigJson = await readJsonFile(tsconfigFilePath);
492
574
  context.tsconfig.tsconfigJson = await resolveTsconfigChanges(context);
493
575
  context.log(LogLevelLabel.TRACE, "Writing updated TypeScript configuration (tsconfig.json) file to disk.");
494
- await context.fs.writeFile(tsconfigFilePath, StormJSON.stringify(context.tsconfig.tsconfigJson), {
495
- mode: "fs"
496
- });
576
+ await writeFile(context.log, tsconfigFilePath, StormJSON.stringify(context.tsconfig.tsconfigJson));
497
577
  context.tsconfig = getParsedTypeScriptConfig(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig, context.config.tsconfigRaw, context.tsconfig.originalTsconfigJson);
498
578
  }
499
579
  __name(initializeTsconfig, "initializeTsconfig");
@@ -553,7 +633,7 @@ async function resolveTsconfig(context) {
553
633
  __name(resolveTsconfig, "resolveTsconfig");
554
634
  var DEFAULT_ENVIRONMENT = "default";
555
635
  function createEnvironment(name, userConfig) {
556
- return defu5(userConfig.environments?.[name] ?? {}, {
636
+ return defu6(userConfig.environments?.[name] ?? {}, {
557
637
  name,
558
638
  title: userConfig.title || titleCase(userConfig.name),
559
639
  ssr: false,
@@ -597,8 +677,7 @@ function createDefaultEnvironment(userConfig) {
597
677
  }
598
678
  __name(createDefaultEnvironment, "createDefaultEnvironment");
599
679
  function resolveOptions(options) {
600
- return defu5(options, {
601
- debug: options.logLevel === "trace",
680
+ return defu6(options, {
602
681
  interopDefault: true,
603
682
  fsCache: options.mode !== "development" ? joinPaths$1(options.cacheDir, "jiti") : false,
604
683
  moduleCache: options.mode !== "development"
@@ -689,7 +768,7 @@ function replacePathTokens(context, path) {
689
768
  if (!path) {
690
769
  return path;
691
770
  }
692
- return path.replaceAll("{workspaceRoot}", context.workspaceConfig.workspaceRoot).replaceAll("{root}", context.config.projectRoot).replaceAll("{projectRoot}", context.config.projectRoot).replaceAll("{powerlinesPath}", context.powerlinesPath).replaceAll("{cachePath}", context.cachePath).replaceAll("{dataPath}", context.dataPath).replaceAll("{logPath}", context.envPaths.log).replaceAll("{tempPath}", context.envPaths.temp).replaceAll("{configPath}", context.envPaths.config).replaceAll("{outputPath}", context.config.output.outputPath).replaceAll("{distPath}", context.config.output.distPath).replaceAll("{artifactsPath}", replacePath(context.artifactsPath, context.workspaceConfig.workspaceRoot)).replaceAll("{builtinPath}", replacePath(context.builtinsPath, context.workspaceConfig.workspaceRoot)).replaceAll("{entryPath}", replacePath(context.entryPath, context.workspaceConfig.workspaceRoot));
771
+ return path.replaceAll("{workspaceRoot}", context.workspaceConfig.workspaceRoot).replaceAll("{root}", context.config.projectRoot).replaceAll("{projectRoot}", context.config.projectRoot).replaceAll("{powerlinesPath}", context.powerlinesPath).replaceAll("{cachePath}", context.cachePath).replaceAll("{dataPath}", context.dataPath).replaceAll("{logPath}", context.envPaths.log).replaceAll("{tempPath}", context.envPaths.temp).replaceAll("{configPath}", context.envPaths.config).replaceAll("{outputPath}", context.config.output.outputPath).replaceAll("{buildPath}", context.config.output.buildPath).replaceAll("{artifactsPath}", replacePath(context.artifactsPath, context.workspaceConfig.workspaceRoot)).replaceAll("{builtinPath}", replacePath(context.builtinsPath, context.workspaceConfig.workspaceRoot)).replaceAll("{entryPath}", replacePath(context.entryPath, context.workspaceConfig.workspaceRoot));
693
772
  }
694
773
  __name(replacePathTokens, "replacePathTokens");
695
774
  function resolveEntryInputFile(context, typeDefinition) {
@@ -773,7 +852,7 @@ var FileMetadata = class _FileMetadata extends $.Struct {
773
852
  static _capnp = {
774
853
  displayName: "FileMetadata",
775
854
  id: "8e2cab5d7e28c7b3",
776
- size: new $.ObjectSize(8, 4),
855
+ size: new $.ObjectSize(8, 3),
777
856
  defaultType: "normal"
778
857
  };
779
858
  static _Properties;
@@ -788,7 +867,7 @@ var FileMetadata = class _FileMetadata extends $.Struct {
788
867
  $.utils.setText(0, value, this);
789
868
  }
790
869
  /**
791
- * The output mode of the file.
870
+ * The timestamp representing the file's creation date.
792
871
  *
793
872
  */
794
873
  get type() {
@@ -798,16 +877,6 @@ var FileMetadata = class _FileMetadata extends $.Struct {
798
877
  $.utils.setText(1, value, this);
799
878
  }
800
879
  /**
801
- * The timestamp representing the file's creation date.
802
- *
803
- */
804
- get mode() {
805
- return $.utils.getText(2, this);
806
- }
807
- set mode(value) {
808
- $.utils.setText(2, value, this);
809
- }
810
- /**
811
880
  * Additional metadata associated with the file.
812
881
  *
813
882
  */
@@ -818,22 +887,22 @@ var FileMetadata = class _FileMetadata extends $.Struct {
818
887
  $.utils.setUint32(0, value, this);
819
888
  }
820
889
  _adoptProperties(value) {
821
- $.utils.adopt(value, $.utils.getPointer(3, this));
890
+ $.utils.adopt(value, $.utils.getPointer(2, this));
822
891
  }
823
892
  _disownProperties() {
824
893
  return $.utils.disown(this.properties);
825
894
  }
826
895
  get properties() {
827
- return $.utils.getList(3, _FileMetadata._Properties, this);
896
+ return $.utils.getList(2, _FileMetadata._Properties, this);
828
897
  }
829
898
  _hasProperties() {
830
- return !$.utils.isNull($.utils.getPointer(3, this));
899
+ return !$.utils.isNull($.utils.getPointer(2, this));
831
900
  }
832
901
  _initProperties(length) {
833
- return $.utils.initList(3, _FileMetadata._Properties, length, this);
902
+ return $.utils.initList(2, _FileMetadata._Properties, length, this);
834
903
  }
835
904
  set properties(value) {
836
- $.utils.copyFrom(value, $.utils.getPointer(3, this));
905
+ $.utils.copyFrom(value, $.utils.getPointer(2, this));
837
906
  }
838
907
  toString() {
839
908
  return "FileMetadata_" + super.toString();
@@ -868,13 +937,13 @@ var FileId = class extends $.Struct {
868
937
  return "FileId_" + super.toString();
869
938
  }
870
939
  };
871
- var FileData = class extends $.Struct {
940
+ var FileStorage = class extends $.Struct {
872
941
  static {
873
- __name(this, "FileData");
942
+ __name(this, "FileStorage");
874
943
  }
875
944
  static _capnp = {
876
- displayName: "FileData",
877
- id: "fa6725c8a360f9a2",
945
+ displayName: "FileStorage",
946
+ id: "9dca66ac858c9ebe",
878
947
  size: new $.ObjectSize(0, 2)
879
948
  };
880
949
  /**
@@ -894,7 +963,7 @@ var FileData = class extends $.Struct {
894
963
  $.utils.setText(1, value, this);
895
964
  }
896
965
  toString() {
897
- return "FileData_" + super.toString();
966
+ return "FileStorage_" + super.toString();
898
967
  }
899
968
  };
900
969
  var FileSystem = class _FileSystem extends $.Struct {
@@ -907,7 +976,7 @@ var FileSystem = class _FileSystem extends $.Struct {
907
976
  size: new $.ObjectSize(0, 3)
908
977
  };
909
978
  static _Ids;
910
- static _Files;
979
+ static _Storage;
911
980
  static _Metadata;
912
981
  _adoptIds(value) {
913
982
  $.utils.adopt(value, $.utils.getPointer(0, this));
@@ -927,22 +996,22 @@ var FileSystem = class _FileSystem extends $.Struct {
927
996
  set ids(value) {
928
997
  $.utils.copyFrom(value, $.utils.getPointer(0, this));
929
998
  }
930
- _adoptFiles(value) {
999
+ _adoptStorage(value) {
931
1000
  $.utils.adopt(value, $.utils.getPointer(1, this));
932
1001
  }
933
- _disownFiles() {
934
- return $.utils.disown(this.files);
1002
+ _disownStorage() {
1003
+ return $.utils.disown(this.storage);
935
1004
  }
936
- get files() {
937
- return $.utils.getList(1, _FileSystem._Files, this);
1005
+ get storage() {
1006
+ return $.utils.getList(1, _FileSystem._Storage, this);
938
1007
  }
939
- _hasFiles() {
1008
+ _hasStorage() {
940
1009
  return !$.utils.isNull($.utils.getPointer(1, this));
941
1010
  }
942
- _initFiles(length) {
943
- return $.utils.initList(1, _FileSystem._Files, length, this);
1011
+ _initStorage(length) {
1012
+ return $.utils.initList(1, _FileSystem._Storage, length, this);
944
1013
  }
945
- set files(value) {
1014
+ set storage(value) {
946
1015
  $.utils.copyFrom(value, $.utils.getPointer(1, this));
947
1016
  }
948
1017
  _adoptMetadata(value) {
@@ -969,12 +1038,15 @@ var FileSystem = class _FileSystem extends $.Struct {
969
1038
  };
970
1039
  FileMetadata._Properties = $.CompositeList(FileMetadata_KeyValuePair);
971
1040
  FileSystem._Ids = $.CompositeList(FileId);
972
- FileSystem._Files = $.CompositeList(FileData);
1041
+ FileSystem._Storage = $.CompositeList(FileStorage);
973
1042
  FileSystem._Metadata = $.CompositeList(FileMetadata);
974
1043
 
975
1044
  // ../powerlines/src/types/fs.ts
976
- var __VFS_PATCH__ = "__VFS_PATCH__";
977
- var __VFS_REVERT__ = "__VFS_REVERT__";
1045
+ var StoragePreset = /* @__PURE__ */ (function(StoragePreset2) {
1046
+ StoragePreset2["VIRTUAL"] = "virtual";
1047
+ StoragePreset2["FS"] = "fs";
1048
+ return StoragePreset2;
1049
+ })({});
978
1050
  var createLog = /* @__PURE__ */ __name((name, options = {}) => {
979
1051
  const logLevel = options.logLevel === null ? LogLevelLabel.SILENT : options.logLevel || LogLevelLabel.INFO;
980
1052
  if (logLevel === LogLevelLabel.SILENT) {
@@ -1013,142 +1085,18 @@ var BADGE_COLORS = [
1013
1085
  var extendLog = /* @__PURE__ */ __name((logFn, name) => {
1014
1086
  return (type, ...args) => logFn(type, ` ${chalk5.inverse.hex(BADGE_COLORS[name.split("").map((char) => char.charCodeAt(0)).reduce((ret, charCode) => ret + charCode, 0) % BADGE_COLORS.length] || BADGE_COLORS[0])(` ${titleCase(name)} `)} ${args.join(" ")} `);
1015
1087
  }, "extendLog");
1016
- function isBufferEncoding(options) {
1017
- return isSetString(options) || options === null;
1018
- }
1019
- __name(isBufferEncoding, "isBufferEncoding");
1020
- function isPowerlinesWriteFileOptions(options) {
1021
- return !isBufferEncoding(options) && isSetObject(options) && "mode" in options && (options.mode === "fs" || options.mode === "virtual");
1088
+ function isFileError(err) {
1089
+ return isError(err) && "code" in err && err.code;
1022
1090
  }
1023
- __name(isPowerlinesWriteFileOptions, "isPowerlinesWriteFileOptions");
1024
- function isVirtualFileData(obj) {
1025
- return !!(isSetObject(obj) && "code" in obj && obj.code);
1091
+ __name(isFileError, "isFileError");
1092
+ function ignoreNotfound(err) {
1093
+ return isFileError(err) && (err.code === "ENOENT" || err.code === "EISDIR" ? null : err);
1026
1094
  }
1027
- __name(isVirtualFileData, "isVirtualFileData");
1095
+ __name(ignoreNotfound, "ignoreNotfound");
1028
1096
  function toFilePath(path) {
1029
1097
  return correctPath(slash(path?.toString() || ".").replace(/^file:\/\//, ""));
1030
1098
  }
1031
1099
  __name(toFilePath, "toFilePath");
1032
- var FS_METHODS = [
1033
- "mkdir",
1034
- "mkdirSync",
1035
- "rmdir",
1036
- "rmdirSync",
1037
- "unlink",
1038
- "unlinkSync",
1039
- "existsSync",
1040
- "realpathSync",
1041
- "writeFileSync",
1042
- "readFileSync",
1043
- "readdirSync",
1044
- "createWriteStream",
1045
- "WriteStream",
1046
- "createReadStream",
1047
- "ReadStream"
1048
- ];
1049
- var FS_PROMISE_METHODS = [
1050
- "mkdir",
1051
- "rm",
1052
- "rmdir",
1053
- "unlink",
1054
- "writeFile",
1055
- "readFile",
1056
- "readdir",
1057
- "stat",
1058
- "lstat"
1059
- ];
1060
- function cloneFS(originalFS) {
1061
- const clonedFS = {
1062
- ...originalFS,
1063
- promises: {
1064
- ...originalFS.promises ?? {}
1065
- }
1066
- };
1067
- for (const method of FS_METHODS) {
1068
- if (originalFS[method]) {
1069
- clonedFS[method] = originalFS[method];
1070
- }
1071
- }
1072
- originalFS.promises ??= {};
1073
- for (const method of FS_PROMISE_METHODS) {
1074
- if (originalFS.promises[method]) {
1075
- clonedFS.promises ??= {};
1076
- clonedFS.promises[method] = originalFS.promises[method];
1077
- clonedFS[method] = originalFS.promises[method];
1078
- }
1079
- }
1080
- for (const prop in clonedFS) {
1081
- if (isFunction(clonedFS[prop])) {
1082
- clonedFS[prop] = clonedFS[prop].bind(originalFS);
1083
- if (isFunction(clonedFS.promises[prop])) {
1084
- clonedFS.promises[prop] = clonedFS.promises[prop].bind(originalFS);
1085
- }
1086
- }
1087
- }
1088
- for (const prop in clonedFS.promises) {
1089
- if (isFunction(clonedFS.promises[prop])) {
1090
- clonedFS.promises[prop] = clonedFS.promises[prop].bind(originalFS);
1091
- }
1092
- }
1093
- return clonedFS;
1094
- }
1095
- __name(cloneFS, "cloneFS");
1096
- function patchFS(originalFS, vfs) {
1097
- const clonedFS = cloneFS(originalFS);
1098
- originalFS.mkdirSync = (file, options) => vfs.mkdirSync(toFilePath(file), options);
1099
- originalFS.mkdir = (file, options, callback) => vfs.mkdir(toFilePath(file), options, callback);
1100
- originalFS.promises.mkdir = async (file, options) => vfs.mkdir(toFilePath(file), options);
1101
- originalFS.unlinkSync = (file) => vfs.unlinkSync(toFilePath(file));
1102
- originalFS.promises.rm = async (file, options) => vfs.rm(toFilePath(file), options);
1103
- originalFS.promises.unlink = async (file) => vfs.unlink(toFilePath(file));
1104
- originalFS.existsSync = (file) => vfs.existsSync(toFilePath(file));
1105
- Object.defineProperty(originalFS, "realpathSync", {
1106
- value: /* @__PURE__ */ __name((file, options) => vfs.realpathSync(toFilePath(file), options), "value")
1107
- });
1108
- originalFS.writeFileSync = (file, data, options) => vfs.writeFileSync(toFilePath(file), data, options);
1109
- originalFS.promises.writeFile = async (file, data, options) => vfs.writeFile(toFilePath(file), data, options);
1110
- originalFS.readFileSync = (file, options) => vfs.readFileSync(toFilePath(file), options);
1111
- originalFS.promises.readFile = (file, options) => vfs.readFile(toFilePath(file), options);
1112
- originalFS.readdirSync = (file, options) => vfs.readdirSync(toFilePath(file), options);
1113
- originalFS.promises.readdir = (file, options) => vfs.readdir(toFilePath(file), options);
1114
- Object.defineProperty(originalFS, "statSync", {
1115
- value: /* @__PURE__ */ __name((file, options) => vfs.statSync(toFilePath(file), options), "value")
1116
- });
1117
- originalFS.stat = (file, options) => vfs.statSync(toFilePath(file), options);
1118
- originalFS.promises.stat = (file, options) => vfs.stat(toFilePath(file), options);
1119
- Object.defineProperty(originalFS, "lstatSync", {
1120
- value: /* @__PURE__ */ __name((file, options) => vfs.lstatSync(toFilePath(file), options), "value")
1121
- });
1122
- originalFS.lstat = (file, options) => vfs.lstatSync(toFilePath(file), options);
1123
- originalFS.promises.lstat = (file, options) => vfs.lstat(toFilePath(file), options);
1124
- return () => {
1125
- originalFS.mkdirSync = clonedFS.mkdirSync;
1126
- originalFS.mkdir = clonedFS.mkdir;
1127
- originalFS.promises.mkdir = clonedFS.promises.mkdir;
1128
- originalFS.unlinkSync = clonedFS.unlinkSync;
1129
- originalFS.promises.rm = clonedFS.promises.rm;
1130
- originalFS.promises.unlink = clonedFS.promises.unlink;
1131
- originalFS.existsSync = clonedFS.existsSync;
1132
- originalFS.realpathSync = clonedFS.realpathSync;
1133
- originalFS.writeFileSync = clonedFS.writeFileSync;
1134
- originalFS.promises.writeFile = clonedFS.promises.writeFile;
1135
- originalFS.readFileSync = clonedFS.readFileSync;
1136
- originalFS.promises.readFile = clonedFS.promises.readFile;
1137
- originalFS.readdirSync = clonedFS.readdirSync;
1138
- originalFS.promises.readdir = clonedFS.promises.readdir;
1139
- Object.defineProperty(originalFS, "statSync", {
1140
- value: clonedFS.statSync
1141
- });
1142
- originalFS.stat = clonedFS.stat;
1143
- originalFS.promises.stat = clonedFS.promises.stat;
1144
- Object.defineProperty(originalFS, "lstatSync", {
1145
- value: clonedFS.lstatSync
1146
- });
1147
- originalFS.lstat = clonedFS.lstat;
1148
- originalFS.promises.lstat = clonedFS.promises.lstat;
1149
- };
1150
- }
1151
- __name(patchFS, "patchFS");
1152
1100
  function isValidId(id, prefix = "powerlines") {
1153
1101
  return id.replace(/^\\0/, "").startsWith(`${prefix.replace(/:$/, "")}`);
1154
1102
  }
@@ -1158,164 +1106,368 @@ function normalizeId(id, prefix = "powerlines") {
1158
1106
  }
1159
1107
  __name(normalizeId, "normalizeId");
1160
1108
  function normalizePath(path, builtinsPath, prefix = "powerlines") {
1161
- return isValidId(toFilePath(path), prefix) ? normalizeId(toFilePath(path), prefix).replace(new RegExp(`^${prefix.replace(/:$/, "")}:`), builtinsPath) : toFilePath(path);
1109
+ return isAbsolutePath(path) ? path : isValidId(toFilePath(path), prefix) ? normalizeId(toFilePath(path), prefix).replace(new RegExp(`^${prefix.replace(/:$/, "")}:`), builtinsPath) : toFilePath(path);
1162
1110
  }
1163
1111
  __name(normalizePath, "normalizePath");
1164
- var UnifiedFS = class _UnifiedFS extends Union {
1112
+ function normalizeKey(key, sep = ":") {
1113
+ if (!key) {
1114
+ return "";
1115
+ }
1116
+ return key.replace(/[:/\\]/g, sep).replace(/^[:/\\]|[:/\\]$/g, "");
1117
+ }
1118
+ __name(normalizeKey, "normalizeKey");
1119
+ function filterKeyByBase(key, base) {
1120
+ if (base) {
1121
+ return key.startsWith(base) && key[key.length - 1] !== "$";
1122
+ }
1123
+ return key[key.length - 1] !== "$";
1124
+ }
1125
+ __name(filterKeyByBase, "filterKeyByBase");
1126
+ var BaseStorageAdapter = class {
1165
1127
  static {
1166
- __name(this, "UnifiedFS");
1128
+ __name(this, "BaseStorageAdapter");
1167
1129
  }
1168
1130
  /**
1169
- * The internal map of virtual files.
1131
+ * Indicates whether the storage adapter has been disposed.
1170
1132
  */
1171
- #virtualFS = new Volume();
1133
+ #isDisposed = false;
1172
1134
  /**
1173
- * The physical file system.
1135
+ * Configuration options for the storage adapter.
1174
1136
  */
1175
- #physicalFS = cloneFS(_fs);
1137
+ options;
1176
1138
  /**
1177
- * The context of the unified file system.
1139
+ * Constructor for the BaseStorageAdapter.
1140
+ *
1141
+ * @param options - Configuration options for the storage adapter.
1178
1142
  */
1179
- #context;
1180
- static create(context, fs2) {
1181
- let result = new _UnifiedFS(context, fs2);
1182
- result = result.use(result.#physicalFS);
1183
- if (result.#context.config.output.mode !== "fs") {
1184
- result = result.use(result.#virtualFS);
1185
- }
1186
- return result;
1143
+ constructor(options = {
1144
+ base: "/"
1145
+ }) {
1146
+ this.options = options;
1147
+ this.options.base = resolve(options.base);
1148
+ this.options.isReadOnly = !!options.isReadOnly;
1187
1149
  }
1188
1150
  /**
1189
- * Gets the virtual file system (VFS).
1151
+ * Asynchronously checks if a key exists in the storage.
1152
+ *
1153
+ * @param key - The key to check for existence.
1154
+ * @returns A promise that resolves to `true` if the key exists, otherwise `false`.
1190
1155
  */
1191
- get virtual() {
1192
- return this.#virtualFS;
1156
+ async exists(key) {
1157
+ return this.existsSync(key);
1193
1158
  }
1194
1159
  /**
1195
- * Gets the physical file system (FS).
1160
+ * Asynchronously retrieves the value associated with a given key.
1161
+ *
1162
+ * @param key - The key whose value is to be retrieved.
1163
+ * @returns A promise that resolves to the value associated with the key, or `null` if the key does not exist.
1196
1164
  */
1197
- get physical() {
1198
- return this.#physicalFS;
1165
+ async get(key) {
1166
+ return this.getSync(key);
1199
1167
  }
1200
1168
  /**
1201
- * Creates a new instance of the VirtualFileSystem.
1169
+ * Asynchronously sets the value for a given key.
1202
1170
  *
1203
- * @param context - The context of the virtual file system, typically containing options and logging functions.
1204
- * @param fs - A buffer containing the serialized virtual file system data.
1171
+ * @param key - The key to set the value for.
1172
+ * @param value - The value to set.
1205
1173
  */
1206
- constructor(context, fs2) {
1207
- super();
1208
- this.#context = context;
1209
- if (!this.#physicalFS.existsSync(this.#context.dataPath)) {
1210
- this.#physicalFS.mkdirSync(this.#context.dataPath, {
1211
- recursive: true
1212
- });
1174
+ async set(key, value) {
1175
+ if (!this.options.isReadOnly) {
1176
+ this.setSync(key, value);
1213
1177
  }
1214
- if (!this.#physicalFS.existsSync(this.#context.cachePath)) {
1215
- this.#physicalFS.mkdirSync(this.#context.cachePath, {
1216
- recursive: true
1217
- });
1218
- }
1219
- if (!this.#physicalFS.existsSync(joinPaths(this.#context.workspaceConfig.workspaceRoot, this.#context.config.output.distPath))) {
1220
- this.#physicalFS.mkdirSync(joinPaths(this.#context.workspaceConfig.workspaceRoot, this.#context.config.output.distPath), {
1221
- recursive: true
1222
- });
1178
+ }
1179
+ /**
1180
+ * Asynchronously removes a key from the storage.
1181
+ *
1182
+ * @param key - The key to remove.
1183
+ */
1184
+ async remove(key) {
1185
+ if (!this.options.isReadOnly) {
1186
+ this.removeSync(key);
1223
1187
  }
1224
- if (this.#context.config.output.mode !== "fs") {
1225
- this.#virtualFS = Volume.fromJSON(fs2._hasFiles() && fs2.files.length > 0 ? fs2.files.values().reduce((ret, file) => {
1226
- ret[file.path] = file.code;
1227
- return ret;
1228
- }, {}) : {});
1229
- if (!this.#virtualFS.existsSync(this.#context.artifactsPath)) {
1230
- this.#virtualFS.mkdirSync(this.#context.artifactsPath, {
1231
- recursive: true
1232
- });
1233
- }
1234
- if (!this.#virtualFS.existsSync(this.#context.builtinsPath)) {
1235
- this.#virtualFS.mkdirSync(this.#context.builtinsPath, {
1236
- recursive: true
1237
- });
1238
- }
1239
- if (!this.#virtualFS.existsSync(this.#context.entryPath)) {
1240
- this.#virtualFS.mkdirSync(this.#context.entryPath, {
1241
- recursive: true
1242
- });
1243
- }
1244
- if (!this.#virtualFS.existsSync(this.#context.dtsPath)) {
1245
- this.#virtualFS.mkdirSync(this.#context.dtsPath, {
1246
- recursive: true
1247
- });
1248
- }
1249
- } else if (this.#context.config.projectType === "application") {
1250
- if (!this.#physicalFS.existsSync(this.#context.artifactsPath)) {
1251
- this.#physicalFS.mkdirSync(this.#context.artifactsPath, {
1252
- recursive: true
1253
- });
1254
- }
1255
- if (!this.#physicalFS.existsSync(this.#context.builtinsPath)) {
1256
- this.#physicalFS.mkdirSync(this.#context.builtinsPath, {
1257
- recursive: true
1258
- });
1188
+ }
1189
+ /**
1190
+ * Synchronously removes all entries from the storage that match the provided base path.
1191
+ *
1192
+ * @param base - The base path to clear keys from.
1193
+ */
1194
+ clearSync(base) {
1195
+ if (!this.options.isReadOnly) {
1196
+ const keys = this.listSync(base || this.options.base);
1197
+ if (!keys.length) {
1198
+ return;
1259
1199
  }
1260
- if (!this.#physicalFS.existsSync(this.#context.entryPath)) {
1261
- this.#physicalFS.mkdirSync(this.#context.entryPath, {
1262
- recursive: true
1263
- });
1200
+ keys.map((key) => this.removeSync(base && !key.startsWith(base) ? joinPaths(base, key) : key));
1201
+ }
1202
+ }
1203
+ /**
1204
+ * Asynchronously removes all entries from the storage that match the provided base path.
1205
+ *
1206
+ * @param base - The base path to clear keys from.
1207
+ * @returns A promise that resolves when the operation is complete.
1208
+ */
1209
+ async clear(base) {
1210
+ if (!this.options.isReadOnly) {
1211
+ const keys = await this.list(base || this.options.base);
1212
+ if (!keys.length) {
1213
+ return;
1264
1214
  }
1265
- if (!this.#physicalFS.existsSync(this.#context.dtsPath)) {
1266
- this.#physicalFS.mkdirSync(this.#context.dtsPath, {
1267
- recursive: true
1268
- });
1215
+ await Promise.all(keys.map(async (key) => this.remove(base && !key.startsWith(base) ? joinPaths(base, key) : key)));
1216
+ }
1217
+ }
1218
+ /**
1219
+ * Asynchronously lists all keys under a given base path.
1220
+ *
1221
+ * @param base - The base path to list keys from.
1222
+ * @returns A promise that resolves to an array of keys under the specified base path.
1223
+ */
1224
+ async list(base) {
1225
+ return this.listSync(base);
1226
+ }
1227
+ /**
1228
+ * Disposes of the storage adapter, releasing any held resources.
1229
+ *
1230
+ * @returns A promise that resolves when the disposal is complete.
1231
+ */
1232
+ dispose() {
1233
+ return Promise.resolve();
1234
+ }
1235
+ /**
1236
+ * Async dispose method to clean up resources.
1237
+ *
1238
+ * @returns A promise that resolves when disposal is complete.
1239
+ */
1240
+ async [Symbol.asyncDispose]() {
1241
+ return this._dispose();
1242
+ }
1243
+ /**
1244
+ * Resolves a given key to its full path within the storage adapter.
1245
+ *
1246
+ * @param key - The key to resolve.
1247
+ * @returns The resolved full path for the key.
1248
+ */
1249
+ resolve(key = this.options.base) {
1250
+ if (/\.\.:|\.\.$/.test(key)) {
1251
+ throw new Error(`[${this.name}]: Invalid key: ${JSON.stringify(key)} provided to storage adapter.`);
1252
+ }
1253
+ return appendPath(correctPath(key).replace(/:/g, "/"), this.options.base);
1254
+ }
1255
+ /**
1256
+ * Disposes of the storage adapter, releasing any held resources.
1257
+ *
1258
+ * @returns A promise that resolves when the disposal is complete.
1259
+ */
1260
+ async _dispose() {
1261
+ if (!this.#isDisposed) {
1262
+ await Promise.resolve(this.dispose());
1263
+ this.#isDisposed = true;
1264
+ }
1265
+ }
1266
+ };
1267
+
1268
+ // ../powerlines/src/lib/fs/storage/file-system.ts
1269
+ var FileSystemStorageAdapter = class extends BaseStorageAdapter {
1270
+ static {
1271
+ __name(this, "FileSystemStorageAdapter");
1272
+ }
1273
+ /**
1274
+ * A name identifying the storage adapter type.
1275
+ */
1276
+ name = "file-system";
1277
+ /**
1278
+ * Constructor for the FileSystemStorageAdapter.
1279
+ *
1280
+ * @param options - Configuration options for the storage adapter.
1281
+ */
1282
+ constructor(options) {
1283
+ super(options);
1284
+ }
1285
+ /**
1286
+ * Synchronously checks if a key exists in the storage.
1287
+ *
1288
+ * @param key - The key to check for existence.
1289
+ * @returns Returns `true` if the key exists, otherwise `false`.
1290
+ */
1291
+ existsSync(key) {
1292
+ return existsSync(this.resolve(key));
1293
+ }
1294
+ /**
1295
+ * Asynchronously checks if a key exists in the storage.
1296
+ *
1297
+ * @param key - The key to check for existence.
1298
+ * @returns A promise that resolves to `true` if the key exists, otherwise `false`.
1299
+ */
1300
+ async exists(key) {
1301
+ return exists(this.resolve(key));
1302
+ }
1303
+ /**
1304
+ * Synchronously retrieves the value associated with a given key.
1305
+ *
1306
+ * @param key - The key whose value is to be retrieved.
1307
+ * @returns The value associated with the key, or `null` if the key does not exist.
1308
+ */
1309
+ getSync(key) {
1310
+ return readFileSync(this.resolve(key));
1311
+ }
1312
+ /**
1313
+ * Asynchronously retrieves the value associated with a given key.
1314
+ *
1315
+ * @param key - The key whose value is to be retrieved.
1316
+ * @returns A promise that resolves to the value associated with the key, or `null` if the key does not exist.
1317
+ */
1318
+ async get(key) {
1319
+ return readFile(this.resolve(key));
1320
+ }
1321
+ /**
1322
+ * Synchronously sets the value for a given key.
1323
+ *
1324
+ * @param key - The key to set the value for.
1325
+ * @param value - The value to set.
1326
+ */
1327
+ setSync(key, value) {
1328
+ if (!this.options.isReadOnly) {
1329
+ return writeFileSync(this.resolve(key), value);
1330
+ }
1331
+ }
1332
+ /**
1333
+ * Asynchronously sets the value for a given key.
1334
+ *
1335
+ * @param key - The key to set the value for.
1336
+ * @param value - The value to set.
1337
+ */
1338
+ async set(key, value) {
1339
+ if (!this.options.isReadOnly) {
1340
+ return writeFile$1(this.resolve(key), value);
1341
+ }
1342
+ }
1343
+ /**
1344
+ * Synchronously removes a key from the storage.
1345
+ *
1346
+ * @param key - The key to remove.
1347
+ */
1348
+ removeSync(key) {
1349
+ if (!this.options.isReadOnly) {
1350
+ try {
1351
+ return unlinkSync(this.resolve(key));
1352
+ } catch (err) {
1353
+ return ignoreNotfound(err);
1269
1354
  }
1270
1355
  }
1271
1356
  }
1272
1357
  /**
1273
- * Select the file system module to use for the operation based on the path or URL.
1358
+ * Asynchronously removes a key from the storage.
1274
1359
  *
1275
- * @param pathOrUrl - The path to perform the file system operation on.
1276
- * @param options - Options for the operation, such as output mode.
1277
- * @returns The file system module used for the operation.
1360
+ * @param key - The key to remove.
1278
1361
  */
1279
- resolveFS(pathOrUrl, options = {}) {
1280
- const mode = this.resolveMode(pathOrUrl, options);
1281
- if (mode === "virtual") {
1282
- return {
1283
- ...this.#virtualFS,
1284
- mode: "virtual"
1285
- };
1286
- } else if (mode === "fs") {
1287
- return {
1288
- ...this.#physicalFS,
1289
- mode: "fs"
1290
- };
1362
+ async remove(key) {
1363
+ if (!this.options.isReadOnly) {
1364
+ return unlink(this.resolve(key)).catch(ignoreNotfound);
1291
1365
  }
1292
- return {
1293
- ...this,
1294
- mode: this.#context.config.output.mode
1295
- };
1296
1366
  }
1297
1367
  /**
1298
- * Select the file system module to use for the operation based on the path or URL.
1368
+ * Lists all keys under a given base path synchronously.
1369
+ *
1370
+ * @param base - The base path to list keys from.
1371
+ * @returns An array of keys under the specified base path.
1372
+ */
1373
+ listSync(base) {
1374
+ try {
1375
+ return listFilesSync(this.resolve(base), {
1376
+ ignore: this.options.ignore
1377
+ });
1378
+ } catch (err) {
1379
+ return ignoreNotfound(err) ?? [];
1380
+ }
1381
+ }
1382
+ /**
1383
+ * Asynchronously lists all keys under a given base path.
1384
+ *
1385
+ * @param base - The base path to list keys from.
1386
+ * @returns A promise that resolves to an array of keys under the specified base path.
1387
+ */
1388
+ async list(base) {
1389
+ return listFiles(this.resolve(base), {
1390
+ ignore: this.options.ignore
1391
+ }).catch(ignoreNotfound).then((r) => r || []);
1392
+ }
1393
+ };
1394
+ var VirtualStorageAdapter = class extends BaseStorageAdapter {
1395
+ static {
1396
+ __name(this, "VirtualStorageAdapter");
1397
+ }
1398
+ /**
1399
+ * A name identifying the storage adapter type.
1400
+ */
1401
+ name = "virtual";
1402
+ /**
1403
+ * In-memory data storage.
1404
+ */
1405
+ data = /* @__PURE__ */ new Map();
1406
+ /**
1407
+ * Constructor for the VirtualStorageAdapter.
1408
+ *
1409
+ * @param options - Configuration options for the storage adapter.
1410
+ */
1411
+ constructor(options) {
1412
+ super(options);
1413
+ }
1414
+ /**
1415
+ * Synchronously checks if a key exists in the storage.
1299
1416
  *
1300
- * @param pathOrUrl - The path to perform the file system operation on.
1301
- * @param options - Options for the operation, such as output mode.
1302
- * @returns The file system module used for the operation.
1417
+ * @param key - The key to check for existence.
1418
+ * @returns Returns `true` if the key exists, otherwise `false`.
1303
1419
  */
1304
- resolveMode(pathOrUrl, options = {}) {
1305
- if (options.mode === "virtual" && this.#context.config.output.mode !== "fs" && isParentPath(toFilePath(pathOrUrl), this.#context.artifactsPath)) {
1306
- return "virtual";
1307
- } else if (options.mode === "fs" || this.#context.config.output.mode === "fs" || isParentPath(toFilePath(pathOrUrl), this.#context.dataPath) || isParentPath(toFilePath(pathOrUrl), this.#context.cachePath) || isParentPath(toFilePath(pathOrUrl), joinPaths(this.#context.workspaceConfig.workspaceRoot, this.#context.config.output.distPath))) {
1308
- return "fs";
1420
+ existsSync(key) {
1421
+ return this.data.has(this.resolve(key));
1422
+ }
1423
+ /**
1424
+ * Synchronously retrieves the value associated with a given key.
1425
+ *
1426
+ * @param key - The key whose value is to be retrieved.
1427
+ * @returns The value associated with the key, or `null` if the key does not exist.
1428
+ */
1429
+ getSync(key) {
1430
+ return this.data.get(this.resolve(key)) ?? null;
1431
+ }
1432
+ /**
1433
+ * Synchronously sets the value for a given key.
1434
+ *
1435
+ * @param key - The key to set the value for.
1436
+ * @param value - The value to set.
1437
+ */
1438
+ setSync(key, value) {
1439
+ if (!this.options.isReadOnly) {
1440
+ this.data.set(this.resolve(key), value);
1309
1441
  }
1310
- return void 0;
1311
1442
  }
1312
1443
  /**
1313
- * Serializes the virtual file system (VFS) to a JSON object.
1444
+ * Synchronously removes a key from the storage.
1314
1445
  *
1315
- * @returns A JSON representation of the virtual file system.
1446
+ * @param key - The key to remove.
1316
1447
  */
1317
- toJSON() {
1318
- return this.#virtualFS.toJSON();
1448
+ removeSync(key) {
1449
+ if (!this.options.isReadOnly) {
1450
+ this.data.delete(this.resolve(key));
1451
+ }
1452
+ }
1453
+ /**
1454
+ * Lists all keys under a given base path synchronously.
1455
+ *
1456
+ * @param base - The base path to list keys from.
1457
+ * @returns An array of keys under the specified base path.
1458
+ */
1459
+ listSync(base) {
1460
+ return [
1461
+ ...this.data.keys().filter((key) => !base ? true : isParentPath(key, this.resolve(base)))
1462
+ ];
1463
+ }
1464
+ /**
1465
+ * Disposes of the storage adapter, releasing any held resources.
1466
+ *
1467
+ * @returns A promise that resolves when the disposal is complete.
1468
+ */
1469
+ async dispose() {
1470
+ return this.clear();
1319
1471
  }
1320
1472
  };
1321
1473
 
@@ -1337,29 +1489,23 @@ var VirtualFileSystem = class _VirtualFileSystem {
1337
1489
  */
1338
1490
  #paths;
1339
1491
  /**
1340
- * A cache for module resolution results.
1341
- */
1342
- #resolverCache;
1343
- /**
1344
1492
  * The unified volume that combines the virtual file system with the real file system.
1345
1493
  *
1346
1494
  * @remarks
1347
1495
  * This volume allows for seamless access to both virtual and real files.
1348
1496
  */
1349
- #unifiedFS;
1497
+ #storage = {
1498
+ "": new FileSystemStorageAdapter()
1499
+ };
1350
1500
  /**
1351
- * Indicator specifying if the file system module is patched
1501
+ * A cache for module resolution results.
1352
1502
  */
1353
- #isPatched = false;
1503
+ #resolverCache;
1354
1504
  /**
1355
1505
  * Indicator specifying if the virtual file system (VFS) is disposed
1356
1506
  */
1357
1507
  #isDisposed = false;
1358
1508
  /**
1359
- * Function to revert require patch
1360
- */
1361
- #revert;
1362
- /**
1363
1509
  * The context of the virtual file system.
1364
1510
  */
1365
1511
  #context;
@@ -1368,15 +1514,6 @@ var VirtualFileSystem = class _VirtualFileSystem {
1368
1514
  */
1369
1515
  #log;
1370
1516
  /**
1371
- * Checks if a path exists in the virtual file system (VFS).
1372
- *
1373
- * @param path - The path to check.
1374
- * @returns `true` if the path exists, otherwise `false`.
1375
- */
1376
- #existsSync(path) {
1377
- return this.#unifiedFS.virtual.existsSync(this.#normalizePath(path)) || this.#unifiedFS.physical.existsSync(this.#normalizePath(path)) || this.#unifiedFS.resolveFS(path).existsSync(this.#normalizePath(path));
1378
- }
1379
- /**
1380
1517
  * Normalizes a given module id by resolving it against the built-ins path.
1381
1518
  *
1382
1519
  * @param id - The module id to normalize.
@@ -1405,6 +1542,43 @@ var VirtualFileSystem = class _VirtualFileSystem {
1405
1542
  return new RegExp(`^${this.#normalizePath(path).replace(/\*\*/g, token).replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(new RegExp(token, "g"), ".*")}$`);
1406
1543
  }
1407
1544
  /**
1545
+ * Gets the storage adapter and relative key for a given key.
1546
+ *
1547
+ * @param key - The key to get the storage adapter for.
1548
+ * @returns The storage adapter and relative key for the given key.
1549
+ */
1550
+ #getStorage(key) {
1551
+ const path = this.resolveSync(this.#normalizePath(key)) || key;
1552
+ for (const base of Object.keys(this.#storage).filter(Boolean).sort().reverse()) {
1553
+ if (isParentPath(path, base)) {
1554
+ return {
1555
+ base,
1556
+ relativeKey: replacePath(path, base),
1557
+ adapter: this.#storage[base]
1558
+ };
1559
+ }
1560
+ }
1561
+ return {
1562
+ base: "",
1563
+ relativeKey: path,
1564
+ adapter: this.#storage[""]
1565
+ };
1566
+ }
1567
+ /**
1568
+ * Gets all storage adapters that match a given base key.
1569
+ *
1570
+ * @param base - The base key to match storage adapters against.
1571
+ * @param includeParent - Whether to include parent storage adapters.
1572
+ * @returns An array of storage adapters that match the given base key.
1573
+ */
1574
+ #getStorages(base = "", includeParent = false) {
1575
+ return Object.keys(this.#storage).sort().reverse().filter((key) => isParentPath(key, base) || includeParent && isParentPath(base, key)).map((key) => ({
1576
+ relativeBase: base.length > key.length ? base.slice(key.length) : void 0,
1577
+ base: key,
1578
+ adapter: this.#storage[key]
1579
+ }));
1580
+ }
1581
+ /**
1408
1582
  * Creates a virtual file system (VFS) that is backed up to a Cap'n Proto message buffer.
1409
1583
  *
1410
1584
  * @param context - The context of the virtual file system, typically containing options and logging functions.
@@ -1414,7 +1588,13 @@ var VirtualFileSystem = class _VirtualFileSystem {
1414
1588
  if (!context.config.skipCache && existsSync(joinPaths$1(context.dataPath, "fs.bin"))) {
1415
1589
  const buffer = await readFileBuffer(joinPaths$1(context.dataPath, "fs.bin"));
1416
1590
  const message2 = new $.Message(buffer, false);
1417
- return new _VirtualFileSystem(context, message2.getRoot(FileSystem));
1591
+ const fs = message2.getRoot(FileSystem);
1592
+ const result = new _VirtualFileSystem(context, fs);
1593
+ if (fs._hasStorage() && fs.storage.length > 0) {
1594
+ await Promise.all(fs.storage.values().map(async (file) => {
1595
+ await result.write(file.path, file.code);
1596
+ }));
1597
+ }
1418
1598
  }
1419
1599
  const message = new $.Message();
1420
1600
  return new _VirtualFileSystem(context, message.initRoot(FileSystem));
@@ -1429,7 +1609,13 @@ var VirtualFileSystem = class _VirtualFileSystem {
1429
1609
  if (!context.config.skipCache && existsSync(joinPaths$1(context.dataPath, "fs.bin"))) {
1430
1610
  const buffer = readFileBufferSync(joinPaths$1(context.dataPath, "fs.bin"));
1431
1611
  const message2 = new $.Message(buffer, false);
1432
- return new _VirtualFileSystem(context, message2.getRoot(FileSystem));
1612
+ const fs = message2.getRoot(FileSystem);
1613
+ const result = new _VirtualFileSystem(context, fs);
1614
+ if (fs._hasStorage() && fs.storage.length > 0) {
1615
+ fs.storage.values().map((file) => {
1616
+ result.writeSync(file.path, file.code);
1617
+ });
1618
+ }
1433
1619
  }
1434
1620
  const message = new $.Message();
1435
1621
  return new _VirtualFileSystem(context, message.initRoot(FileSystem));
@@ -1464,6 +1650,9 @@ var VirtualFileSystem = class _VirtualFileSystem {
1464
1650
  }, "get")
1465
1651
  });
1466
1652
  }
1653
+ /**
1654
+ * Gets the resolver cache.
1655
+ */
1467
1656
  get resolverCache() {
1468
1657
  if (!this.#resolverCache) {
1469
1658
  this.#resolverCache = create({
@@ -1482,16 +1671,34 @@ var VirtualFileSystem = class _VirtualFileSystem {
1482
1671
  * @param context - The context of the virtual file system, typically containing options and logging functions.
1483
1672
  * @param fs - A buffer containing the serialized virtual file system data.
1484
1673
  */
1485
- constructor(context, fs2) {
1674
+ constructor(context, fs) {
1486
1675
  this.#context = context;
1487
- this.#unifiedFS = UnifiedFS.create(context, fs2);
1676
+ if (isSetObject(this.#context.config.output.storage)) {
1677
+ this.#storage = {
1678
+ ...this.#storage,
1679
+ ...this.#context.config.output.storage
1680
+ };
1681
+ }
1682
+ this.#storage.virtual ??= new VirtualStorageAdapter({
1683
+ base: "/_virtual"
1684
+ });
1685
+ if (this.#context.config.output.storage !== StoragePreset.FS) {
1686
+ this.#storage[this.#context.artifactsPath] ??= new VirtualStorageAdapter({
1687
+ base: this.#context.artifactsPath
1688
+ });
1689
+ this.#storage[this.#context.builtinsPath] ??= new VirtualStorageAdapter({
1690
+ base: this.#context.builtinsPath
1691
+ });
1692
+ this.#storage[this.#context.entryPath] ??= new VirtualStorageAdapter({
1693
+ base: this.#context.entryPath
1694
+ });
1695
+ }
1488
1696
  this.#metadata = {};
1489
- if (fs2._hasMetadata()) {
1490
- this.#metadata = fs2.metadata.values().reduce((ret, metadata) => {
1697
+ if (fs._hasMetadata()) {
1698
+ this.#metadata = fs.metadata.values().reduce((ret, metadata) => {
1491
1699
  ret[metadata.id] = {
1492
1700
  id: metadata.id,
1493
1701
  type: metadata.type,
1494
- mode: metadata.mode,
1495
1702
  timestamp: metadata.timestamp || Date.now(),
1496
1703
  properties: metadata._hasProperties() ? metadata.properties.values().reduce((ret2, item) => {
1497
1704
  ret2[item.key] = item.value;
@@ -1503,12 +1710,12 @@ var VirtualFileSystem = class _VirtualFileSystem {
1503
1710
  }
1504
1711
  this.#ids = {};
1505
1712
  this.#paths = {};
1506
- if (fs2._hasIds()) {
1507
- this.#ids = fs2.ids.values().reduce((ret, identifier) => {
1713
+ if (fs._hasIds()) {
1714
+ this.#ids = fs.ids.values().reduce((ret, identifier) => {
1508
1715
  ret[identifier.path] ??= identifier.id;
1509
1716
  return ret;
1510
1717
  }, {});
1511
- this.#paths = fs2.ids.values().reduce((ret, identifier) => {
1718
+ this.#paths = fs.ids.values().reduce((ret, identifier) => {
1512
1719
  ret[identifier.id] ??= identifier.path;
1513
1720
  return ret;
1514
1721
  }, {});
@@ -1516,187 +1723,123 @@ var VirtualFileSystem = class _VirtualFileSystem {
1516
1723
  this.#log = extendLog(this.#context.log, "file-system");
1517
1724
  }
1518
1725
  /**
1519
- * Check if a path or id corresponds to a virtual file **(does not actually exists on disk)**.
1726
+ * Asynchronously checks if a file exists in the virtual file system (VFS).
1520
1727
  *
1521
- * @param pathOrId - The path or id to check.
1522
- * @returns Whether the path or id corresponds to a virtual file **(does not actually exists on disk)**.
1523
- */
1524
- isVirtual(pathOrId, importer, options = {}) {
1525
- if (!pathOrId) {
1526
- return false;
1527
- }
1528
- const resolvedPath = this.resolveSync(pathOrId, importer, options);
1529
- if (!resolvedPath) {
1530
- return false;
1531
- }
1532
- return this.metadata[resolvedPath]?.mode === "virtual";
1533
- }
1534
- /**
1535
- * Check if a path or id corresponds to a file written to the file system **(actually exists on disk)**.
1536
- *
1537
- * @param pathOrId - The path or id to check.
1538
- * @returns Whether the path or id corresponds to a file written to the file system **(actually exists on disk)**.
1539
- */
1540
- isPhysical(pathOrId, importer, options = {}) {
1541
- if (!pathOrId) {
1542
- return false;
1543
- }
1544
- const resolvedPath = this.resolveSync(pathOrId, importer, options);
1545
- if (!resolvedPath) {
1546
- return false;
1547
- }
1548
- return this.metadata[resolvedPath]?.mode === "fs";
1549
- }
1550
- /**
1551
- * Lists files in a given path.
1552
- *
1553
- * @param path - The path to list files from.
1554
- * @param options - Options for listing files, such as encoding and recursion.
1555
- * @returns An array of file names in the specified path.
1556
- */
1557
- readdirSync(path, options = "utf8") {
1558
- return this.#unifiedFS.resolveFS(path).readdirSync(toFilePath(path), options);
1559
- }
1560
- /**
1561
- * Removes a file in the virtual file system (VFS).
1562
- *
1563
- * @param path - The path to create the directory at.
1564
- */
1565
- unlinkSync(path, options) {
1566
- if (!this.isFile(this.#normalizePath(path))) {
1567
- return;
1568
- }
1569
- this.#log(LogLevelLabel.TRACE, `Synchronously removing file: ${this.#normalizePath(path)}`);
1570
- this.#unifiedFS.resolveFS(path, options).unlinkSync(this.#normalizePath(path));
1571
- if (this.#ids[this.#normalizePath(path)] && this.#metadata[this.#ids[this.#normalizePath(path)]]) {
1572
- delete this.#metadata[this.#ids[this.#normalizePath(path)]];
1573
- delete this.#ids[this.#normalizePath(path)];
1574
- delete this.#paths[this.#normalizeId(path)];
1575
- this.#resolverCache.delete(this.#normalizePath(path));
1576
- }
1577
- }
1578
- /**
1579
- * Removes a file in the virtual file system (VFS).
1580
- *
1581
- * @param path - The path to create the directory at.
1728
+ * @param path - The path to the file.
1729
+ * @returns A promise that resolves to `true` if the file exists, otherwise `false`.
1582
1730
  */
1583
- async unlink(path, options) {
1584
- if (!this.isFile(this.#normalizePath(path))) {
1585
- return;
1586
- }
1587
- this.#log(LogLevelLabel.TRACE, `Removing file: ${this.#normalizePath(path)}`);
1588
- if (isFunction(this.#unifiedFS.resolveFS(path, options).promises.unlink)) {
1589
- await this.#unifiedFS.resolveFS(path, options).promises.unlink(this.#normalizePath(path));
1590
- if (this.#ids[this.#normalizePath(path)] && this.#metadata[this.#ids[this.#normalizePath(path)]]) {
1591
- delete this.#metadata[this.#ids[this.#normalizePath(path)]];
1592
- }
1593
- } else {
1594
- this.unlinkSync(this.#normalizePath(path), options);
1595
- }
1731
+ async exists(path) {
1732
+ const { relativeKey, adapter } = this.#getStorage(path);
1733
+ return adapter.exists(relativeKey);
1596
1734
  }
1597
1735
  /**
1598
- * Removes a directory in the virtual file system (VFS).
1736
+ * Synchronously checks if a file exists in the virtual file system (VFS).
1599
1737
  *
1600
- * @param path - The path to create the directory at.
1601
- * @param options - Options for creating the directory.
1738
+ * @param path - The path to the file.
1739
+ * @returns `true` if the file exists, otherwise `false`.
1602
1740
  */
1603
- rmdirSync(path, options = {}) {
1604
- if (!this.isDirectory(this.#normalizePath(path))) {
1605
- return;
1606
- }
1607
- this.#log(LogLevelLabel.TRACE, `Synchronously removing directory: ${this.#normalizePath(path)}`);
1608
- this.#unifiedFS.resolveFS(path, options).rmdirSync(this.#normalizePath(path), defu5(options, {
1609
- recursive: true
1610
- }));
1741
+ existsSync(path) {
1742
+ const { relativeKey, adapter } = this.#getStorage(path);
1743
+ return adapter.existsSync(relativeKey);
1611
1744
  }
1612
1745
  /**
1613
- * Removes a directory in the virtual file system (VFS).
1746
+ * Checks if a file is virtual in the virtual file system (VFS).
1614
1747
  *
1615
- * @param path - The path to create the directory at.
1616
- * @param options - Options for creating the directory.
1617
- * @returns A promise that resolves to the path of the created directory, or undefined if the directory could not be created.
1748
+ * @param path - The path to the file.
1749
+ * @returns `true` if the file is virtual, otherwise `false`.
1618
1750
  */
1619
- async rmdir(path, options = {}) {
1620
- if (!this.isDirectory(this.#normalizePath(path))) {
1621
- return;
1622
- }
1623
- this.#log(LogLevelLabel.TRACE, `Removing directory: ${this.#normalizePath(path)}`);
1624
- if (isFunction(this.#unifiedFS.resolveFS(path, options).promises.rm)) {
1625
- await this.#unifiedFS.resolveFS(path, options).promises.rm(this.#normalizePath(path), defu5(options, {
1626
- force: true,
1627
- recursive: true
1628
- }));
1629
- } else {
1630
- this.rmdirSync(this.#normalizePath(path), defu5(options ?? {}, {
1631
- force: true,
1632
- recursive: true
1633
- }));
1751
+ isVirtual(path) {
1752
+ const resolved = this.resolveSync(path);
1753
+ if (!resolved) {
1754
+ return false;
1634
1755
  }
1756
+ return this.#getStorage(resolved)?.adapter?.name === "virtual";
1635
1757
  }
1636
1758
  /**
1637
- * Removes a file in the virtual file system (VFS).
1759
+ * Lists files in a given path.
1638
1760
  *
1639
- * @param path - The path to the file to remove.
1640
- * @param options - Options for removing the file.
1641
- * @returns A promise that resolves when the file is removed.
1761
+ * @param path - The path to list files from.
1762
+ * @returns An array of file names in the specified path.
1642
1763
  */
1643
- async rm(path, options = {}) {
1644
- this.#log(LogLevelLabel.TRACE, `Removing: ${this.#normalizePath(path)}`);
1645
- if (this.isDirectory(this.#normalizePath(path))) {
1646
- return this.rmdir(this.#normalizePath(path), options);
1764
+ listSync(path) {
1765
+ let maskedMounts = [];
1766
+ const allKeys = [];
1767
+ for (const storage of this.#getStorages(path, true)) {
1768
+ for (const key of storage.adapter.listSync(storage.relativeBase)) {
1769
+ if (!maskedMounts.some((p) => `${storage.base}${normalizeKey(key)}`.startsWith(p))) {
1770
+ allKeys.push(`${storage.base}${normalizeKey(key)}`);
1771
+ }
1772
+ }
1773
+ maskedMounts = [
1774
+ storage.base,
1775
+ ...maskedMounts.filter((p) => !p.startsWith(storage.base))
1776
+ ];
1647
1777
  }
1648
- return this.unlink(this.#normalizePath(path), options);
1778
+ return allKeys.filter((key) => filterKeyByBase(key, path));
1649
1779
  }
1650
1780
  /**
1651
- * Synchronously removes a file or directory in the virtual file system (VFS).
1781
+ * Lists files in a given path.
1652
1782
  *
1653
- * @param path - The path to the file or directory to remove.
1654
- * @param options - Options for removing the file or directory.
1783
+ * @param path - The path to list files from.
1784
+ * @returns An array of file names in the specified path.
1655
1785
  */
1656
- rmSync(path, options = {}) {
1657
- this.#log(LogLevelLabel.TRACE, `Removing: ${this.#normalizePath(path)}`);
1658
- if (this.isDirectory(this.#normalizePath(path))) {
1659
- return this.rmdirSync(this.#normalizePath(path), options);
1786
+ async list(path) {
1787
+ let maskedMounts = [];
1788
+ const allKeys = [];
1789
+ for (const storage of this.#getStorages(path, true)) {
1790
+ for (const key of await storage.adapter.list(storage.relativeBase)) {
1791
+ if (!maskedMounts.some((p) => `${storage.base}${normalizeKey(key)}`.startsWith(p))) {
1792
+ allKeys.push(`${storage.base}${normalizeKey(key)}`);
1793
+ }
1794
+ }
1795
+ maskedMounts = [
1796
+ storage.base,
1797
+ ...maskedMounts.filter((p) => !p.startsWith(storage.base))
1798
+ ];
1660
1799
  }
1661
- return this.unlinkSync(this.#normalizePath(path), options);
1800
+ return allKeys.filter((key) => filterKeyByBase(key, path));
1662
1801
  }
1663
1802
  /**
1664
- * Creates a directory in the virtual file system (VFS).
1803
+ * Removes a file in the virtual file system (VFS).
1665
1804
  *
1666
1805
  * @param path - The path to create the directory at.
1667
- * @param options - Options for creating the directory.
1668
- * @returns A promise that resolves to the path of the created directory, or undefined if the directory could not be created.
1669
- */
1670
- mkdirSync(path, options = {}) {
1671
- return this.#unifiedFS.resolveFS(this.#normalizePath(path), options).mkdirSync(this.#normalizePath(path), defu5(omit(options, [
1672
- "mode"
1673
- ]), {
1674
- recursive: true
1675
- }));
1806
+ */
1807
+ async remove(path) {
1808
+ const normalizedPath = this.#normalizePath(path);
1809
+ this.#log(LogLevelLabel.TRACE, `Removing file: ${normalizedPath}`);
1810
+ const { relativeKey, adapter } = this.#getStorage(normalizedPath);
1811
+ if (hasFileExtension(normalizedPath)) {
1812
+ await adapter.remove(relativeKey);
1813
+ } else {
1814
+ await adapter.clear(relativeKey);
1815
+ }
1816
+ const id = this.#ids[normalizedPath];
1817
+ if (id && this.#metadata[id]) {
1818
+ delete this.#metadata[id];
1819
+ delete this.#ids[normalizedPath];
1820
+ delete this.#paths[id];
1821
+ }
1676
1822
  }
1677
1823
  /**
1678
- * Creates a directory in the virtual file system (VFS).
1824
+ * Removes a file in the virtual file system (VFS).
1679
1825
  *
1680
1826
  * @param path - The path to create the directory at.
1681
- * @param options - Options for creating the directory.
1682
- * @returns A promise that resolves to the path of the created directory, or undefined if the directory could not be created.
1683
1827
  */
1684
- async mkdir(path, options = {}) {
1685
- let result;
1686
- if (isFunction(this.#unifiedFS.resolveFS(this.#normalizePath(path), options).promises.mkdir)) {
1687
- result = await this.#unifiedFS.resolveFS(this.#normalizePath(path), options).promises.mkdir(this.#normalizePath(path), defu5(omit(options, [
1688
- "mode"
1689
- ]), {
1690
- recursive: true
1691
- }));
1828
+ removeSync(path) {
1829
+ const normalizedPath = this.#normalizePath(path);
1830
+ this.#log(LogLevelLabel.TRACE, `Removing file: ${normalizedPath}`);
1831
+ const { relativeKey, adapter } = this.#getStorage(normalizedPath);
1832
+ if (hasFileExtension(normalizedPath)) {
1833
+ adapter.removeSync(relativeKey);
1692
1834
  } else {
1693
- result = this.#unifiedFS.resolveFS(this.#normalizePath(path), options).mkdirSync(this.#normalizePath(path), defu5(omit(options, [
1694
- "mode"
1695
- ]), {
1696
- recursive: true
1697
- }));
1835
+ adapter.clearSync(relativeKey);
1836
+ }
1837
+ const id = this.#ids[normalizedPath];
1838
+ if (id && this.#metadata[id]) {
1839
+ delete this.#metadata[id];
1840
+ delete this.#ids[normalizedPath];
1841
+ delete this.#paths[id];
1698
1842
  }
1699
- return result;
1700
1843
  }
1701
1844
  /**
1702
1845
  * Glob files in the virtual file system (VFS) based on the provided pattern(s).
@@ -1718,38 +1861,14 @@ var VirtualFileSystem = class _VirtualFileSystem {
1718
1861
  const absPattern = isAbsolutePath(normalized) ? normalized : this.#normalizePath(joinPaths$1(this.#context.workspaceConfig.workspaceRoot, normalized));
1719
1862
  const firstGlobIdx = absPattern.search(/[*?[\]{}]/);
1720
1863
  const baseDir = firstGlobIdx === -1 ? findFilePath(absPattern) : absPattern.slice(0, Math.max(0, absPattern.lastIndexOf("/", firstGlobIdx)));
1721
- const stack = [
1722
- baseDir && isAbsolutePath(baseDir) ? baseDir : this.#context.workspaceConfig.workspaceRoot
1723
- ];
1724
- while (stack.length) {
1725
- const dir = stack.pop();
1726
- let entries = [];
1727
- try {
1728
- entries = await this.readdir(dir);
1729
- } catch {
1730
- continue;
1731
- }
1732
- for (const entry of entries) {
1733
- const full = this.#normalizePath(joinPaths$1(dir, entry));
1734
- let stats;
1735
- try {
1736
- stats = this.#unifiedFS.lstatSync(full);
1737
- } catch {
1738
- stats = void 0;
1739
- }
1740
- if (!stats) continue;
1741
- if (stats.isDirectory()) {
1742
- stack.push(full);
1743
- } else if (stats.isFile()) {
1744
- if (this.#buildRegex(absPattern).test(full)) {
1745
- const resolved = this.resolveSync(full);
1746
- if (resolved && !results.includes(resolved)) {
1747
- results.push(resolved);
1748
- }
1749
- }
1864
+ await Promise.all((await this.list(baseDir && isAbsolutePath(baseDir) ? baseDir : this.#context.workspaceConfig.workspaceRoot)).map(async (file) => {
1865
+ if (this.#buildRegex(absPattern).test(file)) {
1866
+ const resolved = this.resolveSync(file);
1867
+ if (resolved && !results.includes(resolved)) {
1868
+ results.push(resolved);
1750
1869
  }
1751
1870
  }
1752
- }
1871
+ }));
1753
1872
  }
1754
1873
  return results;
1755
1874
  }
@@ -1773,35 +1892,12 @@ var VirtualFileSystem = class _VirtualFileSystem {
1773
1892
  const absPattern = isAbsolutePath(normalized) ? normalized : this.#normalizePath(joinPaths$1(this.#context.workspaceConfig.workspaceRoot, normalized));
1774
1893
  const firstGlobIdx = absPattern.search(/[*?[\]{}]/);
1775
1894
  const baseDir = firstGlobIdx === -1 ? findFilePath(absPattern) : absPattern.slice(0, Math.max(0, absPattern.lastIndexOf("/", firstGlobIdx)));
1776
- const stack = [
1777
- baseDir && isAbsolutePath(baseDir) ? baseDir : this.#context.workspaceConfig.workspaceRoot
1778
- ];
1779
- while (stack.length) {
1780
- const dir = stack.pop();
1781
- let entries = [];
1782
- try {
1783
- entries = this.readdirSync(dir);
1784
- } catch {
1785
- continue;
1786
- }
1787
- for (const entry of entries) {
1788
- const full = this.#normalizePath(joinPaths$1(dir, entry));
1789
- let stats;
1790
- try {
1791
- stats = this.#unifiedFS.lstatSync(full);
1792
- } catch {
1793
- stats = void 0;
1794
- }
1795
- if (!stats) continue;
1796
- if (stats.isDirectory()) {
1797
- stack.push(full);
1798
- } else if (stats.isFile()) {
1799
- if (this.#buildRegex(absPattern).test(full)) {
1800
- const resolved = this.resolveSync(full);
1801
- if (resolved && !results.includes(resolved)) {
1802
- results.push(resolved);
1803
- }
1804
- }
1895
+ const files = this.listSync(baseDir && isAbsolutePath(baseDir) ? baseDir : this.#context.workspaceConfig.workspaceRoot);
1896
+ for (const file of files) {
1897
+ if (this.#buildRegex(absPattern).test(file)) {
1898
+ const resolved = this.resolveSync(file);
1899
+ if (resolved && !results.includes(resolved)) {
1900
+ results.push(resolved);
1805
1901
  }
1806
1902
  }
1807
1903
  }
@@ -1809,36 +1905,27 @@ var VirtualFileSystem = class _VirtualFileSystem {
1809
1905
  return results;
1810
1906
  }
1811
1907
  /**
1812
- * Moves a file from one path to another in the virtual file system (VFS).
1813
- *
1814
- * @param srcPath - The source path to move
1815
- * @param destPath - The destination path to move to
1816
- */
1817
- async move(srcPath, destPath) {
1818
- const content = await this.readFile(srcPath);
1819
- await this.writeFile(destPath, content);
1820
- await this.rm(srcPath);
1821
- }
1822
- /**
1823
- * Synchronously moves a file from one path to another in the virtual file system (VFS).
1824
- *
1825
- * @param srcPath - The source path to move
1826
- * @param destPath - The destination path to move to
1827
- */
1828
- moveSync(srcPath, destPath) {
1829
- const content = this.readFileSync(srcPath);
1830
- this.writeFileSync(destPath, content);
1831
- this.rmSync(srcPath);
1832
- }
1833
- /**
1834
1908
  * Copies a file from one path to another in the virtual file system (VFS).
1835
1909
  *
1836
1910
  * @param srcPath - The source path to copy
1837
1911
  * @param destPath - The destination path to copy to
1838
1912
  */
1839
1913
  async copy(srcPath, destPath) {
1840
- const content = await this.readFile(srcPath);
1841
- await this.writeFile(destPath, content);
1914
+ if (hasFileExtension(srcPath)) {
1915
+ const content = await this.read(srcPath);
1916
+ if (content !== void 0) {
1917
+ await this.write(hasFileExtension(destPath) ? destPath : joinPaths$1(destPath, findFileName(srcPath)), content);
1918
+ }
1919
+ } else {
1920
+ await Promise.all((await this.list(srcPath)).map(async (file) => {
1921
+ const relativePath2 = file.replace(this.#normalizePath(srcPath), "");
1922
+ const destinationPath = this.#normalizePath(appendPath(destPath, relativePath2));
1923
+ const content = await this.read(file);
1924
+ if (content !== void 0) {
1925
+ await this.write(destinationPath, content);
1926
+ }
1927
+ }));
1928
+ }
1842
1929
  }
1843
1930
  /**
1844
1931
  * Synchronously copies a file from one path to another in the virtual file system (VFS).
@@ -1847,51 +1934,85 @@ var VirtualFileSystem = class _VirtualFileSystem {
1847
1934
  * @param destPath - The destination path to copy to
1848
1935
  */
1849
1936
  copySync(srcPath, destPath) {
1850
- const content = this.readFileSync(srcPath);
1851
- this.writeFileSync(destPath, content);
1937
+ if (hasFileExtension(srcPath)) {
1938
+ const content = this.readSync(srcPath);
1939
+ if (content !== void 0) {
1940
+ this.writeSync(hasFileExtension(destPath) ? destPath : joinPaths$1(destPath, findFileName(srcPath)), content);
1941
+ }
1942
+ } else {
1943
+ this.listSync(srcPath).forEach((file) => {
1944
+ const relativePath2 = file.replace(this.#normalizePath(srcPath), "");
1945
+ const destinationPath = this.#normalizePath(appendPath(destPath, relativePath2));
1946
+ const content = this.readSync(file);
1947
+ if (content !== void 0) {
1948
+ this.writeSync(destinationPath, content);
1949
+ }
1950
+ });
1951
+ }
1852
1952
  }
1853
1953
  /**
1854
- * Lists files in a given path.
1954
+ * Moves a file (or files) from one path to another in the virtual file system (VFS).
1855
1955
  *
1856
- * @param pathOrId - The path to list files from.
1857
- * @param options - Options for listing files, such as encoding and recursion.
1858
- * @returns An array of file names in the specified path.
1956
+ * @param srcPath - The source path to move
1957
+ * @param destPath - The destination path to move to
1958
+ */
1959
+ async move(srcPath, destPath) {
1960
+ if (hasFileExtension(srcPath)) {
1961
+ await this.copy(srcPath, destPath);
1962
+ await this.remove(srcPath);
1963
+ } else {
1964
+ await Promise.all((await this.list(srcPath)).map(async (file) => {
1965
+ await this.copy(file, destPath);
1966
+ await this.remove(file);
1967
+ }));
1968
+ }
1969
+ }
1970
+ /**
1971
+ * Synchronously moves a file (or files) from one path to another in the virtual file system (VFS).
1972
+ *
1973
+ * @param srcPath - The source path to move
1974
+ * @param destPath - The destination path to move to
1859
1975
  */
1860
- async readdir(pathOrId, options = "utf8") {
1861
- return this.#unifiedFS.resolveFS(pathOrId).promises.readdir(toFilePath(pathOrId), options);
1976
+ moveSync(srcPath, destPath) {
1977
+ if (hasFileExtension(srcPath)) {
1978
+ this.copySync(srcPath, destPath);
1979
+ this.removeSync(srcPath);
1980
+ } else {
1981
+ this.listSync(srcPath).forEach((file) => {
1982
+ this.copySync(file, destPath);
1983
+ this.removeSync(file);
1984
+ });
1985
+ }
1862
1986
  }
1863
1987
  /**
1864
1988
  * Asynchronously reads a file from the virtual file system (VFS).
1865
1989
  *
1866
- * @param pathOrId - The path or ID of the file to read.
1990
+ * @param path - The path or ID of the file to read.
1867
1991
  * @returns A promise that resolves to the contents of the file as a string, or undefined if the file does not exist.
1868
1992
  */
1869
- async readFile(pathOrId, options = "utf8") {
1870
- const filePath = await this.resolve(pathOrId);
1871
- if (filePath && this.isFile(filePath)) {
1872
- let result;
1873
- if (isFunction(this.#unifiedFS.resolveFS(filePath).promises.readFile)) {
1874
- result = (await this.#unifiedFS.resolveFS(filePath).promises.readFile(filePath, options))?.toString("utf8");
1875
- } else {
1876
- result = this.#unifiedFS.resolveFS(filePath).readFileSync(filePath, options);
1877
- }
1878
- return isBuffer(result) ? bufferToString(result) : result;
1993
+ async read(path) {
1994
+ const filePath = await this.resolve(path);
1995
+ if (!filePath) {
1996
+ return void 0;
1879
1997
  }
1880
- return void 0;
1998
+ const { relativeKey, adapter } = this.#getStorage(filePath);
1999
+ this.#log(LogLevelLabel.TRACE, `Reading ${adapter.name} file: ${filePath}`);
2000
+ return await adapter.get(relativeKey) ?? void 0;
1881
2001
  }
1882
2002
  /**
1883
2003
  * Synchronously reads a file from the virtual file system (VFS).
1884
2004
  *
1885
- * @param pathOrId - The path or ID of the file to read.
2005
+ * @param path - The path or ID of the file to read.
1886
2006
  * @returns The contents of the file as a string, or undefined if the file does not exist.
1887
2007
  */
1888
- readFileSync(pathOrId, options = "utf8") {
1889
- const filePath = this.resolveSync(pathOrId);
1890
- if (filePath && this.isFile(filePath)) {
1891
- const result = this.#unifiedFS.resolveFS(filePath).readFileSync(filePath, options);
1892
- return isBuffer(result) ? bufferToString(result) : result;
2008
+ readSync(path) {
2009
+ const filePath = this.resolveSync(path);
2010
+ if (!filePath) {
2011
+ return void 0;
1893
2012
  }
1894
- return void 0;
2013
+ const { relativeKey, adapter } = this.#getStorage(filePath);
2014
+ this.#log(LogLevelLabel.TRACE, `Reading ${adapter.name} file: ${filePath}`);
2015
+ return adapter.getSync(relativeKey) ?? void 0;
1895
2016
  }
1896
2017
  /**
1897
2018
  * Writes a file to the virtual file system (VFS).
@@ -1901,41 +2022,28 @@ var VirtualFileSystem = class _VirtualFileSystem {
1901
2022
  * @param options - Optional parameters for writing the file.
1902
2023
  * @returns A promise that resolves when the file is written.
1903
2024
  */
1904
- async writeFile(path, data = "", options = "utf8") {
1905
- if (!this.isDirectory(findFilePath(this.#normalizePath(path)))) {
1906
- await this.mkdir(findFilePath(this.#normalizePath(path)), isPowerlinesWriteFileOptions(options) ? options : void 0);
1907
- }
1908
- const metadata = isVirtualFileData(data) ? data : {};
1909
- metadata.id = this.#normalizeId(path);
1910
- let code = isVirtualFileData(data) ? metadata.code : data;
1911
- if ((!isPowerlinesWriteFileOptions(options) || !options.skipFormat) && isSetString(code)) {
2025
+ async write(path, data = "", options = {}) {
2026
+ let code = data;
2027
+ if (!options.skipFormat) {
1912
2028
  const resolvedConfig = await resolveConfig(this.#normalizePath(path));
1913
2029
  if (resolvedConfig) {
1914
- code = await format(code, {
2030
+ code = await format(data, {
1915
2031
  absolutePath: this.#normalizePath(path),
1916
2032
  ...resolvedConfig
1917
2033
  });
1918
2034
  }
1919
2035
  }
1920
- const outputMode = this.#unifiedFS.resolveMode(this.#normalizePath(path), isPowerlinesWriteFileOptions(options) ? options : void 0);
1921
- this.#log(LogLevelLabel.TRACE, `Writing ${this.#normalizePath(path)} file to the ${outputMode === "fs" ? "" : "virtual "}file system (size: ${prettyBytes(new Blob(toArray(code)).size)})`);
1922
- this.#metadata[metadata.id] = {
1923
- mode: outputMode,
2036
+ const { relativeKey, adapter } = this.#getStorage(path);
2037
+ this.#log(LogLevelLabel.TRACE, `Writing ${this.#normalizePath(path)} to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob(toArray(code)).size)})`);
2038
+ const id = options?.meta?.id || this.#normalizeId(path);
2039
+ this.#metadata[id] = {
1924
2040
  variant: "normal",
1925
2041
  timestamp: Date.now(),
1926
- ...metadata
2042
+ ...options.meta ?? {}
1927
2043
  };
1928
- this.#paths[metadata.id] = this.#normalizePath(path);
1929
- this.#ids[this.#normalizePath(path)] = metadata.id;
1930
- const ifs = this.#unifiedFS.resolveFS(this.#normalizePath(path), isPowerlinesWriteFileOptions(options) ? options : void 0);
1931
- if (isFunction(ifs.promises.writeFile)) {
1932
- return ifs.promises.writeFile(this.#normalizePath(path), code, isSetObject(options) ? omit(options, [
1933
- "mode"
1934
- ]) : "utf8");
1935
- }
1936
- return ifs.writeFileSync(this.#normalizePath(path), code, isSetObject(options) ? omit(options, [
1937
- "mode"
1938
- ]) : "utf8");
2044
+ this.#paths[id] = this.#normalizePath(path);
2045
+ this.#ids[this.#normalizePath(path)] = id;
2046
+ return adapter.set(relativeKey, code);
1939
2047
  }
1940
2048
  /**
1941
2049
  * Synchronously writes a file to the virtual file system (VFS).
@@ -1944,38 +2052,18 @@ var VirtualFileSystem = class _VirtualFileSystem {
1944
2052
  * @param data - The contents of the file.
1945
2053
  * @param options - Optional parameters for writing the file.
1946
2054
  */
1947
- writeFileSync(path, data = "", options = "utf8") {
1948
- if (!this.isDirectory(findFilePath(this.#normalizePath(path)))) {
1949
- this.mkdirSync(findFilePath(this.#normalizePath(path)), isPowerlinesWriteFileOptions(options) ? options : void 0);
1950
- }
1951
- const metadata = isVirtualFileData(data) ? data : {};
1952
- metadata.id = this.#normalizeId(path);
1953
- const code = isVirtualFileData(data) ? metadata.code : data;
1954
- const outputMode = this.#unifiedFS.resolveMode(this.#normalizePath(path), isPowerlinesWriteFileOptions(options) ? options : void 0);
1955
- this.#log(LogLevelLabel.TRACE, `Writing ${this.#normalizePath(path)} file to the ${outputMode === "fs" ? "" : "virtual "}file system (size: ${prettyBytes(new Blob(toArray(code)).size)})`);
1956
- this.#metadata[metadata.id] = {
1957
- mode: outputMode,
2055
+ writeSync(path, data = "", options = {}) {
2056
+ const { relativeKey, adapter } = this.#getStorage(path);
2057
+ this.#log(LogLevelLabel.TRACE, `Writing ${this.#normalizePath(path)} file to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob(toArray(data)).size)})`);
2058
+ const id = options?.meta?.id || this.#normalizeId(path);
2059
+ this.#metadata[id] = {
1958
2060
  variant: "normal",
1959
2061
  timestamp: Date.now(),
1960
- ...metadata
2062
+ ...options.meta ?? {}
1961
2063
  };
1962
- this.#paths[metadata.id] = this.#normalizePath(path);
1963
- this.#ids[this.#normalizePath(path)] = metadata.id;
1964
- const writeStream = this.#unifiedFS.resolveFS(this.#normalizePath(path), isPowerlinesWriteFileOptions(options) ? options : void 0).createWriteStream(this.#normalizePath(path));
1965
- try {
1966
- writeStream.write(code);
1967
- } finally {
1968
- writeStream.close();
1969
- }
1970
- }
1971
- /**
1972
- * Synchronously checks if a file exists in the virtual file system (VFS).
1973
- *
1974
- * @param pathOrId - The path or ID of the file to check.
1975
- * @returns `true` if the file exists, otherwise `false`.
1976
- */
1977
- existsSync(pathOrId) {
1978
- return !!this.resolveSync(pathOrId);
2064
+ this.#paths[id] = this.#normalizePath(path);
2065
+ this.#ids[this.#normalizePath(path)] = id;
2066
+ return adapter.setSync(relativeKey, data);
1979
2067
  }
1980
2068
  /**
1981
2069
  * Retrieves the metadata of a file in the virtual file system (VFS).
@@ -1991,78 +2079,6 @@ var VirtualFileSystem = class _VirtualFileSystem {
1991
2079
  return void 0;
1992
2080
  }
1993
2081
  /**
1994
- * Checks if a file exists in the virtual file system (VFS).
1995
- *
1996
- * @remarks
1997
- * This is a base method used by {@link existsSync} - it does not try to resolve the path prior to checking if it exists or not.
1998
- *
1999
- * @param pathOrId - The path of the file to check.
2000
- * @returns `true` if the file exists, otherwise `false`.
2001
- */
2002
- isFile(pathOrId) {
2003
- const resolved = this.resolveSync(pathOrId);
2004
- return !!(resolved && (this.#unifiedFS.virtual.existsSync(resolved) && this.#unifiedFS.virtual.lstatSync(resolved).isFile() || this.#unifiedFS.physical.existsSync(resolved) && this.#unifiedFS.physical.lstatSync(resolved).isFile() || this.#unifiedFS.resolveFS(resolved).existsSync(resolved) && this.#unifiedFS.resolveFS(resolved).lstatSync(resolved).isFile()));
2005
- }
2006
- /**
2007
- * Checks if a directory exists in the virtual file system (VFS).
2008
- *
2009
- * @param pathOrId - The path of the directory to check.
2010
- * @returns `true` if the directory exists, otherwise `false`.
2011
- */
2012
- isDirectory(pathOrId) {
2013
- const resolved = this.resolveSync(pathOrId);
2014
- return !!(resolved && (this.#unifiedFS.virtual.existsSync(resolved) && this.#unifiedFS.virtual.lstatSync(resolved).isDirectory() || this.#unifiedFS.physical.existsSync(resolved) && this.#unifiedFS.physical.lstatSync(resolved).isDirectory() || this.#unifiedFS.resolveFS(resolved).existsSync(resolved) && this.#unifiedFS.resolveFS(resolved).lstatSync(resolved).isDirectory()));
2015
- }
2016
- /**
2017
- * Retrieves the status of a file in the virtual file system (VFS).
2018
- *
2019
- * @param pathOrId - The path or ID of the file to retrieve status for.
2020
- * @returns A promise that resolves to the file's status information, or false if the file does not exist.
2021
- */
2022
- async stat(pathOrId, options) {
2023
- return this.#unifiedFS.resolveFS(pathOrId).promises.stat(await this.resolve(pathOrId) || pathOrId, options);
2024
- }
2025
- /**
2026
- * Synchronously retrieves the status of a file in the virtual file system (VFS).
2027
- *
2028
- * @param pathOrId - The path or ID of the file to retrieve status for.
2029
- * @returns The file's status information, or false if the file does not exist.
2030
- */
2031
- statSync(pathOrId) {
2032
- return this.#unifiedFS.resolveFS(pathOrId).statSync(this.resolveSync(pathOrId) || pathOrId);
2033
- }
2034
- /**
2035
- * Retrieves the status of a symbolic link in the virtual file system (VFS).
2036
- *
2037
- * @param pathOrId - The path or ID of the symbolic link to retrieve status for.
2038
- * @returns A promise that resolves to the symbolic link's status information, or false if the link does not exist.
2039
- */
2040
- async lstat(pathOrId, options) {
2041
- return this.#unifiedFS.resolveFS(pathOrId).promises.lstat(await this.resolve(pathOrId) || pathOrId, options);
2042
- }
2043
- /**
2044
- * Synchronously retrieves the status of a symbolic link in the virtual file system (VFS).
2045
- *
2046
- * @param pathOrId - The path or ID of the symbolic link to retrieve status for.
2047
- * @returns The symbolic link's status information, or false if the link does not exist.
2048
- */
2049
- lstatSync(pathOrId, options) {
2050
- return this.#unifiedFS.resolveFS(pathOrId).lstatSync(this.resolveSync(pathOrId) || pathOrId, options);
2051
- }
2052
- /**
2053
- * Resolves a path or ID to its real path in the virtual file system (VFS).
2054
- *
2055
- * @param pathOrId - The path or ID to resolve.
2056
- * @returns The resolved real path if it exists, otherwise undefined.
2057
- */
2058
- realpathSync(pathOrId) {
2059
- const filePath = this.resolveSync(pathOrId);
2060
- if (!filePath) {
2061
- throw new Error(`File not found: ${pathOrId}`);
2062
- }
2063
- return filePath;
2064
- }
2065
- /**
2066
2082
  * A helper function to resolve modules in the virtual file system (VFS).
2067
2083
  *
2068
2084
  * @remarks
@@ -2079,9 +2095,15 @@ var VirtualFileSystem = class _VirtualFileSystem {
2079
2095
  * @returns A promise that resolves to the resolved module path.
2080
2096
  */
2081
2097
  async resolve(id, importer, options = {}) {
2082
- let result = this.resolverCache.get(this.#normalizeId(id));
2083
- if (result) {
2084
- return result;
2098
+ if (isAbsolutePath(id)) {
2099
+ return id;
2100
+ }
2101
+ let result;
2102
+ if (!this.#context.config.skipCache) {
2103
+ result = this.resolverCache.get(this.#normalizeId(id));
2104
+ if (result) {
2105
+ return result;
2106
+ }
2085
2107
  }
2086
2108
  result = this.paths[this.#normalizeId(id)];
2087
2109
  if (!result) {
@@ -2096,12 +2118,14 @@ var VirtualFileSystem = class _VirtualFileSystem {
2096
2118
  for (const combination of getResolutionCombinations(id, {
2097
2119
  paths
2098
2120
  })) {
2099
- if (this.#existsSync(combination)) {
2121
+ const { relativeKey, adapter } = this.#getStorage(combination);
2122
+ if (await adapter.exists(relativeKey)) {
2100
2123
  result = combination;
2124
+ break;
2101
2125
  }
2102
2126
  }
2103
2127
  try {
2104
- result = await resolve(id, {
2128
+ result = await resolve$1(id, {
2105
2129
  paths
2106
2130
  });
2107
2131
  } catch {
@@ -2109,7 +2133,9 @@ var VirtualFileSystem = class _VirtualFileSystem {
2109
2133
  }
2110
2134
  if (result) {
2111
2135
  result = toAbsolutePath(appendPath(result, this.#context.config.projectRoot), this.#context.workspaceConfig.workspaceRoot);
2112
- this.resolverCache.set(this.#normalizeId(id), result);
2136
+ if (!this.#context.config.skipCache) {
2137
+ this.resolverCache.set(this.#normalizeId(id), result);
2138
+ }
2113
2139
  }
2114
2140
  return result;
2115
2141
  }
@@ -2130,9 +2156,15 @@ var VirtualFileSystem = class _VirtualFileSystem {
2130
2156
  * @returns The resolved module path.
2131
2157
  */
2132
2158
  resolveSync(id, importer, options = {}) {
2133
- let result = this.resolverCache.get(this.#normalizeId(id));
2134
- if (result) {
2135
- return result;
2159
+ if (isAbsolutePath(id)) {
2160
+ return id;
2161
+ }
2162
+ let result;
2163
+ if (!this.#context.config.skipCache) {
2164
+ result = this.resolverCache.get(this.#normalizeId(id));
2165
+ if (result) {
2166
+ return result;
2167
+ }
2136
2168
  }
2137
2169
  result = this.paths[this.#normalizeId(id)];
2138
2170
  if (!result) {
@@ -2141,14 +2173,16 @@ var VirtualFileSystem = class _VirtualFileSystem {
2141
2173
  paths.push(importer);
2142
2174
  }
2143
2175
  paths.push(this.#context.workspaceConfig.workspaceRoot);
2144
- paths.push(joinPaths$1(this.#context.workspaceConfig.workspaceRoot, this.#context.config.projectRoot));
2145
- paths.push(joinPaths$1(this.#context.workspaceConfig.workspaceRoot, this.#context.config.sourceRoot));
2146
- paths.push(...Object.keys(this.#context.tsconfig?.options?.paths ?? {}).filter((tsconfigPath) => id.startsWith(tsconfigPath.replace(/\*$/, ""))).map((tsconfigPath) => this.#context.tsconfig?.options?.paths?.[tsconfigPath]).flat().filter(Boolean).map((tsconfigPath) => appendPath(tsconfigPath, this.#context.workspaceConfig.workspaceRoot)));
2176
+ paths.push(appendPath(this.#context.config.projectRoot, this.#context.workspaceConfig.workspaceRoot));
2177
+ paths.push(appendPath(this.#context.config.sourceRoot, this.#context.workspaceConfig.workspaceRoot));
2178
+ paths.push(...Object.keys(this.#context.tsconfig.options.paths ?? {}).filter((tsconfigPath) => id.startsWith(tsconfigPath.replace(/\*$/, ""))).map((tsconfigPath) => this.#context.tsconfig.options.paths?.[tsconfigPath]).flat().filter(Boolean).map((tsconfigPath) => appendPath(tsconfigPath, this.#context.workspaceConfig.workspaceRoot)));
2147
2179
  for (const combination of getResolutionCombinations(id, {
2148
2180
  paths
2149
2181
  })) {
2150
- if (this.#existsSync(combination)) {
2182
+ const { relativeKey, adapter } = this.#getStorage(combination);
2183
+ if (adapter.existsSync(relativeKey)) {
2151
2184
  result = combination;
2185
+ break;
2152
2186
  }
2153
2187
  }
2154
2188
  try {
@@ -2160,7 +2194,9 @@ var VirtualFileSystem = class _VirtualFileSystem {
2160
2194
  }
2161
2195
  if (result) {
2162
2196
  result = toAbsolutePath(appendPath(result, this.#context.config.projectRoot), this.#context.workspaceConfig.workspaceRoot);
2163
- this.resolverCache.set(this.#normalizeId(id), result);
2197
+ if (!this.#context.config.skipCache) {
2198
+ this.resolverCache.set(this.#normalizeId(id), result);
2199
+ }
2164
2200
  }
2165
2201
  return result;
2166
2202
  }
@@ -2171,27 +2207,27 @@ var VirtualFileSystem = class _VirtualFileSystem {
2171
2207
  if (!this.#isDisposed) {
2172
2208
  this.#isDisposed = true;
2173
2209
  this.#log(LogLevelLabel.DEBUG, "Disposing virtual file system...");
2174
- await this.unlink(joinPaths$1(this.#context.dataPath, "fs.bin"));
2210
+ await this.remove(joinPaths$1(this.#context.dataPath, "fs.bin"));
2175
2211
  const message = new $.Message();
2176
- const fs2 = message.initRoot(FileSystem);
2177
- const virtualFiles = Object.entries(this.#unifiedFS.toJSON()).filter(([, code]) => code);
2178
- const files = fs2._initFiles(virtualFiles.length);
2179
- virtualFiles.filter(([, code]) => code).forEach(([path, code], index) => {
2180
- const fd = files.get(index);
2212
+ const fs = message.initRoot(FileSystem);
2213
+ const paths = await this.list();
2214
+ const storage = fs._initStorage(paths.length);
2215
+ await Promise.all(paths.map(async (path, index) => {
2216
+ const code = await this.read(path);
2217
+ const fd = storage.get(index);
2181
2218
  fd.path = path;
2182
2219
  fd.code = code || "";
2183
- });
2184
- const ids = fs2._initIds(Object.keys(this.ids).length);
2220
+ }));
2221
+ const ids = fs._initIds(Object.keys(this.ids).length);
2185
2222
  Object.entries(this.ids).filter(([, path]) => path).forEach(([id, path], index) => {
2186
2223
  const fileId = ids.get(index);
2187
2224
  fileId.id = id;
2188
2225
  fileId.path = path;
2189
2226
  });
2190
- const metadata = fs2._initMetadata(Object.keys(this.metadata).length);
2227
+ const metadata = fs._initMetadata(Object.keys(this.metadata).length);
2191
2228
  Object.entries(this.metadata).filter(([, value]) => value).forEach(([id, value], index) => {
2192
2229
  const fileMetadata = metadata.get(index);
2193
2230
  fileMetadata.id = id;
2194
- fileMetadata.mode = value.mode;
2195
2231
  fileMetadata.type = value.type;
2196
2232
  fileMetadata.timestamp = value.timestamp ?? BigInt(Date.now());
2197
2233
  if (value.properties) {
@@ -2204,134 +2240,40 @@ var VirtualFileSystem = class _VirtualFileSystem {
2204
2240
  }
2205
2241
  });
2206
2242
  await writeFileBuffer(joinPaths$1(this.#context.dataPath, "fs.bin"), message.toArrayBuffer());
2207
- this.#resolverCache.save(true);
2208
- this.#log(LogLevelLabel.DEBUG, "Virtual file system disposed.");
2209
- }
2210
- }
2211
- /**
2212
- * Initializes the virtual file system (VFS) by patching the file system module if necessary.
2213
- */
2214
- [__VFS_PATCH__]() {
2215
- if (!this.#isPatched && this.#context.config.output.mode !== "fs") {
2216
- this.#revert = patchFS(_fs, this);
2217
- this.#isPatched = true;
2218
- }
2219
- }
2220
- /**
2221
- * Reverts the file system module to its original state if it was previously patched.
2222
- */
2223
- [__VFS_REVERT__]() {
2224
- if (this.#isPatched && this.#context.config.output.mode !== "fs") {
2225
- if (!this.#revert) {
2226
- throw new Error("Attempting to revert File System patch prior to calling `__init__` function");
2227
- }
2228
- this.#revert?.();
2229
- this.#isPatched = false;
2230
- }
2231
- }
2243
+ if (!this.#context.config.skipCache) {
2244
+ this.#resolverCache.save(true);
2245
+ }
2246
+ await Promise.all(this.#getStorages().map(async (storage2) => storage2.adapter.dispose()));
2247
+ this.#log(LogLevelLabel.TRACE, "Virtual file system has been disposed.");
2248
+ }
2249
+ }
2250
+ // /**
2251
+ // * Initializes the virtual file system (VFS) by patching the file system module if necessary.
2252
+ // */
2253
+ // public [__VFS_PATCH__]() {
2254
+ // if (!this.#isPatched && this.#context.config.output.mode !== "fs") {
2255
+ // this.#revert = patchFS(fs, this);
2256
+ // this.#isPatched = true;
2257
+ // }
2258
+ // }
2259
+ // /**
2260
+ // * Reverts the file system module to its original state if it was previously patched.
2261
+ // */
2262
+ // public [__VFS_REVERT__]() {
2263
+ // if (this.#isPatched && this.#context.config.output.mode !== "fs") {
2264
+ // if (!this.#revert) {
2265
+ // throw new Error(
2266
+ // "Attempting to revert File System patch prior to calling `__init__` function"
2267
+ // );
2268
+ // }
2269
+ // this.#revert?.();
2270
+ // this.#isPatched = false;
2271
+ // }
2272
+ // }
2232
2273
  async [Symbol.asyncDispose]() {
2233
2274
  return this.dispose();
2234
2275
  }
2235
2276
  };
2236
- var VirtualFileSystemHost = class VirtualFileSystemHost2 extends InMemoryFileSystemHost {
2237
- static {
2238
- __name(this, "VirtualFileSystemHost");
2239
- }
2240
- #fs;
2241
- constructor(fs2) {
2242
- super();
2243
- this.#fs = fs2;
2244
- }
2245
- deleteSync(path) {
2246
- this.#fs.rmSync(path);
2247
- }
2248
- readDirSync(dirPath) {
2249
- return this.#fs.readdirSync(dirPath).reduce((ret, entry) => {
2250
- const fullPath = this.#fs.resolveSync(joinPaths(dirPath, entry));
2251
- if (fullPath) {
2252
- ret.push({
2253
- name: entry,
2254
- isDirectory: this.#fs.isDirectory(fullPath),
2255
- isFile: this.#fs.isFile(fullPath),
2256
- isSymlink: false
2257
- });
2258
- }
2259
- return ret;
2260
- }, []);
2261
- }
2262
- async readFile(filePath) {
2263
- if (!this.#fs.existsSync(filePath)) {
2264
- throw new Error(`File not found: '${filePath}'. Please check the path and try again.`);
2265
- }
2266
- return await this.#fs.readFile(filePath);
2267
- }
2268
- readFileSync(filePath) {
2269
- if (!this.#fs.existsSync(filePath)) {
2270
- throw new Error(`File not found: '${filePath}'. Please check the path and try again.`);
2271
- }
2272
- return this.#fs.readFileSync(filePath);
2273
- }
2274
- async writeFile(filePath, fileText) {
2275
- return this.#fs.writeFile(filePath, fileText);
2276
- }
2277
- writeFileSync(filePath, fileText) {
2278
- this.#fs.writeFileSync(filePath, fileText);
2279
- }
2280
- async mkdir(dirPath) {
2281
- await this.#fs.mkdir(dirPath);
2282
- }
2283
- mkdirSync(dirPath) {
2284
- this.#fs.mkdirSync(dirPath);
2285
- }
2286
- async move(srcPath, destPath) {
2287
- await this.#fs.move(srcPath, destPath);
2288
- }
2289
- moveSync(srcPath, destPath) {
2290
- this.#fs.moveSync(srcPath, destPath);
2291
- }
2292
- async copy(srcPath, destPath) {
2293
- await this.#fs.copy(srcPath, destPath);
2294
- }
2295
- copySync(srcPath, destPath) {
2296
- this.#fs.copySync(srcPath, destPath);
2297
- }
2298
- async fileExists(filePath) {
2299
- return this.#fs.isFile(filePath);
2300
- }
2301
- fileExistsSync(filePath) {
2302
- return this.#fs.isFile(filePath);
2303
- }
2304
- async directoryExists(dirPath) {
2305
- return this.#fs.isDirectory(dirPath);
2306
- }
2307
- directoryExistsSync(dirPath) {
2308
- return this.#fs.isDirectory(dirPath);
2309
- }
2310
- realpathSync(path) {
2311
- return this.#fs.resolveSync(path) || path;
2312
- }
2313
- getCurrentDirectory() {
2314
- return "/";
2315
- }
2316
- async glob(patterns) {
2317
- return this.#fs.glob(patterns);
2318
- }
2319
- globSync(patterns) {
2320
- return this.#fs.globSync(patterns);
2321
- }
2322
- };
2323
- function createProgram(context, override) {
2324
- const project = new Project({
2325
- compilerOptions: {
2326
- ...context.tsconfig.options
2327
- },
2328
- tsConfigFilePath: context.tsconfig.tsconfigFilePath,
2329
- fileSystem: new VirtualFileSystemHost(context.fs),
2330
- ...override
2331
- });
2332
- return project;
2333
- }
2334
- __name(createProgram, "createProgram");
2335
2277
 
2336
2278
  // ../powerlines/src/lib/contexts/context.ts
2337
2279
  var configCache = /* @__PURE__ */ new WeakMap();
@@ -2532,7 +2474,7 @@ var PowerlinesContext = class _PowerlinesContext {
2532
2474
  * Get the path to the artifacts directory for the project
2533
2475
  */
2534
2476
  get artifactsPath() {
2535
- return joinPaths(this.workspaceConfig.workspaceRoot, this.config.projectRoot, this.config.output.artifactsFolder);
2477
+ return joinPaths(this.workspaceConfig.workspaceRoot, this.config.projectRoot, this.config.output.artifactsPath);
2536
2478
  }
2537
2479
  /**
2538
2480
  * Get the path to the builtin modules used by the project
@@ -2672,7 +2614,7 @@ var PowerlinesContext = class _PowerlinesContext {
2672
2614
  if (!resolvedId) {
2673
2615
  return void 0;
2674
2616
  }
2675
- const code = await this.fs.readFile(resolvedId);
2617
+ const code = await this.fs.read(resolvedId);
2676
2618
  if (!code) {
2677
2619
  return void 0;
2678
2620
  }
@@ -2686,7 +2628,7 @@ var PowerlinesContext = class _PowerlinesContext {
2686
2628
  */
2687
2629
  async getBuiltins() {
2688
2630
  return Promise.all(Object.entries(this.fs.metadata).filter(([, meta]) => meta && meta.type === "builtin").map(async ([path, meta]) => {
2689
- const code = await this.fs.readFile(path);
2631
+ const code = await this.fs.read(path);
2690
2632
  return {
2691
2633
  ...meta,
2692
2634
  path,
@@ -2702,11 +2644,8 @@ var PowerlinesContext = class _PowerlinesContext {
2702
2644
  * @param options - Optional write file options
2703
2645
  */
2704
2646
  async emitEntry(code, path, options = {}) {
2705
- return this.fs.writeFile(isAbsolute(path) ? path : appendPath(path, this.entryPath), {
2706
- code,
2647
+ return this.fs.write(isAbsolute(path) ? path : appendPath(path, this.entryPath), code, defu6(options, {
2707
2648
  type: "entry"
2708
- }, defu5(options, {
2709
- mode: this.config.output.mode
2710
2649
  }));
2711
2650
  }
2712
2651
  /**
@@ -2718,12 +2657,8 @@ var PowerlinesContext = class _PowerlinesContext {
2718
2657
  * @param options - Optional write file options
2719
2658
  */
2720
2659
  async emitBuiltin(code, id, path, options = {}) {
2721
- return this.fs.writeFile(path ? isAbsolute(path) ? path : joinPaths(this.builtinsPath, path) : appendPath(id, this.builtinsPath), {
2722
- id,
2723
- code,
2660
+ return this.fs.write(path ? isAbsolute(path) ? path : joinPaths(this.builtinsPath, path) : appendPath(id, this.builtinsPath), code, defu6(options, {
2724
2661
  type: "builtin"
2725
- }, defu5(options, {
2726
- mode: this.config.output.mode
2727
2662
  }));
2728
2663
  }
2729
2664
  /**
@@ -2917,9 +2852,9 @@ var PowerlinesContext = class _PowerlinesContext {
2917
2852
  userConfig
2918
2853
  });
2919
2854
  }
2920
- this.config.tsconfig ??= getTsconfigFilePath(this.workspaceConfig.workspaceRoot, cacheKey.projectRoot, config.tsconfig);
2855
+ config.tsconfig ??= getTsconfigFilePath(this.workspaceConfig.workspaceRoot, cacheKey.projectRoot, config.tsconfig);
2921
2856
  if (isSetObject(config)) {
2922
- this.resolvedConfig = defu5({
2857
+ this.resolvedConfig = defu6({
2923
2858
  inlineConfig: this.config.inlineConfig,
2924
2859
  userConfig: this.config.userConfig
2925
2860
  }, options.isHighPriority ? this.#getConfigProps(config) : {}, {
@@ -2934,12 +2869,11 @@ var PowerlinesContext = class _PowerlinesContext {
2934
2869
  version: this.packageJson?.version,
2935
2870
  description: this.packageJson?.description,
2936
2871
  sourceRoot: this.projectJson?.sourceRoot || appendPath("src", cacheKey.projectRoot),
2937
- output: {
2872
+ output: defu6(config.output ?? {}, {
2938
2873
  outputPath: cacheKey.projectRoot ? joinPaths(this.workspaceConfig?.directories?.build || "dist", cacheKey.projectRoot) : this.workspaceConfig?.directories?.build || "dist",
2939
- mode: "virtual",
2874
+ artifactsPath: joinPaths(cacheKey.projectRoot, `.${config.framework ?? "powerlines"}`),
2940
2875
  dts: joinPaths(cacheKey.projectRoot, `${config.framework ?? "powerlines"}.d.ts`),
2941
2876
  builtinPrefix: config.framework ?? "powerlines",
2942
- artifactsFolder: joinPaths(cacheKey.projectRoot, `.${config.framework ?? "powerlines"}`),
2943
2877
  assets: [
2944
2878
  {
2945
2879
  glob: "LICENSE"
@@ -2953,7 +2887,7 @@ var PowerlinesContext = class _PowerlinesContext {
2953
2887
  glob: "package.json"
2954
2888
  }
2955
2889
  ]
2956
- }
2890
+ })
2957
2891
  }, options.isHighPriority ? {} : this.#getConfigProps(config), {
2958
2892
  inlineConfig: {},
2959
2893
  userConfig: {},
@@ -2998,10 +2932,10 @@ var PowerlinesContext = class _PowerlinesContext {
2998
2932
  ])));
2999
2933
  if (this.config.projectRoot && this.config.projectRoot !== "." && this.config.projectRoot !== "./" && this.config.projectRoot !== this.workspaceConfig.workspaceRoot) {
3000
2934
  this.config.output.outputPath ??= joinPaths("dist", this.config.projectRoot);
3001
- this.config.output.distPath ??= joinPaths(this.config.projectRoot, "dist");
2935
+ this.config.output.buildPath ??= joinPaths(this.config.projectRoot, "dist");
3002
2936
  } else {
3003
2937
  this.config.output.outputPath ??= "dist";
3004
- this.config.output.distPath ??= "dist";
2938
+ this.config.output.buildPath ??= "dist";
3005
2939
  }
3006
2940
  this.config.output.assets = getUnique(this.config.output.assets.map((asset) => {
3007
2941
  return {
@@ -3039,7 +2973,7 @@ var PowerlinesContext = class _PowerlinesContext {
3039
2973
  this.#fs ??= await VirtualFileSystem.create(this);
3040
2974
  }
3041
2975
  mergeUserConfig(from = {}, into = this.config.userConfig ?? {}) {
3042
- this.config.userConfig = defu5({
2976
+ this.config.userConfig = defu6({
3043
2977
  entry: Array.isArray(from.entry) && from.entry.length > 0 ? from.entry : Array.isArray(into?.entry) && into.entry.length > 0 ? into.entry : []
3044
2978
  }, omit(from ?? {}, [
3045
2979
  "entry"
@@ -3344,12 +3278,49 @@ var PowerlinesAPIContext = class _PowerlinesAPIContext extends PowerlinesContext
3344
3278
  }
3345
3279
  return context;
3346
3280
  }
3281
+ /**
3282
+ * Update the context using a new user configuration options
3283
+ *
3284
+ * @param userConfig - The new user configuration options.
3285
+ */
3286
+ async withUserConfig(userConfig, options = {
3287
+ isHighPriority: true
3288
+ }) {
3289
+ await super.withUserConfig(userConfig, options);
3290
+ await Promise.all(Object.keys(this.#environments).map(async (name) => {
3291
+ await this.#environments[name].withUserConfig(userConfig, options);
3292
+ }));
3293
+ }
3294
+ /**
3295
+ * Update the context using a new inline configuration options
3296
+ *
3297
+ * @param inlineConfig - The new inline configuration options.
3298
+ */
3299
+ async withInlineConfig(inlineConfig, options = {
3300
+ isHighPriority: true
3301
+ }) {
3302
+ await super.withInlineConfig(inlineConfig, options);
3303
+ await Promise.all(Object.keys(this.#environments).map(async (name) => {
3304
+ await this.#environments[name].withInlineConfig(inlineConfig, options);
3305
+ }));
3306
+ }
3307
+ /**
3308
+ * Add a plugin to the API context and all environments
3309
+ *
3310
+ * @param plugin - The plugin to add.
3311
+ */
3347
3312
  async addPlugin(plugin) {
3348
3313
  this.plugins.push(plugin);
3349
3314
  await Promise.all(Object.keys(this.environments).map(async (name) => {
3350
3315
  await this.environments[name].addPlugin(plugin);
3351
3316
  }));
3352
3317
  }
3318
+ /**
3319
+ * Get an environment by name, or the default environment if no name is provided
3320
+ *
3321
+ * @param name - The name of the environment to retrieve.
3322
+ * @returns The requested environment context.
3323
+ */
3353
3324
  async getEnvironment(name) {
3354
3325
  let environment;
3355
3326
  if (name) {
@@ -3471,21 +3442,17 @@ ${formatLogMessage(context.config)}`);
3471
3442
  await writeMetaFile(context);
3472
3443
  context.persistedMeta = context.meta;
3473
3444
  if (!context.fs.existsSync(context.cachePath)) {
3474
- await context.fs.mkdir(context.cachePath, {
3475
- mode: "fs"
3476
- });
3445
+ await createDirectory(context.cachePath);
3477
3446
  }
3478
3447
  if (!context.fs.existsSync(context.dataPath)) {
3479
- await context.fs.mkdir(context.dataPath, {
3480
- mode: "fs"
3481
- });
3448
+ await createDirectory(context.dataPath);
3482
3449
  }
3483
3450
  await this.callPreHook(context, "prepare");
3484
3451
  await this.callNormalHook(context, "prepare");
3485
3452
  if (context.config.output.dts !== false) {
3486
3453
  context.log(LogLevelLabel.TRACE, `Preparing the TypeScript definitions for the Powerlines project.`);
3487
3454
  if (context.fs.existsSync(context.dtsPath)) {
3488
- await context.fs.unlink(context.dtsPath);
3455
+ await context.fs.remove(context.dtsPath);
3489
3456
  }
3490
3457
  context.log(LogLevelLabel.TRACE, "Transforming built-ins runtime modules files.");
3491
3458
  const builtinFilePaths = await Promise.all((await context.getBuiltins()).map(async (file) => {
@@ -3572,7 +3539,7 @@ ${formatLogMessage(context.config)}`);
3572
3539
  generatedTypes = result;
3573
3540
  }
3574
3541
  }
3575
- await context.fs.writeFile(context.dtsPath, `${directives ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
3542
+ await context.fs.write(context.dtsPath, `${directives ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
3576
3543
 
3577
3544
  ` : ""}${getFileHeader(context, {
3578
3545
  directive: null,
@@ -3580,9 +3547,7 @@ ${formatLogMessage(context.config)}`);
3580
3547
  })}
3581
3548
 
3582
3549
  ${formatTypes(generatedTypes)}
3583
- `, {
3584
- mode: "fs"
3585
- });
3550
+ `);
3586
3551
  }
3587
3552
  context.tsconfig = getParsedTypeScriptConfig(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig);
3588
3553
  if (!context.tsconfig) {
@@ -3650,8 +3615,8 @@ ${formatTypes(generatedTypes)}
3650
3615
  await this.prepare(inlineConfig);
3651
3616
  await this.#executeEnvironments(async (context) => {
3652
3617
  this.context.log(LogLevelLabel.TRACE, "Cleaning the project's dist and artifacts directories.");
3653
- await context.fs.rmdir(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.output.distPath));
3654
- await context.fs.rmdir(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.output.artifactsFolder));
3618
+ await context.fs.remove(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.output.buildPath));
3619
+ await context.fs.remove(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.output.artifactsPath));
3655
3620
  await callHook(context, "clean", {
3656
3621
  sequential: true
3657
3622
  });
@@ -3693,11 +3658,11 @@ ${formatTypes(generatedTypes)}
3693
3658
  await this.#executeEnvironments(async (context) => {
3694
3659
  await this.callPreHook(context, "build");
3695
3660
  await this.callNormalHook(context, "build");
3696
- if (context.config.output.distPath !== context.config.output.outputPath) {
3697
- const sourcePath = appendPath(context.config.output.distPath, context.workspaceConfig.workspaceRoot);
3661
+ if (context.config.output.buildPath !== context.config.output.outputPath) {
3662
+ const sourcePath = appendPath(context.config.output.buildPath, context.workspaceConfig.workspaceRoot);
3698
3663
  const destinationPath = joinPaths$1(appendPath(context.config.output.outputPath, context.workspaceConfig.workspaceRoot), "dist");
3699
3664
  if (sourcePath !== destinationPath) {
3700
- context.log(LogLevelLabel.INFO, `Copying build output files from project's build directory (${context.config.output.distPath}) to the workspace's output directory (${context.config.output.outputPath}).`);
3665
+ context.log(LogLevelLabel.INFO, `Copying build output files from project's build directory (${context.config.output.buildPath}) to the workspace's output directory (${context.config.output.outputPath}).`);
3701
3666
  await copyFiles({
3702
3667
  input: sourcePath,
3703
3668
  glob: "**/*"
@@ -4040,7 +4005,7 @@ function withExecutor(command, executorFn) {
4040
4005
  throw new Error("The executor requires `projectsConfigurations` on the context object.");
4041
4006
  }
4042
4007
  const projectConfig = context.projectsConfigurations.projects[context.projectName];
4043
- const api = await src_default.from(workspaceConfig.workspaceRoot, defu5({
4008
+ const api = await src_default.from(workspaceConfig.workspaceRoot, defu6({
4044
4009
  root: projectConfig.root,
4045
4010
  type: projectConfig.projectType,
4046
4011
  sourceRoot: projectConfig.sourceRoot,
@@ -4053,7 +4018,7 @@ function withExecutor(command, executorFn) {
4053
4018
  }
4054
4019
  }, options));
4055
4020
  try {
4056
- return await Promise.resolve(executorFn(defu5({
4021
+ return await Promise.resolve(executorFn(defu6({
4057
4022
  projectName: context.projectName,
4058
4023
  options,
4059
4024
  workspaceConfig,