@powerlines/engine 0.43.30 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/_internal/worker.cjs +195 -95
  2. package/dist/_internal/worker.mjs +198 -98
  3. package/dist/_internal/worker.mjs.map +1 -1
  4. package/dist/api.cjs +11 -8
  5. package/dist/api.d.cts.map +1 -1
  6. package/dist/api.d.mts.map +1 -1
  7. package/dist/api.mjs +11 -8
  8. package/dist/api.mjs.map +1 -1
  9. package/dist/{base-context-B9AROf66.cjs → base-context-5_AZZYFu.cjs} +27 -32
  10. package/dist/{base-context-D8a2XGIK.mjs → base-context-D_ZidDDm.mjs} +29 -34
  11. package/dist/base-context-D_ZidDDm.mjs.map +1 -0
  12. package/dist/context/index.cjs +3 -3
  13. package/dist/context/index.d.cts +67 -32
  14. package/dist/context/index.d.cts.map +1 -1
  15. package/dist/context/index.d.mts +67 -32
  16. package/dist/context/index.d.mts.map +1 -1
  17. package/dist/context/index.mjs +3 -3
  18. package/dist/{engine-context-DsA9XGVb.mjs → engine-context-PQ3BgcgR.mjs} +36 -11
  19. package/dist/engine-context-PQ3BgcgR.mjs.map +1 -0
  20. package/dist/{engine-context-qCVw66U_.cjs → engine-context-w4fts28j.cjs} +36 -10
  21. package/dist/{execution-context-CprxWvYn.cjs → execution-context-0GmpbWbs.cjs} +176 -71
  22. package/dist/{execution-context-CBJxP2B2.mjs → execution-context-zedP0h4Z.mjs} +179 -74
  23. package/dist/execution-context-zedP0h4Z.mjs.map +1 -0
  24. package/dist/index.cjs +140 -58
  25. package/dist/index.d.cts.map +1 -1
  26. package/dist/index.d.mts.map +1 -1
  27. package/dist/index.mjs +140 -58
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/storage/index.cjs +1 -1
  30. package/dist/storage/index.d.mts +1 -1
  31. package/dist/storage/index.mjs +1 -1
  32. package/dist/typescript/index.d.mts +1 -1
  33. package/dist/{virtual-BNdKVkRw.cjs → virtual-1hYa9zCy.cjs} +1 -1
  34. package/dist/{virtual-gIlTc3Lj.mjs → virtual-CUgOdyIa.mjs} +2 -2
  35. package/dist/{virtual-gIlTc3Lj.mjs.map → virtual-CUgOdyIa.mjs.map} +1 -1
  36. package/package.json +3 -3
  37. package/dist/base-context-D8a2XGIK.mjs.map +0 -1
  38. package/dist/engine-context-DsA9XGVb.mjs.map +0 -1
  39. package/dist/execution-context-CBJxP2B2.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env -S NODE_OPTIONS=--enable-source-maps node
2
- import { colorText, createLog, extendLog } from "@powerlines/core/lib/logger";
2
+ import { colorText, createLogFn, extendLogFn } from "@powerlines/core/lib/logger";
3
3
  import { getFileHeaderWarningText, getTypescriptFileHeader } from "@powerlines/core/lib/utilities/file-header";
4
4
  import { format, formatFolder } from "@powerlines/core/lib/utilities/format";
5
- import { addPluginHook, dedupeHooklist, findInvalidPluginConfig, isDuplicate, isPlugin, isPluginConfig, isPluginConfigObject, isPluginConfigTuple, isPluginHook, isPluginHookField, mergeConfig, replacePathTokens } from "@powerlines/core/plugin-utils";
5
+ import { addPluginHook, dedupeHooklist, findInvalidPluginConfig, isDuplicate, isPlugin, isPluginConfig, isPluginConfigObject, isPluginConfigTuple, isPluginHook, isPluginHookField, mergeConfig, replacePathTokens, resolveLogLevel } from "@powerlines/core/plugin-utils";
6
6
  import { formatLogMessage } from "@storm-software/config-tools/logger/console";
7
7
  import { toArray } from "@stryke/convert/to-array";
8
8
  import { copyFiles } from "@stryke/fs/copy-file";
@@ -32,10 +32,12 @@ import { isString } from "@stryke/type-checks/is-string";
32
32
  import chalk from "chalk";
33
33
  import defu, { createDefu, defu as defu$1 } from "defu";
34
34
  import Handlebars from "handlebars";
35
- import { CACHE_HASH_LENGTH, DEFAULT_ENVIRONMENT, GLOBAL_ENVIRONMENT, PLUGIN_NON_HOOK_FIELDS, ROOT_HASH_LENGTH } from "@powerlines/core/constants";
35
+ import { CACHE_HASH_LENGTH, DEFAULT_DEVELOPMENT_LOG_LEVEL, DEFAULT_ENVIRONMENT, DEFAULT_PRODUCTION_LOG_LEVEL, DEFAULT_TEST_LOG_LEVEL, GLOBAL_ENVIRONMENT, PLUGIN_NON_HOOK_FIELDS, ROOT_HASH_LENGTH } from "@powerlines/core/constants";
36
36
  import { readJsonFile, readJsonFileSync } from "@stryke/fs/json";
37
37
  import { deepClone } from "@stryke/helpers/deep-clone";
38
38
  import { joinPaths as joinPaths$1 } from "@stryke/path/join";
39
+ import { uuid } from "@stryke/unique-id/uuid";
40
+ import { createLogFn as createLogFn$1, extendLogFn as extendLogFn$1 } from "@powerlines/core";
39
41
  import { getUniqueInputs, isTypeDefinition, resolveInputsSync } from "@powerlines/core/lib/entry";
