@powerlines/engine 0.45.2 → 0.46.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 (52) hide show
  1. package/dist/_internal/worker.cjs +844 -788
  2. package/dist/_internal/worker.mjs +847 -791
  3. package/dist/_internal/worker.mjs.map +1 -1
  4. package/dist/api.cjs +292 -323
  5. package/dist/api.d.cts +44 -11
  6. package/dist/api.d.cts.map +1 -1
  7. package/dist/api.d.mts +44 -11
  8. package/dist/api.d.mts.map +1 -1
  9. package/dist/api.mjs +292 -323
  10. package/dist/api.mjs.map +1 -1
  11. package/dist/{base-context-Byizvf4F.cjs → base-context-BCG0xN2e.cjs} +70 -64
  12. package/dist/{base-context-BSAC5sO9.mjs → base-context-Cmo6TTh7.mjs} +73 -67
  13. package/dist/base-context-Cmo6TTh7.mjs.map +1 -0
  14. package/dist/context/index.cjs +3 -3
  15. package/dist/context/index.d.cts +44 -617
  16. package/dist/context/index.d.cts.map +1 -1
  17. package/dist/context/index.d.mts +44 -617
  18. package/dist/context/index.d.mts.map +1 -1
  19. package/dist/context/index.mjs +3 -3
  20. package/dist/engine-context-BjFMVQEE.mjs +86 -0
  21. package/dist/engine-context-BjFMVQEE.mjs.map +1 -0
  22. package/dist/engine-context-DOsGtgD9.cjs +91 -0
  23. package/dist/execution-context-BdZt7wWa.d.mts +631 -0
  24. package/dist/execution-context-BdZt7wWa.d.mts.map +1 -0
  25. package/dist/execution-context-CU6iNchD.d.cts +631 -0
  26. package/dist/execution-context-CU6iNchD.d.cts.map +1 -0
  27. package/dist/{execution-context-BRzNYU9u.mjs → execution-context-Cp32TarF.mjs} +421 -363
  28. package/dist/execution-context-Cp32TarF.mjs.map +1 -0
  29. package/dist/{execution-context-BlWK2rTX.cjs → execution-context-DgqxcDDx.cjs} +419 -361
  30. package/dist/index.cjs +15 -16
  31. package/dist/index.d.cts +3 -3
  32. package/dist/index.d.cts.map +1 -1
  33. package/dist/index.d.mts +3 -3
  34. package/dist/index.d.mts.map +1 -1
  35. package/dist/index.mjs +15 -16
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/{tsconfig-QMSxSwBD.cjs → tsconfig-BUDqmOaT.cjs} +13 -13
  38. package/dist/{tsconfig-CI6bla4E.mjs → tsconfig-MeFEs21S.mjs} +14 -14
  39. package/dist/tsconfig-MeFEs21S.mjs.map +1 -0
  40. package/dist/typescript/index.cjs +1 -1
  41. package/dist/typescript/index.d.cts +6 -6
  42. package/dist/typescript/index.d.cts.map +1 -1
  43. package/dist/typescript/index.d.mts +6 -6
  44. package/dist/typescript/index.d.mts.map +1 -1
  45. package/dist/typescript/index.mjs +1 -1
  46. package/package.json +17 -17
  47. package/dist/base-context-BSAC5sO9.mjs.map +0 -1
  48. package/dist/engine-context-CI_0NWIk.cjs +0 -73
  49. package/dist/engine-context-_RMFwG4J.mjs +0 -68
  50. package/dist/engine-context-_RMFwG4J.mjs.map +0 -1
  51. package/dist/execution-context-BRzNYU9u.mjs.map +0 -1
  52. package/dist/tsconfig-CI6bla4E.mjs.map +0 -1
@@ -69,21 +69,21 @@ let _stryke_helpers_deep_clone = require("@stryke/helpers/deep-clone");
69
69
  let _stryke_path_join = require("@stryke/path/join");
70
70
  let _stryke_unique_id_uuid = require("@stryke/unique-id/uuid");
71
71
  let _powerlines_core_lib_entry = require("@powerlines/core/lib/entry");
72
- let _stryke_convert_to_bool = require("@stryke/convert/to-bool");
73
72
  let _stryke_env_get_env_paths = require("@stryke/env/get-env-paths");
74
73
  let _stryke_fs_get_workspace_root = require("@stryke/fs/get-workspace-root");
75
74
  let _stryke_hash = require("@stryke/hash");
76
75
  let _stryke_hash_node = require("@stryke/hash/node");
77
76
  let _stryke_http_fetch = require("@stryke/http/fetch");
78
77
  let _stryke_path_is_equal = require("@stryke/path/is-equal");
79
- let _stryke_string_format_kebab_case = require("@stryke/string-format/kebab-case");
80
78
  let bundle_require = require("bundle-require");
81
79
  let compatx = require("compatx");
82
80
  let flat_cache = require("flat-cache");
83
81
  let oxc_parser = require("oxc-parser");
84
82
  let undici = require("undici");
85
83
  require("@stryke/fs/remove-file");
84
+ let _stryke_string_format_kebab_case = require("@stryke/string-format/kebab-case");
86
85
  let _powerlines_core = require("@powerlines/core");
86
+ let jest_worker = require("jest-worker");
87
87
  let _stryke_capnp = require("@stryke/capnp");
88
88
  _stryke_capnp = __toESM(_stryke_capnp, 1);
89
89
  let _stryke_fs_buffer = require("@stryke/fs/buffer");
@@ -117,9 +117,9 @@ let _donedeal0_superdiff = require("@donedeal0/superdiff");
117
117
  let _stryke_json_storm_json = require("@stryke/json/storm-json");
118
118
 
119
119
  //#region src/_internal/helpers/environment.ts
