@powerlines/nx 0.10.46 → 0.10.48

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 (30) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{chunk-R6ECHVU4.mjs → chunk-22IQ22WZ.mjs} +665 -229
  3. package/dist/{chunk-PE72KJBW.mjs → chunk-2Z55S53G.mjs} +1 -1
  4. package/dist/{chunk-N4LRSAGW.mjs → chunk-3K4DAFFO.mjs} +1 -1
  5. package/dist/{chunk-EUCVGGMW.js → chunk-AWWEVPW6.js} +2 -2
  6. package/dist/{chunk-FKZWCQXX.js → chunk-CSSCW7NJ.js} +2 -2
  7. package/dist/{chunk-6MIGHWXS.js → chunk-D5NQ7RJL.js} +2 -2
  8. package/dist/{chunk-QFQYFQT4.mjs → chunk-IZGOLA5N.mjs} +1 -1
  9. package/dist/{chunk-BA3VSEVV.js → chunk-J2P7ZMNQ.js} +2 -2
  10. package/dist/{chunk-3BM4F7DF.js → chunk-JLTPLOQU.js} +2 -2
  11. package/dist/{chunk-WDCMFWCL.mjs → chunk-Q3ETCCV3.mjs} +1 -1
  12. package/dist/{chunk-BTBIUGND.mjs → chunk-XRZRSXSO.mjs} +1 -1
  13. package/dist/{chunk-B73RQF3Y.js → chunk-YYQPZELV.js} +663 -227
  14. package/dist/executors.js +14 -14
  15. package/dist/executors.mjs +6 -6
  16. package/dist/index.js +14 -14
  17. package/dist/index.mjs +6 -6
  18. package/dist/src/base/base-executor.js +2 -2
  19. package/dist/src/base/base-executor.mjs +1 -1
  20. package/dist/src/executors/build/executor.js +4 -4
  21. package/dist/src/executors/build/executor.mjs +2 -2
  22. package/dist/src/executors/clean/executor.js +4 -4
  23. package/dist/src/executors/clean/executor.mjs +2 -2
  24. package/dist/src/executors/docs/executor.js +4 -4
  25. package/dist/src/executors/docs/executor.mjs +2 -2
  26. package/dist/src/executors/lint/executor.js +4 -4
  27. package/dist/src/executors/lint/executor.mjs +2 -2
  28. package/dist/src/executors/prepare/executor.js +4 -4
  29. package/dist/src/executors/prepare/executor.mjs +2 -2
  30. package/package.json +8 -8