40
42
  import { relativeToWorkspaceRoot } from "@stryke/fs/get-workspace-root";
41
43
  import { murmurhash } from "@stryke/hash";
@@ -43,15 +45,12 @@ import { hashDirectory } from "@stryke/hash/node";
43
45
  import { fetchRequest } from "@stryke/http/fetch";
44
46
  import { isEqual } from "@stryke/path/is-equal";
45
47
  import { kebabCase } from "@stryke/string-format/kebab-case";
46
- import { isNull } from "@stryke/type-checks/is-null";
47
- import { uuid } from "@stryke/unique-id/uuid";
48
48
  import { match, tsconfigPathsToRegExp } from "bundle-require";
49
49
  import { resolveCompatibilityDates } from "compatx";
50
50
  import { create } from "flat-cache";
51
51
  import { parse } from "oxc-parser";
52
52
  import { Agent, Response, interceptors, setGlobalDispatcher } from "undici";
53
53
  import "@stryke/fs/remove-file";
54
- import { LogLevelLabel } from "@storm-software/config-tools/types";
55
54
  import * as $ from "@stryke/capnp";
56
55
  import { readFileBuffer, readFileBufferSync, writeFileBuffer } from "@stryke/fs/buffer";
57
56
  import { correctPath, stripStars } from "@stryke/path/correct-path";
@@ -82,6 +81,7 @@ import { getObjectDiff } from "@donedeal0/superdiff";
82
81
  //#region src/_internal/helpers/environment.ts
83
82
  function createEnvironment(name, config = {}) {
84
83
  return defu(config.environments?.[name] ?? {}, {
84
+ environmentId: uuid(),
85
85
  name,
86
86
  title: config.title ?? titleCase(config.name),
87
87
  ssr: false,
@@ -1199,7 +1199,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1199
1199
  }
1200
1200
  }));
1201
1201
  } else result = new VirtualFileSystem(context, new $.Message().initRoot(FileSystem));
1202
- result.#log(LogLevelLabel.DEBUG, "Successfully completed virtual file system (VFS) initialization.");
1202
+ result.#log("debug", "Successfully completed virtual file system (VFS) initialization.");
1203
1203
  return result;
1204
1204
  }
1205
1205
  /**
@@ -1233,7 +1233,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1233
1233
  }
1234
1234
  });
1235
1235
  } else result = new VirtualFileSystem(context, new $.Message().initRoot(FileSystem));
1236
- result.#log(LogLevelLabel.DEBUG, "Successfully completed virtual file system (VFS) initialization.");
1236
+ result.#log("debug", "Successfully completed virtual file system (VFS) initialization.");
1237
1237
  return result;
1238
1238
  }
1239
1239
  /**
@@ -1367,7 +1367,10 @@ var VirtualFileSystem = class VirtualFileSystem {
1367
1367
  return ret;
1368
1368
  }, {});
1369
1369
  }
1370
- this.#log = extendLog(this.#context.log, "file-system");
1370
+ this.#log = context.extendLog({
1371
+ source: "VFS",
1372
+ category: "fs"
1373
+ });
1371
1374
  }
1372
1375
  /**
1373
1376
  * Asynchronously checks if a file exists in the virtual file system (VFS).
@@ -1494,7 +1497,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1494
1497
  listSync(path) {
1495
1498
  let resolvedPath = path;
1496
1499
  if (resolvedPath.includes("*")) {
1497
- this.#log(LogLevelLabel.WARN, `Invoking "listSync" with a glob pattern is not supported. It is likely you meant to use "globSync". Path: ${path}`);
1500
+ this.#log("warn", `Invoking "listSync" with a glob pattern is not supported. It is likely you meant to use "globSync". Path: ${path}`);
1498
1501
  resolvedPath = stripStars(resolvedPath);
1499
1502
  }
1500
1503
  return getUnique(this.#getStorages(resolvedPath, true).map((storage) => storage.adapter.listSync(storage.relativeBase ? storage.base ? appendPath(storage.relativeBase, storage.base) : storage.relativeBase : storage.base)).flat().filter(Boolean));
@@ -1508,7 +1511,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1508
1511
  async list(path) {
1509
1512
  let resolvedPath = path;
1510
1513
  if (resolvedPath.includes("*")) {
1511
- this.#log(LogLevelLabel.WARN, `Invoking "list" with a glob pattern is not supported. It is likely you meant to use "glob". Path: ${path}`);
1514
+ this.#log("warn", `Invoking "list" with a glob pattern is not supported. It is likely you meant to use "glob". Path: ${path}`);
1512
1515
  resolvedPath = stripStars(resolvedPath);
1513
1516
  }
1514
1517
  return getUnique((await Promise.all(this.#getStorages(resolvedPath, true).map(async (storage) => storage.adapter.list(storage.relativeBase ? storage.base ? appendPath(storage.relativeBase, storage.base) : storage.relativeBase : storage.base)))).flat().filter(Boolean));
@@ -1520,7 +1523,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1520
1523
  */