120
- function createEnvironment(name, config = {}) {
120
+ function createEnvironment(name, config) {
121
121
  return (0, defu.default)(config.environments?.[name] ?? {}, {
122
- environmentId: (0, _stryke_unique_id_uuid.uuid)(),
122
+ id: (0, _stryke_unique_id_uuid.uuid)(),
123
123
  name,
124
124
  title: config.title ?? (0, _stryke_string_format_title_case.titleCase)(config.name),
125
125
  ssr: false,
@@ -145,7 +145,7 @@ function createEnvironment(name, config = {}) {
145
145
  } : void 0
146
146
  });
147
147
  }
148
- function createDefaultEnvironment(config = {}) {
148
+ function createDefaultEnvironment(config) {
149
149
  return createEnvironment(_powerlines_core_constants.DEFAULT_ENVIRONMENT, config);
150
150
  }
151
151
 
@@ -202,16 +202,16 @@ async function writeMetaFile(context) {
202
202
 
203
203
  //#endregion
204
204
  //#region src/_internal/ipc/send.ts
205
- function sendWriteLogMessage(context, meta, message) {
205
+ function formatWriteLogMessage(context, meta, message) {
206
206
  const combinedMeta = {
207
207
  ...context.logger.options,
208
208
  ...(0, _stryke_type_checks_is_set_object.isSetObject)(meta) ? meta : { type: meta }
209
209
  };
210
- process.send?.({
210
+ return {
211
211
  id: (0, _stryke_unique_id_uuid.uuid)(),
212
212
  type: "write-log",
213
- executionId: combinedMeta.executionId || context.config.executionId,
214
- executionIndex: combinedMeta.executionIndex ?? context.config.executionIndex,
213
+ executionId: combinedMeta.executionId || context.options.executionId,
214
+ executionIndex: combinedMeta.executionIndex ?? context.options.executionIndex,
215
215
  environment: combinedMeta.environment,
216
216
  timestamp: Date.now(),
217
217
  payload: {
@@ -221,8 +221,8 @@ function sendWriteLogMessage(context, meta, message) {
221
221
  logId: combinedMeta.logId || (0, _stryke_unique_id_uuid.uuid)(),
222
222
  timestamp: combinedMeta.timestamp ?? Date.now(),
223
223
  name: combinedMeta.name || context.config.name,
224
- executionId: combinedMeta.executionId || context.config.executionId,
225
- executionIndex: combinedMeta.executionIndex ?? context.config.executionIndex,
224
+ executionId: combinedMeta.executionId || context.options.executionId,
225
+ executionIndex: combinedMeta.executionIndex ?? context.options.executionIndex,
226
226
  command: combinedMeta.command || context.config.command,
227
227
  hook: combinedMeta.hook,
228
228
  environment: combinedMeta.environment,
@@ -231,7 +231,21 @@ function sendWriteLogMessage(context, meta, message) {
231
231
  },
232
232
  message
233
233
  }
234
- });
234
+ };
235
+ }
236
+ function childProcessSend(message) {
237
+ process.send?.(message);
238
+ }
239
+ function workerThreadSend(message) {
240
+ (0, jest_worker.messageParent)(message);
241
+ }
242
+ function send(message) {
243
+ if (process.env.POWERLINES_EXECUTION_THREAD_TYPE === "child-process") childProcessSend(message);
244
+ else if (process.env.POWERLINES_EXECUTION_THREAD_TYPE === "worker-thread") workerThreadSend(message);
245
+ else console.warn("No IPC mechanism available to send message:", message);
246
+ }
247
+ function sendWriteLogMessage(context, meta, message) {
248
+ send(formatWriteLogMessage(context, meta, message));
235
249
  }
236
250
 
237
251
  //#endregion
@@ -2029,40 +2043,40 @@ var VirtualFileSystem = class VirtualFileSystem {
2029
2043
  /**
2030
2044
  * Get the path to the tsconfig.json file.
2031
2045
  *
2032
- * @param workspaceRoot - The root directory of the workspace.
2033
- * @param projectRoot - The root directory of the project.
2046
+ * @param cwd - The root directory of the workspace.
2047
+ * @param root - The root directory of the project.
2034
2048
  * @param tsconfig - The path to the tsconfig.json file.
2035
2049
  * @returns The absolute path to the tsconfig.json file.
2036
2050
  * @throws If the tsconfig.json file does not exist.
2037
2051
  */
2038
- function getTsconfigFilePath(workspaceRoot, projectRoot, tsconfig) {
2052
+ function getTsconfigFilePath(cwd, root, tsconfig) {
2039
2053
  let tsconfigFilePath;
2040
- if (tsconfig) tsconfigFilePath = tryTsconfigFilePath(workspaceRoot, projectRoot, tsconfig);
2054
+ if (tsconfig) tsconfigFilePath = tryTsconfigFilePath(cwd, root, tsconfig);
2041
2055
  else {
2042
- tsconfigFilePath = tryTsconfigFilePath(workspaceRoot, projectRoot, "tsconfig.app.json");
2056
+ tsconfigFilePath = tryTsconfigFilePath(cwd, root, "tsconfig.app.json");
2043
2057
  if (!tsconfigFilePath) {
2044
- tsconfigFilePath = tryTsconfigFilePath(workspaceRoot, projectRoot, "tsconfig.lib.json");
2045
- if (!tsconfigFilePath) tsconfigFilePath = tryTsconfigFilePath(workspaceRoot, projectRoot, "tsconfig.json");
2058
+ tsconfigFilePath = tryTsconfigFilePath(cwd, root, "tsconfig.lib.json");
2059
+ if (!tsconfigFilePath) tsconfigFilePath = tryTsconfigFilePath(cwd, root, "tsconfig.json");
2046
2060
  }
2047
2061
  }
2048
- if (!tsconfigFilePath) throw new Error(`Cannot find the \`tsconfig.json\` configuration file for the project at ${projectRoot}.`);
2062
+ if (!tsconfigFilePath) throw new Error(`Cannot find the \`tsconfig.json\` configuration file for the project at ${root}.`);
2049
2063
  return tsconfigFilePath;
2050
2064
  }
2051
2065
  /**
2052
2066
  * Get the path to the tsconfig.json file.
2053
2067
  *
2054
- * @param workspaceRoot - The root directory of the workspace.
2055
- * @param projectRoot - The root directory of the project.
2068
+ * @param cwd - The root directory of the workspace.
2069
+ * @param root - The root directory of the project.
2056
2070
  * @param tsconfig - The path to the tsconfig.json file.
2057
2071
  * @returns The absolute path to the tsconfig.json file.
2058
2072
  * @throws If the tsconfig.json file does not exist.
2059
2073
  */
2060
- function tryTsconfigFilePath(workspaceRoot, projectRoot, tsconfig) {
2074
+ function tryTsconfigFilePath(cwd, root, tsconfig) {
2061
2075
  let tsconfigFilePath = tsconfig;
2062
2076
  if (!(0, _stryke_fs_exists.existsSync)(tsconfigFilePath)) {
2063
- tsconfigFilePath = (0, _stryke_path_append.appendPath)(tsconfig, projectRoot);
2077
+ tsconfigFilePath = (0, _stryke_path_append.appendPath)(tsconfig, root);
2064
2078
  if (!(0, _stryke_fs_exists.existsSync)(tsconfigFilePath)) {
2065
- tsconfigFilePath = (0, _stryke_path_append.appendPath)(tsconfig, (0, _stryke_path_append.appendPath)(projectRoot, workspaceRoot));
2079
+ tsconfigFilePath = (0, _stryke_path_append.appendPath)(tsconfig, (0, _stryke_path_append.appendPath)(root, cwd));
2066
2080
  if (!(0, _stryke_fs_exists.existsSync)(tsconfigFilePath)) return;
2067
2081
  }
2068
2082
  }
@@ -2200,17 +2214,17 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2200
2214
  */
2201
2215
  resolver;
2202
2216
  /**
2203
- * The options provided to the Powerlines process
2217
+ * The options provided to the Powerlines process, resolved with default values and merged with any configuration provided by plugins or other sources. This is typically the final configuration used during the build process, but may also include additional options that are relevant to the context and its interactions with the Powerlines engine.
2204
2218
  */
2205
2219
  options;
2206
2220
  /**
2207
- * The input options used to initialize the context, which may be used when cloning the context to ensure the same configuration is applied to the new context
2221
+ * The parsed `package.json` file for the project
2208
2222
  */
2209
- initialOptions = {};
2223
+ packageJson;
2210
2224
  /**
2211
- * The initial configuration provided when initializing the context, which may be used during the setup process to ensure that the configuration is properly merged and applied to the context. This is typically the user configuration provided in the Powerlines configuration file, but may also include additional configuration options provided by plugins or other sources.
2225
+ * The parsed `project.json` file for the project
2212
2226
  */
2213
- initialConfig = {};
2227
+ projectJson = void 0;
2214
2228
  /**
2215
2229
  * The parsed configuration file for the project
2216
2230
  */
@@ -2249,8 +2263,8 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2249
2263
  * @returns A promise that resolves to the cloned context.
2250
2264
  */
2251
2265
  async clone() {
2252
- const clone = new PowerlinesBaseContext();
2253
- await clone.init(this.options, this.initialConfig);
2266
+ const clone = new PowerlinesBaseContext(this.options, this.initialConfig);
2267
+ await clone.init();
2254
2268
  return clone;
2255
2269
  }
2256
2270
  /**
@@ -2333,7 +2347,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2333
2347
  * @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.
2334
2348
  */
2335
2349
  createLogger(options, logFn) {
2336
- return (0, _powerlines_core_plugin_utils_logging.createLogger)(this.options.name || this.options.root, {
2350
+ return (0, _powerlines_core_plugin_utils_logging.createLogger)(this.options.name || this.options.root || "powerlines", {
2337
2351
  ...this.configFile.config,
2338
2352
  ...this.options,
2339
2353
  ...options
@@ -2349,6 +2363,24 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2349
2363
  return (0, _powerlines_core_plugin_utils_logging.extendLogger)(this.logger, options);
2350
2364
  }
2351
2365
  /**
2366
+ * The input options used to initialize the context, which may be used when cloning the context to ensure the same configuration is applied to the new context
2367
+ */
2368
+ initialOptions = {};
2369
+ /**
2370
+ * The initial configuration provided when initializing the context, which may be used during the setup process to ensure that the configuration is properly merged and applied to the context. This is typically the user configuration provided in the Powerlines configuration file, but may also include additional configuration options provided by plugins or other sources.
2371
+ */
2372
+ initialConfig = {};
2373
+ /**
2374
+ * Initialize the context with the provided configuration options and set up the resolver and user configuration file. This method is called during the construction of the context and can also be called when cloning the context to ensure that the new context has the same configuration and resolver setup as the original context.
2375
+ *
2376
+ * @param options - The configuration options to initialize the context with, which can include properties such as the project root, mode, log level, and other settings that affect the behavior of the context and its plugins.
2377
+ * @param initialConfig - The initial configuration to initialize the context with, which is typically the user configuration provided in the Powerlines configuration file. This can also include additional configuration options provided by plugins or other sources that should be merged with the user configuration during initialization
2378
+ */
2379
+ constructor(options, initialConfig = {}) {
2380
+ this.initialOptions = options;
2381
+ this.initialConfig = initialConfig;
2382
+ }
2383
+ /**
2352
2384
  * Retrieve the workspace configuration for the current project, if it exists. This function will look for a configuration file in the project root and return its contents as a JavaScript object. If no configuration file is found, it will return undefined.
2353
2385
  *
2354
2386
  * @returns A promise that resolves to the workspace configuration object, or undefined if no configuration file is found.
@@ -2360,64 +2392,47 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2360
2392
  } : void 0);
2361
2393
  }
2362
2394
  /**
2363
- * Determine the default mode for the current execution based on the environment and workspace configuration. This function will check the `NODE_ENV` environment variable to determine if the current environment is development, production, or test. If `NODE_ENV` is not set, it will look for a `mode` property in the workspace configuration file. If no mode is specified in the workspace configuration, it will default to "production".
2364
- *
2365
- * @returns A promise that resolves to the default mode for the current execution, which can be "development", "production", or "test".
2366
- */
2367
- async getDefaultMode() {
2368
- const workspaceConfig = await this.getWorkspaceConfig();
2369
- return _stryke_env_environment_checks.isProduction ? "production" : _stryke_env_environment_checks.isDevelopment ? "development" : _stryke_env_environment_checks.isTest ? "test" : workspaceConfig?.mode || "production";
2370
- }
2371
- /**
2372
- * Determine the default log level for the current execution based on the environment and workspace configuration. This function will check the `logLevel` property in the workspace configuration file and resolve it to a `LogLevelResolvedConfig` value. If no log level is specified in the workspace configuration, it will default to "info" for development mode and "warn" for production mode.
2373
- *
2374
- * @returns A promise that resolves to the default log level for the current execution, which can be "fatal", "error", "warn", "info", "debug", or "trace".
2375
- */
2376
- async getDefaultLogLevel() {
2377
- const workspaceConfig = await this.getWorkspaceConfig();
2378
- return (0, _powerlines_core_plugin_utils.resolveLogLevel)(workspaceConfig?.logLevel ? workspaceConfig.logLevel === "success" || workspaceConfig.logLevel === "performance" ? "info" : workspaceConfig.logLevel === "all" ? "debug" : workspaceConfig.logLevel === "fatal" ? "error" : workspaceConfig.logLevel : void 0, this.options?.mode || this.initialOptions?.mode || workspaceConfig?.mode || await this.getDefaultMode());
2379
- }
2380
- /**
2381
2395
  * Initialize the context with the provided configuration options
2382
2396
  *
2383
2397
  * @remarks
2384
2398
  * This method will set up the resolver and load the user configuration file based on the provided options. It is called during the construction of the context and can also be called when cloning the context to ensure that the new context has the same configuration and resolver setup.
2385
- *
2386
- * @param options - The configuration options to initialize the context with
2387
- * @param initialConfig - The initial configuration to initialize the context with
2388
2399
  */
2389
- async init(options, initialConfig) {
2390
- this.initialOptions = { ...options };
2391
- this.initialConfig = { ...initialConfig };
2400
+ async init() {
2392
2401
  if (!this.powerlinesPath) {
2393
2402
  const powerlinesPath = await (0, _stryke_fs_resolve.resolvePackage)("powerlines");
2394
2403
  if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
2395
2404
  this.powerlinesPath = powerlinesPath;
2396
2405
  }
2397
- const cwd = options.cwd || this.options?.cwd || process.cwd();
2398
- const root = (0, _stryke_path_replace.replacePath)((options.root || this.options?.root) && (options.root || this.options.root).replace(/^\.\/?/, "") && !(0, _stryke_path_is_equal.isEqual)(options.root || this.options.root, cwd) ? options.root || this.options.root : ".", cwd);
2399
- this.options = (0, defu.default)({
2400
- name: options.name || this.initialConfig.name,
2401
- root,
2402
- cwd,
2403
- mode: options.mode || this.initialConfig.mode,
2404
- logLevel: options.logLevel || this.initialConfig.logLevel,
2405
- framework: options.framework || this.initialConfig.framework,
2406
- organization: options.organization || this.initialConfig.organization,
2407
- configFile: options.configFile || this.initialConfig.configFile
2408
- }, this.options ?? {}, {
2406
+ this.options = (0, defu.default)(this.initialOptions, this.initialConfig, {
2407
+ cwd: process.cwd(),
2409
2408
  mode: await this.getDefaultMode(),
2410
- logLevel: await this.getDefaultLogLevel()
2409
+ logLevel: await this.getDefaultLogLevel(),
2410
+ framework: "powerlines"
2411
2411
  });
2412
+ if (!this.options.root) if (this.options.configFile) {
2413
+ const configFile = (0, _stryke_path_append.appendPath)(this.options.configFile, this.options.cwd);
2414
+ if (!(0, node_fs.existsSync)(configFile)) throw new Error(`The user-provided configuration file at "${this.options.configFile}" does not exist. Please ensure this path is correct and try again.`);
2415
+ if (!(0, _stryke_fs.isFile)(configFile)) throw new Error(`The user-provided configuration file at "${this.options.configFile}" is not a file. Please ensure this path is correct and try again.`);
2416
+ this.options.root = (0, _stryke_path.relativePath)(this.options.cwd, (0, _stryke_path.findFilePath)(configFile));
2417
+ } else this.options.root = ".";
2418
+ else this.options.root = (0, _stryke_path_replace.replacePath)(this.options.root, this.options.cwd);
2412
2419
  this.resolver = createResolver({
2413
- workspaceRoot: cwd,
2414
- root,
2420
+ workspaceRoot: this.options.cwd,
2421
+ root: this.options.root,
2415
2422
  cacheDir: this.envPaths.cache,
2416
2423
  mode: this.options.mode
2417
2424
  });
2425
+ const projectJsonPath = (0, _stryke_path.joinPaths)((0, _stryke_path_append.appendPath)(this.options.root, this.options.cwd), "project.json");
2426
+ if ((0, node_fs.existsSync)(projectJsonPath)) this.projectJson = await (0, _stryke_fs.readJsonFile)(projectJsonPath);
2427
+ const packageJsonPath = (0, _stryke_path.joinPaths)((0, _stryke_path_append.appendPath)(this.options.root, this.options.cwd), "package.json");
2428
+ if ((0, node_fs.existsSync)(packageJsonPath)) {
2429
+ this.packageJson = await (0, _stryke_fs.readJsonFile)(packageJsonPath);
2430
+ this.options.organization ??= (0, _stryke_type_checks_is_set_object.isSetObject)(this.packageJson?.author) ? (0, _stryke_string_format_kebab_case.kebabCase)(this.packageJson?.author?.name) : (0, _stryke_string_format_kebab_case.kebabCase)(this.packageJson?.author);
2431
+ }
2418
2432
  this.configFile = await (0, _powerlines_core_lib_config.loadUserConfigFile)(this.options, this.resolver);
2419
- if (!this.options.name) {
2420
- if (this.configFile.config) {
2433
+ if (this.configFile.config) {
2434
+ if ((0, _stryke_type_checks_is_set_string.isSetString)(this.configFile.configFile)) this.options.configFile ??= (0, _stryke_path_replace.replacePath)(this.configFile.configFile, this.options.cwd);
2435
+ if (!this.options.name) {
2421
2436
  if ((0, _stryke_type_checks_is_set_object.isSetObject)(this.configFile.config) && (0, _stryke_type_checks_is_set_string.isSetString)(this.configFile.config.name)) this.options.name = this.configFile.config.name;
2422
2437
  else if (Array.isArray(this.configFile.config)) {
2423
2438
  for (const config of this.configFile.config) if ((0, _stryke_type_checks_is_set_object.isSetObject)(config) && (0, _stryke_type_checks_is_set_string.isSetString)(config.name)) {
@@ -2426,22 +2441,27 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2426
2441
  }
2427
2442
  }
2428
2443
  }
2429
- if (!this.options.name) {
2430
- const packageJsonPath = (0, _stryke_path.joinPaths)((0, _stryke_path_append.appendPath)(this.options.root, this.options.cwd), "package.json");
2431
- if ((0, node_fs.existsSync)(packageJsonPath)) {
2432
- const packageJson = await (0, _stryke_fs.readJsonFile)(packageJsonPath);
2433
- this.options.name = packageJson.name;
2434
- }
2435
- if (!this.options.name) {
2436
- const projectJsonPath = (0, _stryke_path.joinPaths)((0, _stryke_path_append.appendPath)(this.options.root, this.options.cwd), "project.json");
2437
- if ((0, node_fs.existsSync)(projectJsonPath)) {
2438
- const projectJson = await (0, _stryke_fs.readJsonFile)(projectJsonPath);
2439
- this.options.name = projectJson.name;
2440
- }
2441
- }
2442
- }
2444
+ if (!this.options.name) this.options.name = this.projectJson?.name || this.packageJson?.name;
2443
2445
  }
2444
2446
  }
2447
+ /**
2448
+ * Determine the default mode for the current execution based on the environment and workspace configuration. This function will check the `NODE_ENV` environment variable to determine if the current environment is development, production, or test. If `NODE_ENV` is not set, it will look for a `mode` property in the workspace configuration file. If no mode is specified in the workspace configuration, it will default to "production".
2449
+ *
2450
+ * @returns A promise that resolves to the default mode for the current execution, which can be "development", "production", or "test".
2451
+ */
2452
+ async getDefaultMode() {
2453
+ const workspaceConfig = await this.getWorkspaceConfig();
2454
+ return _stryke_env_environment_checks.isProduction ? "production" : _stryke_env_environment_checks.isDevelopment ? "development" : _stryke_env_environment_checks.isTest ? "test" : workspaceConfig?.mode || "production";
2455
+ }
2456
+ /**
2457
+ * Determine the default log level for the current execution based on the environment and workspace configuration. This function will check the `logLevel` property in the workspace configuration file and resolve it to a `LogLevelResolvedConfig` value. If no log level is specified in the workspace configuration, it will default to "info" for development mode and "warn" for production mode.
2458
+ *
2459
+ * @returns A promise that resolves to the default log level for the current execution, which can be "fatal", "error", "warn", "info", "debug", or "trace".
2460
+ */
2461
+ async getDefaultLogLevel() {
2462
+ const workspaceConfig = await this.getWorkspaceConfig();
2463
+ return (0, _powerlines_core_plugin_utils.resolveLogLevel)(workspaceConfig?.logLevel ? workspaceConfig.logLevel === "success" || workspaceConfig.logLevel === "performance" ? "info" : workspaceConfig.logLevel === "all" ? "debug" : workspaceConfig.logLevel === "fatal" ? "error" : workspaceConfig.logLevel : void 0, this.options?.mode || this.initialOptions?.mode || workspaceConfig?.mode || await this.getDefaultMode());
2464
+ }
2445
2465
  };
2446
2466
 
2447
2467
  //#endregion
@@ -2453,27 +2473,13 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
2453
2473
  timeoutFactor: 2,
2454
2474
  retryAfter: true
2455
2475
  })));
2456
- const SKIP_CLONING_PROPS = [
2457
- "dependencies",
2458
- "devDependencies",
2459
- "persistedMeta",
2460
- "packageJson",
2461
- "projectJson",
2462
- "tsconfig",
2463
- "resolver",
2464
- "fs",
2465
- "$$internal"
2476
+ const UNRESOLVED_CONFIG_NAMES = [
2477
+ "initialConfig",
2478
+ "userConfig",
2479
+ "inlineConfig",
2480
+ "pluginConfig"
2466
2481
  ];
2467
2482
  var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2468
- /**
2469
- * Internal references storage
2470
- *
2471
- * @danger
2472
- * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
2473
- *
2474
- * @internal
2475
- */
2476
- #internal = {};
2477
2483
  #checksum = null;
2478
2484
  #buildId = (0, _stryke_unique_id_uuid.uuid)();
2479
2485
  #releaseId = (0, _stryke_unique_id_uuid.uuid)();
@@ -2481,24 +2487,22 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2481
2487
  #tsconfig;
2482
2488
  #parserCache;
2483
2489
  #requestCache;
2490
+ #configProxy;
2484
2491
  /**
2485
- * Create a new Storm context from the workspace root and user config.
2492
+ * Create a new context from the workspace root and user config.
2486
2493
  *
2487
2494
  * @param options - The options for resolving the context.
2488
2495
  * @returns A promise that resolves to the new context.
2489
2496
  */
2490
- static async init(options, initialConfig) {
2491
- const context = new PowerlinesContext(options);
2492
- await context.init(options, initialConfig);
2493
- const powerlinesPath = await (0, _stryke_fs_resolve.resolvePackage)("powerlines");
2494
- if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
2495
- context.powerlinesPath = powerlinesPath;
2497
+ static async fromInitialConfig(options, initialConfig) {
2498
+ const context = new PowerlinesContext(options, initialConfig);
2499
+ await context.init();
2496
2500
  return context;
2497
2501
  }
2498
2502
  /**
2499
- * The options provided to the Powerlines process
2503
+ * The options provided to the Powerlines process, resolved with default values and merged with any configuration provided by plugins or other sources. This is typically the final configuration used during the build process, but may also include additional options that are relevant to the context and its interactions with the Powerlines engine.
2500
2504
  */
2501
- options;
2505
+ options = {};
2502
2506
  /**
2503
2507
  * An object containing the dependencies that should be installed for the project
2504
2508
  */
@@ -2512,39 +2516,33 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2512
2516
  */
2513
2517
  persistedMeta = void 0;
2514
2518
  /**
2515
- * The parsed `package.json` file for the project
2519
+ * The resolved tsconfig file paths for the project
2516
2520
  */
2517
- packageJson;
2521
+ resolvePatterns = [];
2518
2522
  /**
2519
- * The parsed `project.json` file for the project
2523
+ * The input options used to initialize the context, which may be used when cloning the context to ensure the same configuration is applied to the new context
2520
2524
  */
2521
- projectJson = void 0;
2525
+ initialOptions = {};
2522
2526
  /**
2523
- * The resolved tsconfig file paths for the project
2527
+ * The resolved configuration for this context
2524
2528
  */
2525
- resolvePatterns = [];
2529
+ resolvedConfig = {};
2526
2530
  /**
2527
- * Internal context fields and methods
2528
- *
2529
- * @danger
2530
- * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
2531
- *
2532
- * @internal
2531
+ * The configuration options that were overridden by plugins during the build process, which may include additional properties or modifications made during the configuration loading process.
2533
2532
  */
2534
- get $$internal() {
2535
- return this.#internal;
2536
- }
2533
+ overriddenConfig = {};
2537
2534
  /**
2538
- * Internal context fields and methods
2539
- *
2540
- * @danger
2541
- * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
2542
- *
2543
- * @internal
2535
+ * The configuration options provided inline during execution, such as CLI flags or other parameters that may be relevant to the command being executed. These options can be used to override or supplement the configuration options defined in a configuration file on disk, and are typically provided as part of the execution context when running a Powerlines command.
2544
2536
  */
2545
- set $$internal(value) {
2546
- this.#internal = value;
2547
- }
2537
+ inlineConfig = {};
2538
+ /**
2539
+ * The configuration options read from a configuration file on disk, which may be used to resolve the final configuration for the context. This typically includes the user configuration options defined in the `powerlines.config.ts` file, as well as any inline configuration options provided during execution.
2540
+ */
2541
+ userConfig = {};
2542
+ /**
2543
+ * The configuration options provided by plugins added by the user (and other plugins)
2544
+ */
2545
+ pluginConfig = {};
2548
2546
  /**
2549
2547
  * The resolved entry type definitions for the project
2550
2548
  */
@@ -2599,13 +2597,14 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2599
2597
  * The resolved configuration options
2600
2598
  */
2601
2599
  get config() {
2602
- return this.resolvedConfig;
2600
+ if (!this.#configProxy) this.#configProxy = this.createConfigProxy();
2601
+ return this.#configProxy;
2603
2602
  }
2604
2603
  /**
2605
2604
  * Get the path to the artifacts directory for the project
2606
2605
  */
2607
2606
  get artifactsPath() {
2608
- return (0, _stryke_path_join.joinPaths)(this.config.cwd, this.config.root, this.config.output.artifactsPath);
2607
+ return (0, _stryke_path_join.joinPaths)(this.config.cwd, this.config.root, this.config.output?.artifactsPath || `.${this.config.framework || "powerlines"}`);
2609
2608
  }
2610
2609
  /**
2611
2610
  * Get the path to the builtin modules used by the project
@@ -2662,7 +2661,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2662
2661
  * Additional arguments provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed.
2663
2662
  */
2664
2663
  get additionalArgs() {
2665
- return Object.entries(this.config.inlineConfig?.additionalArgs ?? {}).reduce((ret, [key, value]) => {
2664
+ return Object.entries(this.config.inlineConfig.additionalArgs ?? {}).reduce((ret, [key, value]) => {
2666
2665
  const formattedKey = key.replace(/^--?/, "");
2667
2666
  if (ret[formattedKey]) if (Array.isArray(ret[formattedKey])) if (Array.isArray(value)) ret[formattedKey] = [...(0, _stryke_convert_to_array.toArray)(ret[formattedKey]), ...value];
2668
2667
  else ret[formattedKey] = [...(0, _stryke_convert_to_array.toArray)(ret[formattedKey]), value];
@@ -2691,29 +2690,6 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2691
2690
  }, {}) : this.config.resolve.alias : {});
2692
2691
  }
2693
2692
  /**
2694
- * Create a new logger instance
2695
- *
2696
- * @param options - 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.
2697
- * @param logFn - The custom logging function to use for logging messages, which can be used to override the default logging behavior of the original logger.
2698
- * @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.
2699
- */
2700
- createLogger(options, logFn) {
2701
- let logger;
2702
- if ((0, _stryke_convert_to_bool.toBool)(process.env.POWERLINES_WORKER_THREAD_EXECUTION)) logger = (0, _powerlines_core_plugin_utils.createLogger)(this.config.name, {
2703
- ...this.options,
2704
- ...this.config,
2705
- ...options
2706
- }, (meta, message) => sendWriteLogMessage(this, meta, message));
2707
- else logger = (0, _powerlines_core_plugin_utils.createLogger)(this.config.name, {
2708
- ...this.options,
2709
- ...this.config,
2710
- ...options
2711
- });
2712
- if (this.config.customLogger) logger = (0, _powerlines_core_plugin_utils.withCustomLogger)(logger, this.config.customLogger);
2713
- if (logFn) logger = (0, _powerlines_core_plugin_utils.withLogFn)(logger, logFn);
2714
- return logger;
2715
- }
2716
- /**
2717
2693
  * The log level for the context, which determines the minimum level of log messages that will be emitted by the logger. This is resolved based on the configuration options provided by the user, and can be set to different levels for development, production, and test environments. The log level can also be overridden by plugins or other parts of the build process to provide more granular control over logging output.
2718
2694
  */
2719
2695
  get logLevel() {
@@ -2775,25 +2751,38 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
2775
2751
  }).filter(Boolean);
2776
2752
  }
2777
2753
  /**
2778
- * Creates a new StormContext instance.
2754
+ * Creates a new Context instance.
2779
2755
  *
2780
2756
  * @param options - The options to use for creating the context, including the resolved configuration and workspace settings.
2757
+ * @param initialConfig - The initial configuration provided by the user, which can be used to resolve the final configuration for the context. This typically includes the user configuration options defined in the `powerlines.config.ts` file, as well as any inline configuration options provided during execution.
2781
2758
  */
2782
- constructor(options) {
2783
- super();
2784
- this.options = options;
2759
+ constructor(options, initialConfig) {
2760
+ super(options, initialConfig);
2761
+ this.initialOptions = options;
2762
+ this.initialConfig = initialConfig;
2785
2763
  }
2786
2764
  /**
2787
- * 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.
2788
- *
2789
- * @remarks
2790
- * The cloned context will have the same configuration and workspace settings as the original context, but will have a different build ID, release ID, and timestamp. The virtual file system and caches will also be separate between the original and cloned contexts.
2765
+ * Create a new logger instance
2791
2766
  *
2792
- * @returns A promise that resolves to the cloned context.
2767
+ * @param options - 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.
2768
+ * @param logFn - The custom logging function to use for logging messages, which can be used to override the default logging behavior of the original logger.
2769
+ * @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.
2793
2770
  */
2794
- async clone() {
2795
- const clone = await PowerlinesContext.init(this.options, this.initialConfig);
2796
- return this.copyTo(clone);
2771
+ createLogger(options, logFn) {
2772
+ let logger;
2773
+ if ((0, _stryke_type_checks_is_set_string.isSetString)(process.env.POWERLINES_EXECUTION_THREAD_TYPE)) logger = (0, _powerlines_core_plugin_utils.createLogger)(this.config.name, {
2774
+ ...this.options,
2775
+ ...this.config,
2776
+ ...options
2777
+ }, (meta, message) => sendWriteLogMessage(this, meta, message));
2778
+ else logger = (0, _powerlines_core_plugin_utils.createLogger)(this.config.name, {
2779
+ ...this.options,
2780
+ ...this.config,
2781
+ ...options
2782
+ });
2783
+ if (this.config.customLogger) logger = (0, _powerlines_core_plugin_utils.withCustomLogger)(logger, this.config.customLogger);
2784
+ if (logFn) logger = (0, _powerlines_core_plugin_utils.withLogFn)(logger, logFn);
2785
+ return logger;
2797
2786
  }
2798
2787
  /**
2799
2788
  * A function to perform HTTP fetch requests
@@ -3123,206 +3112,233 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
3123
3112
  /**
3124
3113
  * Generates a checksum representing the current context state
3125
3114
  *
3126
- * @param root - The root directory of the project to generate the checksum for
3115
+ * @param path - The root directory of the project to generate the checksum for
3127
3116
  * @returns A promise that resolves to a string representing the checksum
3128
3117
  */
3129
- async generateChecksum(root = this.config.root) {
3130
- this.#checksum = await (0, _stryke_hash_node.hashDirectory)(root, { ignore: [
3131
- "node_modules",
3132
- ".git",
3133
- ".nx",
3134
- ".cache",
3135
- "tmp",
3136
- "dist"
3137
- ] });
3138
- return this.#checksum;
3118
+ async generateChecksum(path) {
3119
+ return (0, _stryke_hash_node.hashDirectory)(path || (0, _stryke_path_append.appendPath)(this.options.root, this.options.cwd));
3139
3120
  }
3140
3121
  /**
3141
- * Initialize the context with the provided configuration options
3122
+ * A setter function to populate the inline config values provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed. This function can be used to update the context with the inline configuration values, which may be used during the configuration resolution process to ensure that the final configuration reflects both the user configuration and any inline configuration provided during execution.
3123
+ *
3124
+ * @param config - The inline configuration values to set.
3125
+ * @returns A promise that resolves when the inline configuration values have been set.
3142
3126
  */
3143
- async setup() {
3144
- this.resolvedConfig = (0, _powerlines_core_plugin_utils.mergeConfig)({
3145
- root: this.options.root,
3146
- cwd: this.options.cwd,
3147
- inlineConfig: this.config.inlineConfig ?? {},
3148
- userConfig: this.config.userConfig ?? {},
3149
- initialConfig: this.config.initialConfig ?? {},
3150
- pluginConfig: this.config.pluginConfig ?? {}
3151
- }, getConfigProps(this.config.inlineConfig), getConfigProps(this.config.userConfig), getConfigProps(this.config.initialConfig), getConfigProps(this.config.pluginConfig), this.options, {
3152
- name: this.projectJson?.name || this.packageJson?.name,
3127
+ async setInlineConfig(config) {
3128
+ this.logger.debug({
3129
+ meta: { category: "config" },
3130
+ message: `Updating inline configuration object: \n${this.logConfig(config)}`
3131
+ });
3132
+ this.inlineConfig = config;
3133
+ await this.resolveConfig();
3134
+ }
3135
+ /**
3136
+ * A setter function to populate the plugin config values provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed. This function can be used to update the context with the plugin configuration values, which may be used during the configuration resolution process to ensure that the final configuration reflects both the user configuration and any plugin configuration provided during execution.
3137
+ *
3138
+ * @param config - The plugin configuration values to set.
3139
+ * @returns A promise that resolves when the plugin configuration values have been set.
3140
+ */
3141
+ async setPluginConfig(config) {
3142
+ this.logger.debug({
3143
+ meta: { category: "config" },
3144
+ message: `Updating plugin configuration object: \n${this.logConfig(config)}`
3145
+ });
3146
+ this.pluginConfig = config;
3147
+ await this.resolveConfig();
3148
+ }
3149
+ /**
3150
+ * A function to merge the various configuration objects (initial, user, inline, and plugin) into a single resolved configuration object that can be used throughout the Powerlines process. This function takes into account the different sources of configuration and their respective priorities, ensuring that the final configuration reflects the intended settings for the project. The merged configuration is then returned as a new object that can be accessed through the `config` property of the context.
3151
+ *
3152
+ * @returns The merged configuration object that combines the initial, user, inline, and plugin configurations.
3153
+ */
3154
+ mergeConfig() {
3155
+ return (0, _powerlines_core_plugin_utils.mergeConfig)({
3156
+ mode: this.initialOptions.mode,
3157
+ framework: this.initialOptions.framework,
3158
+ initialOptions: this.initialOptions,
3159
+ options: this.options,
3160
+ inlineConfig: this.inlineConfig,
3161
+ userConfig: this.userConfig,
3162
+ initialConfig: this.initialConfig,
3163
+ pluginConfig: this.pluginConfig
3164
+ }, getConfigProps(this.overriddenConfig), (0, _stryke_helpers_omit.omit)(this.options, ["mode", "framework"]), getConfigProps(this.inlineConfig), getConfigProps(this.userConfig), getConfigProps(this.initialConfig), getConfigProps(this.pluginConfig), {
3153
3165
  version: this.packageJson?.version,
3154
3166
  description: this.packageJson?.description
3155
3167
  }, {
3156
3168
  environments: {},
3157
3169
  resolve: {}
3158
3170
  });
3159
- this.config.plugins = (this.config.initialConfig.plugins ?? []).concat(this.config.userConfig.plugins ?? [], this.config.inlineConfig.plugins ?? []);
3160
- await this.innerSetup();
3161
3171
  }
3162
3172
  /**
3163
- * The resolved configuration for this context
3164
- */
3165
- resolvedConfig = {};
3166
- /**
3167
- * 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.
3168
- *
3169
- * @remarks
3170
- * The cloned context will have the same configuration and workspace settings as the original context, but will have a different build ID, release ID, and timestamp. The virtual file system and caches will also be separate between the original and cloned contexts.
3173
+ * A setter function to populate the user config values provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed. This function can be used to update the context with the user configuration values, which may be used during the configuration resolution process to ensure that the final configuration reflects both the user configuration and any inline configuration provided during execution.
3171
3174
  *
3172
- * @returns The cloned context.
3175
+ * @param config - The user configuration values to set.
3176
+ * @returns A promise that resolves when the user configuration values have been set.
3173
3177
  */
3174
- copyTo(context) {
3175
- for (const [key, value] of Object.entries(this)) if (!SKIP_CLONING_PROPS.includes(key)) if ((0, _stryke_type_checks_is_object.isObject)(value) || Array.isArray(value)) context[key] = (0, _stryke_helpers_deep_clone.deepClone)(value);
3176
- else context[key] = value;
3177
- context.initialConfig = (0, _stryke_helpers_deep_clone.deepClone)(this.initialConfig);
3178
- context.initialOptions = (0, _stryke_helpers_deep_clone.deepClone)(this.initialOptions);
3179
- context.options = (0, _stryke_helpers_deep_clone.deepClone)(this.options);
3180
- context.dependencies = (0, _stryke_helpers_deep_clone.deepClone)(this.dependencies);
3181
- context.devDependencies = (0, _stryke_helpers_deep_clone.deepClone)(this.devDependencies);
3182
- context.persistedMeta = this.persistedMeta ? (0, _stryke_helpers_deep_clone.deepClone)(this.persistedMeta) : void 0;
3183
- context.packageJson = (0, _stryke_helpers_deep_clone.deepClone)(this.packageJson);
3184
- context.projectJson = this.projectJson ? (0, _stryke_helpers_deep_clone.deepClone)(this.projectJson) : void 0;
3185
- context.tsconfig ??= (0, _stryke_helpers_deep_clone.deepClone)(this.tsconfig);
3186
- context.resolver ??= this.resolver;
3187
- context.fs ??= this.#fs;
3188
- context.$$internal = this.$$internal;
3189
- return context;
3178
+ async setUserConfig(config) {
3179
+ this.logger.debug({
3180
+ meta: { category: "config" },
3181
+ message: `Updating user configuration object: \n${this.logConfig(config)}`
3182
+ });
3183
+ this.userConfig = config;
3184
+ await this.resolveConfig();
3190
3185
  }
3191
3186
  /**
3192
3187
  * Initialize the context with the provided configuration options
3193
- *
3194
- * @remarks
3195
- * This method will set up the resolver and load the user configuration file based on the provided options. It is called during the construction of the context and can also be called when cloning the context to ensure that the new context has the same configuration and resolver setup.
3196
- *
3197
- * @param options - The configuration options to initialize the context with
3198
- */
3199
- async init(options, initialConfig) {
3200
- await super.init(options, initialConfig ?? {});
3201
- this.options.executionId = options.executionId ?? this.options.executionId;
3202
- this.options.executionIndex = options.executionIndex ?? this.options.executionIndex ?? 0;
3203
- const projectJsonPath = (0, _stryke_path_join.joinPaths)(this.options.cwd, this.options.root, "project.json");
3204
- if ((0, _stryke_fs_exists.existsSync)(projectJsonPath)) this.projectJson = await (0, _stryke_fs_json.readJsonFile)(projectJsonPath);
3205
- const packageJsonPath = (0, _stryke_path_join.joinPaths)(this.options.cwd, this.options.root, "package.json");
3206
- if ((0, _stryke_fs_exists.existsSync)(packageJsonPath)) {
3207
- this.packageJson = await (0, _stryke_fs_json.readJsonFile)(packageJsonPath);
3208
- this.options.organization ??= (0, _stryke_type_checks_is_set_object.isSetObject)(this.packageJson?.author) ? (0, _stryke_string_format_kebab_case.kebabCase)(this.packageJson?.author?.name) : (0, _stryke_string_format_kebab_case.kebabCase)(this.packageJson?.author);
3209
- }
3210
- this.#checksum = await this.generateChecksum((0, _stryke_path_join.joinPaths)(this.options.cwd, this.options.root));
3211
- 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 : {};
3212
- this.resolvedConfig = {
3213
- cwd: this.options.cwd,
3214
- root: this.options.root,
3215
- ...this.initialOptions,
3216
- ...initialConfig,
3217
- ...userConfig,
3218
- inlineConfig: {},
3219
- pluginConfig: {},
3220
- initialConfig,
3221
- userConfig
3222
- };
3188
+ */
3189
+ async init() {
3190
+ await super.init();
3191
+ this.options.executionId = this.initialOptions.executionId || (0, _stryke_unique_id_uuid.uuid)();
3192
+ this.options.executionIndex = this.initialOptions.executionIndex ?? 0;
3193
+ this.#checksum = await this.generateChecksum();
3194
+ const result = this.configFile.config && (0, _stryke_convert_to_array.toArray)(this.configFile.config).length > this.options.executionIndex ? (0, _stryke_convert_to_array.toArray)(this.configFile.config)[this.options.executionIndex] : this.configFile.config;
3195
+ if (!result) this.logger.warn(`No configuration found in ${this.options.configFile} for execution index ${this.options.executionIndex}.`);
3196
+ else await this.setUserConfig((0, _stryke_type_checks_is_function.isFunction)(result) ? await Promise.resolve(result(this.options)) : result);
3223
3197
  }
3224
3198
  /**
3225
3199
  * Initialize the context with the provided configuration options
3226
3200
  */
3227
- async innerSetup() {
3228
- const logger = this.extendLogger({ category: "config" });
3229
- this.config.output = (0, defu.default)(this.config.output ?? {}, {
3201
+ async resolveConfig() {
3202
+ const mergedConfig = this.mergeConfig();
3203
+ this.logger.trace({
3204
+ meta: { category: "config" },
3205
+ message: `Pre-setup Powerlines configuration object: \n --- Pre-Resolved Config --- \n${this.logConfig(mergedConfig)} \n --- Initial Config --- \n${this.logConfig(this.initialConfig)} \n --- User Config --- \n${this.logConfig(this.userConfig)} \n --- Inline Config --- \n${this.logConfig(this.inlineConfig)} \n --- Plugin Config --- \n${this.logConfig(this.pluginConfig)}`
3206
+ });
3207
+ mergedConfig.output = (0, defu.default)(mergedConfig.output ?? {}, {
3230
3208
  copy: { assets: [
3231
3209
  { glob: "LICENSE" },
3232
3210
  {
3233
- input: this.config.root,
3211
+ input: mergedConfig.root,
3234
3212
  glob: "*.md"
3235
3213
  },
3236
3214
  {
3237
- input: this.config.root,
3215
+ input: mergedConfig.root,
3238
3216
  glob: "package.json"
3239
3217
  }
3240
3218
  ] },
3241
3219
  dts: true
3242
3220
  });
3243
- logger.trace(`Pre-setup Powerlines configuration object: \n${(0, _storm_software_config_tools_logger_console.formatLogMessage)({
3244
- ...(0, _stryke_helpers_omit.omit)(this.config, [
3245
- "inlineConfig",
3246
- "userConfig",
3247
- "initialConfig",
3248
- "pluginConfig",
3249
- "plugins"
3250
- ]),
3251
- inlineConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.inlineConfig) ? (0, _stryke_helpers_omit.omit)(this.config.inlineConfig, ["plugins"]) : void 0,
3252
- userConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.userConfig) ? (0, _stryke_helpers_omit.omit)(this.config.userConfig, ["plugins"]) : void 0,
3253
- initialConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.initialConfig) ? (0, _stryke_helpers_omit.omit)(this.config.initialConfig, ["plugins"]) : void 0,
3254
- pluginConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.pluginConfig) ? (0, _stryke_helpers_omit.omit)(this.config.pluginConfig, ["plugins"]) : void 0
3255
- })}`);
3256
- if (!this.initialOptions.mode && !this.config.userConfig?.mode && !this.config.inlineConfig?.mode && !this.config.initialConfig?.mode && !this.config.pluginConfig?.mode) {
3257
- this.options.mode = "production";
3258
- this.config.mode = "production";
3259
- }
3260
- if (!this.initialOptions.framework && !this.config.userConfig?.framework && !this.config.inlineConfig?.framework && !this.config.initialConfig?.framework && !this.config.pluginConfig?.framework) {
3261
- this.options.framework = "powerlines";
3262
- this.config.framework = "powerlines";
3263
- }
3264
- if (!this.config.userConfig?.projectType && !this.config.inlineConfig?.projectType && !this.config.initialConfig?.projectType && !this.config.pluginConfig?.projectType) this.config.projectType = "application";
3265
- if (!this.config.userConfig?.platform && !this.config.inlineConfig?.platform && !this.config.initialConfig?.platform && !this.config.pluginConfig?.platform) this.config.platform = "neutral";
3266
- this.config.compatibilityDate = (0, compatx.resolveCompatibilityDates)(this.config.inlineConfig.compatibilityDate ?? this.config.userConfig.compatibilityDate ?? this.config.initialConfig.compatibilityDate ?? this.config.pluginConfig.compatibilityDate, "latest");
3267
- this.config.input = (0, _powerlines_core_lib_entry.getUniqueInputs)(this.config.input);
3268
- if (this.config.name?.startsWith("@") && this.config.name.split("/").filter(Boolean).length > 1) this.config.name = this.config.name.split("/").filter(Boolean)[1];
3269
- this.config.title ??= (0, _stryke_string_format_title_case.titleCase)(this.config.name);
3270
- if (this.config.resolve.external) this.config.resolve.external = (0, _stryke_helpers_get_unique.getUnique)(this.config.resolve.external);
3271
- if (this.config.resolve.noExternal) this.config.resolve.noExternal = (0, _stryke_helpers_get_unique.getUnique)(this.config.resolve.noExternal);
3272
- this.config.plugins = (this.config.plugins ?? []).flatMap((plugin) => (0, _stryke_convert_to_array.toArray)(plugin)).filter(Boolean).reduce((ret, plugin) => {
3221
+ if (!mergedConfig.mode) mergedConfig.mode = "production";
3222
+ if (!mergedConfig.framework) mergedConfig.framework = "powerlines";
3223
+ if (!mergedConfig.projectType) mergedConfig.projectType = "application";
3224
+ if (!mergedConfig.platform) mergedConfig.platform = "neutral";
3225
+ mergedConfig.compatibilityDate = (0, compatx.resolveCompatibilityDates)(mergedConfig.compatibilityDate, "latest");
3226
+ this.resolvedConfig = mergedConfig;
3227
+ this.#configProxy = this.createConfigProxy();
3228
+ mergedConfig.input = (0, _powerlines_core_lib_entry.getUniqueInputs)(mergedConfig.input);
3229
+ if (mergedConfig.name?.startsWith("@") && mergedConfig.name.split("/").filter(Boolean).length > 1) mergedConfig.name = mergedConfig.name.split("/").filter(Boolean)[1];
3230
+ mergedConfig.title ??= (0, _stryke_string_format_title_case.titleCase)(mergedConfig.name);
3231
+ if (mergedConfig.resolve.external) mergedConfig.resolve.external = (0, _stryke_helpers_get_unique.getUnique)(mergedConfig.resolve.external);
3232
+ if (mergedConfig.resolve.noExternal) mergedConfig.resolve.noExternal = (0, _stryke_helpers_get_unique.getUnique)(mergedConfig.resolve.noExternal);
3233
+ mergedConfig.plugins = (mergedConfig.plugins ?? []).flatMap((plugin) => (0, _stryke_convert_to_array.toArray)(plugin)).filter(Boolean).reduce((ret, plugin) => {
3273
3234
  if ((0, _powerlines_core_plugin_utils.isPlugin)(plugin) && (0, _powerlines_core_plugin_utils.isDuplicate)(plugin, ret.filter((p) => (0, _powerlines_core_plugin_utils.isPlugin)(p)))) return ret;
3274
3235
  ret.push(plugin);
3275
3236
  return ret;
3276
3237
  }, []);
3277
- if (!this.config.userConfig?.logLevel && !this.config.initialConfig?.logLevel && !this.config.pluginConfig?.logLevel && !this.config.inlineConfig?.logLevel) if (this.config.mode === "development") this.config.logLevel = _powerlines_core_constants.DEFAULT_DEVELOPMENT_LOG_LEVEL;
3278
- else if (this.config.mode === "test") this.config.logLevel = _powerlines_core_constants.DEFAULT_TEST_LOG_LEVEL;
3279
- else this.config.logLevel = _powerlines_core_constants.DEFAULT_PRODUCTION_LOG_LEVEL;
3280
- if (!this.config.userConfig?.tsconfig && !this.config.initialConfig?.tsconfig && !this.config.pluginConfig?.tsconfig && !this.config.inlineConfig?.tsconfig) this.config.tsconfig = getTsconfigFilePath(this.config.cwd, this.config.root);
3281
- else if (this.config.tsconfig) this.config.tsconfig = (0, _stryke_path_replace.replacePath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, this.config.tsconfig), this.config.cwd);
3282
- this.config.output.format = (0, _stryke_helpers_get_unique.getUnique)((0, _stryke_convert_to_array.toArray)(this.config.output?.format ?? (this.config.projectType === "library" ? ["cjs", "esm"] : ["esm"])));
3283
- if (this.config.output.path) this.config.output.path = (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, this.config.output.path), this.config.cwd);
3284
- else this.config.output.path = (0, _stryke_path_append.appendPath)((0, _stryke_path_join.joinPaths)(this.config.root, "dist"), this.config.cwd);
3285
- if (this.config.output.copy !== false) {
3286
- this.config.output.copy ??= {};
3287
- if (!this.config.root.replace(/^\.\/?/, "")) this.config.output.copy.path = this.config.output.copy.path ? (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, this.config.output.copy.path), this.config.cwd) : this.config.output.path;
3288
- else this.config.output.copy.path = (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, this.config.output.copy.path || (0, _stryke_path_join.joinPaths)("dist", this.config.root)), this.config.cwd);
3289
- }
3290
- if (this.config.output.types !== false) this.config.output.types = (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, this.config.userConfig?.output?.types || this.config.inlineConfig?.output?.types || this.config.initialConfig?.output?.types || this.config.pluginConfig?.output?.types || (0, _stryke_path_join.joinPaths)(this.config.root, `${this.config.framework ?? "powerlines"}.d.ts`)), this.config.cwd);
3291
- 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 = (0, _stryke_helpers_get_unique.getUniqueBy)(this.config.output.copy.assets.map((asset) => {
3238
+ if (!mergedConfig.logLevel) if (mergedConfig.mode === "development") mergedConfig.logLevel = _powerlines_core_constants.DEFAULT_DEVELOPMENT_LOG_LEVEL;
3239
+ else if (mergedConfig.mode === "test") mergedConfig.logLevel = _powerlines_core_constants.DEFAULT_TEST_LOG_LEVEL;
3240
+ else mergedConfig.logLevel = _powerlines_core_constants.DEFAULT_PRODUCTION_LOG_LEVEL;
3241
+ if (mergedConfig.tsconfig) mergedConfig.tsconfig = (0, _stryke_path_replace.replacePath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, mergedConfig.tsconfig), mergedConfig.cwd);
3242
+ else mergedConfig.tsconfig = getTsconfigFilePath(mergedConfig.cwd, mergedConfig.root);
3243
+ mergedConfig.output.format = (0, _stryke_helpers_get_unique.getUnique)((0, _stryke_convert_to_array.toArray)(mergedConfig.output?.format ?? (mergedConfig.projectType === "library" ? ["cjs", "esm"] : ["esm"])));
3244
+ if (mergedConfig.output.path) mergedConfig.output.path = (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, mergedConfig.output.path), mergedConfig.cwd);
3245
+ else mergedConfig.output.path = (0, _stryke_path_append.appendPath)((0, _stryke_path_join.joinPaths)(mergedConfig.root, "dist"), mergedConfig.cwd);
3246
+ mergedConfig.output.copy ??= {};
3247
+ if (mergedConfig.output.copy !== false) if (!mergedConfig.root.replace(/^\.\/?/, "")) mergedConfig.output.copy.path = mergedConfig.output.copy.path ? (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, mergedConfig.output.copy.path), mergedConfig.cwd) : mergedConfig.output.path;
3248
+ else mergedConfig.output.copy.path = (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, mergedConfig.output.copy.path || (0, _stryke_path_join.joinPaths)("dist", mergedConfig.root)), mergedConfig.cwd);
3249
+ if (mergedConfig.output.types !== false) mergedConfig.output.types = (0, _stryke_path_append.appendPath)((0, _powerlines_core_plugin_utils.replacePathTokens)(this, mergedConfig.output.types || (0, _stryke_path_join.joinPaths)(mergedConfig.root, `${mergedConfig.framework ?? "powerlines"}.d.ts`)), mergedConfig.cwd);
3250
+ if (mergedConfig.output.copy && mergedConfig.output.copy.path && mergedConfig.output.copy.assets && Array.isArray(mergedConfig.output.copy.assets)) mergedConfig.output.copy.assets = (0, _stryke_helpers_get_unique.getUniqueBy)(mergedConfig.output.copy.assets.map((asset) => {
3292
3251
  return {
3293
3252
  glob: (0, _stryke_type_checks_is_set_object.isSetObject)(asset) ? asset.glob : asset,
3294
- input: (0, _stryke_type_checks_is_string.isString)(asset) || !asset.input || asset.input === "." || asset.input === "/" || asset.input === "./" ? this.options.cwd : (0, _stryke_path_is_parent_path.isParentPath)(asset.input, this.config.cwd) || (0, _stryke_path_is_equal.isEqual)(asset.input, this.config.cwd) ? asset.input : (0, _stryke_path_append.appendPath)(asset.input, this.config.cwd),
3295
- output: (0, _stryke_type_checks_is_set_object.isSetObject)(asset) && asset.output ? (0, _stryke_path_is_parent_path.isParentPath)(asset.output, this.config.cwd) ? asset.output : (0, _stryke_path_append.appendPath)((0, _stryke_path_join.joinPaths)(this.config.output.copy.path, (0, _stryke_path_replace.replacePath)((0, _stryke_path_replace.replacePath)(asset.output, (0, _stryke_path_replace.replacePath)(this.config.output.copy.path, this.config.cwd)), this.config.output.copy.path)), this.config.cwd) : (0, _stryke_path_append.appendPath)(this.config.output.copy.path, this.config.cwd),
3253
+ input: (0, _stryke_type_checks_is_string.isString)(asset) || !asset.input || asset.input === "." || asset.input === "/" || asset.input === "./" ? mergedConfig.cwd : (0, _stryke_path_is_parent_path.isParentPath)(asset.input, mergedConfig.cwd) || (0, _stryke_path_is_equal.isEqual)(asset.input, mergedConfig.cwd) ? asset.input : (0, _stryke_path_append.appendPath)(asset.input, mergedConfig.cwd),
3254
+ output: (0, _stryke_type_checks_is_set_object.isSetObject)(asset) && asset.output ? (0, _stryke_path_is_parent_path.isParentPath)(asset.output, mergedConfig.cwd) ? asset.output : (0, _stryke_path_append.appendPath)((0, _stryke_path_join.joinPaths)(mergedConfig.output.copy.path, (0, _stryke_path_replace.replacePath)((0, _stryke_path_replace.replacePath)(asset.output, (0, _stryke_path_replace.replacePath)(mergedConfig.output.copy.path, mergedConfig.cwd)), mergedConfig.output.copy.path)), mergedConfig.cwd) : (0, _stryke_path_append.appendPath)(mergedConfig.output.copy.path, mergedConfig.cwd),
3296
3255
  ignore: (0, _stryke_type_checks_is_set_object.isSetObject)(asset) && asset.ignore ? (0, _stryke_convert_to_array.toArray)(asset.ignore) : void 0
3297
3256
  };
3298
3257
  }), (a) => `${a.input}-${a.glob}-${a.output}`);
3299
- if (!this.config.userConfig?.output?.sourceMap && !this.config.initialConfig?.output?.sourceMap && !this.config.inlineConfig?.output?.sourceMap && !this.config.pluginConfig?.output?.sourceMap) if (this.config.mode === "development") this.config.output.sourceMap = true;
3300
- else this.config.output.sourceMap = false;
3301
- if (!this.config.userConfig?.output?.minify && !this.config.initialConfig?.output?.minify && !this.config.inlineConfig?.output?.minify && !this.config.pluginConfig?.output?.minify) if (this.config.mode === "production") this.config.output.minify = true;
3302
- else this.config.output.minify = false;
3303
- if (!this.config.userConfig?.output?.artifactsPath && !this.config.initialConfig?.output?.artifactsPath && !this.config.inlineConfig?.output?.artifactsPath && !this.config.pluginConfig?.output?.artifactsPath) this.config.output.artifactsPath = `.${this.config.framework || "powerlines"}`;
3304
- if (this.config.output.copy && this.config.output.copy.assets) this.config.output.copy.assets = this.config.output.copy.assets.map((asset) => ({
3258
+ if (!mergedConfig.output?.sourceMap) if (mergedConfig.mode === "development") mergedConfig.output.sourceMap = true;
3259
+ else mergedConfig.output.sourceMap = false;
3260
+ if (!mergedConfig.output.minify) if (mergedConfig.mode === "production") mergedConfig.output.minify = true;
3261
+ else mergedConfig.output.minify = false;
3262
+ if (!mergedConfig.output.artifactsPath) mergedConfig.output.artifactsPath = `.${mergedConfig.framework || "powerlines"}`;
3263
+ if (mergedConfig.output.copy && mergedConfig.output.copy.assets) mergedConfig.output.copy.assets = mergedConfig.output.copy.assets.map((asset) => ({
3305
3264
  ...asset,
3306
3265
  glob: (0, _powerlines_core_plugin_utils.replacePathTokens)(this, asset.glob),
3307
3266
  ignore: asset.ignore ? asset.ignore.map((ignore) => (0, _powerlines_core_plugin_utils.replacePathTokens)(this, ignore)) : void 0,
3308
3267
  input: (0, _powerlines_core_plugin_utils.replacePathTokens)(this, asset.input),
3309
3268
  output: (0, _powerlines_core_plugin_utils.replacePathTokens)(this, asset.output)
3310
3269
  }));
3311
- if ((0, _stryke_type_checks_is_set_string.isSetString)(this.config.output?.storage) && this.config.output.storage === "virtual" || (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.output?.storage) && Object.values(this.config.output.storage).every((adapter) => adapter.preset === "virtual")) this.config.output.overwrite = true;
3270
+ if ((0, _stryke_type_checks_is_set_string.isSetString)(mergedConfig.output?.storage) && mergedConfig.output.storage === "virtual" || (0, _stryke_type_checks_is_set_object.isSetObject)(mergedConfig.output?.storage) && Object.values(mergedConfig.output.storage).every((adapter) => adapter.preset === "virtual")) mergedConfig.output.overwrite = true;
3271
+ this.resolvedConfig = mergedConfig;
3272
+ this.#configProxy = this.createConfigProxy();
3273
+ this.logger.debug({
3274
+ meta: { category: "config" },
3275
+ message: `Resolved Powerlines configuration object: \n --- Resolved Config --- \n${this.logConfig(this.resolvedConfig)} \n --- Initial Config --- \n${this.logConfig(this.initialConfig)} \n --- User Config --- \n${this.logConfig(this.userConfig)} \n --- Inline Config --- \n${this.logConfig(this.inlineConfig)} \n --- Plugin Config --- \n${this.logConfig(this.pluginConfig)}`
3276
+ });
3312
3277
  this.#fs ??= await VirtualFileSystem.create(this);
3313
- if ((0, _stryke_type_checks_is_set_object.isSetObject)(this.config.inlineConfig) && (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.userConfig) && (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.initialConfig) && (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.pluginConfig)) logger.debug(`Resolved Powerlines configuration object: \n${(0, _storm_software_config_tools_logger_console.formatLogMessage)({
3314
- ...(0, _stryke_helpers_omit.omit)(this.config, [
3315
- "inlineConfig",
3316
- "userConfig",
3317
- "initialConfig",
3318
- "pluginConfig",
3319
- "plugins"
3320
- ]),
3321
- inlineConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.inlineConfig) ? (0, _stryke_helpers_omit.omit)(this.config.inlineConfig, ["plugins"]) : void 0,
3322
- userConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.userConfig) ? (0, _stryke_helpers_omit.omit)(this.config.userConfig, ["plugins"]) : void 0,
3323
- initialConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.initialConfig) ? (0, _stryke_helpers_omit.omit)(this.config.initialConfig, ["plugins"]) : void 0,
3324
- pluginConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(this.config.pluginConfig) ? (0, _stryke_helpers_omit.omit)(this.config.pluginConfig, ["plugins"]) : void 0
3325
- })}`);
3278
+ }
3279
+ logConfig(config) {
3280
+ return (0, _storm_software_config_tools_logger_console.formatLogMessage)({
3281
+ ...(0, _stryke_helpers_omit.omit)(config, ["plugins"]),
3282
+ plugins: config.plugins ? config.plugins.flatMap((plugin) => (0, _stryke_convert_to_array.toArray)(plugin)).map((plugin) => String((0, _stryke_type_checks_is_set_string.isSetString)(plugin) ? plugin : (0, _stryke_type_checks_is_promise.isPromise)(plugin) ? "<promise>" : (0, _stryke_type_checks_is_function.isFunction)(plugin) ? plugin.name || "<anonymous function>" : Array.isArray(plugin) ? plugin[0] || "<anonymous function plugin>" : "<unknown plugin>")) : void 0
3283
+ });
3284
+ }
3285
+ createConfigProxy() {
3286
+ return new Proxy(this.resolvedConfig, {
3287
+ /**
3288
+ * A trap for the `delete` operator.
3289
+ * @param target - The original object which is being proxied.
3290
+ * @param key - The name or `Symbol` of the property to delete.
3291
+ * @returns A `boolean` indicating whether or not the property was deleted.
3292
+ */
3293
+ deleteProperty: (target, key) => {
3294
+ if (UNRESOLVED_CONFIG_NAMES.includes(key.toString())) throw new Error(`Cannot delete property ${key.toString()} from config - it is only intended to be used as a reference.`);
3295
+ Reflect.deleteProperty(this.overriddenConfig, key);
3296
+ return Reflect.deleteProperty(target, key);
3297
+ },
3298
+ /**
3299
+ * A trap for getting a property value.
3300
+ * @param target - The original object which is being proxied.
3301
+ * @param key - The name or `Symbol` of the property to get.
3302
+ * @param receiver - The proxy or an object that inherits from the proxy.
3303
+ */
3304
+ get: (target, key, receiver) => {
3305
+ if (UNRESOLVED_CONFIG_NAMES.includes(key.toString())) {
3306
+ if (key === "initialConfig") return this.initialConfig;
3307
+ if (key === "userConfig") return this.userConfig;
3308
+ if (key === "inlineConfig") return this.inlineConfig;
3309
+ if (key === "pluginConfig") return this.pluginConfig;
3310
+ }
3311
+ return Reflect.get(target, key, receiver);
3312
+ },
3313
+ /**
3314
+ * A trap for the `in` operator.
3315
+ * @param target - The original object which is being proxied.
3316
+ * @param key - The name or `Symbol` of the property to check for existence.
3317
+ */
3318
+ has: (target, key) => {
3319
+ return Reflect.has(target, key) || UNRESOLVED_CONFIG_NAMES.includes(key.toString());
3320
+ },
3321
+ /**
3322
+ * A trap for `Reflect.ownKeys()`.
3323
+ * @param target - The original object which is being proxied.
3324
+ */
3325
+ ownKeys: (target) => {
3326
+ return (0, _stryke_helpers_get_unique.getUnique)([...Reflect.ownKeys(target), ...UNRESOLVED_CONFIG_NAMES]);
3327
+ },
3328
+ /**
3329
+ * A trap for setting a property value.
3330
+ * @param target - The original object which is being proxied.
3331
+ * @param key - The name or `Symbol` of the property to set.
3332
+ * @param newValue - The new value to assign to the property.
3333
+ * @param receiver - The object to which the assignment was originally directed.
3334
+ * @returns A `boolean` indicating whether or not the property was set.
3335
+ */
3336
+ set: (target, key, newValue, receiver) => {
3337
+ if (UNRESOLVED_CONFIG_NAMES.includes(key.toString())) throw new Error(`Cannot change property ${key.toString()} from config - it is only intended to be used as a reference.`);
3338
+ Reflect.set(this.overriddenConfig, key, newValue, receiver);
3339
+ return Reflect.set(target, key, newValue, receiver);
3340
+ }
3341
+ });
3326
3342
  }
3327
3343
  };
3328
3344
 
@@ -3467,7 +3483,7 @@ function createPluginContext(pluginId, plugin, environment) {
3467
3483
  return {
3468
3484
  meta: {
3469
3485
  ...(0, _stryke_type_checks_is_set_object.isSetObject)(message) ? message.meta : {},
3470
- environment: environment.environment?.name,
3486
+ environment: environment.config.environment.name,
3471
3487
  plugin: plugin.name
3472
3488
  },
3473
3489
  message: (0, _stryke_type_checks_is_string.isString)(message) ? message : message.message
@@ -3490,6 +3506,8 @@ function createPluginContext(pluginId, plugin, environment) {
3490
3506
  callHook: callHookFn,
3491
3507
  meta
3492
3508
  };
3509
+ if (prop === "api") return environment.$$internal.api;
3510
+ if (prop === "environment") return environment;
3493
3511
  if (prop === "id") return pluginId;
3494
3512
  if (prop === "logger") return logger;
3495
3513
  if (prop === "log") return (type, message) => {
@@ -3542,6 +3560,15 @@ function createPluginContext(pluginId, plugin, environment) {
3542
3560
  //#endregion
3543
3561
  //#region src/context/environment-context.ts
3544
3562
  var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends PowerlinesContext {
3563
+ /**
3564
+ * Internal references storage
3565
+ *
3566
+ * @danger
3567
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3568
+ *
3569
+ * @internal
3570
+ */
3571
+ #internal = {};
3545
3572
  /**
3546
3573
  * The hooks registered by plugins in this environment
3547
3574
  */
@@ -3551,37 +3578,72 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3551
3578
  *
3552
3579
  * @param options - The resolved execution options.
3553
3580
  * @param config - The user configuration options.
3554
- * @returns A promise that resolves to the new context.
3581
+ * @param overriddenConfig - The configuration options that should override all other configuration sources, such as CLI flags or environment variables. This is used to ensure that certain configuration values take precedence over any other settings defined in the user configuration or environment configuration, allowing for dynamic overrides based on the execution context.
3582
+ * @param environment - The resolved environment configuration, which may include additional properties or modifications made during the configuration loading process. This is used to provide context about the environment in which the command is being executed, allowing for environment-specific behavior and configuration resolution.
3583
+ * @returns A promise that resolves to an instance of the PowerlinesEnvironmentContext class, initialized with the provided configuration and environment data.
3555
3584
  */
3556
- static async fromConfig(options, config, environment) {
3557
- const context = new PowerlinesEnvironmentContext(options, config, environment);
3558
- await context.setup();
3559
- const powerlinesPath = await (0, _stryke_fs_resolve.resolvePackage)("powerlines");
3560
- if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
3561
- context.powerlinesPath = powerlinesPath;
3585
+ static async createEnvironment(options, config, overriddenConfig, environment) {
3586
+ const context = new PowerlinesEnvironmentContext(options, config, overriddenConfig);
3587
+ await context.setEnvironmentConfig(environment);
3562
3588
  return context;
3563
3589
  }
3564
3590
  /**
3565
- * The resolved environment configuration
3591
+ * The configuration options provided by plugins added by the user (and other plugins)
3566
3592
  */
3567
- environment;
3593
+ environmentConfig = {};
3568
3594
  /**
3569
3595
  * The list of plugins applied to this environment
3570
3596
  */
3571
3597
  plugins = [];
3572
3598
  /**
3573
- * 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.
3599
+ * Internal context fields and methods
3600
+ *
3601
+ * @danger
3602
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3603
+ *
3604
+ * @internal
3574
3605
  */
3575
- get id() {
3576
- return this.environment.environmentId;
3606
+ get $$internal() {
3607
+ return this.#internal;
3577
3608
  }
3578
3609
  /**
3579
- * The hooks registered by plugins in this environment
3610
+ * Internal context fields and methods
3611
+ *
3612
+ * @danger
3613
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3614
+ *
3615
+ * @internal
3616
+ */
3617
+ set $$internal(value) {
3618
+ this.#internal = value;
3619
+ }
3620
+ /**
3621
+ * 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.
3622
+ */
3623
+ get id() {
3624
+ return this.config.environment.id;
3625
+ }
3626
+ /**
3627
+ * The hooks registered by plugins in this environment
3580
3628
  */
3581
3629
  get hooks() {
3582
3630
  return this.#hooks;
3583
3631
  }
3584
3632
  /**
3633
+ * A setter function to populate the environment config values provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed. This function can be used to update the context with the environment configuration values, which may be used during the configuration resolution process to ensure that the final configuration reflects both the user configuration and any environment configuration provided during execution.
3634
+ *
3635
+ * @param config - The environment configuration values to set.
3636
+ * @returns A promise that resolves when the environment configuration values have been set.
3637
+ */
3638
+ async setEnvironmentConfig(config) {
3639
+ this.logger.debug({
3640
+ meta: { category: "config" },
3641
+ message: `Updating environment configuration object: \n${this.logConfig(config)}`
3642
+ });
3643
+ this.environmentConfig = config;
3644
+ await this.resolveConfig();
3645
+ }
3646
+ /**
3585
3647
  * Create a new logger instance
3586
3648
  *
3587
3649
  * @param options - 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.
@@ -3591,7 +3653,7 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3591
3653
  createLogger(options, logFn) {
3592
3654
  return super.createLogger({
3593
3655
  ...options,
3594
- environment: this.environment?.name
3656
+ environment: this.config.environment?.name
3595
3657
  }, logFn);
3596
3658
  }
3597
3659
  /**
@@ -3603,39 +3665,13 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3603
3665
  extendLogger(options) {
3604
3666
  return super.extendLogger({
3605
3667
  ...options,
3606
- environment: this.environment?.name
3668
+ environment: this.config.environment?.name
3607
3669
  });
3608
3670
  }
3609
- /**
3610
- * 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.
3611
- *
3612
- * @remarks
3613
- * The cloned context will have the same configuration and workspace settings as the original context, but will have a different build ID, release ID, and timestamp. The virtual file system and caches will also be separate between the original and cloned contexts.
3614
- *
3615
- * @returns A promise that resolves to the cloned context.
3616
- */
3617
- async clone() {
3618
- const context = await PowerlinesEnvironmentContext.fromConfig((0, _stryke_helpers_deep_clone.deepClone)(this.options), (0, _stryke_helpers_deep_clone.deepClone)(this.config), (0, _stryke_helpers_deep_clone.deepClone)(this.environment));
3619
- return this.copyTo(context);
3620
- }
3621
- /**
3622
- * Initialize the context with the provided configuration options
3623
- */
3624
- async setup() {
3625
- this.resolvedConfig = (0, _powerlines_core_plugin_utils.mergeConfig)({
3626
- name: this.config.name,
3627
- title: this.config.title
3628
- }, getConfigProps({
3629
- ...this.environment,
3630
- root: this.options.root,
3631
- cwd: this.options.cwd
3632
- }), this.config);
3633
- await this.innerSetup();
3634
- }
3635
3671
  async addPlugin(plugin) {
3636
3672
  let resolvedPlugin = plugin;
3637
3673
  if ((0, _stryke_type_checks_is_function.isFunction)(plugin.applyToEnvironment)) {
3638
- const result = await Promise.resolve(plugin.applyToEnvironment(this.environment));
3674
+ const result = await Promise.resolve(plugin.applyToEnvironment(this.config.environment));
3639
3675
  if (!result || (0, _stryke_type_checks_is_object.isObject)(result) && Object.keys(result).length === 0) return;
3640
3676
  if ((0, _powerlines_core_plugin_utils.isPluginConfig)(result)) return this.$$internal.addPlugin(result);
3641
3677
  resolvedPlugin = (0, _powerlines_core_plugin_utils.isPlugin)(result) ? result : plugin;
@@ -3686,29 +3722,51 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
3686
3722
  }
3687
3723
  return result;
3688
3724
  }
3689
- constructor(options, config, environment) {
3690
- super(options);
3691
- this.resolvedConfig = config;
3692
- this.environment = environment;
3725
+ constructor(options, config, overriddenConfig) {
3726
+ super(options, config.initialConfig);
3727
+ this.userConfig = config.userConfig ?? {};
3728
+ this.inlineConfig = config.inlineConfig ?? {};
3729
+ this.pluginConfig = config.pluginConfig ?? {};
3730
+ this.overriddenConfig = overriddenConfig;
3693
3731
  }
3694
3732
  /**
3695
- * 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.
3733
+ * A function to merge the various configuration objects (initial, user, inline, and plugin) into a single resolved configuration object that can be used throughout the Powerlines process. This function takes into account the different sources of configuration and their respective priorities, ensuring that the final configuration reflects the intended settings for the project. The merged configuration is then returned as a new object that can be accessed through the `config` property of the context.
3696
3734
  *
3697
- * @remarks
3698
- * The cloned context will have the same configuration and workspace settings as the original context, but will have a different build ID, release ID, and timestamp. The virtual file system and caches will also be separate between the original and cloned contexts.
3699
- *
3700
- * @returns The cloned context.
3735
+ * @returns The merged configuration object that combines the initial, user, inline, and plugin configurations.
3701
3736
  */
3702
- copyTo(context) {
3703
- context.plugins = this.plugins;
3704
- return super.copyTo(context);
3737
+ mergeConfig() {
3738
+ return (0, _powerlines_core_plugin_utils.mergeConfig)({
3739
+ ...(0, _stryke_helpers_omit.omit)(this.environmentConfig ?? {}, [
3740
+ "ssr",
3741
+ "preview",
3742
+ "consumer",
3743
+ "runtime"
3744
+ ]),
3745
+ environment: { name: this.environmentConfig?.name || _powerlines_core_constants.DEFAULT_ENVIRONMENT },
3746
+ environmentConfig: this.environmentConfig ?? {}
3747
+ }, super.mergeConfig());
3705
3748
  }
3706
3749
  };
3707
3750
 
3708
3751
  //#endregion
3709
3752
  //#region src/context/execution-context.ts
3710
3753
  var PowerlinesExecutionContext = class PowerlinesExecutionContext extends PowerlinesContext {
3754
+ /**
3755
+ * Internal references storage
3756
+ *
3757
+ * @danger
3758
+ * This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3759
+ *
3760
+ * @internal
3761
+ */
3762
+ #internal = {};
3763
+ /**
3764
+ * A record of all environments by name
3765
+ */
3711
3766
  #environments = {};
3767
+ /**
3768
+ * The plugins added to this execution context, which may be used to track the plugins that have been added to the context and ensure that they are properly registered and executed during the build process. This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
3769
+ */
3712
3770
  #plugins = [];
3713
3771
  /**
3714
3772
  * Create a new Storm context from the workspace root and user config.
@@ -3716,12 +3774,9 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3716
3774
  * @param options - The options for resolving the context.
3717
3775
  * @returns A promise that resolves to the new context.
3718
3776
  */
3719
- static async init(options, initialConfig) {
3720
- const context = new PowerlinesExecutionContext(options);
3721
- await context.init(options, initialConfig);
3722
- const powerlinesPath = await (0, _stryke_fs_resolve.resolvePackage)("powerlines");
3723
- if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
3724
- context.powerlinesPath = powerlinesPath;
3777
+ static async fromInitialConfig(options, initialConfig) {
3778
+ const context = new PowerlinesExecutionContext(options, initialConfig);
3779
+ await context.init();
3725
3780
  return context;
3726
3781
  }
3727
3782
  /**
@@ -3730,19 +3785,10 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3730
3785
  * @param options - The options for resolving the context.
3731
3786
  * @returns A promise that resolves to the new context.
3732
3787
  */
3733
- static async inline(options, initialConfig, inlineConfig) {
3734
- const context = new PowerlinesExecutionContext(options);
3735
- await context.init(options, initialConfig);
3736
- context.config.inlineConfig = inlineConfig;
3737
- if (context.config.inlineConfig.command === "new") {
3738
- const workspacePackageJsonPath = (0, _stryke_path_join.joinPaths)(context.config.cwd, "package.json");
3739
- if (!(0, _stryke_fs_exists.existsSync)(workspacePackageJsonPath)) throw new Error(`The workspace package.json file could not be found at ${workspacePackageJsonPath}`);
3740
- context.packageJson = await (0, _stryke_fs_json.readJsonFile)(workspacePackageJsonPath);
3741
- }
3742
- await context.setup();
3743
- const powerlinesPath = await (0, _stryke_fs_resolve.resolvePackage)("powerlines");
3744
- if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
3745
- context.powerlinesPath = powerlinesPath;
3788
+ static async fromInlineConfig(options, initialConfig, inlineConfig) {
3789
+ const context = new PowerlinesExecutionContext(options, initialConfig);
3790
+ await context.init();
3791
+ await context.setInlineConfig(inlineConfig);
3746
3792
  return context;
3747
3793
  }
3748
3794
  /**
@@ -3754,7 +3800,7 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3754
3800
  * @internal
3755
3801
  */
3756
3802
  get $$internal() {
3757
- return super.$$internal;
3803
+ return this.#internal;
3758
3804
  }
3759
3805
  /**
3760
3806
  * Internal context fields and methods
@@ -3765,8 +3811,8 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3765
3811
  * @internal
3766
3812
  */
3767
3813
  set $$internal(value) {
3768
- super.$$internal = value;
3769
- for (const environment of Object.values(this.environments)) environment.$$internal = super.$$internal;
3814
+ this.#internal = value;
3815
+ for (const environment of Object.values(this.environments)) environment.$$internal = value;
3770
3816
  }
3771
3817
  /**
3772
3818
  * 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.
@@ -3787,9 +3833,26 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3787
3833
  * Creates a new instance.
3788
3834
  *
3789
3835
  * @param options - The options to use for creating the context, including the resolved configuration and workspace settings.
3836
+ * @param initialConfig - The initial configuration options to use for the context, which can be used to provide default values for configuration options that may be overridden by user configuration or inline configuration. This is typically the configuration options provided by the user in a configuration file on disk, and can include any relevant settings such as environment definitions, plugin configurations, and other parameters that may be relevant to the execution of a Powerlines command.
3837
+ */
3838
+ constructor(options, initialConfig = {}) {
3839
+ super(options, initialConfig);
3840
+ this.initialOptions = options;
3841
+ this.initialConfig = initialConfig;
3842
+ }
3843
+ /**
3844
+ * A setter function to populate the inline config values provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed. This function can be used to update the context with the inline configuration values, which may be used during the configuration resolution process to ensure that the final configuration reflects both the user configuration and any inline configuration provided during execution.
3845
+ *
3846
+ * @param config - The inline configuration values to set.
3847
+ * @returns A promise that resolves when the inline configuration values have been set.
3790
3848
  */
3791
- constructor(options) {
3792
- super(options);
3849
+ async setInlineConfig(config) {
3850
+ await super.setInlineConfig(config);
3851
+ if (this.inlineConfig.command === "new") {
3852
+ const workspacePackageJsonPath = (0, _stryke_path_join.joinPaths)(this.config.cwd, "package.json");
3853
+ if (!(0, _stryke_fs_exists.existsSync)(workspacePackageJsonPath)) throw new Error(`The workspace package.json file could not be found at ${workspacePackageJsonPath}`);
3854
+ this.packageJson = await (0, _stryke_fs_json.readJsonFile)(workspacePackageJsonPath);
3855
+ }
3793
3856
  }
3794
3857
  /**
3795
3858
  * Create a new logger instance
@@ -3819,31 +3882,20 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3819
3882
  });
3820
3883
  }
3821
3884
  /**
3822
- * 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.
3823
- *
3824
- * @remarks
3825
- * The cloned context will have the same configuration and workspace settings as the original context, but will have a different build ID, release ID, and timestamp. The virtual file system and caches will also be separate between the original and cloned contexts.
3826
- *
3827
- * @returns A promise that resolves to the cloned context.
3828
- */
3829
- async clone() {
3830
- const clone = await PowerlinesExecutionContext.init(this.options, this.initialConfig);
3831
- clone.config.userConfig = (0, _stryke_helpers_deep_clone.deepClone)(this.config.userConfig);
3832
- clone.config.initialConfig = (0, _stryke_helpers_deep_clone.deepClone)(this.config.initialConfig);
3833
- clone.config.inlineConfig = (0, _stryke_helpers_deep_clone.deepClone)(this.config.inlineConfig);
3834
- clone.config.pluginConfig = (0, _stryke_helpers_deep_clone.deepClone)(this.config.pluginConfig);
3835
- await clone.setup();
3836
- clone.$$internal = this.$$internal;
3837
- return this.copyTo(clone);
3838
- }
3839
- /**
3840
3885
  * A function to copy the context and update the fields for a specific environment
3841
3886
  *
3842
3887
  * @param environment - The environment configuration to use.
3843
3888
  * @returns A new context instance with the updated environment.
3844
3889
  */
3845
- async in(environment) {
3846
- const context = this.copyTo(await PowerlinesEnvironmentContext.fromConfig((0, _stryke_helpers_deep_clone.deepClone)(this.options), (0, _stryke_helpers_deep_clone.deepClone)(this.config), (0, _stryke_helpers_deep_clone.deepClone)(environment)));
3890
+ async createEnvironment(environment) {
3891
+ const context = await PowerlinesEnvironmentContext.createEnvironment((0, _stryke_helpers_deep_clone.deepClone)(this.options), (0, _stryke_helpers_deep_clone.deepClone)(this.config), (0, _stryke_helpers_deep_clone.deepClone)(this.overriddenConfig), (0, _stryke_helpers_deep_clone.deepClone)(environment));
3892
+ context.dependencies = (0, _stryke_helpers_deep_clone.deepClone)(this.dependencies);
3893
+ context.devDependencies = (0, _stryke_helpers_deep_clone.deepClone)(this.devDependencies);
3894
+ context.persistedMeta = (0, _stryke_helpers_deep_clone.deepClone)(this.persistedMeta);
3895
+ context.resolvePatterns = (0, _stryke_helpers_deep_clone.deepClone)(this.resolvePatterns);
3896
+ context.powerlinesPath ??= this.powerlinesPath;
3897
+ context.resolver ??= this.resolver;
3898
+ context.$$internal = this.$$internal;
3847
3899
  context.plugins = [];
3848
3900
  for (const plugin of this.plugins) await context.addPlugin(plugin);
3849
3901
  return context;
@@ -3851,10 +3903,10 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3851
3903
  /**
3852
3904
  * Update the context using a new inline configuration options
3853
3905
  */
3854
- async setup() {
3855
- await super.setup();
3906
+ async resolveConfig() {
3907
+ await super.resolveConfig();
3856
3908
  await Promise.all((0, _stryke_convert_to_array.toArray)(this.config.environments && Object.keys(this.config.environments).length > 0 ? Object.keys(this.config.environments).map((name) => createEnvironment(name, this.config)) : createDefaultEnvironment(this.config)).map(async (env) => {
3857
- this.#environments[env.name] = await this.in(env);
3909
+ this.#environments[env.name] = await this.createEnvironment(env);
3858
3910
  }));
3859
3911
  }
3860
3912
  /**
@@ -3879,12 +3931,20 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3879
3931
  if (name) environment = this.environments[name];
3880
3932
  if (Object.keys(this.environments).length === 1) {
3881
3933
  environment = this.environments[Object.keys(this.environments)[0]];
3882
- this.debug(`Applying the only configured environment: ${chalk.default.bold.cyanBright(environment?.environment.name)}`);
3934
+ this.trace({
3935
+ meta: { category: "plugins" },
3936
+ message: `Applying the only configured environment: ${chalk.default.bold.cyanBright(environment?.config.environment?.name)}`
3937
+ });
3883
3938
  }
3884
3939
  if (!environment) {
3885
3940
  if (name) throw new Error(`Environment "${name}" not found.`);
3886
- environment = await this.in(createDefaultEnvironment(this.config));
3887
- this.warn(`No environment specified, and no default environment found. Using a temporary default environment: ${chalk.default.bold.cyanBright(environment?.environment.name)}`);
3941
+ environment = await PowerlinesEnvironmentContext.createEnvironment((0, _stryke_helpers_deep_clone.deepClone)(this.options), (0, _stryke_helpers_deep_clone.deepClone)(this.config), (0, _stryke_helpers_deep_clone.deepClone)(this.overriddenConfig), (0, _stryke_helpers_deep_clone.deepClone)(createDefaultEnvironment(this.config)));
3942
+ environment.plugins = [];
3943
+ for (const plugin of this.plugins) await environment.addPlugin(plugin);
3944
+ this.warn({
3945
+ meta: { category: "plugins" },
3946
+ message: `No environment specified, and no default environment found. Using a temporary default environment: ${chalk.default.bold.cyanBright(environment.config.environment?.name)}`
3947
+ });
3888
3948
  }
3889
3949
  return environment;
3890
3950
  }
@@ -3912,8 +3972,11 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
3912
3972
  async toEnvironment() {
3913
3973
  let environment;
3914
3974
  if (Object.keys(this.environments).length > 1) {
3915
- environment = await this.in(createEnvironment(_powerlines_core_constants.GLOBAL_ENVIRONMENT, this.config));
3916
- this.debug(`Combined all ${Object.keys(this.environments).length} environments into a single global context.`);
3975
+ environment = await this.createEnvironment(createEnvironment(_powerlines_core_constants.GLOBAL_ENVIRONMENT, this.config));
3976
+ this.debug({
3977
+ meta: { category: "plugins" },
3978
+ message: `Combined all ${Object.keys(this.environments).length} environments into a single global context.`
3979
+ });
3917
3980
  } else environment = await this.getEnvironment();
3918
3981
  return environment;
3919
3982
  }
@@ -4333,11 +4396,11 @@ async function installDependencies(context) {
4333
4396
  //#endregion
4334
4397
  //#region src/_internal/helpers/resolve-tsconfig.ts
4335
4398
  function getTsconfigDtsPath(context) {
4336
- return (0, _stryke_path_join_paths.joinPaths)((0, _stryke_path_file_path_fns.relativePath)((0, _stryke_path_join_paths.joinPaths)(context.options.cwd, context.options.root), (0, _stryke_path_file_path_fns.findFilePath)(context.typesPath)), (0, _stryke_path_file_path_fns.findFileName)(context.typesPath));
4399
+ return (0, _stryke_path_join_paths.joinPaths)((0, _stryke_path_file_path_fns.relativePath)((0, _stryke_path_join_paths.joinPaths)(context.config.cwd, context.config.root), (0, _stryke_path_file_path_fns.findFilePath)(context.typesPath)), (0, _stryke_path_file_path_fns.findFileName)(context.typesPath));
4337
4400
  }
4338
4401
  async function resolveTsconfigChanges(context) {
4339
- const tsconfig = getParsedTypeScriptConfig(context.options.cwd, context.options.root, context.config.tsconfig, context.config.tsconfigRaw);
4340
- const tsconfigJson = await (0, _stryke_fs_json.readJsonFile)(getTsconfigFilePath(context.options.cwd, context.options.root, context.config.tsconfig));
4402
+ const tsconfig = getParsedTypeScriptConfig(context.config.cwd, context.config.root, context.config.tsconfig, context.config.tsconfigRaw);
4403
+ const tsconfigJson = await (0, _stryke_fs_json.readJsonFile)(getTsconfigFilePath(context.config.cwd, context.config.root, context.config.tsconfig));
4341
4404
  tsconfigJson.compilerOptions ??= {};
4342
4405
  if (context.config.output.dts !== false) {
4343
4406
  const dtsRelativePath = getTsconfigDtsPath(context);
@@ -4427,342 +4490,76 @@ var PowerlinesExecution = class PowerlinesExecution {
4427
4490
  * The Powerlines context
4428
4491
  */
4429
4492
  #context;
4430
- async #handleBuild(context) {
4431
- await this.callHook("build", {
4432
- environment: context,
4433
- order: "pre"
4434
- });
4435
- context.debug("Formatting the generated entry files before the build process starts.");
4436
- await (0, _powerlines_core_lib_utilities_format.formatFolder)(context, context.entryPath);
4437
- await this.callHook("build", {
4438
- environment: context,
4439
- order: "normal"
4440
- });
4441
- if (context.config.output.copy) {
4442
- context.debug("Copying project's files from build output directory.");
4443
- const destinationPath = (0, _stryke_path_is_parent_path.isParentPath)((0, _stryke_path_append.appendPath)(context.config.output.path, context.config.cwd), (0, _stryke_path_append.appendPath)(context.config.root, context.config.cwd)) ? (0, _stryke_path_join_paths.joinPaths)(context.config.output.copy.path, (0, _stryke_path_file_path_fns.relativePath)((0, _stryke_path_append.appendPath)(context.config.root, context.config.cwd), (0, _stryke_path_append.appendPath)(context.config.output.path, context.config.cwd))) : (0, _stryke_path_join_paths.joinPaths)(context.config.output.copy.path, "dist");
4444
- const sourcePath = context.config.output.path;
4445
- if ((0, _stryke_fs_exists.existsSync)(sourcePath) && sourcePath !== destinationPath) {
4446
- context.debug(`Copying files from project's build output directory (${context.config.output.path}) to the project's copy/publish directory (${destinationPath}).`);
4447
- await (0, _stryke_fs_copy_file.copyFiles)(sourcePath, destinationPath);
4448
- } else context.warn(`The source path for the copy operation ${!(0, _stryke_fs_exists.existsSync)(sourcePath) ? "does not exist" : "is the same as the destination path"}. Source: ${sourcePath}, Destination: ${destinationPath}. Skipping copying of build output files.`);
4449
- if (context.config.output.copy.assets && Array.isArray(context.config.output.copy.assets)) await Promise.all(context.config.output.copy.assets.map(async (asset) => {
4450
- context.trace(`Copying asset(s): ${chalk.default.redBright(context.config.cwd === asset.input ? asset.glob : (0, _stryke_path_append.appendPath)(asset.glob, (0, _stryke_path_replace.replacePath)(asset.input, context.config.cwd)))} -> ${chalk.default.greenBright((0, _stryke_path_append.appendPath)(asset.glob, (0, _stryke_path_replace.replacePath)(asset.output, context.config.cwd)))} ${Array.isArray(asset.ignore) && asset.ignore.length > 0 ? ` (ignoring: ${asset.ignore.map((i) => chalk.default.yellowBright(i)).join(", ")})` : ""}`);
4451
- await context.fs.copy(asset, asset.output);
4452
- }));
4453
- } else context.debug("No copy configuration found for the project output. Skipping the copying of build output files.");
4454
- await this.callHook("build", {
4455
- environment: context,
4456
- order: "post"
4457
- });
4458
- }
4459
4493
  /**
4460
- * Get the configured environments
4494
+ * Initialize a Powerlines API instance
4461
4495
  *
4462
- * @returns The configured environments
4496
+ * @param options - The options to initialize the API with
4497
+ * @returns A new instance of the Powerlines API
4463
4498
  */
4464
- async #getEnvironments() {
4465
- if (!this.context.config.environments || Object.keys(this.context.config.environments).length <= 1) {
4466
- this.context.debug("No environments are configured for this Powerlines project. Using the default environment.");
4467
- return [await this.context.getEnvironment()];
4468
- }
4469
- this.context.debug(`Found ${Object.keys(this.context.config.environments).length} configured environment(s) for this Powerlines project.`);
4470
- return (await Promise.all(Object.entries(this.context.config.environments).map(async ([name, config]) => {
4471
- if (!await this.context.getEnvironmentSafe(name)) {
4472
- const resolvedEnvironment = await this.callHook("configEnvironment", { environment: name }, name, config);
4473
- if (resolvedEnvironment) this.context.environments[name] = await this.context.in(resolvedEnvironment);
4474
- }
4475
- return this.context.environments[name];
4476
- }))).filter((context) => (0, _stryke_type_checks_is_set.isSet)(context));
4499
+ static async from(options, initialConfig) {
4500
+ const api = new PowerlinesExecution(await PowerlinesExecutionContext.fromInitialConfig(options, initialConfig ?? {}));
4501
+ await api.init();
4502
+ return api;
4477
4503
  }
4478
4504
  /**
4479
- * Execute a handler function for each environment
4480
- *
4481
- * @param handle - The handler function to execute for each environment
4505
+ * The Powerlines context
4482
4506
  */
4483
- async #executeEnvironments(handle) {
4484
- await Promise.all((await this.#getEnvironments()).map(async (context) => {
4485
- return Promise.resolve(handle(context));
4486
- }));
4507
+ get context() {
4508
+ return this.#context;
4487
4509
  }
4488
4510
  /**
4489
- * Initialize a Powerlines plugin
4511
+ * Generate the Powerlines typescript declaration file
4490
4512
  *
4491
- * @param config - The configuration for the plugin
4492
- * @returns The initialized plugin instance, or null if the plugin was a duplicate
4493
- * @throws Will throw an error if the plugin cannot be found or is invalid
4513
+ * @remarks
4514
+ * This method will only generate the typescript declaration file for the Powerlines project. It is generally recommended to run the full `prepare` command, which will run this method as part of its process.
4515
+ *
4516
+ * @param inlineConfig - The inline configuration for the types command
4494
4517
  */
4495
- async #initPlugin(config) {
4496
- let awaited = config;
4497
- if ((0, _stryke_type_checks_is_promise.isPromiseLike)(config)) awaited = await Promise.resolve(config);
4498
- if (!(0, _powerlines_core_plugin_utils.isPluginConfig)(awaited)) {
4499
- const invalid = (0, _powerlines_core_plugin_utils.findInvalidPluginConfig)(awaited);
4500
- throw new Error(`Invalid ${invalid && invalid.length > 1 ? "plugins" : "plugin"} specified in the configuration - ${invalid && invalid.length > 0 ? JSON.stringify(awaited) : invalid?.join("\n\n")} \n\nPlease ensure the value is one of the following: \n - an instance of \`Plugin\` \n - a plugin name \n - an object with the \`plugin\` and \`options\` properties \n - a tuple array with the plugin and options \n - a factory function that returns a plugin or array of plugins \n - an array of plugins or plugin configurations`);
4501
- }
4502
- let plugins;
4503
- if ((0, _powerlines_core_plugin_utils.isPlugin)(awaited)) plugins = [awaited];
4504
- else if ((0, _stryke_type_checks_is_function.isFunction)(awaited)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(awaited()));
4505
- else if ((0, _stryke_type_checks_is_string.isString)(awaited)) {
4506
- const resolved = await this.#resolvePlugin(awaited);
4507
- if ((0, _stryke_type_checks_is_function.isFunction)(resolved)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(resolved()));
4508
- else plugins = (0, _stryke_convert_to_array.toArray)(resolved);
4509
- } else if (Array.isArray(awaited) && awaited.every(_powerlines_core_plugin_utils.isPlugin)) plugins = awaited;
4510
- else if (Array.isArray(awaited) && awaited.every(_powerlines_core_plugin_utils.isPluginConfig)) {
4511
- plugins = [];
4512
- for (const pluginConfig of awaited) {
4513
- const initialized = await this.#initPlugin(pluginConfig);
4514
- if (initialized) plugins.push(...initialized);
4515
- }
4516
- } else if ((0, _powerlines_core_plugin_utils.isPluginConfigTuple)(awaited) || (0, _powerlines_core_plugin_utils.isPluginConfigObject)(awaited)) {
4517
- let pluginConfig;
4518
- let pluginOptions;
4519
- if ((0, _powerlines_core_plugin_utils.isPluginConfigTuple)(awaited)) {
4520
- pluginConfig = awaited[0];
4521
- pluginOptions = awaited?.length === 2 ? awaited[1] : void 0;
4522
- } else {
4523
- pluginConfig = awaited.plugin;
4524
- pluginOptions = awaited.options;
4525
- }
4526
- if ((0, _stryke_type_checks_is_set_string.isSetString)(pluginConfig)) {
4527
- const resolved = await this.#resolvePlugin(pluginConfig);
4528
- if ((0, _stryke_type_checks_is_function.isFunction)(resolved)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(pluginOptions ? resolved(pluginOptions) : resolved()));
4529
- else plugins = (0, _stryke_convert_to_array.toArray)(resolved);
4530
- } else if ((0, _stryke_type_checks_is_function.isFunction)(pluginConfig)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(pluginConfig(pluginOptions)));
4531
- else if (Array.isArray(pluginConfig) && pluginConfig.every(_powerlines_core_plugin_utils.isPlugin)) plugins = pluginConfig;
4532
- else if ((0, _powerlines_core_plugin_utils.isPlugin)(pluginConfig)) plugins = (0, _stryke_convert_to_array.toArray)(pluginConfig);
4533
- }
4534
- if (!plugins) throw new Error(`The plugin configuration ${JSON.stringify(awaited)} is invalid. This configuration must point to a valid Powerlines plugin module.`);
4535
- if (plugins.length > 0 && !plugins.every(_powerlines_core_plugin_utils.isPlugin)) throw new Error(`The plugin option ${JSON.stringify(plugins)} does not export a valid module. This configuration must point to a valid Powerlines plugin module.`);
4536
- const result = [];
4537
- for (const plugin of plugins) if ((0, _powerlines_core_plugin_utils.isDuplicate)(plugin, this.context.plugins)) this.context.trace(`Duplicate ${chalk.default.bold.cyanBright(plugin.name)} plugin dependency detected - Skipping initialization.`);
4538
- else {
4539
- result.push(plugin);
4540
- this.context.trace(`Initializing the ${chalk.default.bold.cyanBright(plugin.name)} plugin...`);
4541
- }
4542
- return result;
4543
- }
4544
- async #resolvePlugin(pluginPath) {
4545
- if (pluginPath.startsWith("@") && pluginPath.split("/").filter(Boolean).length > 2) {
4546
- const splits = pluginPath.split("/").filter(Boolean);
4547
- pluginPath = `${splits[0]}/${splits[1]}`;
4548
- }
4549
- const isInstalled = (0, _stryke_fs_package_fns.isPackageExists)(pluginPath, { paths: [this.context.config.cwd, this.context.config.root] });
4550
- if (!isInstalled && this.context.config.autoInstall) {
4551
- this.#context.warn(`The plugin package "${pluginPath}" is not installed. It will be installed automatically.`);
4552
- const result = await (0, _stryke_fs_install.install)(pluginPath, { cwd: this.context.config.root });
4553
- if ((0, _stryke_type_checks_is_number.isNumber)(result.exitCode) && result.exitCode > 0) {
4554
- this.#context.error(result.stderr);
4555
- throw new Error(`An error occurred while installing the build plugin package "${pluginPath}" `);
4556
- }
4557
- }
4558
- try {
4559
- const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve((0, _stryke_path_join_paths.joinPaths)(pluginPath, "plugin")));
4560
- const result = module.plugin ?? module.default;
4561
- if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
4562
- return result;
4563
- } catch (error) {
4564
- try {
4565
- const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve(pluginPath));
4566
- const result = module.plugin ?? module.default;
4567
- if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
4568
- return result;
4569
- } catch {
4570
- if (!isInstalled) throw new Error(`The plugin package "${pluginPath}" is not installed. Please install the package using the command: "npm install ${pluginPath} --save-dev"`);
4571
- else throw new Error(`An error occurred while importing the build plugin package "${pluginPath}":
4572
- ${(0, _stryke_type_checks_is_error.isError)(error) ? error.message : String(error)}
4573
-
4574
- Note: Please ensure the plugin package's default export is a class that extends \`Plugin\` with a constructor that excepts a single arguments of type \`PluginOptions\`.`);
4518
+ async types(inlineConfig = { command: "types" }) {
4519
+ this.context.debug(" Aggregating configuration options for the Powerlines project");
4520
+ inlineConfig.command ??= "types";
4521
+ await this.context.setInlineConfig(inlineConfig);
4522
+ await this.executeEnvironments(async (context) => {
4523
+ context.debug(`Initializing the processing options for the Powerlines project.`);
4524
+ await this.callHook("configResolved", {
4525
+ environment: context,
4526
+ order: "pre"
4527
+ });
4528
+ await initializeTsconfig(context);
4529
+ await this.callHook("configResolved", {
4530
+ environment: context,
4531
+ order: "normal"
4532
+ });
4533
+ if (context.entry.length > 0) context.debug(`The configuration provided ${(0, _stryke_type_checks_is_object.isObject)(context.config.input) ? Object.keys(context.config.input).length : (0, _stryke_convert_to_array.toArray)(context.config.input).length} entry point(s), Powerlines has found ${context.entry.length} entry files(s) for the ${context.config.title} project${context.entry.length > 0 && context.entry.length < 10 ? `: \n${context.entry.map((entry) => `- ${entry.file}${entry.output ? ` -> ${entry.output}` : ""}`).join(" \n")}` : ""}`);
4534
+ else context.warn(`No entry files were found for the ${context.config.title} project. Please ensure this is correct. Powerlines plugins generally require at least one entry point to function properly.`);
4535
+ await resolveTsconfig(context);
4536
+ await installDependencies(context);
4537
+ await this.callHook("configResolved", {
4538
+ environment: context,
4539
+ order: "post"
4540
+ });
4541
+ context.trace(`Powerlines configuration has been resolved: \n\n${(0, _storm_software_config_tools_logger_console.formatLogMessage)({
4542
+ ...context.config,
4543
+ userConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(context.config.userConfig) ? (0, _stryke_helpers_omit.omit)(context.config.userConfig, ["plugins"]) : void 0,
4544
+ inlineConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(context.config.inlineConfig) ? (0, _stryke_helpers_omit.omit)(context.config.inlineConfig, ["plugins"]) : void 0,
4545
+ plugins: context.plugins.map((plugin) => plugin.plugin.name)
4546
+ })}`);
4547
+ if (!context.fs.existsSync(context.cachePath)) await (0, _stryke_fs_helpers.createDirectory)(context.cachePath);
4548
+ if (!context.fs.existsSync(context.dataPath)) await (0, _stryke_fs_helpers.createDirectory)(context.dataPath);
4549
+ if (context.config.skipCache === true || context.persistedMeta?.checksum !== context.meta.checksum) context.debug(`Using previously prepared files as the meta checksum has not changed.`);
4550
+ else {
4551
+ context.info(`Running \`prepare\` command as the meta checksum has changed since the last run.`);
4552
+ await this.prepare((0, defu.default)({ output: { types: false } }, inlineConfig));
4575
4553
  }
4576
- }
4554
+ await this.handleTypes(context);
4555
+ this.context.debug("Formatting files generated during the types step.");
4556
+ await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, await context.fs.read(context.typesPath) ?? "");
4557
+ await writeMetaFile(context);
4558
+ context.persistedMeta = context.meta;
4559
+ });
4577
4560
  }
4578
4561
  /**
4579
- * Generate the Powerlines TypeScript declaration file
4580
- *
4581
- * @remarks
4582
- * This method will generate the TypeScript declaration file for the Powerlines project, including any types provided by plugins.
4583
- *
4584
- * @param context - The environment context to use for generating the TypeScript declaration file
4585
- * @returns A promise that resolves when the TypeScript declaration file has been generated
4586
- */
4587
- async #types(context) {
4588
- context.debug(`Preparing the TypeScript definitions for the Powerlines project.`);
4589
- if (context.fs.existsSync(context.typesPath)) await context.fs.remove(context.typesPath);
4590
- if (!await (0, _stryke_fs_resolve.resolvePackage)("typescript")) throw new Error("Could not resolve TypeScript package location. Please ensure TypeScript is installed.");
4591
- context.debug("Running TypeScript compiler for built-in runtime module files.");
4592
- let { code, directives } = await emitBuiltinTypes(context, (await context.getBuiltins()).reduce((ret, builtin) => {
4593
- const formatted = (0, _stryke_path_replace.replacePath)(builtin.path, context.config.cwd);
4594
- if (!ret.includes(formatted)) ret.push(formatted);
4595
- return ret;
4596
- }, []));
4597
- context.debug(`Generating TypeScript declaration file ${context.typesPath}.`);
4598
- const merge = async (currentResult, previousResult) => {
4599
- if (!(0, _stryke_type_checks_is_set_string.isSetString)(currentResult) && !(0, _stryke_type_checks_is_set_object.isSetObject)(currentResult) && !(0, _stryke_type_checks_is_set_string.isSetString)(previousResult) && !(0, _stryke_type_checks_is_set_object.isSetObject)(previousResult)) return {
4600
- code,
4601
- directives
4602
- };
4603
- const previous = (await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, (0, _stryke_type_checks_is_set_string.isSetString)(previousResult) ? previousResult : (0, _stryke_type_checks_is_set_object.isSetObject)(previousResult) ? previousResult.code : "")).trim().replace(code, "").trim();
4604
- const current = (await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, (0, _stryke_type_checks_is_set_string.isSetString)(currentResult) ? currentResult : (0, _stryke_type_checks_is_set_object.isSetObject)(currentResult) ? currentResult.code : "")).trim().replace(previous, "").trim().replace(code, "").trim();
4605
- return {
4606
- directives: [...(0, _stryke_type_checks_is_set_object.isSetObject)(currentResult) && currentResult.directives ? currentResult.directives : [], ...(0, _stryke_type_checks_is_set_object.isSetObject)(previousResult) && previousResult.directives ? previousResult.directives : []],
4607
- code: await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, `${!previous.includes((0, _powerlines_core_lib_utilities_file_header.getTypescriptFileHeader)(context)) && !current.includes((0, _powerlines_core_lib_utilities_file_header.getTypescriptFileHeader)(context)) ? `${code}\n` : ""}${previous}\n${current}`.trim())
4608
- };
4609
- };
4610
- const asNextParam = (previousResult) => (0, _stryke_type_checks_is_object.isObject)(previousResult) ? previousResult.code : previousResult;
4611
- let result = await this.callHook("types", {
4612
- environment: context,
4613
- sequential: true,
4614
- order: "pre",
4615
- result: "merge",
4616
- merge,
4617
- asNextParam
4618
- }, code);
4619
- if (result) {
4620
- if ((0, _stryke_type_checks_is_set_object.isSetObject)(result)) {
4621
- code = result.code;
4622
- if (Array.isArray(result.directives) && result.directives.length > 0) directives = (0, _stryke_helpers_get_unique.getUnique)([...directives, ...result.directives]).filter(Boolean);
4623
- } else if ((0, _stryke_type_checks_is_set_string.isSetString)(result)) code = result;
4624
- }
4625
- result = await this.callHook("types", {
4626
- environment: context,
4627
- sequential: true,
4628
- order: "normal",
4629
- result: "merge",
4630
- merge,
4631
- asNextParam
4632
- }, code);
4633
- if (result) {
4634
- if ((0, _stryke_type_checks_is_set_object.isSetObject)(result)) {
4635
- code = result.code;
4636
- if (Array.isArray(result.directives) && result.directives.length > 0) directives = (0, _stryke_helpers_get_unique.getUnique)([...directives, ...result.directives]).filter(Boolean);
4637
- } else if ((0, _stryke_type_checks_is_set_string.isSetString)(result)) code = result;
4638
- }
4639
- result = await this.callHook("types", {
4640
- environment: context,
4641
- sequential: true,
4642
- order: "post",
4643
- result: "merge",
4644
- merge,
4645
- asNextParam
4646
- }, code);
4647
- if (result) {
4648
- if ((0, _stryke_type_checks_is_set_object.isSetObject)(result)) {
4649
- code = result.code;
4650
- if (Array.isArray(result.directives) && result.directives.length > 0) directives = (0, _stryke_helpers_get_unique.getUnique)([...directives, ...result.directives]).filter(Boolean);
4651
- } else if ((0, _stryke_type_checks_is_set_string.isSetString)(result)) code = result;
4652
- }
4653
- if ((0, _stryke_type_checks_is_set_string.isSetString)(code?.trim()) || directives.length > 0) await context.fs.write(context.typesPath, `${directives.length > 0 ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
4654
-
4655
- ` : ""}${(0, _powerlines_core_lib_utilities_file_header.getTypescriptFileHeader)(context, {
4656
- directive: null,
4657
- prettierIgnore: false
4658
- })}
4659
-
4660
- ${formatTypes(code)}
4661
- `);
4662
- }
4663
- /**
4664
- * Initialize a Powerlines API instance
4665
- *
4666
- * @param options - The options to initialize the API with
4667
- * @returns A new instance of the Powerlines API
4668
- */
4669
- static async init(options, initialConfig) {
4670
- const api = new PowerlinesExecution(await PowerlinesExecutionContext.init(options, initialConfig ?? {}));
4671
- api.#context.config.initialConfig = initialConfig ?? {};
4672
- await api.setup();
4673
- return api;
4674
- }
4675
- /**
4676
- * The Powerlines context
4677
- */
4678
- get context() {
4679
- return this.#context;
4680
- }
4681
- /**
4682
- * Initialize the execution API with the provided configuration options
4683
- */
4684
- async setup() {
4685
- await this.#context.setup();
4686
- this.#context.$$internal = {
4687
- api: this,
4688
- addPlugin: this.addPlugin.bind(this)
4689
- };
4690
- const timer = this.#context.timer("Initialization");
4691
- for (const plugin of this.#context.config.plugins.flatMap((p) => (0, _stryke_convert_to_array.toArray)(p)) ?? []) await this.addPlugin(plugin);
4692
- if (this.#context.plugins.length === 0) this.#context.warn({
4693
- meta: { category: "plugins" },
4694
- message: "No Powerlines plugins were specified in the options. Please ensure this is correct, as it is generally not recommended."
4695
- });
4696
- else this.#context.info({
4697
- meta: { category: "plugins" },
4698
- message: `Loaded ${this.#context.plugins.length} ${(0, _stryke_string_format_title_case.titleCase)(this.#context.config.framework)} plugin${this.#context.plugins.length > 1 ? "s" : ""}: \n${this.#context.plugins.map((plugin, index) => ` ${index + 1}. ${(0, _powerlines_core_plugin_utils_logging.colorText)(plugin.name)}`).join("\n")}`
4699
- });
4700
- const pluginConfig = await this.callHook("config", {
4701
- environment: await this.#context.getEnvironment(),
4702
- sequential: true,
4703
- result: "merge",
4704
- merge: mergeConfigs
4705
- });
4706
- if (pluginConfig) {
4707
- this.#context.config.pluginConfig = pluginConfig;
4708
- await this.#context.setup();
4709
- }
4710
- timer();
4711
- }
4712
- /**
4713
- * Generate the Powerlines typescript declaration file
4714
- *
4715
- * @remarks
4716
- * This method will only generate the typescript declaration file for the Powerlines project. It is generally recommended to run the full `prepare` command, which will run this method as part of its process.
4717
- *
4718
- * @param inlineConfig - The inline configuration for the types command
4719
- */
4720
- async types(inlineConfig = { command: "types" }) {
4721
- this.context.debug(" Aggregating configuration options for the Powerlines project");
4722
- inlineConfig.command ??= "types";
4723
- this.context.config.inlineConfig = inlineConfig;
4724
- await this.setup();
4725
- await this.#executeEnvironments(async (context) => {
4726
- context.debug(`Initializing the processing options for the Powerlines project.`);
4727
- await this.callHook("configResolved", {
4728
- environment: context,
4729
- order: "pre"
4730
- });
4731
- await initializeTsconfig(context);
4732
- await this.callHook("configResolved", {
4733
- environment: context,
4734
- order: "normal"
4735
- });
4736
- if (context.entry.length > 0) context.debug(`The configuration provided ${(0, _stryke_type_checks_is_object.isObject)(context.config.input) ? Object.keys(context.config.input).length : (0, _stryke_convert_to_array.toArray)(context.config.input).length} entry point(s), Powerlines has found ${context.entry.length} entry files(s) for the ${context.config.title} project${context.entry.length > 0 && context.entry.length < 10 ? `: \n${context.entry.map((entry) => `- ${entry.file}${entry.output ? ` -> ${entry.output}` : ""}`).join(" \n")}` : ""}`);
4737
- else context.warn(`No entry files were found for the ${context.config.title} project. Please ensure this is correct. Powerlines plugins generally require at least one entry point to function properly.`);
4738
- await resolveTsconfig(context);
4739
- await installDependencies(context);
4740
- await this.callHook("configResolved", {
4741
- environment: context,
4742
- order: "post"
4743
- });
4744
- context.trace(`Powerlines configuration has been resolved: \n\n${(0, _storm_software_config_tools_logger_console.formatLogMessage)({
4745
- ...context.config,
4746
- userConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(context.config.userConfig) ? (0, _stryke_helpers_omit.omit)(context.config.userConfig, ["plugins"]) : void 0,
4747
- inlineConfig: (0, _stryke_type_checks_is_set_object.isSetObject)(context.config.inlineConfig) ? (0, _stryke_helpers_omit.omit)(context.config.inlineConfig, ["plugins"]) : void 0,
4748
- plugins: context.plugins.map((plugin) => plugin.plugin.name)
4749
- })}`);
4750
- if (!context.fs.existsSync(context.cachePath)) await (0, _stryke_fs_helpers.createDirectory)(context.cachePath);
4751
- if (!context.fs.existsSync(context.dataPath)) await (0, _stryke_fs_helpers.createDirectory)(context.dataPath);
4752
- if (context.config.skipCache === true || context.persistedMeta?.checksum !== context.meta.checksum) context.debug(`Using previously prepared files as the meta checksum has not changed.`);
4753
- else {
4754
- context.info(`Running \`prepare\` command as the meta checksum has changed since the last run.`);
4755
- await this.prepare((0, defu.default)({ output: { types: false } }, inlineConfig));
4756
- }
4757
- await this.#types(context);
4758
- this.context.debug("Formatting files generated during the types step.");
4759
- await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, await context.fs.read(context.typesPath) ?? "");
4760
- await writeMetaFile(context);
4761
- context.persistedMeta = context.meta;
4762
- });
4763
- }
4764
- /**
4765
- * Prepare the Powerlines API
4562
+ * Prepare the Powerlines API
4766
4563
  *
4767
4564
  * @remarks
4768
4565
  * This method will prepare the Powerlines API for use, initializing any necessary resources.
@@ -4771,9 +4568,8 @@ ${formatTypes(code)}
4771
4568
  */
4772
4569
  async prepare(inlineConfig = { command: "prepare" }) {
4773
4570
  inlineConfig.command ??= "prepare";
4774
- this.context.config.inlineConfig = inlineConfig;
4775
- await this.setup();
4776
- await this.#executeEnvironments(async (context) => {
4571
+ await this.context.setInlineConfig(inlineConfig);
4572
+ await this.executeEnvironments(async (context) => {
4777
4573
  context.debug(`Initializing the processing options for the Powerlines project.`);
4778
4574
  await this.callHook("configResolved", {
4779
4575
  environment: context,
@@ -4823,7 +4619,7 @@ ${formatTypes(code)}
4823
4619
  environment: context,
4824
4620
  order: "post"
4825
4621
  });
4826
- if (context.config.output.types !== false) await this.#types(context);
4622
+ if (context.config.output.types !== false) await this.handleTypes(context);
4827
4623
  this.context.debug("Formatting files generated during the prepare step.");
4828
4624
  await Promise.all([(0, _powerlines_core_lib_utilities_format.formatFolder)(context, context.builtinsPath), (0, _powerlines_core_lib_utilities_format.formatFolder)(context, context.entryPath)]);
4829
4625
  await writeMetaFile(context);
@@ -4842,7 +4638,7 @@ ${formatTypes(code)}
4842
4638
  async new(inlineConfig) {
4843
4639
  inlineConfig.command ??= "new";
4844
4640
  await this.prepare(inlineConfig);
4845
- await this.#executeEnvironments(async (context) => {
4641
+ await this.executeEnvironments(async (context) => {
4846
4642
  context.debug("Initializing the processing options for the Powerlines project.");
4847
4643
  await this.callHook("new", {
4848
4644
  environment: context,
@@ -4891,7 +4687,7 @@ ${formatTypes(code)}
4891
4687
  async clean(inlineConfig = { command: "clean" }) {
4892
4688
  inlineConfig.command ??= "clean";
4893
4689
  await this.prepare(inlineConfig);
4894
- await this.#executeEnvironments(async (context) => {
4690
+ await this.executeEnvironments(async (context) => {
4895
4691
  context.debug("Cleaning the project's dist and artifacts directories.");
4896
4692
  await context.fs.remove((0, _stryke_path_join_paths.joinPaths)(context.config.cwd, context.config.output.path));
4897
4693
  await context.fs.remove((0, _stryke_path_join_paths.joinPaths)(context.config.cwd, context.config.root, context.config.output.artifactsPath));
@@ -4910,7 +4706,7 @@ ${formatTypes(code)}
4910
4706
  async lint(inlineConfig = { command: "lint" }) {
4911
4707
  inlineConfig.command ??= "lint";
4912
4708
  await this.prepare(inlineConfig);
4913
- await this.#executeEnvironments(async (context) => {
4709
+ await this.executeEnvironments(async (context) => {
4914
4710
  await this.callHook("lint", {
4915
4711
  environment: context,
4916
4712
  sequential: false
@@ -4926,7 +4722,7 @@ ${formatTypes(code)}
4926
4722
  async test(inlineConfig = { command: "test" }) {
4927
4723
  inlineConfig.command ??= "test";
4928
4724
  await this.prepare(inlineConfig);
4929
- await this.#executeEnvironments(async (context) => {
4725
+ await this.executeEnvironments(async (context) => {
4930
4726
  await this.callHook("test", {
4931
4727
  environment: context,
4932
4728
  sequential: false
@@ -4944,17 +4740,15 @@ ${formatTypes(code)}
4944
4740
  */
4945
4741
  async build(inlineConfig = { command: "build" }) {
4946
4742
  inlineConfig.command ??= "build";
4743
+ await this.context.setInlineConfig(inlineConfig);
4947
4744
  await this.context.generateChecksum();
4948
4745
  if (this.context.meta.checksum !== this.context.persistedMeta?.checksum || this.context.config.skipCache) {
4949
4746
  this.context.info(!this.context.persistedMeta?.checksum ? "No previous build cache found. Preparing the project for the initial build." : this.context.meta.checksum !== this.context.persistedMeta.checksum ? "The project has been modified since the last time `prepare` was ran. Re-preparing the project." : "The project is configured to skip cache. Re-preparing the project.");
4950
4747
  await this.prepare(inlineConfig);
4951
- } else {
4952
- this.context.config.inlineConfig = inlineConfig;
4953
- await this.context.setup();
4954
4748
  }
4955
- if (this.context.config.singleBuild) await this.#handleBuild(await this.#context.toEnvironment());
4956
- else await this.#executeEnvironments(async (context) => {
4957
- await this.#handleBuild(context);
4749
+ if (this.context.config.singleBuild) await this.handleBuild(await this.#context.toEnvironment());
4750
+ else await this.executeEnvironments(async (context) => {
4751
+ await this.handleBuild(context);
4958
4752
  });
4959
4753
  }
4960
4754
  /**
@@ -4965,8 +4759,9 @@ ${formatTypes(code)}
4965
4759
  */
4966
4760
  async docs(inlineConfig = { command: "docs" }) {
4967
4761
  inlineConfig.command ??= "docs";
4762
+ await this.context.setInlineConfig(inlineConfig);
4968
4763
  await this.prepare(inlineConfig);
4969
- await this.#executeEnvironments(async (context) => {
4764
+ await this.executeEnvironments(async (context) => {
4970
4765
  context.debug("Writing documentation for the Powerlines project artifacts.");
4971
4766
  await this.callHook("docs", { environment: context });
4972
4767
  });
@@ -4981,8 +4776,9 @@ ${formatTypes(code)}
4981
4776
  */
4982
4777
  async deploy(inlineConfig = { command: "deploy" }) {
4983
4778
  inlineConfig.command ??= "deploy";
4779
+ await this.context.setInlineConfig(inlineConfig);
4984
4780
  await this.prepare(inlineConfig);
4985
- await this.#executeEnvironments(async (context) => {
4781
+ await this.executeEnvironments(async (context) => {
4986
4782
  await this.callHook("deploy", { environment: context });
4987
4783
  });
4988
4784
  }
@@ -4995,7 +4791,7 @@ ${formatTypes(code)}
4995
4791
  * @returns A promise that resolves when the finalization process has completed
4996
4792
  */
4997
4793
  async finalize() {
4998
- await this.#executeEnvironments(async (context) => {
4794
+ await this.executeEnvironments(async (context) => {
4999
4795
  await this.callHook("finalize", { environment: context });
5000
4796
  await context.fs.dispose();
5001
4797
  if ((0, _stryke_fs_exists.existsSync)(context.cachePath) && !(await (0, _stryke_fs_list_files.listFiles)((0, _stryke_path_join_paths.joinPaths)(context.cachePath, "**/*")))?.length) await (0, _stryke_fs_helpers.removeDirectory)(context.cachePath);
@@ -5027,13 +4823,40 @@ ${formatTypes(code)}
5027
4823
  this.#context = context;
5028
4824
  }
5029
4825
  /**
4826
+ * Initialize the execution API with the provided configuration options
4827
+ */
4828
+ async init() {
4829
+ this.#context.$$internal = {
4830
+ api: this,
4831
+ addPlugin: this.addPlugin.bind(this)
4832
+ };
4833
+ const timer = this.#context.timer("Initialization");
4834
+ for (const plugin of this.#context.config.plugins.flatMap((p) => (0, _stryke_convert_to_array.toArray)(p)) ?? []) await this.addPlugin(plugin);
4835
+ if (this.#context.plugins.length === 0) this.#context.warn({
4836
+ meta: { category: "plugins" },
4837
+ message: "No Powerlines plugins were specified in the options. Please ensure this is correct, as it is generally not recommended."
4838
+ });
4839
+ else this.#context.info({
4840
+ meta: { category: "plugins" },
4841
+ message: `Loaded ${this.#context.plugins.length} ${(0, _stryke_string_format_title_case.titleCase)(this.#context.config.framework)} plugin${this.#context.plugins.length > 1 ? "s" : ""}: \n${this.#context.plugins.map((plugin, index) => ` ${index + 1}. ${(0, _powerlines_core_plugin_utils_logging.colorText)(plugin.name)}`).join("\n")}`
4842
+ });
4843
+ const pluginConfig = await this.callHook("config", {
4844
+ environment: await this.#context.getEnvironment(),
4845
+ sequential: true,
4846
+ result: "merge",
4847
+ merge: mergeConfigs
4848
+ });
4849
+ if (pluginConfig) await this.context.setPluginConfig(pluginConfig);
4850
+ timer();
4851
+ }
4852
+ /**
5030
4853
  * Add a Powerlines plugin used in the build process
5031
4854
  *
5032
4855
  * @param config - The import path of the plugin to add
5033
4856
  */
5034
4857
  async addPlugin(config) {
5035
4858
  if (config) {
5036
- const result = await this.#initPlugin(config);
4859
+ const result = await this.initPlugin(config);
5037
4860
  if (!result) return;
5038
4861
  for (const plugin of result) {
5039
4862
  this.context.debug({
@@ -5044,33 +4867,266 @@ ${formatTypes(code)}
5044
4867
  }
5045
4868
  }
5046
4869
  }
4870
+ /**
4871
+ * Get the configured environments
4872
+ *
4873
+ * @returns The configured environments
4874
+ */
4875
+ async getEnvironments() {
4876
+ if (!this.context.config.environments || Object.keys(this.context.config.environments).length <= 1) {
4877
+ this.context.debug("No environments are configured for this Powerlines project. Using the default environment.");
4878
+ return [await this.context.getEnvironment()];
4879
+ }
4880
+ this.context.debug(`Found ${Object.keys(this.context.config.environments).length} configured environment(s) for this Powerlines project.`);
4881
+ return (await Promise.all(Object.entries(this.context.config.environments).map(async ([name, config]) => {
4882
+ if (!await this.context.getEnvironmentSafe(name)) {
4883
+ const resolvedEnvironment = await this.callHook("configEnvironment", { environment: name }, name, config);
4884
+ if (resolvedEnvironment) this.context.environments[name] = await this.context.createEnvironment(resolvedEnvironment);
4885
+ }
4886
+ return this.context.environments[name];
4887
+ }))).filter((context) => (0, _stryke_type_checks_is_set.isSet)(context));
4888
+ }
4889
+ /**
4890
+ * Execute a handler function for each environment
4891
+ *
4892
+ * @param handle - The handler function to execute for each environment
4893
+ */
4894
+ async executeEnvironments(handle) {
4895
+ await Promise.all((await this.getEnvironments()).map(async (context) => {
4896
+ return Promise.resolve(handle(context));
4897
+ }));
4898
+ }
4899
+ /**
4900
+ * Initialize a Powerlines plugin
4901
+ *
4902
+ * @param config - The configuration for the plugin
4903
+ * @returns The initialized plugin instance, or null if the plugin was a duplicate
4904
+ * @throws Will throw an error if the plugin cannot be found or is invalid
4905
+ */
4906
+ async initPlugin(config) {
4907
+ let awaited = config;
4908
+ if ((0, _stryke_type_checks_is_promise.isPromiseLike)(config)) awaited = await Promise.resolve(config);
4909
+ if (!(0, _powerlines_core_plugin_utils.isPluginConfig)(awaited)) {
4910
+ const invalid = (0, _powerlines_core_plugin_utils.findInvalidPluginConfig)(awaited);
4911
+ throw new Error(`Invalid ${invalid && invalid.length > 1 ? "plugins" : "plugin"} specified in the configuration - ${invalid && invalid.length > 0 ? JSON.stringify(awaited) : invalid?.join("\n\n")} \n\nPlease ensure the value is one of the following: \n - an instance of \`Plugin\` \n - a plugin name \n - an object with the \`plugin\` and \`options\` properties \n - a tuple array with the plugin and options \n - a factory function that returns a plugin or array of plugins \n - an array of plugins or plugin configurations`);
4912
+ }
4913
+ let plugins;
4914
+ if ((0, _powerlines_core_plugin_utils.isPlugin)(awaited)) plugins = [awaited];
4915
+ else if ((0, _stryke_type_checks_is_function.isFunction)(awaited)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(awaited()));
4916
+ else if ((0, _stryke_type_checks_is_string.isString)(awaited)) {
4917
+ const resolved = await this.resolvePlugin(awaited);
4918
+ if ((0, _stryke_type_checks_is_function.isFunction)(resolved)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(resolved()));
4919
+ else plugins = (0, _stryke_convert_to_array.toArray)(resolved);
4920
+ } else if (Array.isArray(awaited) && awaited.every(_powerlines_core_plugin_utils.isPlugin)) plugins = awaited;
4921
+ else if (Array.isArray(awaited) && awaited.every(_powerlines_core_plugin_utils.isPluginConfig)) {
4922
+ plugins = [];
4923
+ for (const pluginConfig of awaited) {
4924
+ const initialized = await this.initPlugin(pluginConfig);
4925
+ if (initialized) plugins.push(...initialized);
4926
+ }
4927
+ } else if ((0, _powerlines_core_plugin_utils.isPluginConfigTuple)(awaited) || (0, _powerlines_core_plugin_utils.isPluginConfigObject)(awaited)) {
4928
+ let pluginConfig;
4929
+ let pluginOptions;
4930
+ if ((0, _powerlines_core_plugin_utils.isPluginConfigTuple)(awaited)) {
4931
+ pluginConfig = awaited[0];
4932
+ pluginOptions = awaited?.length === 2 ? awaited[1] : void 0;
4933
+ } else {
4934
+ pluginConfig = awaited.plugin;
4935
+ pluginOptions = awaited.options;
4936
+ }
4937
+ if ((0, _stryke_type_checks_is_set_string.isSetString)(pluginConfig)) {
4938
+ const resolved = await this.resolvePlugin(pluginConfig);
4939
+ if ((0, _stryke_type_checks_is_function.isFunction)(resolved)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(pluginOptions ? resolved(pluginOptions) : resolved()));
4940
+ else plugins = (0, _stryke_convert_to_array.toArray)(resolved);
4941
+ } else if ((0, _stryke_type_checks_is_function.isFunction)(pluginConfig)) plugins = (0, _stryke_convert_to_array.toArray)(await Promise.resolve(pluginConfig(pluginOptions)));
4942
+ else if (Array.isArray(pluginConfig) && pluginConfig.every(_powerlines_core_plugin_utils.isPlugin)) plugins = pluginConfig;
4943
+ else if ((0, _powerlines_core_plugin_utils.isPlugin)(pluginConfig)) plugins = (0, _stryke_convert_to_array.toArray)(pluginConfig);
4944
+ }
4945
+ if (!plugins) throw new Error(`The plugin configuration ${JSON.stringify(awaited)} is invalid. This configuration must point to a valid Powerlines plugin module.`);
4946
+ if (plugins.length > 0 && !plugins.every(_powerlines_core_plugin_utils.isPlugin)) throw new Error(`The plugin option ${JSON.stringify(plugins)} does not export a valid module. This configuration must point to a valid Powerlines plugin module.`);
4947
+ const result = [];
4948
+ for (const plugin of plugins) if ((0, _powerlines_core_plugin_utils.isDuplicate)(plugin, this.context.plugins)) this.context.trace(`Duplicate ${chalk.default.bold.cyanBright(plugin.name)} plugin dependency detected - Skipping initialization.`);
4949
+ else {
4950
+ result.push(plugin);
4951
+ this.context.trace(`Initializing the ${chalk.default.bold.cyanBright(plugin.name)} plugin...`);
4952
+ }
4953
+ return result;
4954
+ }
4955
+ async resolvePlugin(pluginPath) {
4956
+ if (pluginPath.startsWith("@") && pluginPath.split("/").filter(Boolean).length > 2) {
4957
+ const splits = pluginPath.split("/").filter(Boolean);
4958
+ pluginPath = `${splits[0]}/${splits[1]}`;
4959
+ }
4960
+ const isInstalled = (0, _stryke_fs_package_fns.isPackageExists)(pluginPath, { paths: [this.context.config.cwd, this.context.config.root] });
4961
+ if (!isInstalled && this.context.config.autoInstall) {
4962
+ this.#context.warn(`The plugin package "${pluginPath}" is not installed. It will be installed automatically.`);
4963
+ const result = await (0, _stryke_fs_install.install)(pluginPath, { cwd: this.context.config.root });
4964
+ if ((0, _stryke_type_checks_is_number.isNumber)(result.exitCode) && result.exitCode > 0) {
4965
+ this.#context.error(result.stderr);
4966
+ throw new Error(`An error occurred while installing the build plugin package "${pluginPath}" `);
4967
+ }
4968
+ }
4969
+ try {
4970
+ const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve((0, _stryke_path_join_paths.joinPaths)(pluginPath, "plugin")));
4971
+ const result = module.plugin ?? module.default;
4972
+ if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
4973
+ return result;
4974
+ } catch (error) {
4975
+ try {
4976
+ const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve(pluginPath));
4977
+ const result = module.plugin ?? module.default;
4978
+ if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
4979
+ return result;
4980
+ } catch {
4981
+ if (!isInstalled) throw new Error(`The plugin package "${pluginPath}" is not installed. Please install the package using the command: "npm install ${pluginPath} --save-dev"`);
4982
+ else throw new Error(`An error occurred while importing the build plugin package "${pluginPath}":
4983
+ ${(0, _stryke_type_checks_is_error.isError)(error) ? error.message : String(error)}
4984
+
4985
+ Note: Please ensure the plugin package's default export is a class that extends \`Plugin\` with a constructor that excepts a single arguments of type \`PluginOptions\`.`);
4986
+ }
4987
+ }
4988
+ }
4989
+ async handleBuild(context) {
4990
+ await this.callHook("build", {
4991
+ environment: context,
4992
+ order: "pre"
4993
+ });
4994
+ context.debug("Formatting the generated entry files before the build process starts.");
4995
+ await (0, _powerlines_core_lib_utilities_format.formatFolder)(context, context.entryPath);
4996
+ await this.callHook("build", {
4997
+ environment: context,
4998
+ order: "normal"
4999
+ });
5000
+ if (context.config.output.copy) {
5001
+ context.debug("Copying project's files from build output directory.");
5002
+ const destinationPath = (0, _stryke_path_is_parent_path.isParentPath)((0, _stryke_path_append.appendPath)(context.config.output.path, context.config.cwd), (0, _stryke_path_append.appendPath)(context.config.root, context.config.cwd)) ? (0, _stryke_path_join_paths.joinPaths)(context.config.output.copy.path, (0, _stryke_path_file_path_fns.relativePath)((0, _stryke_path_append.appendPath)(context.config.root, context.config.cwd), (0, _stryke_path_append.appendPath)(context.config.output.path, context.config.cwd))) : (0, _stryke_path_join_paths.joinPaths)(context.config.output.copy.path, "dist");
5003
+ const sourcePath = context.config.output.path;
5004
+ if ((0, _stryke_fs_exists.existsSync)(sourcePath) && sourcePath !== destinationPath) {
5005
+ context.debug(`Copying files from project's build output directory (${context.config.output.path}) to the project's copy/publish directory (${destinationPath}).`);
5006
+ await (0, _stryke_fs_copy_file.copyFiles)(sourcePath, destinationPath);
5007
+ } else context.warn(`The source path for the copy operation ${!(0, _stryke_fs_exists.existsSync)(sourcePath) ? "does not exist" : "is the same as the destination path"}. Source: ${sourcePath}, Destination: ${destinationPath}. Skipping copying of build output files.`);
5008
+ if (context.config.output.copy.assets && Array.isArray(context.config.output.copy.assets)) await Promise.all(context.config.output.copy.assets.map(async (asset) => {
5009
+ context.trace(`Copying asset(s): ${chalk.default.redBright(context.config.cwd === asset.input ? asset.glob : (0, _stryke_path_append.appendPath)(asset.glob, (0, _stryke_path_replace.replacePath)(asset.input, context.config.cwd)))} -> ${chalk.default.greenBright((0, _stryke_path_append.appendPath)(asset.glob, (0, _stryke_path_replace.replacePath)(asset.output, context.config.cwd)))} ${Array.isArray(asset.ignore) && asset.ignore.length > 0 ? ` (ignoring: ${asset.ignore.map((i) => chalk.default.yellowBright(i)).join(", ")})` : ""}`);
5010
+ await context.fs.copy(asset, asset.output);
5011
+ }));
5012
+ } else context.debug("No copy configuration found for the project output. Skipping the copying of build output files.");
5013
+ await this.callHook("build", {
5014
+ environment: context,
5015
+ order: "post"
5016
+ });
5017
+ }
5018
+ /**
5019
+ * Generate the Powerlines TypeScript declaration file
5020
+ *
5021
+ * @remarks
5022
+ * This method will generate the TypeScript declaration file for the Powerlines project, including any types provided by plugins.
5023
+ *
5024
+ * @param context - The environment context to use for generating the TypeScript declaration file
5025
+ * @returns A promise that resolves when the TypeScript declaration file has been generated
5026
+ */
5027
+ async handleTypes(context) {
5028
+ context.debug(`Preparing the TypeScript definitions for the Powerlines project.`);
5029
+ if (context.fs.existsSync(context.typesPath)) await context.fs.remove(context.typesPath);
5030
+ if (!await (0, _stryke_fs_resolve.resolvePackage)("typescript")) throw new Error("Could not resolve TypeScript package location. Please ensure TypeScript is installed.");
5031
+ context.debug("Running TypeScript compiler for built-in runtime module files.");
5032
+ let { code, directives } = await emitBuiltinTypes(context, (await context.getBuiltins()).reduce((ret, builtin) => {
5033
+ const formatted = (0, _stryke_path_replace.replacePath)(builtin.path, context.config.cwd);
5034
+ if (!ret.includes(formatted)) ret.push(formatted);
5035
+ return ret;
5036
+ }, []));
5037
+ context.debug(`Generating TypeScript declaration file ${context.typesPath}.`);
5038
+ const merge = async (currentResult, previousResult) => {
5039
+ if (!(0, _stryke_type_checks_is_set_string.isSetString)(currentResult) && !(0, _stryke_type_checks_is_set_object.isSetObject)(currentResult) && !(0, _stryke_type_checks_is_set_string.isSetString)(previousResult) && !(0, _stryke_type_checks_is_set_object.isSetObject)(previousResult)) return {
5040
+ code,
5041
+ directives
5042
+ };
5043
+ const previous = (await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, (0, _stryke_type_checks_is_set_string.isSetString)(previousResult) ? previousResult : (0, _stryke_type_checks_is_set_object.isSetObject)(previousResult) ? previousResult.code : "")).trim().replace(code, "").trim();
5044
+ const current = (await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, (0, _stryke_type_checks_is_set_string.isSetString)(currentResult) ? currentResult : (0, _stryke_type_checks_is_set_object.isSetObject)(currentResult) ? currentResult.code : "")).trim().replace(previous, "").trim().replace(code, "").trim();
5045
+ return {
5046
+ directives: [...(0, _stryke_type_checks_is_set_object.isSetObject)(currentResult) && currentResult.directives ? currentResult.directives : [], ...(0, _stryke_type_checks_is_set_object.isSetObject)(previousResult) && previousResult.directives ? previousResult.directives : []],
5047
+ code: await (0, _powerlines_core_lib_utilities_format.format)(context, context.typesPath, `${!previous.includes((0, _powerlines_core_lib_utilities_file_header.getTypescriptFileHeader)(context)) && !current.includes((0, _powerlines_core_lib_utilities_file_header.getTypescriptFileHeader)(context)) ? `${code}\n` : ""}${previous}\n${current}`.trim())
5048
+ };
5049
+ };
5050
+ const asNextParam = (previousResult) => (0, _stryke_type_checks_is_object.isObject)(previousResult) ? previousResult.code : previousResult;
5051
+ let result = await this.callHook("types", {
5052
+ environment: context,
5053
+ sequential: true,
5054
+ order: "pre",
5055
+ result: "merge",
5056
+ merge,
5057
+ asNextParam
5058
+ }, code);
5059
+ if (result) {
5060
+ if ((0, _stryke_type_checks_is_set_object.isSetObject)(result)) {
5061
+ code = result.code;
5062
+ if (Array.isArray(result.directives) && result.directives.length > 0) directives = (0, _stryke_helpers_get_unique.getUnique)([...directives, ...result.directives]).filter(Boolean);
5063
+ } else if ((0, _stryke_type_checks_is_set_string.isSetString)(result)) code = result;
5064
+ }
5065
+ result = await this.callHook("types", {
5066
+ environment: context,
5067
+ sequential: true,
5068
+ order: "normal",
5069
+ result: "merge",
5070
+ merge,
5071
+ asNextParam
5072
+ }, code);
5073
+ if (result) {
5074
+ if ((0, _stryke_type_checks_is_set_object.isSetObject)(result)) {
5075
+ code = result.code;
5076
+ if (Array.isArray(result.directives) && result.directives.length > 0) directives = (0, _stryke_helpers_get_unique.getUnique)([...directives, ...result.directives]).filter(Boolean);
5077
+ } else if ((0, _stryke_type_checks_is_set_string.isSetString)(result)) code = result;
5078
+ }
5079
+ result = await this.callHook("types", {
5080
+ environment: context,
5081
+ sequential: true,
5082
+ order: "post",
5083
+ result: "merge",
5084
+ merge,
5085
+ asNextParam
5086
+ }, code);
5087
+ if (result) {
5088
+ if ((0, _stryke_type_checks_is_set_object.isSetObject)(result)) {
5089
+ code = result.code;
5090
+ if (Array.isArray(result.directives) && result.directives.length > 0) directives = (0, _stryke_helpers_get_unique.getUnique)([...directives, ...result.directives]).filter(Boolean);
5091
+ } else if ((0, _stryke_type_checks_is_set_string.isSetString)(result)) code = result;
5092
+ }
5093
+ if ((0, _stryke_type_checks_is_set_string.isSetString)(code?.trim()) || directives.length > 0) await context.fs.write(context.typesPath, `${directives.length > 0 ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
5094
+
5095
+ ` : ""}${(0, _powerlines_core_lib_utilities_file_header.getTypescriptFileHeader)(context, {
5096
+ directive: null,
5097
+ prettierIgnore: false
5098
+ })}
5099
+
5100
+ ${formatTypes(code)}
5101
+ `);
5102
+ }
5047
5103
  };
5048
5104
 
5049
5105
  //#endregion
5050
5106
  //#region src/_internal/worker.ts
5051
5107
  async function clean({ options, initialConfig, inlineConfig }) {
5052
- await (await PowerlinesExecution.init(options, initialConfig)).clean(inlineConfig);
5108
+ await (await PowerlinesExecution.from(options, initialConfig)).clean(inlineConfig);
5053
5109
  }
5054
5110
  async function prepare({ options, initialConfig, inlineConfig }) {
5055
- await (await PowerlinesExecution.init(options, initialConfig)).prepare(inlineConfig);
5111
+ await (await PowerlinesExecution.from(options, initialConfig)).prepare(inlineConfig);
5056
5112
  }
5057
5113
  async function types({ options, initialConfig, inlineConfig }) {
5058
- await (await PowerlinesExecution.init(options, initialConfig)).types(inlineConfig);
5114
+ await (await PowerlinesExecution.from(options, initialConfig)).types(inlineConfig);
5059
5115
  }
5060
5116
  async function lint({ options, initialConfig, inlineConfig }) {
5061
- await (await PowerlinesExecution.init(options, initialConfig)).lint(inlineConfig);
5117
+ await (await PowerlinesExecution.from(options, initialConfig)).lint(inlineConfig);
5062
5118
  }
5063
5119
  async function test({ options, initialConfig, inlineConfig }) {
5064
- await (await PowerlinesExecution.init(options, initialConfig)).test(inlineConfig);
5120
+ await (await PowerlinesExecution.from(options, initialConfig)).test(inlineConfig);
5065
5121
  }
5066
5122
  async function build({ options, initialConfig, inlineConfig }) {
5067
- await (await PowerlinesExecution.init(options, initialConfig)).build(inlineConfig);
5123
+ await (await PowerlinesExecution.from(options, initialConfig)).build(inlineConfig);
5068
5124
  }
5069
5125
  async function docs({ options, initialConfig, inlineConfig }) {
5070
- await (await PowerlinesExecution.init(options, initialConfig)).docs(inlineConfig);
5126
+ await (await PowerlinesExecution.from(options, initialConfig)).docs(inlineConfig);
5071
5127
  }
5072
5128
  async function deploy({ options, initialConfig, inlineConfig }) {
5073
- await (await PowerlinesExecution.init(options, initialConfig)).deploy(inlineConfig);
5129
+ await (await PowerlinesExecution.from(options, initialConfig)).deploy(inlineConfig);
5074
5130
  }
5075
5131
 
5076
5132
  //#endregion