@@ -3,13 +3,12 @@ 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 defu6, { defu } from 'defu';
6
+ import defu6, { createDefu, 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
- import { copyFiles } from '@stryke/fs/copy-file';
12
- import { createDirectory } from '@stryke/fs/helpers';
11
+ import { createDirectorySync, createDirectory } from '@stryke/fs/helpers';
13
12
  import { install } from '@stryke/fs/install';
14
13
  import { listFilesSync, listFiles } from '@stryke/fs/list-files';
15
14
  import { isPackageExists, isPackageListed, doesPackageMatch, getPackageListing } from '@stryke/fs/package-fns';
@@ -19,6 +18,7 @@ import { joinPaths as joinPaths$1 } from '@stryke/path/join-paths';
19
18
  import { replacePath, replaceExtension } from '@stryke/path/replace';
20
19
  import { isFunction } from '@stryke/type-checks/is-function';
21
20
  import { isNumber } from '@stryke/type-checks/is-number';
21
+ import { isObject } from '@stryke/type-checks/is-object';
22
22
  import { isPromiseLike } from '@stryke/type-checks/is-promise';
23
23
  import { isSet } from '@stryke/type-checks/is-set';
24
24
  import { isSetObject } from '@stryke/type-checks/is-set-object';
@@ -28,8 +28,8 @@ import Handlebars from 'handlebars';
28
28
  import { declare } from '@babel/helper-plugin-utils';
29
29
  import * as t from '@babel/types';
30
30
  import ts, { flattenDiagnosticMessageText } from 'typescript';
31
- import { joinPaths } from '@stryke/path/join';
32
31
  import { InMemoryFileSystemHost, Project } from 'ts-morph';
32
+ import { isString } from '@stryke/type-checks/is-string';
33
33
  import { getPackageName, hasPackageVersion, getPackageVersion } from '@stryke/string-format/package';
34
34
  import { getObjectDiff } from '@donedeal0/superdiff';
35
35
  import { readJsonFile, readJsonFileSync } from '@stryke/fs/json';
@@ -37,38 +37,41 @@ import { StormJSON } from '@stryke/json/storm-json';
37
37
  import { hasFileExtension, findFilePath, findFileName, relativePath, findFileDotExtensionSafe } from '@stryke/path/file-path-fns';
38
38
  import { titleCase } from '@stryke/string-format/title-case';
39
39
  import { existsSync, exists } from '@stryke/fs/exists';
40
- import { writeFileSync, writeFile as writeFile$1 } from '@stryke/fs/write-file';
41
- import { resolveConfig, format } from 'prettier';
42
40
  import { getEnvPaths } from '@stryke/env/get-env-paths';
43
41
  import { relativeToWorkspaceRoot } from '@stryke/fs/get-workspace-root';
44
42
  import { hashDirectory } from '@stryke/hash/hash-files';
45
43
  import { murmurhash } from '@stryke/hash/murmurhash';
46
44
  import { getUnique, getUniqueBy } from '@stryke/helpers/get-unique';
47
45
  import { omit } from '@stryke/helpers/omit';
46
+ import { fetchRequest } from '@stryke/http/fetch';
48
47
  import { isAbsolutePath, isAbsolute } from '@stryke/path/is-type';
48
+ import { joinPaths } from '@stryke/path/join';
49
49
  import { isNull } from '@stryke/type-checks/is-null';
50
- import { isString } from '@stryke/type-checks/is-string';
51
50
  import { uuid } from '@stryke/unique-id/uuid';
52
51
  import { tsconfigPathsToRegExp, match } from 'bundle-require';
52
+ import { create } from 'flat-cache';
53
+ import { parse } from 'oxc-parser';
54
+ import { Agent, setGlobalDispatcher, interceptors, Response } from 'undici';
53
55
  import { createJiti } from 'jiti';
54
56
  import { isUndefined } from '@stryke/type-checks/is-undefined';
55
57
  import { parseTypeDefinition } from '@stryke/convert/parse-type-definition';
56
- import { isFile } from '@stryke/fs/is-file';
58
+ import { isDirectory, isFile } from '@stryke/fs/is-file';
57
59
  import * as $ from '@stryke/capnp';
58
60
  import { readFileBuffer, readFileBufferSync, writeFileBuffer } from '@stryke/fs/buffer';
59
- import { correctPath, toAbsolutePath } from '@stryke/path/correct-path';
60
61
  import { isParentPath } from '@stryke/path/is-parent-path';
61
62
  import { prettyBytes } from '@stryke/string-format/pretty-bytes';
62
- import { create } from 'flat-cache';
63
63
  import { Blob } from 'node:buffer';
64
+ import { fileURLToPath } from 'node:url';
65
+ import { resolveConfig, format } from 'prettier';
64
66
  import { getColor } from '@storm-software/config-tools/utilities/colors';
65
67
  import { noop } from '@stryke/helpers/noop';
68
+ import { correctPath } from '@stryke/path/correct-path';
66
69
  import { slash } from '@stryke/path/slash';
67
70
  import { readFileSync, readFile } from '@stryke/fs/read-file';
71
+ import { writeFileSync, writeFile } from '@stryke/fs/write-file';
68
72
  import { unlinkSync } from 'node:fs';
69
73
  import { unlink } from 'node:fs/promises';
70
74
  import { resolve } from 'node:path';
71
- import { isObject } from '@stryke/type-checks/is-object';
72
75
 
73
76
  function resolveModulePath(nodePath, state) {
74
77
  if (!t.isStringLiteral(nodePath.node)) {
@@ -184,13 +187,16 @@ var VirtualFileSystemHost = class extends InMemoryFileSystemHost {
184
187
  this.#context.fs.removeSync(path);
185
188
  }
186
189
  readDirSync(dirPath) {
190
+ if (!this.#context.fs.isDirectorySync(dirPath)) {
191
+ return [];
192
+ }
187
193
  return this.#context.fs.listSync(dirPath).reduce((ret, entry) => {
188
- const fullPath = this.#context.fs.resolveSync(joinPaths(dirPath, entry));
194
+ const fullPath = this.#context.fs.resolveSync(entry);
189
195
  if (fullPath) {
190
196
  ret.push({
191
197
  name: entry,
192
- isDirectory: this.#context.fs.existsSync(fullPath),
193
- isFile: this.#context.fs.existsSync(fullPath),
198
+ isDirectory: this.#context.fs.isDirectorySync(fullPath),
199
+ isFile: this.#context.fs.isFileSync(fullPath),
194
200
  isSymlink: false
195
201
  });
196
202
  }
@@ -198,14 +204,14 @@ var VirtualFileSystemHost = class extends InMemoryFileSystemHost {
198
204
  }, []);
199
205
  }
200
206
  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.`);
207
+ if (!this.#context.fs.isFileSync(filePath)) {
208
+ return "";
203
209
  }
204
210
  return await this.#context.fs.read(filePath);
205
211
  }
206
212
  readFileSync(filePath) {
207
- if (!this.#context.fs.existsSync(filePath)) {
208
- throw new Error(`File not found: '${filePath}'. Please check the path and try again.`);
213
+ if (!this.#context.fs.isFileSync(filePath)) {
214
+ return "";
209
215
  }
210
216
  return this.#context.fs.readSync(filePath);
211
217
  }
@@ -215,9 +221,11 @@ var VirtualFileSystemHost = class extends InMemoryFileSystemHost {
215
221
  writeFileSync(filePath, fileText) {
216
222
  this.#context.fs.writeSync(filePath, fileText);
217
223
  }
218
- async mkdir(_dirPath) {
224
+ async mkdir(dirPath) {
225
+ await this.#context.fs.mkdir(dirPath);
219
226
  }
220
- mkdirSync(_dirPath) {
227
+ mkdirSync(dirPath) {
228
+ this.#context.fs.mkdirSync(dirPath);
221
229
  }
222
230
  async move(srcPath, destPath) {
223
231
  await this.#context.fs.move(srcPath, destPath);
@@ -232,16 +240,16 @@ var VirtualFileSystemHost = class extends InMemoryFileSystemHost {
232
240
  this.#context.fs.copySync(srcPath, destPath);
233
241
  }
234
242
  async fileExists(filePath) {
235
- return this.#context.fs.exists(filePath);
243
+ return this.#context.fs.isFile(filePath);
236
244
  }
237
245
  fileExistsSync(filePath) {
238
- return this.#context.fs.existsSync(filePath);
246
+ return this.#context.fs.isFileSync(filePath);
239
247
  }
240
248
  async directoryExists(dirPath) {
241
- return this.#context.fs.exists(dirPath);
249
+ return this.#context.fs.isDirectory(dirPath);
242
250
  }
243
251
  directoryExistsSync(dirPath) {
244
- return this.#context.fs.existsSync(dirPath);
252
+ return this.#context.fs.isDirectorySync(dirPath);
245
253
  }
246
254
  realpathSync(path) {
247
255
  return this.#context.fs.resolveSync(path) || path;
@@ -320,6 +328,14 @@ ${diagnosticMessage.length > 5e3 ? `${diagnosticMessage.slice(0, 5e3)}...` : dia
320
328
  return formatTypes(builtinModules);
321
329
  }
322
330
  __name(emitTypes, "emitTypes");
331
+ var mergeResults = createDefu((obj, key, value) => {
332
+ if (isString(obj[key]) && isString(value)) {
333
+ obj[key] = `${obj[key] || ""}
334
+ ${value || ""}`.trim();
335
+ return true;
336
+ }
337
+ return false;
338
+ });
323
339
  async function callHook(context, hook, options, ...args) {
324
340
  const handlers = context.selectHooks(hook, options);
325
341
  if (handlers.length > 0) {
@@ -327,18 +343,28 @@ async function callHook(context, hook, options, ...args) {
327
343
  let results = [];
328
344
  if (options?.sequential === false) {
329
345
  results = await Promise.all(handlers.map(async (handler) => {
330
- if (!isFunction(handler)) {
346
+ if (!isFunction(handler.handle)) {
331
347
  throw new Error(`Plugin hook handler for hook "${hook}" is not a function.`);
332
348
  }
333
- return Promise.resolve(handler.apply(null, ...args));
349
+ return Promise.resolve(
350
+ // eslint-disable-next-line ts/no-unsafe-call
351
+ handler.handle.apply(handler.context, [
352
+ ...args
353
+ ])
354
+ );
334
355
  }));
335
356
  } else {
336
357
  for (const handler of handlers) {
337
- if (!isFunction(handler)) {
358
+ if (!isFunction(handler.handle)) {
338
359
  throw new Error(`Plugin hook handler for hook "${hook}" is not a function.`);
339
360
  }
340
361
  if (options?.result === "first" || options?.asNextParam === false) {
341
- results.push(await Promise.resolve(handler.apply(null, ...args)));
362
+ results.push(await Promise.resolve(
363
+ // eslint-disable-next-line ts/no-unsafe-call
364
+ handler.handle.apply(handler.context, [
365
+ ...args
366
+ ])
367
+ ));
342
368
  if (options?.result === "first" && isSet(results[results.length - 1])) {
343
369
  break;
344
370
  }
@@ -351,11 +377,26 @@ async function callHook(context, hook, options, ...args) {
351
377
  }
352
378
  const result = await Promise.resolve(
353
379
  // eslint-disable-next-line ts/no-unsafe-call
354
- handler.apply(null, ...sequenceArgs)
380
+ handler.handle.apply(handler.context, [
381
+ ...sequenceArgs
382
+ ])
355
383
  );
356
- results = [
357
- result
358
- ];
384
+ if (result) {
385
+ if (options?.result === "last") {
386
+ results = [
387
+ result
388
+ ];
389
+ } else if (isString(result)) {
390
+ results = [
391
+ `${isString(results[0]) ? results[0] || "" : ""}
392
+ ${result || ""}`.trim()
393
+ ];
394
+ } else if (isObject(result)) {
395
+ results = [
396
+ mergeResults(result, results[0] ?? {})
397
+ ];
398
+ }
399
+ }
359
400
  }
360
401
  }
361
402
  }
@@ -521,33 +562,20 @@ ${parsedCommandLine.errors.map((error) => `- ${(error.category !== void 0 && err
521
562
  };
522
563
  }
523
564
  __name(getParsedTypeScriptConfig, "getParsedTypeScriptConfig");
524
- async function writeFile(log, filepath, content, skipFormat = false) {
525
- try {
526
- if (skipFormat) {
527
- await writeFile$1(filepath, content);
528
- } else {
529
- const config = await resolveConfig(filepath);
530
- const formatted = await format(content, {
531
- ...config ?? {},
532
- filepath
533
- });
534
- await writeFile$1(filepath, formatted || "");
535
- }
536
- } catch (error) {
537
- log(LogLevelLabel.ERROR, `Failed to write file ${filepath} to disk
538
- ${error?.message ? error.message : ""}`);
539
- }
540
- }
541
- __name(writeFile, "writeFile");
542
565
 
543
566
  // ../powerlines/src/internal/helpers/resolve-tsconfig.ts
567
+ function getTsconfigDtsPath(context) {
568
+ const dtsRelativePath = joinPaths$1(relativePath(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.projectRoot), findFilePath(context.dtsPath)), findFileName(context.dtsPath));
569
+ return dtsRelativePath;
570
+ }
571
+ __name(getTsconfigDtsPath, "getTsconfigDtsPath");
544
572
  async function resolveTsconfigChanges(context) {
545
573
  const tsconfig = getParsedTypeScriptConfig(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig, context.config.tsconfigRaw);
546
574
  const tsconfigFilePath = getTsconfigFilePath(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig);
547
575
  const tsconfigJson = await readJsonFile(tsconfigFilePath);
548
576
  tsconfigJson.compilerOptions ??= {};
549
577
  if (context.config.output.dts !== false) {
550
- const dtsRelativePath = joinPaths$1(relativePath(joinPaths$1(context.workspaceConfig.workspaceRoot, context.config.projectRoot), findFilePath(context.dtsPath)), findFileName(context.dtsPath));
578
+ const dtsRelativePath = getTsconfigDtsPath(context);
551
579
  if (!tsconfigJson.include?.some((filePattern) => isIncludeMatchFound(filePattern, [
552
580
  context.dtsPath,
553
581
  dtsRelativePath
@@ -589,7 +617,7 @@ async function initializeTsconfig(context) {
589
617
  context.tsconfig.originalTsconfigJson = await readJsonFile(tsconfigFilePath);
590
618
  context.tsconfig.tsconfigJson = await resolveTsconfigChanges(context);
591
619
  context.log(LogLevelLabel.TRACE, "Writing updated TypeScript configuration (tsconfig.json) file to disk.");
592
- await writeFile(context.log, tsconfigFilePath, StormJSON.stringify(context.tsconfig.tsconfigJson));
620
+ await context.fs.write(tsconfigFilePath, StormJSON.stringify(context.tsconfig.tsconfigJson));
593
621
  context.tsconfig = getParsedTypeScriptConfig(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig, context.config.tsconfigRaw, context.tsconfig.originalTsconfigJson);
594
622
  }
595
623
  __name(initializeTsconfig, "initializeTsconfig");
@@ -638,13 +666,11 @@ async function resolveTsconfig(context) {
638
666
  `).join("\n")}
639
667
  `);
640
668
  }
641
- await writeFile(context.log, context.tsconfig.tsconfigFilePath, StormJSON.stringify(updateTsconfigJson));
669
+ await context.fs.write(context.tsconfig.tsconfigFilePath, StormJSON.stringify(updateTsconfigJson));
642
670
  context.tsconfig = getParsedTypeScriptConfig(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig);
643
671
  if (!context.tsconfig) {
644
672
  throw new Error("Failed to parse the TypeScript configuration file.");
645
673
  }
646
- context.tsconfig.tsconfigJson.compilerOptions ??= {};
647
- context.tsconfig.tsconfigJson.compilerOptions.strict = false;
648
674
  }
649
675
  __name(resolveTsconfig, "resolveTsconfig");
650
676
  var DEFAULT_ENVIRONMENT = "default";
@@ -784,7 +810,7 @@ function replacePathTokens(context, path) {
784
810
  if (!path) {
785
811
  return path;
786
812
  }
787
- 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));
813
+ return path.replaceAll("{workspaceRoot}", context.workspaceConfig.workspaceRoot).replaceAll("{root}", context.config.projectRoot).replaceAll("{projectRoot}", context.config.projectRoot).replaceAll("{sourceRoot}", context.config.sourceRoot).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));
788
814
  }
789
815
  __name(replacePathTokens, "replacePathTokens");
790
816
  function resolveEntryInputFile(context, typeDefinition) {
@@ -1125,20 +1151,17 @@ function normalizePath(path, builtinsPath, prefix = "powerlines") {
1125
1151
  return isAbsolutePath(path) ? path : isValidId(toFilePath(path), prefix) ? normalizeId(toFilePath(path), prefix).replace(new RegExp(`^${prefix.replace(/:$/, "")}:`), builtinsPath) : toFilePath(path);
1126
1152
  }
1127
1153
  __name(normalizePath, "normalizePath");
1128
- function normalizeKey(key, sep = ":") {
1129
- if (!key) {
1130
- return "";
1131
- }
1132
- return key.replace(/[:/\\]/g, sep).replace(/^[:/\\]|[:/\\]$/g, "");
1133
- }
1134
- __name(normalizeKey, "normalizeKey");
1135
- function filterKeyByBase(key, base) {
1136
- if (base) {
1137
- return key.startsWith(base) && key[key.length - 1] !== "$";
1138
- }
1139
- return key[key.length - 1] !== "$";
1154
+ function normalizeGlobPatterns(workspaceRoot, patterns) {
1155
+ return getUnique(toArray(patterns).map((pattern) => {
1156
+ if (isSetObject(pattern) && (isSetString(pattern.input) || isSetString(pattern.glob))) {
1157
+ return joinPaths(pattern.input || workspaceRoot, pattern.glob || "**/*");
1158
+ } else if (!isSetString(pattern)) {
1159
+ return void 0;
1160
+ }
1161
+ return pattern;
1162
+ }).filter(isSetString));
1140
1163
  }
1141
- __name(filterKeyByBase, "filterKeyByBase");
1164
+ __name(normalizeGlobPatterns, "normalizeGlobPatterns");
1142
1165
  var BaseStorageAdapter = class {
1143
1166
  static {
1144
1167
  __name(this, "BaseStorageAdapter");
@@ -1193,6 +1216,21 @@ var BaseStorageAdapter = class {
1193
1216
  }
1194
1217
  }
1195
1218
  /**
1219
+ * Synchronously creates a directory at the specified path.
1220
+ *
1221
+ * @param _ - The path of the directory to create.
1222
+ */
1223
+ mkdirSync(_) {
1224
+ }
1225
+ /**
1226
+ * Creates a directory at the specified path.
1227
+ *
1228
+ * @param dirPath - The path of the directory to create.
1229
+ */
1230
+ async mkdir(dirPath) {
1231
+ return Promise.resolve(this.mkdirSync(dirPath));
1232
+ }
1233
+ /**
1196
1234
  * Asynchronously removes a key from the storage.
1197
1235
  *
1198
1236
  * @param key - The key to remove.
@@ -1241,6 +1279,42 @@ var BaseStorageAdapter = class {
1241
1279
  return this.listSync(base);
1242
1280
  }
1243
1281
  /**
1282
+ * Synchronously checks if the given key is a directory.
1283
+ *
1284
+ * @param _ - The key to check.
1285
+ * @returns `true` if the key is a directory, otherwise `false`.
1286
+ */
1287
+ isDirectorySync(_) {
1288
+ return false;
1289
+ }
1290
+ /**
1291
+ * Checks if the given key is a directory.
1292
+ *
1293
+ * @param key - The key to check.
1294
+ * @returns A promise that resolves to `true` if the key is a directory, otherwise `false`.
1295
+ */
1296
+ async isDirectory(key) {
1297
+ return Promise.resolve(this.isDirectorySync(key));
1298
+ }
1299
+ /**
1300
+ * Synchronously checks if the given key is a file.
1301
+ *
1302
+ * @param key - The key to check.
1303
+ * @returns `true` if the key is a file, otherwise `false`.
1304
+ */
1305
+ isFileSync(key) {
1306
+ return this.existsSync(key) && !this.isDirectorySync(key);
1307
+ }
1308
+ /**
1309
+ * Checks if the given key is a file.
1310
+ *
1311
+ * @param key - The key to check.
1312
+ * @returns A promise that resolves to `true` if the key is a file, otherwise `false`.
1313
+ */
1314
+ async isFile(key) {
1315
+ return Promise.resolve(this.isFileSync(key));
1316
+ }
1317
+ /**
1244
1318
  * Disposes of the storage adapter, releasing any held resources.
1245
1319
  *
1246
1320
  * @returns A promise that resolves when the disposal is complete.
@@ -1353,7 +1427,7 @@ var FileSystemStorageAdapter = class extends BaseStorageAdapter {
1353
1427
  */
1354
1428
  async set(key, value) {
1355
1429
  if (!this.options.isReadOnly) {
1356
- return writeFile$1(this.resolve(key), value);
1430
+ return writeFile(this.resolve(key), value);
1357
1431
  }
1358
1432
  }
1359
1433
  /**
@@ -1381,6 +1455,22 @@ var FileSystemStorageAdapter = class extends BaseStorageAdapter {
1381
1455
  }
1382
1456
  }
1383
1457
  /**
1458
+ * Synchronously creates a directory at the specified path.
1459
+ *
1460
+ * @param dirPath - The path of the directory to create.
1461
+ */
1462
+ mkdirSync(dirPath) {
1463
+ createDirectorySync(this.resolve(dirPath));
1464
+ }
1465
+ /**
1466
+ * Creates a directory at the specified path.
1467
+ *
1468
+ * @param dirPath - The path of the directory to create.
1469
+ */
1470
+ async mkdir(dirPath) {
1471
+ await createDirectory(this.resolve(dirPath));
1472
+ }
1473
+ /**
1384
1474
  * Lists all keys under a given base path synchronously.
1385
1475
  *
1386
1476
  * @param base - The base path to list keys from.
@@ -1406,6 +1496,24 @@ var FileSystemStorageAdapter = class extends BaseStorageAdapter {
1406
1496
  ignore: this.options.ignore
1407
1497
  }).catch(ignoreNotfound).then((r) => r || []);
1408
1498
  }
1499
+ /**
1500
+ * Synchronously checks if the given key is a directory.
1501
+ *
1502
+ * @param key - The key to check.
1503
+ * @returns `true` if the key is a directory, otherwise `false`.
1504
+ */
1505
+ isDirectorySync(key) {
1506
+ return isDirectory(this.resolve(key));
1507
+ }
1508
+ /**
1509
+ * Synchronously checks if the given key is a file.
1510
+ *
1511
+ * @param key - The key to check.
1512
+ * @returns `true` if the key is a file, otherwise `false`.
1513
+ */
1514
+ isFileSync(key) {
1515
+ return !isFile(this.resolve(key));
1516
+ }
1409
1517
  };
1410
1518
  var VirtualStorageAdapter = class extends BaseStorageAdapter {
1411
1519
  static {
@@ -1536,7 +1644,11 @@ var VirtualFileSystem = class _VirtualFileSystem {
1536
1644
  * @returns The normalized module id.
1537
1645
  */
1538
1646
  #normalizeId(id) {
1539
- return normalizeId(id, this.#context.config.output.builtinPrefix);
1647
+ let normalized = id;
1648
+ if (isParentPath(normalized, this.#context.builtinsPath)) {
1649
+ normalized = replacePath(normalized, this.#context.builtinsPath);
1650
+ }
1651
+ return normalizeId(normalized, this.#context.config.output.builtinPrefix);
1540
1652
  }
1541
1653
  /**
1542
1654
  * Normalizes a given path by resolving it against the project root, workspace root, and built-ins path.
@@ -1545,7 +1657,7 @@ var VirtualFileSystem = class _VirtualFileSystem {
1545
1657
  * @returns The normalized path.
1546
1658
  */
1547
1659
  #normalizePath(path) {
1548
- return normalizePath(path, this.#context.builtinsPath, this.#context.config.output.builtinPrefix);
1660
+ return normalizePath(path.includes("{") || path.includes("}") ? replacePathTokens(this.#context, path) : path, this.#context.builtinsPath, this.#context.config.output.builtinPrefix);
1549
1661
  }
1550
1662
  /**
1551
1663
  * Builds a regular expression from a string pattern for path matching.
@@ -1772,26 +1884,65 @@ var VirtualFileSystem = class _VirtualFileSystem {
1772
1884
  return this.#getStorage(resolved)?.adapter?.name === "virtual";
1773
1885
  }
1774
1886
  /**
1887
+ * Checks if a path is a directory in the virtual file system (VFS).
1888
+ *
1889
+ * @param path - The path to check.
1890
+ * @returns `true` if the path is a directory, otherwise `false`.
1891
+ */
1892
+ isDirectorySync(path) {
1893
+ const resolved = this.resolveSync(path);
1894
+ if (!resolved) {
1895
+ return false;
1896
+ }
1897
+ return !!(this.existsSync(resolved) && this.#getStorage(resolved)?.adapter?.isDirectorySync(resolved));
1898
+ }
1899
+ /**
1900
+ * Checks if a path is a directory in the virtual file system (VFS).
1901
+ *
1902
+ * @param path - The path to check.
1903
+ * @returns `true` if the path is a directory, otherwise `false`.
1904
+ */
1905
+ async isDirectory(path) {
1906
+ const resolved = await this.resolve(path);
1907
+ if (!resolved) {
1908
+ return false;
1909
+ }
1910
+ return !!(await this.exists(resolved) && await this.#getStorage(resolved)?.adapter?.isDirectory(resolved));
1911
+ }
1912
+ /**
1913
+ * Checks if a path is a file in the virtual file system (VFS).
1914
+ *
1915
+ * @param path - The path to check.
1916
+ * @returns `true` if the path is a file, otherwise `false`.
1917
+ */
1918
+ isFileSync(path) {
1919
+ const resolved = this.resolveSync(path);
1920
+ if (!resolved) {
1921
+ return false;
1922
+ }
1923
+ return this.#getStorage(resolved)?.adapter?.isFileSync(resolved) ?? false;
1924
+ }
1925
+ /**
1926
+ * Checks if a path is a file in the virtual file system (VFS).
1927
+ *
1928
+ * @param path - The path to check.
1929
+ * @returns `true` if the path is a file, otherwise `false`.
1930
+ */
1931
+ async isFile(path) {
1932
+ const resolved = await this.resolve(path);
1933
+ if (!resolved) {
1934
+ return false;
1935
+ }
1936
+ return await this.#getStorage(resolved)?.adapter?.isFile(resolved) ?? false;
1937
+ }
1938
+ /**
1775
1939
  * Lists files in a given path.
1776
1940
  *
1777
1941
  * @param path - The path to list files from.
1778
1942
  * @returns An array of file names in the specified path.
1779
1943
  */
1780
1944
  listSync(path) {
1781
- let maskedMounts = [];
1782
- const allKeys = [];
1783
- for (const storage of this.#getStorages(path, true)) {
1784
- for (const key of storage.adapter.listSync(storage.relativeBase)) {
1785
- if (!maskedMounts.some((p) => `${storage.base}${normalizeKey(key)}`.startsWith(p))) {
1786
- allKeys.push(`${storage.base}${normalizeKey(key)}`);
1787
- }
1788
- }
1789
- maskedMounts = [
1790
- storage.base,
1791
- ...maskedMounts.filter((p) => !p.startsWith(storage.base))
1792
- ];
1793
- }
1794
- return allKeys.filter((key) => filterKeyByBase(key, path));
1945
+ return getUnique(this.#getStorages(path, true).map((storage) => storage.adapter.listSync(storage.relativeBase ? storage.base ? appendPath(storage.relativeBase, storage.base) : storage.relativeBase : storage.base)).flat());
1795
1946
  }
1796
1947
  /**
1797
1948
  * Lists files in a given path.
@@ -1800,20 +1951,7 @@ var VirtualFileSystem = class _VirtualFileSystem {
1800
1951
  * @returns An array of file names in the specified path.
1801
1952
  */
1802
1953
  async list(path) {
1803
- let maskedMounts = [];
1804
- const allKeys = [];
1805
- for (const storage of this.#getStorages(path, true)) {
1806
- for (const key of await storage.adapter.list(storage.relativeBase)) {
1807
- if (!maskedMounts.some((p) => `${storage.base}${normalizeKey(key)}`.startsWith(p))) {
1808
- allKeys.push(`${storage.base}${normalizeKey(key)}`);
1809
- }
1810
- }
1811
- maskedMounts = [
1812
- storage.base,
1813
- ...maskedMounts.filter((p) => !p.startsWith(storage.base))
1814
- ];
1815
- }
1816
- return allKeys.filter((key) => filterKeyByBase(key, path));
1954
+ return getUnique((await Promise.all(this.#getStorages(path, true).map(async (storage) => storage.adapter.list(storage.relativeBase ? storage.base ? appendPath(storage.relativeBase, storage.base) : storage.relativeBase : storage.base)))).flat());
1817
1955
  }
1818
1956
  /**
1819
1957
  * Removes a file in the virtual file system (VFS).
@@ -1865,12 +2003,16 @@ var VirtualFileSystem = class _VirtualFileSystem {
1865
2003
  */
1866
2004
  async glob(patterns) {
1867
2005
  const results = [];
1868
- for (const pattern of toArray(patterns)) {
2006
+ for (const pattern of normalizeGlobPatterns(this.#context.workspaceConfig.workspaceRoot, patterns)) {
1869
2007
  const normalized = this.#normalizePath(pattern);
1870
2008
  if (!/[*?[\]{}]/.test(normalized) && !normalized.includes("**")) {
1871
- const resolved = this.resolveSync(normalized);
1872
- if (resolved && !results.includes(resolved)) {
1873
- results.push(resolved);
2009
+ if (this.isDirectorySync(normalized)) {
2010
+ results.push(...await this.list(normalized));
2011
+ } else {
2012
+ const resolved = await this.resolve(normalized);
2013
+ if (resolved && !results.includes(resolved)) {
2014
+ results.push(resolved);
2015
+ }
1874
2016
  }
1875
2017
  continue;
1876
2018
  }
@@ -1896,12 +2038,16 @@ var VirtualFileSystem = class _VirtualFileSystem {
1896
2038
  */
1897
2039
  globSync(patterns) {
1898
2040
  const results = [];
1899
- for (const pattern of toArray(patterns)) {
2041
+ for (const pattern of normalizeGlobPatterns(this.#context.workspaceConfig.workspaceRoot, patterns)) {
1900
2042
  const normalized = this.#normalizePath(pattern);
1901
2043
  if (!/[*?[\]{}]/.test(normalized) && !normalized.includes("**")) {
1902
- const resolved = this.resolveSync(normalized);
1903
- if (resolved && !results.includes(resolved)) {
1904
- results.push(resolved);
2044
+ if (this.isDirectorySync(normalized)) {
2045
+ results.push(...this.listSync(normalized));
2046
+ } else {
2047
+ const resolved = this.resolveSync(normalized);
2048
+ if (resolved && !results.includes(resolved)) {
2049
+ results.push(resolved);
2050
+ }
1905
2051
  }
1906
2052
  continue;
1907
2053
  }
@@ -1927,20 +2073,27 @@ var VirtualFileSystem = class _VirtualFileSystem {
1927
2073
  * @param destPath - The destination path to copy to
1928
2074
  */
1929
2075
  async copy(srcPath, destPath) {
1930
- if (hasFileExtension(srcPath)) {
1931
- const content = await this.read(srcPath);
2076
+ const src = srcPath instanceof URL ? fileURLToPath(srcPath) : srcPath;
2077
+ const dest = destPath instanceof URL ? fileURLToPath(destPath) : destPath;
2078
+ if (!isSetString(src) && (!isSetObject(src) || !isSetString(src.input)) || !isSetString(dest)) {
2079
+ return;
2080
+ }
2081
+ const sourceStr = isString(src) ? src : src.input ? src.input : this.#context.workspaceConfig.workspaceRoot;
2082
+ const source = await this.resolve(sourceStr);
2083
+ if (!source) {
2084
+ return;
2085
+ }
2086
+ if (this.isDirectorySync(source) || isSetString(src) && src.includes("*") || isSetObject(src) && isSetString(src.glob)) {
2087
+ await Promise.all((await this.glob(src)).map(async (file) => {
2088
+ return this.copy(file, appendPath(replacePath(file, sourceStr), dest));
2089
+ }));
2090
+ } else {
2091
+ const content = await this.read(source);
1932
2092
  if (content !== void 0) {
1933
- await this.write(hasFileExtension(destPath) ? destPath : joinPaths$1(destPath, findFileName(srcPath)), content);
2093
+ await this.write(this.#normalizePath(dest), content, {
2094
+ skipFormat: true
2095
+ });
1934
2096
  }
1935
- } else {
1936
- await Promise.all((await this.list(srcPath)).map(async (file) => {
1937
- const relativePath2 = file.replace(this.#normalizePath(srcPath), "");
1938
- const destinationPath = this.#normalizePath(appendPath(destPath, relativePath2));
1939
- const content = await this.read(file);
1940
- if (content !== void 0) {
1941
- await this.write(destinationPath, content);
1942
- }
1943
- }));
1944
2097
  }
1945
2098
  }
1946
2099
  /**
@@ -1950,20 +2103,27 @@ var VirtualFileSystem = class _VirtualFileSystem {
1950
2103
  * @param destPath - The destination path to copy to
1951
2104
  */
1952
2105
  copySync(srcPath, destPath) {
1953
- if (hasFileExtension(srcPath)) {
1954
- const content = this.readSync(srcPath);
2106
+ const src = srcPath instanceof URL ? fileURLToPath(srcPath) : srcPath;
2107
+ const dest = destPath instanceof URL ? fileURLToPath(destPath) : destPath;
2108
+ if (!isSetString(src) && (!isSetObject(src) || !isSetString(src.input)) || !isSetString(dest)) {
2109
+ return;
2110
+ }
2111
+ const sourceStr = isString(src) ? src : src.input ? src.input : this.#context.workspaceConfig.workspaceRoot;
2112
+ const source = this.resolveSync(sourceStr);
2113
+ if (!source) {
2114
+ return;
2115
+ }
2116
+ if (this.isDirectorySync(source) || isSetString(src) && src.includes("*") || isSetObject(src) && isSetString(src.glob)) {
2117
+ this.globSync(src).map((file) => {
2118
+ return this.copySync(file, appendPath(findFilePath(replacePath(file, sourceStr)), dest));
2119
+ });
2120
+ } else {
2121
+ const content = this.readSync(source);
1955
2122
  if (content !== void 0) {
1956
- this.writeSync(hasFileExtension(destPath) ? destPath : joinPaths$1(destPath, findFileName(srcPath)), content);
2123
+ this.writeSync(this.#normalizePath(hasFileExtension(dest) ? dest : appendPath(findFileName(source), dest)), content, {
2124
+ skipFormat: true
2125
+ });
1957
2126
  }
1958
- } else {
1959
- this.listSync(srcPath).forEach((file) => {
1960
- const relativePath2 = file.replace(this.#normalizePath(srcPath), "");
1961
- const destinationPath = this.#normalizePath(appendPath(destPath, relativePath2));
1962
- const content = this.readSync(file);
1963
- if (content !== void 0) {
1964
- this.writeSync(destinationPath, content);
1965
- }
1966
- });
1967
2127
  }
1968
2128
  }
1969
2129
  /**
@@ -2050,15 +2210,15 @@ var VirtualFileSystem = class _VirtualFileSystem {
2050
2210
  }
2051
2211
  }
2052
2212
  const { relativeKey, adapter } = this.#getStorage(path);
2053
- 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)})`);
2054
- const id = options?.meta?.id || this.#normalizeId(path);
2213
+ this.#log(LogLevelLabel.TRACE, `Writing ${this.#normalizePath(relativeKey)} 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)})`);
2214
+ const id = options?.meta?.id || this.#normalizeId(relativeKey);
2055
2215
  this.#metadata[id] = {
2056
2216
  variant: "normal",
2057
2217
  timestamp: Date.now(),
2058
2218
  ...options.meta ?? {}
2059
2219
  };
2060
- this.#paths[id] = this.#normalizePath(path);
2061
- this.#ids[this.#normalizePath(path)] = id;
2220
+ this.#paths[id] = this.#normalizePath(relativeKey);
2221
+ this.#ids[this.#normalizePath(relativeKey)] = id;
2062
2222
  return adapter.set(relativeKey, code);
2063
2223
  }
2064
2224
  /**
@@ -2070,18 +2230,34 @@ var VirtualFileSystem = class _VirtualFileSystem {
2070
2230
  */
2071
2231
  writeSync(path, data = "", options = {}) {
2072
2232
  const { relativeKey, adapter } = this.#getStorage(path);
2073
- 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)})`);
2074
- const id = options?.meta?.id || this.#normalizeId(path);
2233
+ this.#log(LogLevelLabel.TRACE, `Writing ${this.#normalizePath(relativeKey)} 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)})`);
2234
+ const id = options?.meta?.id || this.#normalizeId(relativeKey);
2075
2235
  this.#metadata[id] = {
2076
2236
  variant: "normal",
2077
2237
  timestamp: Date.now(),
2078
2238
  ...options.meta ?? {}
2079
2239
  };
2080
- this.#paths[id] = this.#normalizePath(path);
2081
- this.#ids[this.#normalizePath(path)] = id;
2240
+ this.#paths[id] = this.#normalizePath(relativeKey);
2241
+ this.#ids[this.#normalizePath(relativeKey)] = id;
2082
2242
  return adapter.setSync(relativeKey, data);
2083
2243
  }
2084
2244
  /**
2245
+ * Synchronously creates a directory at the specified path.
2246
+ *
2247
+ * @param dirPath - The path of the directory to create.
2248
+ */
2249
+ mkdirSync(dirPath) {
2250
+ return this.#getStorage(dirPath)?.adapter?.mkdirSync(dirPath);
2251
+ }
2252
+ /**
2253
+ * Creates a directory at the specified path.
2254
+ *
2255
+ * @param path - The path of the directory to create.
2256
+ */
2257
+ async mkdir(path) {
2258
+ return this.#getStorage(path)?.adapter?.mkdir(path);
2259
+ }
2260
+ /**
2085
2261
  * Retrieves the metadata of a file in the virtual file system (VFS).
2086
2262
  *
2087
2263
  * @param pathOrId - The path or ID of the file to retrieve metadata for.
@@ -2111,11 +2287,15 @@ var VirtualFileSystem = class _VirtualFileSystem {
2111
2287
  * @returns A promise that resolves to the resolved module path.
2112
2288
  */
2113
2289
  async resolve(id, importer, options = {}) {
2114
- if (isAbsolutePath(id)) {
2115
- return id;
2290
+ let path = id;
2291
+ if (path.includes("{") || path.includes("}")) {
2292
+ path = replacePathTokens(this.#context, path);
2293
+ }
2294
+ if (isAbsolutePath(path)) {
2295
+ return path;
2116
2296
  }
2117
2297
  const resolverCacheKey = murmurhash({
2118
- id: this.#normalizeId(id),
2298
+ path: this.#normalizeId(path),
2119
2299
  importer,
2120
2300
  options
2121
2301
  });
@@ -2126,7 +2306,7 @@ var VirtualFileSystem = class _VirtualFileSystem {
2126
2306
  return result;
2127
2307
  }
2128
2308
  }
2129
- result = this.paths[this.#normalizeId(id)];
2309
+ result = this.paths[this.#normalizeId(path)];
2130
2310
  if (!result) {
2131
2311
  const paths = options.paths ?? [];
2132
2312
  if (importer && !paths.includes(importer)) {
@@ -2135,8 +2315,8 @@ var VirtualFileSystem = class _VirtualFileSystem {
2135
2315
  paths.push(this.#context.workspaceConfig.workspaceRoot);
2136
2316
  paths.push(appendPath(this.#context.config.projectRoot, this.#context.workspaceConfig.workspaceRoot));
2137
2317
  paths.push(appendPath(this.#context.config.sourceRoot, this.#context.workspaceConfig.workspaceRoot));
2138
- 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)));
2139
- for (const combination of getResolutionCombinations(id, {
2318
+ paths.push(...Object.keys(this.#context.tsconfig?.options?.paths ?? {}).filter((tsconfigPath) => path.startsWith(tsconfigPath.replace(/\*$/, ""))).map((tsconfigPath) => this.#context.tsconfig?.options?.paths?.[tsconfigPath]).flat().filter(Boolean).map((tsconfigPath) => appendPath(tsconfigPath, this.#context.workspaceConfig.workspaceRoot)));
2319
+ for (const combination of getResolutionCombinations(path, {
2140
2320
  paths
2141
2321
  })) {
2142
2322
  const { relativeKey, adapter } = this.#getStorage(combination);
@@ -2145,19 +2325,18 @@ var VirtualFileSystem = class _VirtualFileSystem {
2145
2325
  break;
2146
2326
  }
2147
2327
  }
2148
- try {
2149
- result = await resolve$1(id, {
2150
- ...options,
2151
- paths
2152
- });
2153
- } catch {
2328
+ if (!result) {
2329
+ try {
2330
+ result = await resolve$1(path, {
2331
+ ...options,
2332
+ paths
2333
+ });
2334
+ } catch {
2335
+ }
2154
2336
  }
2155
2337
  }
2156
- if (result) {
2157
- result = toAbsolutePath(appendPath(result, this.#context.config.projectRoot), this.#context.workspaceConfig.workspaceRoot);
2158
- if (!this.#context.config.skipCache) {
2159
- this.resolverCache.set(resolverCacheKey, result);
2160
- }
2338
+ if (result && !this.#context.config.skipCache) {
2339
+ this.resolverCache.set(resolverCacheKey, result);
2161
2340
  }
2162
2341
  return result;
2163
2342
  }
@@ -2178,17 +2357,21 @@ var VirtualFileSystem = class _VirtualFileSystem {
2178
2357
  * @returns The resolved module path.
2179
2358
  */
2180
2359
  resolveSync(id, importer, options = {}) {
2181
- if (isAbsolutePath(id)) {
2182
- return id;
2360
+ let path = id;
2361
+ if (path.includes("{") || path.includes("}")) {
2362
+ path = replacePathTokens(this.#context, path);
2363
+ }
2364
+ if (isAbsolutePath(path)) {
2365
+ return path;
2183
2366
  }
2184
2367
  let result;
2185
2368
  if (!this.#context.config.skipCache) {
2186
- result = this.resolverCache.get(this.#normalizeId(id));
2369
+ result = this.resolverCache.get(this.#normalizeId(path));
2187
2370
  if (result) {
2188
2371
  return result;
2189
2372
  }
2190
2373
  }
2191
- result = this.paths[this.#normalizeId(id)];
2374
+ result = this.paths[this.#normalizeId(path)];
2192
2375
  if (!result) {
2193
2376
  const paths = options.paths ?? [];
2194
2377
  if (importer && !paths.includes(importer)) {
@@ -2197,8 +2380,8 @@ var VirtualFileSystem = class _VirtualFileSystem {
2197
2380
  paths.push(this.#context.workspaceConfig.workspaceRoot);
2198
2381
  paths.push(appendPath(this.#context.config.projectRoot, this.#context.workspaceConfig.workspaceRoot));
2199
2382
  paths.push(appendPath(this.#context.config.sourceRoot, this.#context.workspaceConfig.workspaceRoot));
2200
- 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)));
2201
- for (const combination of getResolutionCombinations(id, {
2383
+ paths.push(...Object.keys(this.#context.tsconfig?.options?.paths ?? {}).filter((tsconfigPath) => path.startsWith(tsconfigPath.replace(/\*$/, ""))).map((tsconfigPath) => this.#context.tsconfig?.options?.paths?.[tsconfigPath]).flat().filter(Boolean).map((tsconfigPath) => appendPath(tsconfigPath, this.#context.workspaceConfig.workspaceRoot)));
2384
+ for (const combination of getResolutionCombinations(path, {
2202
2385
  paths
2203
2386
  })) {
2204
2387
  const { relativeKey, adapter } = this.#getStorage(combination);
@@ -2207,18 +2390,18 @@ var VirtualFileSystem = class _VirtualFileSystem {
2207
2390
  break;
2208
2391
  }
2209
2392
  }
2210
- try {
2211
- result = resolveSync(id, {
2212
- paths
2213
- });
2214
- } catch {
2393
+ if (!result) {
2394
+ try {
2395
+ result = resolveSync(path, {
2396
+ ...options,
2397
+ paths
2398
+ });
2399
+ } catch {
2400
+ }
2215
2401
  }
2216
2402
  }
2217
- if (result) {
2218
- result = toAbsolutePath(appendPath(result, this.#context.config.projectRoot), this.#context.workspaceConfig.workspaceRoot);
2219
- if (!this.#context.config.skipCache) {
2220
- this.resolverCache.set(this.#normalizeId(id), result);
2221
- }
2403
+ if (result && !this.#context.config.skipCache) {
2404
+ this.resolverCache.set(this.#normalizeId(path), result);
2222
2405
  }
2223
2406
  return result;
2224
2407
  }
@@ -2299,16 +2482,29 @@ var VirtualFileSystem = class _VirtualFileSystem {
2299
2482
 
2300
2483
  // ../powerlines/src/lib/contexts/context.ts
2301
2484
  var configCache = /* @__PURE__ */ new WeakMap();
2485
+ var agent = new Agent({
2486
+ keepAliveTimeout: 1e4
2487
+ });
2488
+ setGlobalDispatcher(agent.compose(interceptors.retry({
2489
+ maxRetries: 3,
2490
+ minTimeout: 1e3,
2491
+ maxTimeout: 1e4,
2492
+ timeoutFactor: 2,
2493
+ retryAfter: true
2494
+ })));
2302
2495
  var PowerlinesContext = class _PowerlinesContext {
2303
2496
  static {
2304
2497
  __name(this, "PowerlinesContext");
2305
2498
  }
2306
2499
  /**
2307
- * Internal reference to the API instance
2500
+ * Internal references storage
2501
+ *
2502
+ * @danger
2503
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
2308
2504
  *
2309
2505
  * @internal
2310
2506
  */
2311
- #api;
2507
+ #internal = {};
2312
2508
  #workspaceConfig;
2313
2509
  #checksum = null;
2314
2510
  #buildId = uuid();
@@ -2318,7 +2514,8 @@ var PowerlinesContext = class _PowerlinesContext {
2318
2514
  #fs;
2319
2515
  #tsconfig;
2320
2516
  #program;
2321
- #resolvePatterns = [];
2517
+ #parserCache;
2518
+ #requestCache;
2322
2519
  #getConfigProps(config = {}) {
2323
2520
  return {
2324
2521
  variant: config.build?.variant,
@@ -2342,7 +2539,8 @@ var PowerlinesContext = class _PowerlinesContext {
2342
2539
  lint: config.lint,
2343
2540
  transform: config.transform,
2344
2541
  build: config.build,
2345
- framework: config.framework
2542
+ framework: config.framework,
2543
+ ...config
2346
2544
  };
2347
2545
  }
2348
2546
  /**
@@ -2390,14 +2588,30 @@ var PowerlinesContext = class _PowerlinesContext {
2390
2588
  */
2391
2589
  resolver;
2392
2590
  /**
2591
+ * The resolved configuration options
2592
+ */
2593
+ resolvePatterns = [];
2594
+ /**
2393
2595
  * Internal context fields and methods
2394
2596
  *
2597
+ * @danger
2598
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
2599
+ *
2395
2600
  * @internal
2396
2601
  */
2397
2602
  get $$internal() {
2398
- return {
2399
- api: this.#api
2400
- };
2603
+ return this.#internal;
2604
+ }
2605
+ /**
2606
+ * Internal context fields and methods
2607
+ *
2608
+ * @danger
2609
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
2610
+ *
2611
+ * @internal
2612
+ */
2613
+ set $$internal(value) {
2614
+ this.#internal = value;
2401
2615
  }
2402
2616
  /**
2403
2617
  * The resolved entry type definitions for the project
@@ -2421,7 +2635,7 @@ var PowerlinesContext = class _PowerlinesContext {
2421
2635
  */
2422
2636
  set tsconfig(value) {
2423
2637
  this.#tsconfig = value;
2424
- this.#resolvePatterns = tsconfigPathsToRegExp(value?.options?.paths ?? {});
2638
+ this.resolvePatterns = tsconfigPathsToRegExp(value?.options?.paths ?? {});
2425
2639
  }
2426
2640
  /**
2427
2641
  * The virtual file system interface for the project
@@ -2562,6 +2776,131 @@ var PowerlinesContext = class _PowerlinesContext {
2562
2776
  return this.#program;
2563
2777
  }
2564
2778
  /**
2779
+ * Gets the parser cache.
2780
+ */
2781
+ get parserCache() {
2782
+ if (!this.#parserCache) {
2783
+ this.#parserCache = create({
2784
+ cacheId: "parser",
2785
+ cacheDir: this.cachePath,
2786
+ ttl: 2 * 60 * 60 * 1e3,
2787
+ lruSize: 5e3,
2788
+ persistInterval: 250
2789
+ });
2790
+ }
2791
+ return this.#parserCache;
2792
+ }
2793
+ /**
2794
+ * Gets the request cache.
2795
+ */
2796
+ get requestCache() {
2797
+ if (!this.#requestCache) {
2798
+ this.#requestCache = create({
2799
+ cacheId: "http",
2800
+ cacheDir: this.cachePath,
2801
+ ttl: 5 * 60 * 1e3,
2802
+ lruSize: 5e3,
2803
+ persistInterval: 250
2804
+ });
2805
+ }
2806
+ return this.#requestCache;
2807
+ }
2808
+ /**
2809
+ * A function to perform HTTP fetch requests
2810
+ *
2811
+ * @remarks
2812
+ * This function uses a caching layer to avoid duplicate requests during the Powerlines process.
2813
+ *
2814
+ * @example
2815
+ * ```ts
2816
+ * const response = await context.fetch("https://api.example.com/data");
2817
+ * const data = await response.json();
2818
+ * ```
2819
+ *
2820
+ * @see https://github.com/nodejs/undici
2821
+ *
2822
+ * @param input - The URL to fetch.
2823
+ * @param options - The fetch request options.
2824
+ * @returns A promise that resolves to a response returned by the fetch.
2825
+ */
2826
+ async fetch(input, options = {}) {
2827
+ const cacheKey = murmurhash({
2828
+ input: input.toString(),
2829
+ options: JSON.stringify(options)
2830
+ });
2831
+ if (!this.config.skipCache && !options.skipCache) {
2832
+ const cached = this.requestCache.get(cacheKey);
2833
+ if (cached) {
2834
+ return new Response(cached.body, {
2835
+ status: cached.status,
2836
+ statusText: cached.statusText,
2837
+ headers: cached.headers
2838
+ });
2839
+ }
2840
+ }
2841
+ const response = await fetchRequest(input, {
2842
+ timeout: 12e3,
2843
+ ...options
2844
+ });
2845
+ const result = {
2846
+ body: await response.text(),
2847
+ status: response.status,
2848
+ statusText: response.statusText,
2849
+ headers: Object.fromEntries(response.headers.entries())
2850
+ };
2851
+ if (!this.config.skipCache && !options.skipCache) {
2852
+ try {
2853
+ this.requestCache.set(cacheKey, result);
2854
+ } catch {
2855
+ }
2856
+ }
2857
+ return new Response(result.body, {
2858
+ status: result.status,
2859
+ statusText: result.statusText,
2860
+ headers: result.headers
2861
+ });
2862
+ }
2863
+ /**
2864
+ * Parse code using [Oxc-Parser](https://github.com/oxc/oxc) into an (ESTree-compatible)[https://github.com/estree/estree] AST object.
2865
+ *
2866
+ * @remarks
2867
+ * This function can be used to parse TypeScript code into an AST for further analysis or transformation.
2868
+ *
2869
+ * @example
2870
+ * ```ts
2871
+ * const ast = context.parse("const x: number = 42;");
2872
+ * ```
2873
+ *
2874
+ * @see https://rollupjs.org/plugin-development/#this-parse
2875
+ * @see https://github.com/oxc/oxc
2876
+ *
2877
+ * @param code - The source code to parse.
2878
+ * @param options - The options to pass to the parser.
2879
+ * @returns An (ESTree-compatible)[https://github.com/estree/estree] AST object.
2880
+ */
2881
+ async parse(code, options = {}) {
2882
+ const cacheKey = murmurhash({
2883
+ code,
2884
+ options
2885
+ });
2886
+ let result;
2887
+ if (!this.config.skipCache) {
2888
+ result = this.parserCache.get(cacheKey);
2889
+ if (result) {
2890
+ return result;
2891
+ }
2892
+ }
2893
+ result = await parse(`source.${options.lang || "ts"}`, code, {
2894
+ ...options,
2895
+ sourceType: "module",
2896
+ showSemanticErrors: this.config.mode === "development"
2897
+ });
2898
+ if (!this.config.skipCache) {
2899
+ this.parserCache.set(cacheKey, result);
2900
+ }
2901
+ return result;
2902
+ }
2903
+ /**
2565
2904
  * A helper function to resolve modules in the Virtual File System
2566
2905
  *
2567
2906
  * @remarks
@@ -2606,7 +2945,7 @@ var PowerlinesContext = class _PowerlinesContext {
2606
2945
  };
2607
2946
  }
2608
2947
  if (this.config.build.skipNodeModulesBundle) {
2609
- if (match(moduleId, this.#resolvePatterns) || match(moduleId, this.config.build.noExternal)) {
2948
+ if (match(moduleId, this.resolvePatterns) || match(moduleId, this.config.build.noExternal)) {
2610
2949
  return void 0;
2611
2950
  }
2612
2951
  if (match(moduleId, this.config.build.external) || moduleId.startsWith("node:")) {
@@ -2800,6 +3139,26 @@ var PowerlinesContext = class _PowerlinesContext {
2800
3139
  return extendLog(this.log, name);
2801
3140
  }
2802
3141
  /**
3142
+ * Generates a checksum representing the current context state
3143
+ *
3144
+ * @param root - The root directory of the project to generate the checksum for
3145
+ * @returns A promise that resolves to a string representing the checksum
3146
+ */
3147
+ async generateChecksum(root = this.config.projectRoot) {
3148
+ this.#checksum = await hashDirectory(root, {
3149
+ ignore: [
3150
+ "node_modules",
3151
+ ".git",
3152
+ ".nx",
3153
+ ".cache",
3154
+ ".storm",
3155
+ "tmp",
3156
+ "dist"
3157
+ ]
3158
+ });
3159
+ return this.#checksum;
3160
+ }
3161
+ /**
2803
3162
  * Creates a new StormContext instance.
2804
3163
  *
2805
3164
  * @param workspaceConfig - The workspace configuration.
@@ -2821,26 +3180,6 @@ var PowerlinesContext = class _PowerlinesContext {
2821
3180
  */
2822
3181
  logFn;
2823
3182
  /**
2824
- * Generates a checksum representing the current context state
2825
- *
2826
- * @param root - The root directory of the project to generate the checksum for
2827
- * @returns A promise that resolves to a string representing the checksum
2828
- */
2829
- async generateChecksum(root = this.config.projectRoot) {
2830
- this.#checksum = await hashDirectory(root, {
2831
- ignore: [
2832
- "node_modules",
2833
- ".git",
2834
- ".nx",
2835
- ".cache",
2836
- ".storm",
2837
- "tmp",
2838
- "dist"
2839
- ]
2840
- });
2841
- return this.#checksum;
2842
- }
2843
- /**
2844
3183
  * Initialize the context with the provided configuration options
2845
3184
  *
2846
3185
  * @param config - The partial user configuration to use for initialization.
@@ -3213,36 +3552,90 @@ var PowerlinesEnvironmentContext = class _PowerlinesEnvironmentContext extends P
3213
3552
  * Retrieves the hook handlers for a specific hook name
3214
3553
  */
3215
3554
  selectHooks(hook, options) {
3216
- const handlers = [];
3555
+ const result = [];
3217
3556
  if (this.hooks[hook]) {
3218
3557
  if (!isHookExternal(hook)) {
3219
3558
  const hooks = this.hooks[hook];
3220
3559
  if (options?.order) {
3221
3560
  if (options?.order === "pre") {
3222
- handlers.push(...(hooks.preOrdered ?? []).map((h) => h.handler));
3223
- handlers.push(...(hooks.preEnforced ?? []).map((h) => h.handler));
3561
+ result.push(...(hooks.preOrdered ?? []).map((h) => {
3562
+ const plugin = this.plugins.find((p) => p.plugin.name === h.plugin.name);
3563
+ if (!plugin) {
3564
+ throw new Error(`Could not find plugin context for plugin "${h.plugin.name}".`);
3565
+ }
3566
+ return {
3567
+ handle: h.handler,
3568
+ context: plugin.context
3569
+ };
3570
+ }));
3571
+ result.push(...(hooks.preEnforced ?? []).map((h) => {
3572
+ const plugin = this.plugins.find((p) => p.plugin.name === h.plugin.name);
3573
+ if (!plugin) {
3574
+ throw new Error(`Could not find plugin context for plugin "${h.plugin.name}".`);
3575
+ }
3576
+ return {
3577
+ handle: h.handler,
3578
+ context: plugin.context
3579
+ };
3580
+ }));
3224
3581
  } else if (options?.order === "post") {
3225
- handlers.push(...(hooks.postOrdered ?? []).map((h) => h.handler));
3226
- handlers.push(...(hooks.postEnforced ?? []).map((h) => h.handler));
3582
+ result.push(...(hooks.postOrdered ?? []).map((h) => {
3583
+ const plugin = this.plugins.find((p) => p.plugin.name === h.plugin.name);
3584
+ if (!plugin) {
3585
+ throw new Error(`Could not find plugin context for plugin "${h.plugin.name}".`);
3586
+ }
3587
+ return {
3588
+ handle: h.handler,
3589
+ context: plugin.context
3590
+ };
3591
+ }));
3592
+ result.push(...(hooks.postEnforced ?? []).map((h) => {
3593
+ const plugin = this.plugins.find((p) => p.plugin.name === h.plugin.name);
3594
+ if (!plugin) {
3595
+ throw new Error(`Could not find plugin context for plugin "${h.plugin.name}".`);
3596
+ }
3597
+ return {
3598
+ handle: h.handler,
3599
+ context: plugin.context
3600
+ };
3601
+ }));
3227
3602
  } else {
3228
- handlers.push(...(hooks.normal ?? []).map((h) => h.handler));
3603
+ result.push(...(hooks.normal ?? []).map((h) => {
3604
+ const plugin = this.plugins.find((p) => p.plugin.name === h.plugin.name);
3605
+ if (!plugin) {
3606
+ throw new Error(`Could not find plugin context for plugin "${h.plugin.name}".`);
3607
+ }
3608
+ return {
3609
+ handle: h.handler,
3610
+ context: plugin.context
3611
+ };
3612
+ }));
3229
3613
  }
3230
3614
  } else {
3231
- handlers.push(...this.selectHooks(hook, {
3615
+ result.push(...this.selectHooks(hook, {
3232
3616
  order: "pre"
3233
3617
  }));
3234
- handlers.push(...this.selectHooks(hook, {
3618
+ result.push(...this.selectHooks(hook, {
3235
3619
  order: "normal"
3236
3620
  }));
3237
- handlers.push(...this.selectHooks(hook, {
3621
+ result.push(...this.selectHooks(hook, {
3238
3622
  order: "post"
3239
3623
  }));
3240
3624
  }
3241
3625
  } else {
3242
- handlers.push(...this.hooks[hook].map((h) => h.handler));
3626
+ result.push(...this.hooks[hook].map((h) => {
3627
+ const plugin = this.plugins.find((p) => p.plugin.name === h.plugin.name);
3628
+ if (!plugin) {
3629
+ throw new Error(`Could not find plugin context for plugin "${h.plugin.name}".`);
3630
+ }
3631
+ return {
3632
+ handle: h.handler,
3633
+ context: plugin.context
3634
+ };
3635
+ }));
3243
3636
  }
3244
3637
  }
3245
- return handlers;
3638
+ return result;
3246
3639
  }
3247
3640
  constructor(config, workspaceConfig) {
3248
3641
  super(workspaceConfig);
@@ -3275,6 +3668,31 @@ var PowerlinesAPIContext = class _PowerlinesAPIContext extends PowerlinesContext
3275
3668
  return context;
3276
3669
  }
3277
3670
  /**
3671
+ * Internal context fields and methods
3672
+ *
3673
+ * @danger
3674
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3675
+ *
3676
+ * @internal
3677
+ */
3678
+ get $$internal() {
3679
+ return super.$$internal;
3680
+ }
3681
+ /**
3682
+ * Internal context fields and methods
3683
+ *
3684
+ * @danger
3685
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3686
+ *
3687
+ * @internal
3688
+ */
3689
+ set $$internal(value) {
3690
+ super.$$internal = value;
3691
+ for (const environment of Object.values(this.environments)) {
3692
+ environment.$$internal = super.$$internal;
3693
+ }
3694
+ }
3695
+ /**
3278
3696
  * A record of all environments by name
3279
3697
  */
3280
3698
  get environments() {
@@ -3448,7 +3866,9 @@ var PowerlinesAPI = class _PowerlinesAPI {
3448
3866
  */
3449
3867
  static async from(workspaceRoot, config) {
3450
3868
  const api = new _PowerlinesAPI(await PowerlinesAPIContext.from(workspaceRoot, config));
3451
- api.#context.$$internal.api = api;
3869
+ api.#context.$$internal = {
3870
+ api
3871
+ };
3452
3872
  for (const plugin of api.context.config.plugins ?? []) {
3453
3873
  await api.#addPlugin(plugin);
3454
3874
  }
@@ -3572,9 +3992,13 @@ ${formatLogMessage(context.config)}`);
3572
3992
  let generatedTypes = await emitTypes(context, files);
3573
3993
  context.log(LogLevelLabel.TRACE, `Generating TypeScript declaration file ${context.dtsPath}.`);
3574
3994
  const directives = [];
3995
+ const asNextParam = /* @__PURE__ */ __name((previousResult) => isObject(previousResult) ? previousResult.code : previousResult, "asNextParam");
3575
3996
  let result = await this.callHook("generateTypes", {
3576
3997
  environment: context,
3577
- order: "pre"
3998
+ sequential: true,
3999
+ order: "pre",
4000
+ result: "merge",
4001
+ asNextParam
3578
4002
  }, generatedTypes);
3579
4003
  if (result) {
3580
4004
  if (isSetObject(result)) {
@@ -3588,7 +4012,10 @@ ${formatLogMessage(context.config)}`);
3588
4012
  }
3589
4013
  result = await this.callHook("generateTypes", {
3590
4014
  environment: context,
3591
- order: "normal"
4015
+ sequential: true,
4016
+ order: "normal",
4017
+ result: "merge",
4018
+ asNextParam
3592
4019
  }, generatedTypes);
3593
4020
  if (result) {
3594
4021
  if (isSetObject(result)) {
@@ -3602,7 +4029,10 @@ ${formatLogMessage(context.config)}`);
3602
4029
  }
3603
4030
  result = await this.callHook("generateTypes", {
3604
4031
  environment: context,
3605
- order: "post"
4032
+ sequential: true,
4033
+ order: "post",
4034
+ result: "merge",
4035
+ asNextParam
3606
4036
  }, generatedTypes);
3607
4037
  if (result) {
3608
4038
  if (isSetObject(result)) {
@@ -3614,15 +4044,24 @@ ${formatLogMessage(context.config)}`);
3614
4044
  generatedTypes = result;
3615
4045
  }
3616
4046
  }
3617
- await context.fs.write(context.dtsPath, `${directives ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
4047
+ if (generatedTypes?.trim() || directives.length > 0) {
4048
+ await context.fs.write(context.dtsPath, `${directives ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
3618
4049
 
3619
4050
  ` : ""}${getFileHeader(context, {
3620
- directive: null,
3621
- prettierIgnore: false
3622
- })}
4051
+ directive: null,
4052
+ prettierIgnore: false
4053
+ })}
3623
4054
 
3624
4055
  ${formatTypes(generatedTypes)}
3625
4056
  `);
4057
+ } else {
4058
+ const dtsRelativePath = getTsconfigDtsPath(context);
4059
+ if (context.tsconfig.tsconfigJson.include && isIncludeMatchFound(dtsRelativePath, context.tsconfig.tsconfigJson.include)) {
4060
+ const normalizedDtsRelativePath = dtsRelativePath.startsWith("./") ? dtsRelativePath.slice(2) : dtsRelativePath;
4061
+ context.tsconfig.tsconfigJson.include = context.tsconfig.tsconfigJson.include.filter((includeValue) => includeValue?.toString() !== normalizedDtsRelativePath);
4062
+ await context.fs.write(context.tsconfig.tsconfigFilePath, JSON.stringify(context.tsconfig.tsconfigJson, null, 2));
4063
+ }
4064
+ }
3626
4065
  }
3627
4066
  context.tsconfig = getParsedTypeScriptConfig(context.workspaceConfig.workspaceRoot, context.config.projectRoot, context.config.tsconfig);
3628
4067
  if (!context.tsconfig) {
@@ -3659,7 +4098,7 @@ ${formatTypes(generatedTypes)}
3659
4098
  for (const file of files) {
3660
4099
  context.log(LogLevelLabel.TRACE, `Adding template file: ${file}`);
3661
4100
  const template = Handlebars.compile(file);
3662
- await writeFile(context.log, joinPaths$1(context.config.projectRoot, file.replace(".hbs", "")), template(context));
4101
+ await context.fs.write(joinPaths$1(context.config.projectRoot, file.replace(".hbs", "")), template(context));
3663
4102
  }
3664
4103
  await this.callHook("new", {
3665
4104
  environment: context,
@@ -3670,14 +4109,14 @@ ${formatTypes(generatedTypes)}
3670
4109
  for (const file of files2) {
3671
4110
  context.log(LogLevelLabel.TRACE, `Adding application template file: ${file}`);
3672
4111
  const template = Handlebars.compile(file);
3673
- await writeFile(context.log, joinPaths$1(context.config.projectRoot, file.replace(".hbs", "")), template(context));
4112
+ await context.fs.write(joinPaths$1(context.config.projectRoot, file.replace(".hbs", "")), template(context));
3674
4113
  }
3675
4114
  } else {
3676
4115
  const files2 = await listFiles(joinPaths$1(context.powerlinesPath, "files/library/**/*.hbs"));
3677
4116
  for (const file of files2) {
3678
4117
  context.log(LogLevelLabel.TRACE, `Adding library template file: ${file}`);
3679
4118
  const template = Handlebars.compile(file);
3680
- await writeFile(context.log, joinPaths$1(context.config.projectRoot, file.replace(".hbs", "")), template(context));
4119
+ await context.fs.write(joinPaths$1(context.config.projectRoot, file.replace(".hbs", "")), template(context));
3681
4120
  }
3682
4121
  }
3683
4122
  await this.callHook("new", {
@@ -3761,15 +4200,12 @@ ${formatTypes(generatedTypes)}
3761
4200
  const destinationPath = joinPaths$1(appendPath(context.config.output.outputPath, context.workspaceConfig.workspaceRoot), "dist");
3762
4201
  if (sourcePath !== destinationPath) {
3763
4202
  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}).`);
3764
- await copyFiles({
3765
- input: sourcePath,
3766
- glob: "**/*"
3767
- }, destinationPath);
4203
+ await context.fs.copy(sourcePath, destinationPath);
3768
4204
  }
3769
4205
  }
3770
4206
  await Promise.all(context.config.output.assets.map(async (asset) => {
3771
4207
  context.log(LogLevelLabel.DEBUG, `Copying asset(s): ${chalk5.redBright(context.workspaceConfig.workspaceRoot === asset.input ? asset.glob : joinPaths$1(replacePath(asset.input, context.workspaceConfig.workspaceRoot), asset.glob))} -> ${chalk5.greenBright(joinPaths$1(replacePath(asset.output, context.workspaceConfig.workspaceRoot), asset.glob))} ${Array.isArray(asset.ignore) && asset.ignore.length > 0 ? ` (ignoring: ${asset.ignore.map((i) => chalk5.yellowBright(i)).join(", ")})` : ""}`);
3772
- await copyFiles(asset, asset.output);
4208
+ await context.fs.copy(asset, asset.output);
3773
4209
  }));
3774
4210
  await this.callHook("build", {
3775
4211
  environment: context,