1521
1524
  async remove(path) {
1522
1525
  const normalizedPath = this.#normalizePath(path);
1523
- this.#log(LogLevelLabel.TRACE, `Removing file: ${normalizedPath}`);
1526
+ this.#log("trace", `Removing file: ${normalizedPath}`);
1524
1527
  const { relativeKey, adapter } = this.#getStorage(normalizedPath);
1525
1528
  if (hasFileExtension(normalizedPath)) await adapter.remove(relativeKey);
1526
1529
  else await adapter.clear(relativeKey);
@@ -1538,7 +1541,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1538
1541
  */
1539
1542
  removeSync(path) {
1540
1543
  const normalizedPath = this.#normalizePath(path);
1541
- this.#log(LogLevelLabel.TRACE, `Removing file: ${normalizedPath}`);
1544
+ this.#log("trace", `Removing file: ${normalizedPath}`);
1542
1545
  const { relativeKey, adapter } = this.#getStorage(normalizedPath);
1543
1546
  if (hasFileExtension(normalizedPath)) adapter.removeSync(relativeKey);
1544
1547
  else adapter.clearSync(relativeKey);
@@ -1684,7 +1687,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1684
1687
  const filePath = await this.resolve(path, void 0, { isFile: true });
1685
1688
  if (!filePath || !this.existsSync(filePath)) return;
1686
1689
  const { adapter } = this.#getStorage(filePath);
1687
- this.#log(LogLevelLabel.TRACE, `Reading ${adapter.name} file: ${filePath}`);
1690
+ this.#log("trace", `Reading ${adapter.name} file: ${filePath}`);
1688
1691
  return await adapter.get(filePath) ?? void 0;
1689
1692
  }
1690
1693
  /**
@@ -1697,7 +1700,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1697
1700
  const filePath = this.resolveSync(path, void 0, { isFile: true });
1698
1701
  if (!filePath || !this.existsSync(filePath)) return;
1699
1702
  const { adapter } = this.#getStorage(filePath);
1700
- this.#log(LogLevelLabel.TRACE, `Reading ${adapter.name} file: ${filePath}`);
1703
+ this.#log("trace", `Reading ${adapter.name} file: ${filePath}`);
1701
1704
  return adapter.getSync(filePath) ?? void 0;
1702
1705
  }
1703
1706
  /**
@@ -1712,15 +1715,15 @@ var VirtualFileSystem = class VirtualFileSystem {
1712
1715
  const meta = options.meta ?? {};
1713
1716
  const resolvedPath = await this.resolve(this.#normalizePath(path)) || path;
1714
1717
  const { relativeKey, adapter } = this.#getStorage(resolvedPath, options.storage);
1715
- this.#log(LogLevelLabel.TRACE, `Writing ${resolvedPath} to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob$1(toArray(data)).size)})`);
1718
+ this.#log("trace", `Writing ${resolvedPath} to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob$1(toArray(data)).size)})`);
1716
1719
  let code = data;
1717
1720
  try {
1718
1721
  if (!options.skipFormat) code = await format(this.#context, resolvedPath, data);
1719
1722
  } catch (err) {
1720
- if (DEFAULT_EXTENSIONS.includes(findFileExtensionSafe(resolvedPath, { fullExtension: true }))) this.#log(LogLevelLabel.WARN, `Failed to format file ${resolvedPath} before writing: ${err.message}`);
1723
+ if (DEFAULT_EXTENSIONS.includes(findFileExtensionSafe(resolvedPath, { fullExtension: true }))) this.#log("warn", `Failed to format file ${resolvedPath} before writing: ${err.message}`);
1721
1724
  code = data;
1722
1725
  }
1723
- this.#log(LogLevelLabel.TRACE, `Writing ${resolvedPath} to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob$1(toArray(code)).size)})`);
1726
+ this.#log("trace", `Writing ${resolvedPath} to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob$1(toArray(code)).size)})`);
1724
1727
  const id = this.#normalizeId(meta.id || resolvedPath);
1725
1728
  this.metadata[id] = {
1726
1729
  type: "normal",
@@ -1743,7 +1746,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1743
1746
  const meta = options.meta ?? {};
1744
1747
  const resolvedPath = this.resolveSync(this.#normalizePath(path)) || path;
1745
1748
  const { relativeKey, adapter } = this.#getStorage(resolvedPath, options.storage);
1746
- this.#log(LogLevelLabel.TRACE, `Writing ${resolvedPath} file to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob$1(toArray(data)).size)})`);
1749
+ this.#log("trace", `Writing ${resolvedPath} file to ${adapter.name === "virtual" ? "the virtual file system" : adapter.name === "file-system" ? "the local file system" : adapter.name} (size: ${prettyBytes(new Blob$1(toArray(data)).size)})`);
1747
1750
  const id = this.#normalizeId(meta.id || resolvedPath);
1748
1751
  this.metadata[id] = {
1749
1752
  type: "normal",
@@ -1907,7 +1910,7 @@ var VirtualFileSystem = class VirtualFileSystem {
1907
1910
  async dispose() {
1908
1911
  if (!this.#isDisposed) {
1909
1912
  this.#isDisposed = true;
1910
- this.#log(LogLevelLabel.DEBUG, "Disposing virtual file system...");
1913
+ this.#log("debug", "Disposing virtual file system...");
1911
1914
  await this.remove(joinPaths$1(this.#context.dataPath, "fs.bin"));
1912
1915
  const message = new $.Message();
1913
1916
  const fs = message.initRoot(FileSystem);
@@ -1942,9 +1945,15 @@ var VirtualFileSystem = class VirtualFileSystem {
1942
1945
  await writeFileBuffer(joinPaths$1(this.#context.dataPath, "fs.bin"), message.toArrayBuffer());
1943
1946
  if (!this.#context.config.skipCache) this.resolverCache.save(true);
1944
1947
  await Promise.all(this.#getStorages().map(async (storage) => storage.adapter.dispose()));
1945
- this.#log(LogLevelLabel.TRACE, "Virtual file system has been disposed.");
1948
+ this.#log("trace", "Virtual file system has been disposed.");
1946
1949
  }
1947
1950
  }
1951
+ /**
1952
+ * Asynchronously disposes of the virtual file system (VFS) by saving its state to disk.
1953
+ *
1954
+ * @remarks
1955
+ * This method is automatically called when the VFS instance is used within a `using` block, or can be manually invoked to ensure that the VFS state is saved and resources are cleaned up properly.
1956
+ */
1948
1957
  async [Symbol.asyncDispose]() {
1949
1958
  return this.dispose();
1950
1959
  }
@@ -2117,7 +2126,6 @@ function createResolver(options) {
2117
2126
  //#region src/context/base-context.ts
2118
2127
  var PowerlinesBaseContext = class PowerlinesBaseContext {
2119
2128
  #timestamp = Date.now();
2120
- #logLevel = "info";
2121
2129
  /**
2122
2130
  * The path to the Powerlines package
2123
2131
  */
@@ -2142,24 +2150,16 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2142
2150
  * A timestamp representing when the context was initialized
2143
2151
  */
2144
2152
  get timestamp() {
2145
- return new Date(this.#timestamp);
2153
+ return this.#timestamp;
2146
2154
  }
2147
2155
  get logLevel() {
2148
- return this.#logLevel || "info";
2149
- }
2150
- set logLevel(level) {
2151
- this.#logLevel = level;
2156
+ return resolveLogLevel(this.options.logLevel, this.options.mode);
2152
2157
  }
2153
2158
  /**
2154
2159
  * The logger function
2155
2160
  */
2156
2161
  get log() {
2157
- const level = this.logLevel || "info";
2158
- if (!this.logger || this.logger.level !== level) this.logger = {
2159
- log: this.createLog(),
2160
- level
2161
- };
2162
- return this.logger.log;
2162
+ return this.createLog();
2163
2163
  }
2164
2164
  /**
2165
2165
  * The environment paths for the project
@@ -2190,7 +2190,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2190
2190
  * @param message - The message to log.
2191
2191
  */
2192
2192
  fatal(message) {
2193
- this.log(LogLevelLabel.FATAL, isString(message) ? message : StormJSON.stringify(message));
2193
+ this.log("error", isString(message) ? message : StormJSON.stringify(message));
2194
2194
  }
2195
2195
  /**
2196
2196
  * A logging function for error messages
@@ -2198,7 +2198,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2198
2198
  * @param message - The message to log.
2199
2199
  */
2200
2200
  error(message) {
2201
- this.log(LogLevelLabel.ERROR, isString(message) ? message : StormJSON.stringify(message));
2201
+ this.log("error", isString(message) ? message : StormJSON.stringify(message));
2202
2202
  }
2203
2203
  /**
2204
2204
  * A logging function for warning messages
@@ -2206,7 +2206,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2206
2206
  * @param message - The message to log.
2207
2207
  */
2208
2208
  warn(message) {
2209
- this.log(LogLevelLabel.WARN, isString(message) ? message : StormJSON.stringify(message));
2209
+ this.log("warn", isString(message) ? message : StormJSON.stringify(message));
2210
2210
  }
2211
2211
  /**
2212
2212
  * A logging function for informational messages
@@ -2214,7 +2214,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2214
2214
  * @param message - The message to log.
2215
2215
  */
2216
2216
  info(message) {
2217
- this.log(LogLevelLabel.INFO, isString(message) ? message : StormJSON.stringify(message));
2217
+ this.log("info", isString(message) ? message : StormJSON.stringify(message));
2218
2218
  }
2219
2219
  /**
2220
2220
  * A logging function for debug messages
@@ -2222,7 +2222,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2222
2222
  * @param message - The message to log.
2223
2223
  */
2224
2224
  debug(message) {
2225
- this.log(LogLevelLabel.DEBUG, isString(message) ? message : StormJSON.stringify(message));
2225
+ this.log("debug", isString(message) ? message : StormJSON.stringify(message));
2226
2226
  }
2227
2227
  /**
2228
2228
  * A logging function for trace messages
@@ -2230,7 +2230,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2230
2230
  * @param message - The message to log.
2231
2231
  */
2232
2232
  trace(message) {
2233
- this.log(LogLevelLabel.TRACE, isString(message) ? message : StormJSON.stringify(message));
2233
+ this.log("trace", isString(message) ? message : StormJSON.stringify(message));
2234
2234
  }
2235
2235
  /**
2236
2236
  * A function to create a timer for measuring the duration of asynchronous operations
@@ -2250,29 +2250,32 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2250
2250
  const startDuration = performance.now();
2251
2251
  return () => {
2252
2252
  const duration = performance.now() - startDuration;
2253
- this.log(LogLevelLabel.PERFORMANCE, `${chalk.bold.cyanBright(name)} completed in ${chalk.bold.cyanBright(duration < 1e3 ? `${duration.toFixed(2)} milliseconds` : formatDistanceToNowStrict(startDate))}`);
2253
+ this.log({
2254
+ level: "info",
2255
+ category: "performance"
2256
+ }, `${chalk.bold.cyanBright(name)} completed in ${chalk.bold.cyanBright(duration < 1e3 ? `${duration.toFixed(2)} milliseconds` : formatDistanceToNowStrict(startDate))}`);
2254
2257
  };
2255
2258
  }
2256
2259
  /**
2257
2260
  * Create a new logger instance
2258
2261
  *
2259
- * @param name - The name to use for the logger instance
2262
+ * @param config - The configuration options to use for the logger instance, which can be used to customize the appearance and behavior of the log messages generated by the logger. This is typically the name of the plugin or module that is creating the logger instance.
2260
2263
  * @returns A logger function
2261
2264
  */
2262
- createLog(name = null) {
2263
- return createLog(name, {
2265
+ createLog(config) {
2266
+ return createLogFn({
2264
2267
  ...this.options,
2265
- logLevel: isNull(this.logLevel) ? "silent" : this.logLevel
2268
+ ...config
2266
2269
  });
2267
2270
  }
2268
2271
  /**
2269
- * Extend the current logger instance with a new name
2272
+ * Extend the current logger instance with a new source
2270
2273
  *
2271
- * @param name - The name to use for the extended logger instance
2272
- * @returns A logger function
2274
+ * @param config - The overlay metadata to use for the badge in the log output, which can be used to customize the appearance and behavior of the log messages generated by the extended logger. This typically includes the name of the plugin or module that is creating the logger instance, and can also include other metadata such as the command or environment.
2275
+ * @returns A new logger function that includes the badge in its output.
2273
2276
  */
2274
- extendLog(name) {
2275
- return extendLog(this.log, name);
2277
+ extendLog(config) {
2278
+ return extendLogFn(this.log, config);
2276
2279
  }
2277
2280
  /**
2278
2281
  * A logger function specific to this context
@@ -2287,18 +2290,19 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2287
2290
  * @param options - The configuration options to initialize the context with
2288
2291
  */
2289
2292
  async init(options = {}) {
2290
- this.inputOptions = options;
2293
+ this.inputOptions = { ...options };
2291
2294
  if (!this.powerlinesPath) {
2292
2295
  const powerlinesPath = await resolvePackage("powerlines");
2293
2296
  if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
2294
2297
  this.powerlinesPath = powerlinesPath;
2295
2298
  }
2296
2299
  const cwd = options.cwd || this.options?.cwd || process.cwd();
2297
- const root = (options.root || this.options?.root) && (options.root || this.options.root).replace(/^\.\/?/, "") && !isEqual(options.root || this.options.root, cwd) ? options.root || this.options.root : ".";
2300
+ const root = replacePath((options.root || this.options?.root) && (options.root || this.options.root).replace(/^\.\/?/, "") && !isEqual(options.root || this.options.root, cwd) ? options.root || this.options.root : ".", cwd);
2298
2301
  this.options = defu({
2299
2302
  root,
2300
2303
  cwd,
2301
2304
  mode: options.mode,
2305
+ logLevel: options.logLevel,
2302
2306
  framework: options.framework,
2303
2307
  organization: options.organization,
2304
2308
  configFile: options.configFile
@@ -2460,7 +2464,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2460
2464
  buildId: this.#buildId,
2461
2465
  releaseId: this.#releaseId,
2462
2466
  checksum: this.#checksum,
2463
- timestamp: this.timestamp.getTime(),
2467
+ timestamp: this.timestamp,
2464
2468
  rootHash: murmurhash({
2465
2469
  workspaceRoot: this.options?.cwd,
2466
2470
  root: this.config?.root
@@ -2618,6 +2622,60 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2618
2622
  this.options = options;
2619
2623
  }
2620
2624
  /**
2625
+ * Create a new log function with the specified configuration, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the logger instance according to your needs.
2626
+ *
2627
+ * @param config - Optional configuration for the log function instance, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the logger instance according to your needs.
2628
+ * @returns A log function that can be used to log messages with the specified configuration.
2629
+ */
2630
+ createLog(config) {
2631
+ const log = createLogFn$1({
2632
+ ...config,
2633
+ logLevel: this.logLevel
2634
+ });
2635
+ return (meta, ...args) => {
2636
+ log(meta, ...args);
2637
+ process.send?.({
2638
+ id: uuid(),
2639
+ type: "write-log",
2640
+ executionId: config?.executionId ?? this.options.executionId,
2641
+ executionIndex: config?.executionIndex ?? this.options.executionIndex,
2642
+ timestamp: Date.now(),
2643
+ payload: {
2644
+ level: meta && isSetObject(meta) && isSetString(meta.level) ? meta.level : isSetString(meta) ? meta : "info",
2645
+ ...config,
2646
+ args
2647
+ }
2648
+ });
2649
+ };
2650
+ }
2651
+ /**
2652
+ * Extend the current log function instance with a new name
2653
+ *
2654
+ * @param config - The configuration for the extended log function instance, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the log function instance according to your needs.
2655
+ * @returns A log function
2656
+ */
2657
+ extendLog(config) {
2658
+ const log = extendLogFn$1(this.log, {
2659
+ ...config,
2660
+ logLevel: this.logLevel
2661
+ });
2662
+ return (meta, ...args) => {
2663
+ log(meta, ...args);
2664
+ process.send?.({
2665
+ id: uuid(),
2666
+ type: "write-log",
2667
+ executionId: config.executionId ?? this.options.executionId,
2668
+ executionIndex: config.executionIndex ?? this.options.executionIndex,
2669
+ timestamp: Date.now(),
2670
+ payload: {
2671
+ level: meta && isSetObject(meta) && isSetString(meta.level) ? meta.level : isSetString(meta) ? meta : "info",
2672
+ ...config,
2673
+ args
2674
+ }
2675
+ });
2676
+ };
2677
+ }
2678
+ /**
2621
2679
  * Creates a clone of the current context with the same configuration and workspace settings. This can be useful for running multiple builds in parallel or for creating isolated contexts for different parts of the build process.
2622
2680
  *
2623
2681
  * @remarks
@@ -2626,22 +2684,10 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2626
2684
  * @returns A promise that resolves to the cloned context.
2627
2685
  */
2628
2686
  async clone() {
2629
- const clone = await PowerlinesContext.fromOptions(this.config);
2687
+ const clone = await PowerlinesContext.fromOptions(this.options);
2630
2688
  return this.copyTo(clone);
2631
2689
  }
2632
2690
  /**
2633
- * Create a new logger instance
2634
- *
2635
- * @param name - The name to use for the logger instance
2636
- * @returns A logger function
2637
- */
2638
- createLog(name = null) {
2639
- return createLog(name, {
2640
- ...this.config,
2641
- logLevel: isNull(this.logLevel) ? "silent" : this.logLevel
2642
- });
2643
- }
2644
- /**
2645
2691
  * A function to perform HTTP fetch requests
2646
2692
  *
2647
2693
  * @remarks
@@ -3017,6 +3063,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3017
3063
  for (const [key, value] of Object.entries(this)) if (!SKIP_CLONING_PROPS.includes(key)) if (isObject(value) || Array.isArray(value)) context[key] = deepClone(value);
3018
3064
  else context[key] = value;
3019
3065
  context.inputOptions = deepClone(this.inputOptions);
3066
+ context.options = deepClone(this.options);
3020
3067
  context.dependencies = deepClone(this.dependencies);
3021
3068
  context.devDependencies = deepClone(this.devDependencies);
3022
3069
  context.persistedMeta = this.persistedMeta ? deepClone(this.persistedMeta) : void 0;
@@ -3038,7 +3085,8 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3038
3085
  */
3039
3086
  async init(options = {}) {
3040
3087
  await super.init(options);
3041
- this.options.configIndex = options.configIndex ?? this.options.configIndex ?? 0;
3088
+ this.options.executionId = options.executionId ?? this.options.executionId;
3089
+ this.options.executionIndex = options.executionIndex ?? this.options.executionIndex ?? 0;
3042
3090
  const projectJsonPath = joinPaths$1(this.options.cwd, this.options.root, "project.json");
3043
3091
  if (existsSync(projectJsonPath)) this.projectJson = await readJsonFile(projectJsonPath);
3044
3092
  const packageJsonPath = joinPaths$1(this.options.cwd, this.options.root, "package.json");
@@ -3047,7 +3095,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3047
3095
  this.options.organization ??= isSetObject(this.packageJson?.author) ? kebabCase(this.packageJson?.author?.name) : kebabCase(this.packageJson?.author);
3048
3096
  }
3049
3097
  this.#checksum = await this.generateChecksum(joinPaths$1(this.options.cwd, this.options.root));
3050
- const userConfig = this.configFile.config ? Array.isArray(this.configFile.config) && this.configFile.config.length > this.options.configIndex ? this.configFile.config[this.options.configIndex] : this.configFile.config : {};
3098
+ const userConfig = this.configFile.config ? Array.isArray(this.configFile.config) && this.configFile.config.length > this.options.executionIndex ? this.configFile.config[this.options.executionIndex] : this.configFile.config : {};
3051
3099
  this.resolvedConfig = {
3052
3100
  ...this.options,
3053
3101
  ...userConfig,
@@ -3067,10 +3115,6 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3067
3115
  this.config.framework = "powerlines";
3068
3116
  }
3069
3117
  this.resolvedConfig.compatibilityDate = resolveCompatibilityDates(this.config.inlineConfig.compatibilityDate ?? this.config.userConfig.compatibilityDate ?? this.config.pluginConfig.compatibilityDate, "latest");
3070
- this.logger = {
3071
- log: this.createLog(this.config.name),
3072
- level: isNull(this.logLevel) ? "silent" : this.logLevel
3073
- };
3074
3118
  this.config.input = getUniqueInputs(this.config.input);
3075
3119
  if (this.config.name?.startsWith("@") && this.config.name.split("/").filter(Boolean).length > 1) this.config.name = this.config.name.split("/").filter(Boolean)[1];
3076
3120
  this.config.title ??= titleCase(this.config.name);
@@ -3078,16 +3122,17 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3078
3122
  if (this.config.userConfig.resolve?.noExternal) this.config.userConfig.resolve.noExternal = getUnique(this.config.userConfig.resolve.noExternal);
3079
3123
  if (this.config.resolve.external) this.config.resolve.external = getUnique(this.config.resolve.external);
3080
3124
  if (this.config.resolve.noExternal) this.config.resolve.noExternal = getUnique(this.config.resolve.noExternal);
3081
- this.config.plugins = (this.config.plugins ?? []).filter(Boolean).reduce((ret, plugin) => {
3125
+ this.config.plugins = (this.config.plugins ?? []).flatMap((plugin) => toArray(plugin)).filter(Boolean).reduce((ret, plugin) => {
3082
3126
  if (isPlugin(plugin) && isDuplicate(plugin, ret.filter((p) => isPlugin(p)))) return ret;
3083
3127
  ret.push(plugin);
3084
3128
  return ret;
3085
3129
  }, []);
3086
- if (!this.config.userConfig?.logLevel && !this.config.inlineConfig?.logLevel) if (this.config.mode === "development") this.config.logLevel = "debug";
3087
- else this.config.logLevel = "info";
3088
- if (!this.config.userConfig?.tsconfig && !this.config.inlineConfig?.tsconfig) this.config.tsconfig = getTsconfigFilePath(this.options.cwd, this.options.root);
3130
+ if (!this.config.userConfig?.logLevel && !this.config.inlineConfig?.logLevel) if (this.config.mode === "development") this.config.logLevel = DEFAULT_DEVELOPMENT_LOG_LEVEL;
3131
+ else if (this.config.mode === "test") this.config.logLevel = DEFAULT_TEST_LOG_LEVEL;
3132
+ else this.config.logLevel = DEFAULT_PRODUCTION_LOG_LEVEL;
3133
+ if (!this.config.userConfig?.tsconfig && !this.config.inlineConfig?.tsconfig) this.config.tsconfig = getTsconfigFilePath(this.config.cwd, this.config.root);
3089
3134
  else if (this.config.tsconfig) this.config.tsconfig = replacePath(replacePathTokens(this, this.config.tsconfig), this.config.cwd);
3090
- this.resolvedConfig.output = defu(this.resolvedConfig.output ?? {}, {
3135
+ this.resolvedConfig.output = defu(this.config.output ?? {}, {
3091
3136
  path: joinPaths$1(this.config.root, "dist"),
3092
3137
  copy: { assets: [
3093
3138
  { glob: "LICENSE" },
@@ -3110,7 +3155,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3110
3155
  if (!this.config.root.replace(/^\.\/?/, "")) this.config.output.copy.path = this.config.output.copy.path ? appendPath(replacePathTokens(this, this.config.output.copy.path), this.config.cwd) : this.config.output.path;
3111
3156
  else this.config.output.copy.path = appendPath(replacePathTokens(this, this.config.output.copy.path || joinPaths$1("dist", this.config.root)), this.config.cwd);
3112
3157
  }
3113
- if (this.config.output.dts !== false && this.config.output.types !== false) this.config.output.types = appendPath(replacePathTokens(this, this.config.output.types || joinPaths$1(this.config.root, `${this.config.framework ?? "powerlines"}.d.ts`)), this.config.cwd);
3158
+ if (this.config.output.dts !== false && this.config.output.types !== false) this.config.output.types = appendPath(replacePathTokens(this, this.config.userConfig?.output?.types || this.config.inlineConfig?.output?.types || this.config.pluginConfig?.output?.types || joinPaths$1(this.config.root, `${this.config.framework ?? "powerlines"}.d.ts`)), this.config.cwd);
3114
3159
  if (this.config.output.copy && this.config.output.copy.path && this.config.output.copy.assets && Array.isArray(this.config.output.copy.assets)) this.config.output.copy.assets = getUniqueBy(this.config.output.copy.assets.map((asset) => {
3115
3160
  return {
3116
3161
  glob: isSetObject(asset) ? asset.glob : asset,
@@ -3132,6 +3177,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3132
3177
  }));
3133
3178
  if (isSetString(this.config.output?.storage) && this.config.output.storage === "virtual" || isSetObject(this.config.output?.storage) && Object.values(this.config.output.storage).every((adapter) => adapter.preset === "virtual")) this.config.output.overwrite = true;
3134
3179
  this.#fs ??= await VirtualFileSystem.create(this);
3180
+ this.extendLog({ category: "config" })("debug", `Resolved Powerlines configuration object: \n${JSON.stringify(this.resolvedConfig, null, 2)}`);
3135
3181
  }
3136
3182
  };
3137
3183
 
@@ -3272,15 +3318,16 @@ function extractHooks(context, hooks, plugin, key, parentKey) {
3272
3318
  /**
3273
3319
  * Create a Proxy-based PluginContext
3274
3320
  *
3321
+ * @param pluginId - The unique identifier of the plugin
3275
3322
  * @param plugin - The plugin instance
3276
3323
  * @param environment - The environment context
3277
3324
  * @returns The proxied plugin context
3278
3325
  */
3279
- function createPluginContext(plugin, environment) {
3326
+ function createPluginContext(pluginId, plugin, environment) {
3280
3327
  const normalizeMessage = (message) => {
3281
3328
  return isString(message) ? message : message.message;
3282
3329
  };
3283
- const log = environment.extendLog(plugin.name.replaceAll(":", " - "));
3330
+ const log = environment.extendLog({ plugin: plugin.name.replaceAll(":", " - ") });
3284
3331
  const callHookFn = async (hook, options, ...args) => {
3285
3332
  return environment.$$internal.api.callHook(hook, {
3286
3333
  sequential: true,
@@ -3298,30 +3345,32 @@ function createPluginContext(plugin, environment) {
3298
3345
  callHook: callHookFn,
3299
3346
  meta
3300
3347
  };
3348
+ if (prop === "id") return pluginId;
3301
3349
  if (prop === "log" || prop === "logger") return log;
3302
3350
  if (prop === "fatal") return (message) => {
3303
- log(LogLevelLabel.FATAL, normalizeMessage(message));
3351
+ log("error", normalizeMessage(message));
3304
3352
  };
3305
3353
  if (prop === "error") return (message) => {
3306
- log(LogLevelLabel.ERROR, normalizeMessage(message));
3354
+ log("error", normalizeMessage(message));
3307
3355
  };
3308
3356
  if (prop === "warn") return (message) => {
3309
- log(LogLevelLabel.WARN, normalizeMessage(message));
3357
+ log("warn", normalizeMessage(message));
3310
3358
  };
3311
3359
  if (prop === "info") return (message) => {
3312
- log(LogLevelLabel.INFO, normalizeMessage(message));
3360
+ log("info", normalizeMessage(message));
3313
3361
  };
3314
3362
  if (prop === "debug") return (message) => {
3315
- log(LogLevelLabel.DEBUG, normalizeMessage(message));
3363
+ log("debug", normalizeMessage(message));
3316
3364
  };
3317
3365
  if (prop === "trace") return (message) => {
3318
- log(LogLevelLabel.TRACE, normalizeMessage(message));
3366
+ log("trace", normalizeMessage(message));
3319
3367
  };
3320
3368
  return environment[prop];
3321
3369
  },
3322
3370
  set(_, prop, value) {
3323
3371
  if ([
3324
3372
  "$$internal",
3373
+ "id",
3325
3374
  "environment",
3326
3375
  "config",
3327
3376
  "log",
@@ -3333,7 +3382,7 @@ function createPluginContext(plugin, environment) {
3333
3382
  "addPlugin",
3334
3383
  "selectHooks"
3335
3384
  ].includes(prop)) {
3336
- log(LogLevelLabel.WARN, `Cannot set read-only property "${String(prop)}"`);
3385
+ log("warn", `Cannot set read-only property "${String(prop)}"`);
3337
3386
  return false;
3338
3387
  }
3339
3388
  environment[prop] = value;
@@ -3373,17 +3422,10 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3373
3422
  */
3374
3423
  plugins = [];
3375
3424
  /**
3376
- * Create a new logger instance
3377
- *
3378
- * @param name - The name to use for the logger instance
3379
- * @returns A logger function
3425
+ * The unique identifier of the environment associated with this context, which can be used for logging and other purposes to distinguish between different environments in the same process.
3380
3426
  */
3381
- createLog(name = null) {
3382
- return createLog(name, {
3383
- ...this.config,
3384
- logLevel: isNull(this.config.logLevel) ? "silent" : this.config.logLevel,
3385
- environment: this.environment?.name
3386
- });
3427
+ get id() {
3428
+ return this.environment.environmentId;
3387
3429
  }
3388
3430
  /**
3389
3431
  * The hooks registered by plugins in this environment
@@ -3392,6 +3434,30 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3392
3434
  return this.#hooks;
3393
3435
  }
3394
3436
  /**
3437
+ * Create a new log function with the specified configuration, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the logger instance according to your needs.
3438
+ *
3439
+ * @param config - Optional configuration for the log function instance, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the logger instance according to your needs.
3440
+ * @returns A log function that can be used to log messages with the specified configuration.
3441
+ */
3442
+ createLog(config) {
3443
+ return super.createLog({
3444
+ ...config,
3445
+ environment: this.environment?.name
3446
+ });
3447
+ }
3448
+ /**
3449
+ * Extend the current log function instance with a new name
3450
+ *
3451
+ * @param config - The configuration for the extended log function instance, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the log function instance according to your needs.
3452
+ * @returns A log function
3453
+ */
3454
+ extendLog(config) {
3455
+ return super.extendLog({
3456
+ ...config,
3457
+ environment: this.environment?.name
3458
+ });
3459
+ }
3460
+ /**
3395
3461
  * Creates a clone of the current context with the same configuration and workspace settings. This can be useful for running multiple builds in parallel or for creating isolated contexts for different parts of the build process.
3396
3462
  *
3397
3463
  * @remarks
@@ -3421,8 +3487,10 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3421
3487
  if (isPluginConfig(result)) return this.$$internal.addPlugin(result);
3422
3488
  resolvedPlugin = isPlugin(result) ? result : plugin;
3423
3489
  }
3424
- const context = createPluginContext(resolvedPlugin, this);
3490
+ const pluginId = uuid();
3491
+ const context = createPluginContext(pluginId, resolvedPlugin, this);
3425
3492
  this.plugins.push({
3493
+ pluginId,
3426
3494
  plugin: resolvedPlugin,
3427
3495
  context
3428
3496
  });
@@ -3548,6 +3616,12 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3548
3616
  for (const environment of Object.values(this.environments)) environment.$$internal = super.$$internal;
3549
3617
  }
3550
3618
  /**
3619
+ * The unique identifier of the execution context, which can be used for logging and other purposes to distinguish between different executions in the same process.
3620
+ */
3621
+ get id() {
3622
+ return this.options.executionId;
3623
+ }
3624
+ /**
3551
3625
  * A record of all environments by name
3552
3626
  */
3553
3627
  get environments() {
@@ -3565,6 +3639,32 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3565
3639
  super(options);
3566
3640
  }
3567
3641
  /**
3642
+ * Create a new log function with the specified configuration, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the logger instance according to your needs.
3643
+ *
3644
+ * @param config - Optional configuration for the log function instance, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the logger instance according to your needs.
3645
+ * @returns A log function that can be used to log messages with the specified configuration.
3646
+ */
3647
+ createLog(config) {
3648
+ return super.createLog({
3649
+ ...config,
3650
+ executionId: this.id,
3651
+ executionIndex: this.options.executionIndex
3652
+ });
3653
+ }
3654
+ /**
3655
+ * Extend the current log function instance with a new name
3656
+ *
3657
+ * @param config - The configuration for the extended log function instance, which can include properties such as log level, colors, and other metadata to be included with each log message. This allows you to customize the behavior and appearance of the log function instance according to your needs.
3658
+ * @returns A log function
3659
+ */
3660
+ extendLog(config) {
3661
+ return super.extendLog({
3662
+ ...config,
3663
+ executionId: this.id,
3664
+ executionIndex: this.options.executionIndex
3665
+ });
3666
+ }
3667
+ /**
3568
3668
  * Creates a clone of the current context with the same configuration and workspace settings. This can be useful for running multiple builds in parallel or for creating isolated contexts for different parts of the build process.
3569
3669
  *
3570
3670
  * @remarks
@@ -4426,7 +4526,7 @@ ${formatTypes(code)}
4426
4526
  addPlugin: api.addPlugin.bind(api)
4427
4527
  };
4428
4528
  const timer = api.context.timer("Initialization");
4429
- for (const plugin of api.context.config.plugins.flat(10) ?? []) await api.addPlugin(plugin);
4529
+ for (const plugin of api.context.config.plugins.flatMap((p) => toArray(p)) ?? []) await api.addPlugin(plugin);
4430
4530
  if (api.context.plugins.length === 0) api.context.warn("No Powerlines plugins were specified in the options. Please ensure this is correct, as it is generally not recommended.");
4431
4531
  else api.context.info(`Loaded ${api.context.plugins.length} ${titleCase(api.context.config.framework)} plugin${api.context.plugins.length > 1 ? "s" : ""}: \n${api.context.plugins.map((plugin, index) => ` ${index + 1}. ${colorText(plugin.name)}`).join("\n")}`);
4432
4532
  const pluginConfig = await api.callHook("config", {