@powerlines/engine 0.45.3 → 0.46.1
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.
- package/dist/_internal/worker.cjs +886 -803
- package/dist/_internal/worker.mjs +889 -806
- package/dist/_internal/worker.mjs.map +1 -1
- package/dist/api.cjs +292 -323
- package/dist/api.d.cts +44 -11
- package/dist/api.d.cts.map +1 -1
- package/dist/api.d.mts +44 -11
- package/dist/api.d.mts.map +1 -1
- package/dist/api.mjs +292 -323
- package/dist/api.mjs.map +1 -1
- package/dist/{base-context-Byizvf4F.cjs → base-context-D7G_24-i.cjs} +82 -76
- package/dist/{base-context-BSAC5sO9.mjs → base-context-DU0NRHDt.mjs} +85 -79
- package/dist/base-context-DU0NRHDt.mjs.map +1 -0
- package/dist/context/index.cjs +3 -3
- package/dist/context/index.d.cts +44 -617
- package/dist/context/index.d.cts.map +1 -1
- package/dist/context/index.d.mts +44 -617
- package/dist/context/index.d.mts.map +1 -1
- package/dist/context/index.mjs +3 -3
- package/dist/engine-context-BuJQY312.cjs +91 -0
- package/dist/engine-context-BvDfqfY7.mjs +86 -0
- package/dist/engine-context-BvDfqfY7.mjs.map +1 -0
- package/dist/execution-context-BpRfsnkE.d.mts +644 -0
- package/dist/execution-context-BpRfsnkE.d.mts.map +1 -0
- package/dist/{execution-context-BYGFYty0.cjs → execution-context-BrX9i_L8.cjs} +449 -364
- package/dist/{execution-context-Bkxp1fML.mjs → execution-context-CgDuoi8o.mjs} +451 -366
- package/dist/execution-context-CgDuoi8o.mjs.map +1 -0
- package/dist/execution-context-CodQucFX.d.cts +644 -0
- package/dist/execution-context-CodQucFX.d.cts.map +1 -0
- package/dist/index.cjs +15 -16
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +15 -16
- package/dist/index.mjs.map +1 -1
- package/dist/{tsconfig-QMSxSwBD.cjs → tsconfig-BUDqmOaT.cjs} +13 -13
- package/dist/{tsconfig-CI6bla4E.mjs → tsconfig-MeFEs21S.mjs} +14 -14
- package/dist/tsconfig-MeFEs21S.mjs.map +1 -0
- package/dist/typescript/index.cjs +1 -1
- package/dist/typescript/index.d.cts +6 -6
- package/dist/typescript/index.d.cts.map +1 -1
- package/dist/typescript/index.d.mts +6 -6
- package/dist/typescript/index.d.mts.map +1 -1
- package/dist/typescript/index.mjs +1 -1
- package/package.json +17 -17
- package/dist/base-context-BSAC5sO9.mjs.map +0 -1
- package/dist/engine-context-CI_0NWIk.cjs +0 -73
- package/dist/engine-context-_RMFwG4J.mjs +0 -68
- package/dist/engine-context-_RMFwG4J.mjs.map +0 -1
- package/dist/execution-context-Bkxp1fML.mjs.map +0 -1
- package/dist/tsconfig-CI6bla4E.mjs.map +0 -1
|
@@ -24,7 +24,7 @@ import { isError } from "@stryke/type-checks/is-error";
|
|
|
24
24
|
import { isFunction } from "@stryke/type-checks/is-function";
|
|
25
25
|
import { isNumber } from "@stryke/type-checks/is-number";
|
|
26
26
|
import { isObject } from "@stryke/type-checks/is-object";
|
|
27
|
-
import { isPromiseLike } from "@stryke/type-checks/is-promise";
|
|
27
|
+
import { isPromise, isPromiseLike } from "@stryke/type-checks/is-promise";
|
|
28
28
|
import { isSet } from "@stryke/type-checks/is-set";
|
|
29
29
|
import { isSetObject } from "@stryke/type-checks/is-set-object";
|
|
30
30
|
import { isSetString } from "@stryke/type-checks/is-set-string";
|
|
@@ -38,21 +38,21 @@ import { deepClone } from "@stryke/helpers/deep-clone";
|
|
|
38
38
|
import { joinPaths as joinPaths$1 } from "@stryke/path/join";
|
|
39
39
|
import { uuid } from "@stryke/unique-id/uuid";
|
|
40
40
|
import { getUniqueInputs, isTypeDefinition, resolveInputsSync } from "@powerlines/core/lib/entry";
|
|
41
|
-
import { toBool } from "@stryke/convert/to-bool";
|
|
42
41
|
import { getEnvPaths } from "@stryke/env/get-env-paths";
|
|
43
42
|
import { relativeToWorkspaceRoot } from "@stryke/fs/get-workspace-root";
|
|
44
43
|
import { murmurhash } from "@stryke/hash";
|
|
45
44
|
import { hashDirectory } from "@stryke/hash/node";
|
|
46
45
|
import { fetchRequest } from "@stryke/http/fetch";
|
|
47
46
|
import { isEqual } from "@stryke/path/is-equal";
|
|
48
|
-
import { kebabCase } from "@stryke/string-format/kebab-case";
|
|
49
47
|
import { match, tsconfigPathsToRegExp } from "bundle-require";
|
|
50
48
|
import { resolveCompatibilityDates } from "compatx";
|
|
51
49
|
import { create } from "flat-cache";
|
|
52
50
|
import { parse } from "oxc-parser";
|
|
53
51
|
import { Agent, Response, interceptors, setGlobalDispatcher } from "undici";
|
|
54
52
|
import "@stryke/fs/remove-file";
|
|
53
|
+
import { kebabCase } from "@stryke/string-format/kebab-case";
|
|
55
54
|
import { LogCategories } from "@powerlines/core";
|
|
55
|
+
import { messageParent } from "jest-worker";
|
|
56
56
|
import * as $ from "@stryke/capnp";
|
|
57
57
|
import { readFileBuffer, readFileBufferSync, writeFileBuffer } from "@stryke/fs/buffer";
|
|
58
58
|
import { correctPath, stripStars } from "@stryke/path/correct-path";
|
|
@@ -73,8 +73,8 @@ import ts from "typescript";
|
|
|
73
73
|
import { loadUserConfigFile } from "@powerlines/core/lib/config";
|
|
74
74
|
import { tryGetWorkspaceConfig } from "@storm-software/config-tools/get-config";
|
|
75
75
|
import { isDevelopment, isProduction, isTest } from "@stryke/env/environment-checks";
|
|
76
|
-
import { readJsonFile as readJsonFile$1 } from "@stryke/fs";
|
|
77
|
-
import { joinPaths as joinPaths$2 } from "@stryke/path";
|
|
76
|
+
import { isFile as isFile$1, readJsonFile as readJsonFile$1 } from "@stryke/fs";
|
|
77
|
+
import { findFilePath as findFilePath$1, joinPaths as joinPaths$2, relativePath as relativePath$1 } from "@stryke/path";
|
|
78
78
|
import { formatDistanceToNowStrict } from "date-fns/formatDistanceToNowStrict";
|
|
79
79
|
import { createJiti } from "jiti";
|
|
80
80
|
import { getField } from "@stryke/helpers/get-field";
|
|
@@ -84,9 +84,9 @@ import { getObjectDiff } from "@donedeal0/superdiff";
|
|
|
84
84
|
import { StormJSON } from "@stryke/json/storm-json";
|
|
85
85
|
|
|
86
86
|
//#region src/_internal/helpers/environment.ts
|
|
87
|
-
function createEnvironment(name, config
|
|
87
|
+
function createEnvironment(name, config) {
|
|
88
88
|
return defu(config.environments?.[name] ?? {}, {
|
|
89
|
-
|
|
89
|
+
id: uuid(),
|
|
90
90
|
name,
|
|
91
91
|
title: config.title ?? titleCase(config.name),
|
|
92
92
|
ssr: false,
|
|
@@ -112,7 +112,7 @@ function createEnvironment(name, config = {}) {
|
|
|
112
112
|
} : void 0
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
-
function createDefaultEnvironment(config
|
|
115
|
+
function createDefaultEnvironment(config) {
|
|
116
116
|
return createEnvironment(DEFAULT_ENVIRONMENT, config);
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -169,16 +169,16 @@ async function writeMetaFile(context) {
|
|
|
169
169
|
|
|
170
170
|
//#endregion
|
|
171
171
|
//#region src/_internal/ipc/send.ts
|
|
172
|
-
function
|
|
172
|
+
function formatWriteLogMessage(context, meta, message) {
|
|
173
173
|
const combinedMeta = {
|
|
174
174
|
...context.logger.options,
|
|
175
175
|
...isSetObject(meta) ? meta : { type: meta }
|
|
176
176
|
};
|
|
177
|
-
|
|
177
|
+
return {
|
|
178
178
|
id: uuid(),
|
|
179
179
|
type: "write-log",
|
|
180
|
-
executionId: combinedMeta.executionId || context.
|
|
181
|
-
executionIndex: combinedMeta.executionIndex ?? context.
|
|
180
|
+
executionId: combinedMeta.executionId || context.options.executionId,
|
|
181
|
+
executionIndex: combinedMeta.executionIndex ?? context.options.executionIndex,
|
|
182
182
|
environment: combinedMeta.environment,
|
|
183
183
|
timestamp: Date.now(),
|
|
184
184
|
payload: {
|
|
@@ -188,8 +188,8 @@ function sendWriteLogMessage(context, meta, message) {
|
|
|
188
188
|
logId: combinedMeta.logId || uuid(),
|
|
189
189
|
timestamp: combinedMeta.timestamp ?? Date.now(),
|
|
190
190
|
name: combinedMeta.name || context.config.name,
|
|
191
|
-
executionId: combinedMeta.executionId || context.
|
|
192
|
-
executionIndex: combinedMeta.executionIndex ?? context.
|
|
191
|
+
executionId: combinedMeta.executionId || context.options.executionId,
|
|
192
|
+
executionIndex: combinedMeta.executionIndex ?? context.options.executionIndex,
|
|
193
193
|
command: combinedMeta.command || context.config.command,
|
|
194
194
|
hook: combinedMeta.hook,
|
|
195
195
|
environment: combinedMeta.environment,
|
|
@@ -198,7 +198,21 @@ function sendWriteLogMessage(context, meta, message) {
|
|
|
198
198
|
},
|
|
199
199
|
message
|
|
200
200
|
}
|
|
201
|
-
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function childProcessSend(message) {
|
|
204
|
+
process.send?.(message);
|
|
205
|
+
}
|
|
206
|
+
function workerThreadSend(message) {
|
|
207
|
+
messageParent(message);
|
|
208
|
+
}
|
|
209
|
+
function send(message) {
|
|
210
|
+
if (process.env.POWERLINES_EXECUTION_THREAD_TYPE === "child-process") childProcessSend(message);
|
|
211
|
+
else if (process.env.POWERLINES_EXECUTION_THREAD_TYPE === "worker-thread") workerThreadSend(message);
|
|
212
|
+
else console.warn("No IPC mechanism available to send message:", message);
|
|
213
|
+
}
|
|
214
|
+
function sendWriteLogMessage(context, meta, message) {
|
|
215
|
+
send(formatWriteLogMessage(context, meta, message));
|
|
202
216
|
}
|
|
203
217
|
|
|
204
218
|
//#endregion
|
|
@@ -1996,40 +2010,40 @@ var VirtualFileSystem = class VirtualFileSystem {
|
|
|
1996
2010
|
/**
|
|
1997
2011
|
* Get the path to the tsconfig.json file.
|
|
1998
2012
|
*
|
|
1999
|
-
* @param
|
|
2000
|
-
* @param
|
|
2013
|
+
* @param cwd - The root directory of the workspace.
|
|
2014
|
+
* @param root - The root directory of the project.
|
|
2001
2015
|
* @param tsconfig - The path to the tsconfig.json file.
|
|
2002
2016
|
* @returns The absolute path to the tsconfig.json file.
|
|
2003
2017
|
* @throws If the tsconfig.json file does not exist.
|
|
2004
2018
|
*/
|
|
2005
|
-
function getTsconfigFilePath(
|
|
2019
|
+
function getTsconfigFilePath(cwd, root, tsconfig) {
|
|
2006
2020
|
let tsconfigFilePath;
|
|
2007
|
-
if (tsconfig) tsconfigFilePath = tryTsconfigFilePath(
|
|
2021
|
+
if (tsconfig) tsconfigFilePath = tryTsconfigFilePath(cwd, root, tsconfig);
|
|
2008
2022
|
else {
|
|
2009
|
-
tsconfigFilePath = tryTsconfigFilePath(
|
|
2023
|
+
tsconfigFilePath = tryTsconfigFilePath(cwd, root, "tsconfig.app.json");
|
|
2010
2024
|
if (!tsconfigFilePath) {
|
|
2011
|
-
tsconfigFilePath = tryTsconfigFilePath(
|
|
2012
|
-
if (!tsconfigFilePath) tsconfigFilePath = tryTsconfigFilePath(
|
|
2025
|
+
tsconfigFilePath = tryTsconfigFilePath(cwd, root, "tsconfig.lib.json");
|
|
2026
|
+
if (!tsconfigFilePath) tsconfigFilePath = tryTsconfigFilePath(cwd, root, "tsconfig.json");
|
|
2013
2027
|
}
|
|
2014
2028
|
}
|
|
2015
|
-
if (!tsconfigFilePath) throw new Error(`Cannot find the \`tsconfig.json\` configuration file for the project at ${
|
|
2029
|
+
if (!tsconfigFilePath) throw new Error(`Cannot find the \`tsconfig.json\` configuration file for the project at ${root}.`);
|
|
2016
2030
|
return tsconfigFilePath;
|
|
2017
2031
|
}
|
|
2018
2032
|
/**
|
|
2019
2033
|
* Get the path to the tsconfig.json file.
|
|
2020
2034
|
*
|
|
2021
|
-
* @param
|
|
2022
|
-
* @param
|
|
2035
|
+
* @param cwd - The root directory of the workspace.
|
|
2036
|
+
* @param root - The root directory of the project.
|
|
2023
2037
|
* @param tsconfig - The path to the tsconfig.json file.
|
|
2024
2038
|
* @returns The absolute path to the tsconfig.json file.
|
|
2025
2039
|
* @throws If the tsconfig.json file does not exist.
|
|
2026
2040
|
*/
|
|
2027
|
-
function tryTsconfigFilePath(
|
|
2041
|
+
function tryTsconfigFilePath(cwd, root, tsconfig) {
|
|
2028
2042
|
let tsconfigFilePath = tsconfig;
|
|
2029
2043
|
if (!existsSync(tsconfigFilePath)) {
|
|
2030
|
-
tsconfigFilePath = appendPath(tsconfig,
|
|
2044
|
+
tsconfigFilePath = appendPath(tsconfig, root);
|
|
2031
2045
|
if (!existsSync(tsconfigFilePath)) {
|
|
2032
|
-
tsconfigFilePath = appendPath(tsconfig, appendPath(
|
|
2046
|
+
tsconfigFilePath = appendPath(tsconfig, appendPath(root, cwd));
|
|
2033
2047
|
if (!existsSync(tsconfigFilePath)) return;
|
|
2034
2048
|
}
|
|
2035
2049
|
}
|
|
@@ -2156,7 +2170,7 @@ function createResolver(options) {
|
|
|
2156
2170
|
|
|
2157
2171
|
//#endregion
|
|
2158
2172
|
//#region src/context/base-context.ts
|
|
2159
|
-
var PowerlinesBaseContext = class
|
|
2173
|
+
var PowerlinesBaseContext = class {
|
|
2160
2174
|
#timestamp = Date.now();
|
|
2161
2175
|
/**
|
|
2162
2176
|
* The path to the Powerlines package
|
|
@@ -2167,17 +2181,17 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
|
|
|
2167
2181
|
*/
|
|
2168
2182
|
resolver;
|
|
2169
2183
|
/**
|
|
2170
|
-
* The options provided to the Powerlines process
|
|
2184
|
+
* 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.
|
|
2171
2185
|
*/
|
|
2172
2186
|
options;
|
|
2173
2187
|
/**
|
|
2174
|
-
* The
|
|
2188
|
+
* The parsed `package.json` file for the project
|
|
2175
2189
|
*/
|
|
2176
|
-
|
|
2190
|
+
packageJson;
|
|
2177
2191
|
/**
|
|
2178
|
-
* The
|
|
2192
|
+
* The parsed `project.json` file for the project
|
|
2179
2193
|
*/
|
|
2180
|
-
|
|
2194
|
+
projectJson = void 0;
|
|
2181
2195
|
/**
|
|
2182
2196
|
* The parsed configuration file for the project
|
|
2183
2197
|
*/
|
|
@@ -2208,19 +2222,6 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
|
|
|
2208
2222
|
});
|
|
2209
2223
|
}
|
|
2210
2224
|
/**
|
|
2211
|
-
* 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.
|
|
2212
|
-
*
|
|
2213
|
-
* @remarks
|
|
2214
|
-
* 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.
|
|
2215
|
-
*
|
|
2216
|
-
* @returns A promise that resolves to the cloned context.
|
|
2217
|
-
*/
|
|
2218
|
-
async clone() {
|
|
2219
|
-
const clone = new PowerlinesBaseContext();
|
|
2220
|
-
await clone.init(this.options, this.initialConfig);
|
|
2221
|
-
return clone;
|
|
2222
|
-
}
|
|
2223
|
-
/**
|
|
2224
2225
|
* A logging function for fatal messages
|
|
2225
2226
|
*
|
|
2226
2227
|
* @param message - The message to log.
|
|
@@ -2300,7 +2301,7 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
|
|
|
2300
2301
|
* @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.
|
|
2301
2302
|
*/
|
|
2302
2303
|
createLogger(options, logFn) {
|
|
2303
|
-
return createLogger$1(this.options.name || this.options.root, {
|
|
2304
|
+
return createLogger$1(this.options.name || this.options.root || "powerlines", {
|
|
2304
2305
|
...this.configFile.config,
|
|
2305
2306
|
...this.options,
|
|
2306
2307
|
...options
|
|
@@ -2316,6 +2317,24 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
|
|
|
2316
2317
|
return extendLogger(this.logger, options);
|
|
2317
2318
|
}
|
|
2318
2319
|
/**
|
|
2320
|
+
* 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
|
|
2321
|
+
*/
|
|
2322
|
+
initialOptions = {};
|
|
2323
|
+
/**
|
|
2324
|
+
* 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.
|
|
2325
|
+
*/
|
|
2326
|
+
initialConfig = {};
|
|
2327
|
+
/**
|
|
2328
|
+
* 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.
|
|
2329
|
+
*
|
|
2330
|
+
* @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.
|
|
2331
|
+
* @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
|
|
2332
|
+
*/
|
|
2333
|
+
constructor(options, initialConfig = {}) {
|
|
2334
|
+
this.initialOptions = options;
|
|
2335
|
+
this.initialConfig = initialConfig;
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2319
2338
|
* 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.
|
|
2320
2339
|
*
|
|
2321
2340
|
* @returns A promise that resolves to the workspace configuration object, or undefined if no configuration file is found.
|
|
@@ -2327,64 +2346,41 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
|
|
|
2327
2346
|
} : void 0);
|
|
2328
2347
|
}
|
|
2329
2348
|
/**
|
|
2330
|
-
* 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".
|
|
2331
|
-
*
|
|
2332
|
-
* @returns A promise that resolves to the default mode for the current execution, which can be "development", "production", or "test".
|
|
2333
|
-
*/
|
|
2334
|
-
async getDefaultMode() {
|
|
2335
|
-
const workspaceConfig = await this.getWorkspaceConfig();
|
|
2336
|
-
return isProduction ? "production" : isDevelopment ? "development" : isTest ? "test" : workspaceConfig?.mode || "production";
|
|
2337
|
-
}
|
|
2338
|
-
/**
|
|
2339
|
-
* 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.
|
|
2340
|
-
*
|
|
2341
|
-
* @returns A promise that resolves to the default log level for the current execution, which can be "fatal", "error", "warn", "info", "debug", or "trace".
|
|
2342
|
-
*/
|
|
2343
|
-
async getDefaultLogLevel() {
|
|
2344
|
-
const workspaceConfig = await this.getWorkspaceConfig();
|
|
2345
|
-
return 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());
|
|
2346
|
-
}
|
|
2347
|
-
/**
|
|
2348
2349
|
* Initialize the context with the provided configuration options
|
|
2349
2350
|
*
|
|
2350
2351
|
* @remarks
|
|
2351
2352
|
* 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.
|
|
2352
|
-
*
|
|
2353
|
-
* @param options - The configuration options to initialize the context with
|
|
2354
|
-
* @param initialConfig - The initial configuration to initialize the context with
|
|
2355
2353
|
*/
|
|
2356
|
-
async init(
|
|
2357
|
-
this.initialOptions = { ...options };
|
|
2358
|
-
this.initialConfig = { ...initialConfig };
|
|
2354
|
+
async init() {
|
|
2359
2355
|
if (!this.powerlinesPath) {
|
|
2360
2356
|
const powerlinesPath = await resolvePackage("powerlines");
|
|
2361
2357
|
if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
|
|
2362
2358
|
this.powerlinesPath = powerlinesPath;
|
|
2363
2359
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
this.options = defu({
|
|
2367
|
-
name: options.name || this.initialConfig.name,
|
|
2368
|
-
root,
|
|
2369
|
-
cwd,
|
|
2370
|
-
mode: options.mode || this.initialConfig.mode,
|
|
2371
|
-
logLevel: options.logLevel || this.initialConfig.logLevel,
|
|
2372
|
-
framework: options.framework || this.initialConfig.framework,
|
|
2373
|
-
organization: options.organization || this.initialConfig.organization,
|
|
2374
|
-
configFile: options.configFile || this.initialConfig.configFile
|
|
2375
|
-
}, this.options ?? {}, {
|
|
2360
|
+
this.options = defu(this.initialOptions, this.initialConfig, {
|
|
2361
|
+
cwd: process.cwd(),
|
|
2376
2362
|
mode: await this.getDefaultMode(),
|
|
2377
|
-
logLevel: await this.getDefaultLogLevel()
|
|
2363
|
+
logLevel: await this.getDefaultLogLevel(),
|
|
2364
|
+
framework: "powerlines"
|
|
2378
2365
|
});
|
|
2366
|
+
if (!this.options.root) if (this.options.configFile) {
|
|
2367
|
+
const configFile = appendPath(this.options.configFile, this.options.cwd);
|
|
2368
|
+
if (!existsSync$1(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.`);
|
|
2369
|
+
if (!isFile$1(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.`);
|
|
2370
|
+
this.options.root = relativePath$1(this.options.cwd, findFilePath$1(configFile));
|
|
2371
|
+
} else this.options.root = ".";
|
|
2372
|
+
else this.options.root = replacePath(this.options.root, this.options.cwd);
|
|
2379
2373
|
this.resolver = createResolver({
|
|
2380
|
-
workspaceRoot: cwd,
|
|
2381
|
-
root,
|
|
2374
|
+
workspaceRoot: this.options.cwd,
|
|
2375
|
+
root: this.options.root,
|
|
2382
2376
|
cacheDir: this.envPaths.cache,
|
|
2383
2377
|
mode: this.options.mode
|
|
2384
2378
|
});
|
|
2379
|
+
await this.resolvePackageConfigs();
|
|
2385
2380
|
this.configFile = await loadUserConfigFile(this.options, this.resolver);
|
|
2386
|
-
if (
|
|
2387
|
-
if (this.configFile.
|
|
2381
|
+
if (this.configFile.config) {
|
|
2382
|
+
if (isSetString(this.configFile.configFile)) this.options.configFile ??= replacePath(this.configFile.configFile, this.options.cwd);
|
|
2383
|
+
if (!this.options.name) {
|
|
2388
2384
|
if (isSetObject(this.configFile.config) && isSetString(this.configFile.config.name)) this.options.name = this.configFile.config.name;
|
|
2389
2385
|
else if (Array.isArray(this.configFile.config)) {
|
|
2390
2386
|
for (const config of this.configFile.config) if (isSetObject(config) && isSetString(config.name)) {
|
|
@@ -2393,22 +2389,46 @@ var PowerlinesBaseContext = class PowerlinesBaseContext {
|
|
|
2393
2389
|
}
|
|
2394
2390
|
}
|
|
2395
2391
|
}
|
|
2396
|
-
if (!this.options.name)
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2392
|
+
if (!this.options.name) this.options.name = this.projectJson?.name || this.packageJson?.name;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Resolve the package configurations for the project by loading the `package.json` and `project.json` files, if they exist. This function will look for these files in the project root and parse their contents as JavaScript objects. The parsed contents will be stored in the context for later use by plugins and other parts of the build process.
|
|
2397
|
+
*
|
|
2398
|
+
* @remarks
|
|
2399
|
+
* The `package.json` file is typically used to store metadata about the project, such as its name, version, dependencies, and other information. The `project.json` file is an optional file that can be used to store additional configuration or metadata specific to the project, and is not required for all projects.
|
|
2400
|
+
*
|
|
2401
|
+
* @param cwd - The current working directory to look for the package configurations. Defaults to the `cwd` specified in the context configuration.
|
|
2402
|
+
* @param root - The root directory of the project to look for the package configurations. Defaults to the `root` specified in the context configuration.
|
|
2403
|
+
* @returns A promise that resolves when the package configurations have been loaded and stored in the context.
|
|
2404
|
+
*/
|
|
2405
|
+
async resolvePackageConfigs(cwd = this.options.cwd, root = this.options.root) {
|
|
2406
|
+
const projectJsonPath = joinPaths$2(appendPath(root, cwd), "project.json");
|
|
2407
|
+
if (existsSync$1(projectJsonPath)) this.projectJson = await readJsonFile$1(projectJsonPath);
|
|
2408
|
+
const packageJsonPath = joinPaths$2(appendPath(root, cwd), "package.json");
|
|
2409
|
+
if (existsSync$1(packageJsonPath)) {
|
|
2410
|
+
this.packageJson = await readJsonFile$1(packageJsonPath);
|
|
2411
|
+
this.options.organization ??= isSetObject(this.packageJson?.author) ? kebabCase(this.packageJson?.author?.name) : kebabCase(this.packageJson?.author);
|
|
2410
2412
|
}
|
|
2411
2413
|
}
|
|
2414
|
+
/**
|
|
2415
|
+
* 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".
|
|
2416
|
+
*
|
|
2417
|
+
* @returns A promise that resolves to the default mode for the current execution, which can be "development", "production", or "test".
|
|
2418
|
+
*/
|
|
2419
|
+
async getDefaultMode() {
|
|
2420
|
+
const workspaceConfig = await this.getWorkspaceConfig();
|
|
2421
|
+
return isProduction ? "production" : isDevelopment ? "development" : isTest ? "test" : workspaceConfig?.mode || "production";
|
|
2422
|
+
}
|
|
2423
|
+
/**
|
|
2424
|
+
* 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.
|
|
2425
|
+
*
|
|
2426
|
+
* @returns A promise that resolves to the default log level for the current execution, which can be "fatal", "error", "warn", "info", "debug", or "trace".
|
|
2427
|
+
*/
|
|
2428
|
+
async getDefaultLogLevel() {
|
|
2429
|
+
const workspaceConfig = await this.getWorkspaceConfig();
|
|
2430
|
+
return 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());
|
|
2431
|
+
}
|
|
2412
2432
|
};
|
|
2413
2433
|
|
|
2414
2434
|
//#endregion
|
|
@@ -2420,27 +2440,13 @@ setGlobalDispatcher(new Agent({ keepAliveTimeout: 1e4 }).compose(interceptors.re
|
|
|
2420
2440
|
timeoutFactor: 2,
|
|
2421
2441
|
retryAfter: true
|
|
2422
2442
|
})));
|
|
2423
|
-
const
|
|
2424
|
-
"
|
|
2425
|
-
"
|
|
2426
|
-
"
|
|
2427
|
-
"
|
|
2428
|
-
"projectJson",
|
|
2429
|
-
"tsconfig",
|
|
2430
|
-
"resolver",
|
|
2431
|
-
"fs",
|
|
2432
|
-
"$$internal"
|
|
2443
|
+
const UNRESOLVED_CONFIG_NAMES = [
|
|
2444
|
+
"initialConfig",
|
|
2445
|
+
"userConfig",
|
|
2446
|
+
"inlineConfig",
|
|
2447
|
+
"pluginConfig"
|
|
2433
2448
|
];
|
|
2434
2449
|
var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
2435
|
-
/**
|
|
2436
|
-
* Internal references storage
|
|
2437
|
-
*
|
|
2438
|
-
* @danger
|
|
2439
|
-
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
2440
|
-
*
|
|
2441
|
-
* @internal
|
|
2442
|
-
*/
|
|
2443
|
-
#internal = {};
|
|
2444
2450
|
#checksum = null;
|
|
2445
2451
|
#buildId = uuid();
|
|
2446
2452
|
#releaseId = uuid();
|
|
@@ -2448,24 +2454,22 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
2448
2454
|
#tsconfig;
|
|
2449
2455
|
#parserCache;
|
|
2450
2456
|
#requestCache;
|
|
2457
|
+
#configProxy;
|
|
2451
2458
|
/**
|
|
2452
|
-
* Create a new
|
|
2459
|
+
* Create a new context from the workspace root and user config.
|
|
2453
2460
|
*
|
|
2454
2461
|
* @param options - The options for resolving the context.
|
|
2455
2462
|
* @returns A promise that resolves to the new context.
|
|
2456
2463
|
*/
|
|
2457
|
-
static async
|
|
2458
|
-
const context = new PowerlinesContext(options);
|
|
2459
|
-
await context.init(
|
|
2460
|
-
const powerlinesPath = await resolvePackage("powerlines");
|
|
2461
|
-
if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
|
|
2462
|
-
context.powerlinesPath = powerlinesPath;
|
|
2464
|
+
static async fromInitialConfig(options, initialConfig) {
|
|
2465
|
+
const context = new PowerlinesContext(options, initialConfig);
|
|
2466
|
+
await context.init();
|
|
2463
2467
|
return context;
|
|
2464
2468
|
}
|
|
2465
2469
|
/**
|
|
2466
|
-
* The options provided to the Powerlines process
|
|
2470
|
+
* 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.
|
|
2467
2471
|
*/
|
|
2468
|
-
options;
|
|
2472
|
+
options = {};
|
|
2469
2473
|
/**
|
|
2470
2474
|
* An object containing the dependencies that should be installed for the project
|
|
2471
2475
|
*/
|
|
@@ -2479,39 +2483,33 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
2479
2483
|
*/
|
|
2480
2484
|
persistedMeta = void 0;
|
|
2481
2485
|
/**
|
|
2482
|
-
* The
|
|
2486
|
+
* The resolved tsconfig file paths for the project
|
|
2483
2487
|
*/
|
|
2484
|
-
|
|
2488
|
+
resolvePatterns = [];
|
|
2485
2489
|
/**
|
|
2486
|
-
* The
|
|
2490
|
+
* 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
|
|
2487
2491
|
*/
|
|
2488
|
-
|
|
2492
|
+
initialOptions = {};
|
|
2489
2493
|
/**
|
|
2490
|
-
* The resolved
|
|
2494
|
+
* The resolved configuration for this context
|
|
2491
2495
|
*/
|
|
2492
|
-
|
|
2496
|
+
resolvedConfig = {};
|
|
2493
2497
|
/**
|
|
2494
|
-
*
|
|
2495
|
-
*
|
|
2496
|
-
* @danger
|
|
2497
|
-
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
2498
|
-
*
|
|
2499
|
-
* @internal
|
|
2498
|
+
* 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.
|
|
2500
2499
|
*/
|
|
2501
|
-
|
|
2502
|
-
return this.#internal;
|
|
2503
|
-
}
|
|
2500
|
+
overriddenConfig = {};
|
|
2504
2501
|
/**
|
|
2505
|
-
*
|
|
2506
|
-
*
|
|
2507
|
-
* @danger
|
|
2508
|
-
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
2509
|
-
*
|
|
2510
|
-
* @internal
|
|
2502
|
+
* 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.
|
|
2511
2503
|
*/
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2504
|
+
inlineConfig = {};
|
|
2505
|
+
/**
|
|
2506
|
+
* 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.
|
|
2507
|
+
*/
|
|
2508
|
+
userConfig = {};
|
|
2509
|
+
/**
|
|
2510
|
+
* The configuration options provided by plugins added by the user (and other plugins)
|
|
2511
|
+
*/
|
|
2512
|
+
pluginConfig = {};
|
|
2515
2513
|
/**
|
|
2516
2514
|
* The resolved entry type definitions for the project
|
|
2517
2515
|
*/
|
|
@@ -2566,13 +2564,14 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
2566
2564
|
* The resolved configuration options
|
|
2567
2565
|
*/
|
|
2568
2566
|
get config() {
|
|
2569
|
-
|
|
2567
|
+
if (!this.#configProxy) this.#configProxy = this.createConfigProxy();
|
|
2568
|
+
return this.#configProxy;
|
|
2570
2569
|
}
|
|
2571
2570
|
/**
|
|
2572
2571
|
* Get the path to the artifacts directory for the project
|
|
2573
2572
|
*/
|
|
2574
2573
|
get artifactsPath() {
|
|
2575
|
-
return joinPaths$1(this.config.cwd, this.config.root, this.config.output.
|
|
2574
|
+
return joinPaths$1(this.config.cwd, this.config.root, this.config.output?.artifactsPath || `.${this.config.framework || "powerlines"}`);
|
|
2576
2575
|
}
|
|
2577
2576
|
/**
|
|
2578
2577
|
* Get the path to the builtin modules used by the project
|
|
@@ -2629,7 +2628,7 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
2629
2628
|
* Additional arguments provided during execution of the command, such as CLI flags or other parameters that may be relevant to the command being executed.
|
|
2630
2629
|
*/
|
|
2631
2630
|
get additionalArgs() {
|
|
2632
|
-
return Object.entries(this.config.inlineConfig
|
|
2631
|
+
return Object.entries(this.config.inlineConfig.additionalArgs ?? {}).reduce((ret, [key, value]) => {
|
|
2633
2632
|
const formattedKey = key.replace(/^--?/, "");
|
|
2634
2633
|
if (ret[formattedKey]) if (Array.isArray(ret[formattedKey])) if (Array.isArray(value)) ret[formattedKey] = [...toArray(ret[formattedKey]), ...value];
|
|
2635
2634
|
else ret[formattedKey] = [...toArray(ret[formattedKey]), value];
|
|
@@ -2658,29 +2657,6 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
2658
2657
|
}, {}) : this.config.resolve.alias : {});
|
|
2659
2658
|
}
|
|
2660
2659
|
/**
|
|
2661
|
-
* Create a new logger instance
|
|
2662
|
-
*
|
|
2663
|
-
* @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.
|
|
2664
|
-
* @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.
|
|
2665
|
-
* @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.
|
|
2666
|
-
*/
|
|
2667
|
-
createLogger(options, logFn) {
|
|
2668
|
-
let logger;
|
|
2669
|
-
if (toBool(process.env.POWERLINES_WORKER_THREAD_EXECUTION)) logger = createLogger(this.config.name, {
|
|
2670
|
-
...this.options,
|
|
2671
|
-
...this.config,
|
|
2672
|
-
...options
|
|
2673
|
-
}, (meta, message) => sendWriteLogMessage(this, meta, message));
|
|
2674
|
-
else logger = createLogger(this.config.name, {
|
|
2675
|
-
...this.options,
|
|
2676
|
-
...this.config,
|
|
2677
|
-
...options
|
|
2678
|
-
});
|
|
2679
|
-
if (this.config.customLogger) logger = withCustomLogger(logger, this.config.customLogger);
|
|
2680
|
-
if (logFn) logger = withLogFn(logger, logFn);
|
|
2681
|
-
return logger;
|
|
2682
|
-
}
|
|
2683
|
-
/**
|
|
2684
2660
|
* 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.
|
|
2685
2661
|
*/
|
|
2686
2662
|
get logLevel() {
|
|
@@ -2742,25 +2718,38 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
2742
2718
|
}).filter(Boolean);
|
|
2743
2719
|
}
|
|
2744
2720
|
/**
|
|
2745
|
-
* Creates a new
|
|
2721
|
+
* Creates a new Context instance.
|
|
2746
2722
|
*
|
|
2747
2723
|
* @param options - The options to use for creating the context, including the resolved configuration and workspace settings.
|
|
2724
|
+
* @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.
|
|
2748
2725
|
*/
|
|
2749
|
-
constructor(options) {
|
|
2750
|
-
super();
|
|
2751
|
-
this.
|
|
2726
|
+
constructor(options, initialConfig) {
|
|
2727
|
+
super(options, initialConfig);
|
|
2728
|
+
this.initialOptions = options;
|
|
2729
|
+
this.initialConfig = initialConfig;
|
|
2752
2730
|
}
|
|
2753
2731
|
/**
|
|
2754
|
-
*
|
|
2755
|
-
*
|
|
2756
|
-
* @remarks
|
|
2757
|
-
* 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.
|
|
2732
|
+
* Create a new logger instance
|
|
2758
2733
|
*
|
|
2759
|
-
* @
|
|
2734
|
+
* @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.
|
|
2735
|
+
* @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.
|
|
2736
|
+
* @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.
|
|
2760
2737
|
*/
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2738
|
+
createLogger(options, logFn) {
|
|
2739
|
+
let logger;
|
|
2740
|
+
if (isSetString(process.env.POWERLINES_EXECUTION_THREAD_TYPE)) logger = createLogger(this.config.name, {
|
|
2741
|
+
...this.options,
|
|
2742
|
+
...this.config,
|
|
2743
|
+
...options
|
|
2744
|
+
}, (meta, message) => sendWriteLogMessage(this, meta, message));
|
|
2745
|
+
else logger = createLogger(this.config.name, {
|
|
2746
|
+
...this.options,
|
|
2747
|
+
...this.config,
|
|
2748
|
+
...options
|
|
2749
|
+
});
|
|
2750
|
+
if (this.config.customLogger) logger = withCustomLogger(logger, this.config.customLogger);
|
|
2751
|
+
if (logFn) logger = withLogFn(logger, logFn);
|
|
2752
|
+
return logger;
|
|
2764
2753
|
}
|
|
2765
2754
|
/**
|
|
2766
2755
|
* A function to perform HTTP fetch requests
|
|
@@ -3090,206 +3079,247 @@ var PowerlinesContext = class PowerlinesContext extends PowerlinesBaseContext {
|
|
|
3090
3079
|
/**
|
|
3091
3080
|
* Generates a checksum representing the current context state
|
|
3092
3081
|
*
|
|
3093
|
-
* @param
|
|
3082
|
+
* @param path - The root directory of the project to generate the checksum for
|
|
3094
3083
|
* @returns A promise that resolves to a string representing the checksum
|
|
3095
3084
|
*/
|
|
3096
|
-
async generateChecksum(
|
|
3097
|
-
|
|
3098
|
-
"node_modules",
|
|
3099
|
-
".git",
|
|
3100
|
-
".nx",
|
|
3101
|
-
".cache",
|
|
3102
|
-
"tmp",
|
|
3103
|
-
"dist"
|
|
3104
|
-
] });
|
|
3105
|
-
return this.#checksum;
|
|
3085
|
+
async generateChecksum(path) {
|
|
3086
|
+
return hashDirectory(path || appendPath(this.options.root, this.options.cwd));
|
|
3106
3087
|
}
|
|
3107
3088
|
/**
|
|
3108
|
-
*
|
|
3089
|
+
* 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.
|
|
3090
|
+
*
|
|
3091
|
+
* @param config - The inline configuration values to set.
|
|
3092
|
+
* @returns A promise that resolves when the inline configuration values have been set.
|
|
3109
3093
|
*/
|
|
3110
|
-
async
|
|
3111
|
-
this.
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3094
|
+
async setInlineConfig(config) {
|
|
3095
|
+
this.logger.debug({
|
|
3096
|
+
meta: { category: "config" },
|
|
3097
|
+
message: `Updating inline configuration object: \n${this.logConfig(config)}`
|
|
3098
|
+
});
|
|
3099
|
+
this.inlineConfig = config;
|
|
3100
|
+
await this.resolveConfig();
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* 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.
|
|
3104
|
+
*
|
|
3105
|
+
* @param config - The plugin configuration values to set.
|
|
3106
|
+
* @returns A promise that resolves when the plugin configuration values have been set.
|
|
3107
|
+
*/
|
|
3108
|
+
async setPluginConfig(config) {
|
|
3109
|
+
this.logger.debug({
|
|
3110
|
+
meta: { category: "config" },
|
|
3111
|
+
message: `Updating plugin configuration object: \n${this.logConfig(config)}`
|
|
3112
|
+
});
|
|
3113
|
+
this.pluginConfig = config;
|
|
3114
|
+
await this.resolveConfig();
|
|
3115
|
+
}
|
|
3116
|
+
/**
|
|
3117
|
+
* 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.
|
|
3118
|
+
*
|
|
3119
|
+
* @returns The merged configuration object that combines the initial, user, inline, and plugin configurations.
|
|
3120
|
+
*/
|
|
3121
|
+
mergeConfig() {
|
|
3122
|
+
return mergeConfig({
|
|
3123
|
+
mode: this.initialOptions.mode,
|
|
3124
|
+
framework: this.initialOptions.framework,
|
|
3125
|
+
initialOptions: this.initialOptions,
|
|
3126
|
+
options: this.options,
|
|
3127
|
+
inlineConfig: this.inlineConfig,
|
|
3128
|
+
userConfig: this.userConfig,
|
|
3129
|
+
initialConfig: this.initialConfig,
|
|
3130
|
+
pluginConfig: this.pluginConfig
|
|
3131
|
+
}, getConfigProps(this.overriddenConfig), omit(this.options, ["mode", "framework"]), getConfigProps(this.inlineConfig), getConfigProps(this.userConfig), getConfigProps(this.initialConfig), getConfigProps(this.pluginConfig), {
|
|
3120
3132
|
version: this.packageJson?.version,
|
|
3121
3133
|
description: this.packageJson?.description
|
|
3122
3134
|
}, {
|
|
3123
3135
|
environments: {},
|
|
3124
3136
|
resolve: {}
|
|
3125
3137
|
});
|
|
3126
|
-
await this.innerSetup();
|
|
3127
3138
|
}
|
|
3128
3139
|
/**
|
|
3129
|
-
*
|
|
3130
|
-
*/
|
|
3131
|
-
resolvedConfig = {};
|
|
3132
|
-
/**
|
|
3133
|
-
* 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.
|
|
3134
|
-
*
|
|
3135
|
-
* @remarks
|
|
3136
|
-
* 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.
|
|
3140
|
+
* 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.
|
|
3137
3141
|
*
|
|
3138
|
-
* @
|
|
3142
|
+
* @param config - The user configuration values to set.
|
|
3143
|
+
* @returns A promise that resolves when the user configuration values have been set.
|
|
3139
3144
|
*/
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
context.devDependencies = deepClone(this.devDependencies);
|
|
3148
|
-
context.persistedMeta = this.persistedMeta ? deepClone(this.persistedMeta) : void 0;
|
|
3149
|
-
context.packageJson = deepClone(this.packageJson);
|
|
3150
|
-
context.projectJson = this.projectJson ? deepClone(this.projectJson) : void 0;
|
|
3151
|
-
context.tsconfig ??= deepClone(this.tsconfig);
|
|
3152
|
-
context.resolver ??= this.resolver;
|
|
3153
|
-
context.fs ??= this.#fs;
|
|
3154
|
-
context.$$internal = this.$$internal;
|
|
3155
|
-
return context;
|
|
3145
|
+
async setUserConfig(config) {
|
|
3146
|
+
this.logger.debug({
|
|
3147
|
+
meta: { category: "config" },
|
|
3148
|
+
message: `Updating user configuration object: \n${this.logConfig(config)}`
|
|
3149
|
+
});
|
|
3150
|
+
this.userConfig = config;
|
|
3151
|
+
await this.resolveConfig();
|
|
3156
3152
|
}
|
|
3157
3153
|
/**
|
|
3158
3154
|
* Initialize the context with the provided configuration options
|
|
3155
|
+
*/
|
|
3156
|
+
async init() {
|
|
3157
|
+
await super.init();
|
|
3158
|
+
this.options.executionId = this.initialOptions.executionId || uuid();
|
|
3159
|
+
this.options.executionIndex = this.initialOptions.executionIndex ?? 0;
|
|
3160
|
+
this.#checksum = await this.generateChecksum();
|
|
3161
|
+
const result = this.configFile.config && toArray(this.configFile.config).length > this.options.executionIndex ? toArray(this.configFile.config)[this.options.executionIndex] : this.configFile.config;
|
|
3162
|
+
if (!result) this.logger.warn(`No configuration found in ${this.options.configFile} for execution index ${this.options.executionIndex}.`);
|
|
3163
|
+
else await this.setUserConfig(isFunction(result) ? await Promise.resolve(result(this.options)) : result);
|
|
3164
|
+
}
|
|
3165
|
+
/**
|
|
3166
|
+
* Resolve the package configurations for the project by loading the `package.json` and `project.json` files, if they exist. This function will look for these files in the project root and parse their contents as JavaScript objects. The parsed contents will be stored in the context for later use by plugins and other parts of the build process.
|
|
3159
3167
|
*
|
|
3160
|
-
*
|
|
3161
|
-
*
|
|
3168
|
+
* @remarks
|
|
3169
|
+
* The `package.json` file is typically used to store metadata about the project, such as its name, version, dependencies, and other information. The `project.json` file is an optional file that can be used to store additional configuration or metadata specific to the project, and is not required for all projects.
|
|
3162
3170
|
*
|
|
3163
|
-
* @param
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
const projectJsonPath = joinPaths$1(this.options.cwd, this.options.root, "project.json");
|
|
3170
|
-
if (existsSync(projectJsonPath)) this.projectJson = await readJsonFile(projectJsonPath);
|
|
3171
|
-
const packageJsonPath = joinPaths$1(this.options.cwd, this.options.root, "package.json");
|
|
3172
|
-
if (existsSync(packageJsonPath)) {
|
|
3173
|
-
this.packageJson = await readJsonFile(packageJsonPath);
|
|
3174
|
-
this.options.organization ??= isSetObject(this.packageJson?.author) ? kebabCase(this.packageJson?.author?.name) : kebabCase(this.packageJson?.author);
|
|
3175
|
-
}
|
|
3176
|
-
this.#checksum = await this.generateChecksum(joinPaths$1(this.options.cwd, this.options.root));
|
|
3177
|
-
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 : {};
|
|
3178
|
-
this.resolvedConfig = {
|
|
3179
|
-
cwd: this.options.cwd,
|
|
3180
|
-
root: this.options.root,
|
|
3181
|
-
...this.initialOptions,
|
|
3182
|
-
...initialConfig,
|
|
3183
|
-
...userConfig,
|
|
3184
|
-
inlineConfig: {},
|
|
3185
|
-
pluginConfig: {},
|
|
3186
|
-
initialConfig,
|
|
3187
|
-
userConfig
|
|
3188
|
-
};
|
|
3171
|
+
* @param cwd - The current working directory to look for the package configurations. Defaults to the `cwd` specified in the context configuration.
|
|
3172
|
+
* @param root - The root directory of the project to look for the package configurations. Defaults to the `root` specified in the context configuration.
|
|
3173
|
+
* @returns A promise that resolves when the package configurations have been loaded and stored in the context.
|
|
3174
|
+
*/
|
|
3175
|
+
async resolvePackageConfigs(cwd = this.config.cwd, root = this.config.root) {
|
|
3176
|
+
return super.resolvePackageConfigs(cwd, root);
|
|
3189
3177
|
}
|
|
3190
3178
|
/**
|
|
3191
3179
|
* Initialize the context with the provided configuration options
|
|
3192
3180
|
*/
|
|
3193
|
-
async
|
|
3194
|
-
const
|
|
3195
|
-
this.
|
|
3196
|
-
|
|
3181
|
+
async resolveConfig() {
|
|
3182
|
+
const mergedConfig = this.mergeConfig();
|
|
3183
|
+
this.logger.trace({
|
|
3184
|
+
meta: { category: "config" },
|
|
3185
|
+
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)}`
|
|
3186
|
+
});
|
|
3187
|
+
mergedConfig.output = defu(mergedConfig.output ?? {}, {
|
|
3197
3188
|
copy: { assets: [
|
|
3198
3189
|
{ glob: "LICENSE" },
|
|
3199
3190
|
{
|
|
3200
|
-
input:
|
|
3191
|
+
input: mergedConfig.root,
|
|
3201
3192
|
glob: "*.md"
|
|
3202
3193
|
},
|
|
3203
3194
|
{
|
|
3204
|
-
input:
|
|
3195
|
+
input: mergedConfig.root,
|
|
3205
3196
|
glob: "package.json"
|
|
3206
3197
|
}
|
|
3207
3198
|
] },
|
|
3208
3199
|
dts: true
|
|
3209
3200
|
});
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
this.options.mode = "production";
|
|
3225
|
-
this.config.mode = "production";
|
|
3226
|
-
}
|
|
3227
|
-
if (!this.initialOptions.framework && !this.config.userConfig?.framework && !this.config.inlineConfig?.framework && !this.config.initialConfig?.framework && !this.config.pluginConfig?.framework) {
|
|
3228
|
-
this.options.framework = "powerlines";
|
|
3229
|
-
this.config.framework = "powerlines";
|
|
3230
|
-
}
|
|
3231
|
-
if (!this.config.userConfig?.projectType && !this.config.inlineConfig?.projectType && !this.config.initialConfig?.projectType && !this.config.pluginConfig?.projectType) this.config.projectType = "application";
|
|
3232
|
-
if (!this.config.userConfig?.platform && !this.config.inlineConfig?.platform && !this.config.initialConfig?.platform && !this.config.pluginConfig?.platform) this.config.platform = "neutral";
|
|
3233
|
-
this.config.compatibilityDate = resolveCompatibilityDates(this.config.inlineConfig.compatibilityDate ?? this.config.userConfig.compatibilityDate ?? this.config.initialConfig.compatibilityDate ?? this.config.pluginConfig.compatibilityDate, "latest");
|
|
3234
|
-
this.config.input = getUniqueInputs(this.config.input);
|
|
3235
|
-
if (this.config.name?.startsWith("@") && this.config.name.split("/").filter(Boolean).length > 1) this.config.name = this.config.name.split("/").filter(Boolean)[1];
|
|
3236
|
-
this.config.title ??= titleCase(this.config.name);
|
|
3237
|
-
if (this.config.resolve.external) this.config.resolve.external = getUnique(this.config.resolve.external);
|
|
3238
|
-
if (this.config.resolve.noExternal) this.config.resolve.noExternal = getUnique(this.config.resolve.noExternal);
|
|
3239
|
-
this.config.plugins = (this.config.plugins ?? []).flatMap((plugin) => toArray(plugin)).filter(Boolean).reduce((ret, plugin) => {
|
|
3201
|
+
if (!mergedConfig.mode) mergedConfig.mode = "production";
|
|
3202
|
+
if (!mergedConfig.framework) mergedConfig.framework = "powerlines";
|
|
3203
|
+
if (!mergedConfig.projectType) mergedConfig.projectType = "application";
|
|
3204
|
+
if (!mergedConfig.platform) mergedConfig.platform = "neutral";
|
|
3205
|
+
mergedConfig.compatibilityDate = resolveCompatibilityDates(mergedConfig.compatibilityDate, "latest");
|
|
3206
|
+
this.resolvedConfig = mergedConfig;
|
|
3207
|
+
this.#configProxy = this.createConfigProxy();
|
|
3208
|
+
if (!this.packageJson) await this.resolvePackageConfigs();
|
|
3209
|
+
mergedConfig.input = getUniqueInputs(mergedConfig.input);
|
|
3210
|
+
if (mergedConfig.name?.startsWith("@") && mergedConfig.name.split("/").filter(Boolean).length > 1) mergedConfig.name = mergedConfig.name.split("/").filter(Boolean)[1];
|
|
3211
|
+
mergedConfig.title ??= titleCase(mergedConfig.name);
|
|
3212
|
+
if (mergedConfig.resolve.external) mergedConfig.resolve.external = getUnique(mergedConfig.resolve.external);
|
|
3213
|
+
if (mergedConfig.resolve.noExternal) mergedConfig.resolve.noExternal = getUnique(mergedConfig.resolve.noExternal);
|
|
3214
|
+
mergedConfig.plugins = (mergedConfig.plugins ?? []).flatMap((plugin) => toArray(plugin)).filter(Boolean).reduce((ret, plugin) => {
|
|
3240
3215
|
if (isPlugin(plugin) && isDuplicate(plugin, ret.filter((p) => isPlugin(p)))) return ret;
|
|
3241
3216
|
ret.push(plugin);
|
|
3242
3217
|
return ret;
|
|
3243
3218
|
}, []);
|
|
3244
|
-
if (!
|
|
3245
|
-
else if (
|
|
3246
|
-
else
|
|
3247
|
-
if (
|
|
3248
|
-
else
|
|
3249
|
-
|
|
3250
|
-
if (
|
|
3251
|
-
else
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
if (this.config.output.types !== false) this.config.output.types = appendPath(replacePathTokens(this, this.config.userConfig?.output?.types || this.config.inlineConfig?.output?.types || this.config.initialConfig?.output?.types || this.config.pluginConfig?.output?.types || joinPaths$1(this.config.root, `${this.config.framework ?? "powerlines"}.d.ts`)), this.config.cwd);
|
|
3258
|
-
if (this.config.output.copy && this.config.output.copy.path && this.config.output.copy.assets && Array.isArray(this.config.output.copy.assets)) this.config.output.copy.assets = getUniqueBy(this.config.output.copy.assets.map((asset) => {
|
|
3219
|
+
if (!mergedConfig.logLevel) if (mergedConfig.mode === "development") mergedConfig.logLevel = DEFAULT_DEVELOPMENT_LOG_LEVEL;
|
|
3220
|
+
else if (mergedConfig.mode === "test") mergedConfig.logLevel = DEFAULT_TEST_LOG_LEVEL;
|
|
3221
|
+
else mergedConfig.logLevel = DEFAULT_PRODUCTION_LOG_LEVEL;
|
|
3222
|
+
if (mergedConfig.tsconfig) mergedConfig.tsconfig = replacePath(replacePathTokens(this, mergedConfig.tsconfig), mergedConfig.cwd);
|
|
3223
|
+
else mergedConfig.tsconfig = getTsconfigFilePath(mergedConfig.cwd, mergedConfig.root);
|
|
3224
|
+
mergedConfig.output.format = getUnique(toArray(mergedConfig.output?.format ?? (mergedConfig.projectType === "library" ? ["cjs", "esm"] : ["esm"])));
|
|
3225
|
+
if (mergedConfig.output.path) mergedConfig.output.path = appendPath(replacePathTokens(this, mergedConfig.output.path), mergedConfig.cwd);
|
|
3226
|
+
else mergedConfig.output.path = appendPath(joinPaths$1(mergedConfig.root, "dist"), mergedConfig.cwd);
|
|
3227
|
+
mergedConfig.output.copy ??= {};
|
|
3228
|
+
if (mergedConfig.output.copy !== false) if (!mergedConfig.root.replace(/^\.\/?/, "")) mergedConfig.output.copy.path = mergedConfig.output.copy.path ? appendPath(replacePathTokens(this, mergedConfig.output.copy.path), mergedConfig.cwd) : mergedConfig.output.path;
|
|
3229
|
+
else mergedConfig.output.copy.path = appendPath(replacePathTokens(this, mergedConfig.output.copy.path || joinPaths$1("dist", mergedConfig.root)), mergedConfig.cwd);
|
|
3230
|
+
if (mergedConfig.output.types !== false) mergedConfig.output.types = appendPath(replacePathTokens(this, mergedConfig.output.types || joinPaths$1(mergedConfig.root, `${mergedConfig.framework ?? "powerlines"}.d.ts`)), mergedConfig.cwd);
|
|
3231
|
+
if (mergedConfig.output.copy && mergedConfig.output.copy.path && mergedConfig.output.copy.assets && Array.isArray(mergedConfig.output.copy.assets)) mergedConfig.output.copy.assets = getUniqueBy(mergedConfig.output.copy.assets.map((asset) => {
|
|
3259
3232
|
return {
|
|
3260
3233
|
glob: isSetObject(asset) ? asset.glob : asset,
|
|
3261
|
-
input: isString(asset) || !asset.input || asset.input === "." || asset.input === "/" || asset.input === "./" ?
|
|
3262
|
-
output: isSetObject(asset) && asset.output ? isParentPath(asset.output,
|
|
3234
|
+
input: isString(asset) || !asset.input || asset.input === "." || asset.input === "/" || asset.input === "./" ? mergedConfig.cwd : isParentPath(asset.input, mergedConfig.cwd) || isEqual(asset.input, mergedConfig.cwd) ? asset.input : appendPath(asset.input, mergedConfig.cwd),
|
|
3235
|
+
output: isSetObject(asset) && asset.output ? isParentPath(asset.output, mergedConfig.cwd) ? asset.output : appendPath(joinPaths$1(mergedConfig.output.copy.path, replacePath(replacePath(asset.output, replacePath(mergedConfig.output.copy.path, mergedConfig.cwd)), mergedConfig.output.copy.path)), mergedConfig.cwd) : appendPath(mergedConfig.output.copy.path, mergedConfig.cwd),
|
|
3263
3236
|
ignore: isSetObject(asset) && asset.ignore ? toArray(asset.ignore) : void 0
|
|
3264
3237
|
};
|
|
3265
3238
|
}), (a) => `${a.input}-${a.glob}-${a.output}`);
|
|
3266
|
-
if (!
|
|
3267
|
-
else
|
|
3268
|
-
if (!
|
|
3269
|
-
else
|
|
3270
|
-
if (!
|
|
3271
|
-
if (
|
|
3239
|
+
if (!mergedConfig.output?.sourceMap) if (mergedConfig.mode === "development") mergedConfig.output.sourceMap = true;
|
|
3240
|
+
else mergedConfig.output.sourceMap = false;
|
|
3241
|
+
if (!mergedConfig.output.minify) if (mergedConfig.mode === "production") mergedConfig.output.minify = true;
|
|
3242
|
+
else mergedConfig.output.minify = false;
|
|
3243
|
+
if (!mergedConfig.output.artifactsPath) mergedConfig.output.artifactsPath = `.${mergedConfig.framework || "powerlines"}`;
|
|
3244
|
+
if (mergedConfig.output.copy && mergedConfig.output.copy.assets) mergedConfig.output.copy.assets = mergedConfig.output.copy.assets.map((asset) => ({
|
|
3272
3245
|
...asset,
|
|
3273
3246
|
glob: replacePathTokens(this, asset.glob),
|
|
3274
3247
|
ignore: asset.ignore ? asset.ignore.map((ignore) => replacePathTokens(this, ignore)) : void 0,
|
|
3275
3248
|
input: replacePathTokens(this, asset.input),
|
|
3276
3249
|
output: replacePathTokens(this, asset.output)
|
|
3277
3250
|
}));
|
|
3278
|
-
if (isSetString(
|
|
3251
|
+
if (isSetString(mergedConfig.output?.storage) && mergedConfig.output.storage === "virtual" || isSetObject(mergedConfig.output?.storage) && Object.values(mergedConfig.output.storage).every((adapter) => adapter.preset === "virtual")) mergedConfig.output.overwrite = true;
|
|
3252
|
+
this.resolvedConfig = mergedConfig;
|
|
3253
|
+
this.#configProxy = this.createConfigProxy();
|
|
3254
|
+
this.logger.debug({
|
|
3255
|
+
meta: { category: "config" },
|
|
3256
|
+
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)}`
|
|
3257
|
+
});
|
|
3279
3258
|
this.#fs ??= await VirtualFileSystem.create(this);
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3259
|
+
}
|
|
3260
|
+
logConfig(config) {
|
|
3261
|
+
return formatLogMessage({
|
|
3262
|
+
...omit(config, ["plugins"]),
|
|
3263
|
+
plugins: config.plugins ? config.plugins.flatMap((plugin) => toArray(plugin)).map((plugin) => String(isSetString(plugin) ? plugin : isPromise(plugin) ? "<promise>" : isFunction(plugin) ? plugin.name || "<anonymous function>" : Array.isArray(plugin) ? plugin[0] || "<anonymous function plugin>" : "<unknown plugin>")) : void 0
|
|
3264
|
+
});
|
|
3265
|
+
}
|
|
3266
|
+
createConfigProxy() {
|
|
3267
|
+
return new Proxy(this.resolvedConfig, {
|
|
3268
|
+
/**
|
|
3269
|
+
* A trap for the `delete` operator.
|
|
3270
|
+
* @param target - The original object which is being proxied.
|
|
3271
|
+
* @param key - The name or `Symbol` of the property to delete.
|
|
3272
|
+
* @returns A `boolean` indicating whether or not the property was deleted.
|
|
3273
|
+
*/
|
|
3274
|
+
deleteProperty: (target, key) => {
|
|
3275
|
+
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.`);
|
|
3276
|
+
Reflect.deleteProperty(this.overriddenConfig, key);
|
|
3277
|
+
return Reflect.deleteProperty(target, key);
|
|
3278
|
+
},
|
|
3279
|
+
/**
|
|
3280
|
+
* A trap for getting a property value.
|
|
3281
|
+
* @param target - The original object which is being proxied.
|
|
3282
|
+
* @param key - The name or `Symbol` of the property to get.
|
|
3283
|
+
* @param receiver - The proxy or an object that inherits from the proxy.
|
|
3284
|
+
*/
|
|
3285
|
+
get: (target, key, receiver) => {
|
|
3286
|
+
if (UNRESOLVED_CONFIG_NAMES.includes(key.toString())) {
|
|
3287
|
+
if (key === "initialConfig") return this.initialConfig;
|
|
3288
|
+
if (key === "userConfig") return this.userConfig;
|
|
3289
|
+
if (key === "inlineConfig") return this.inlineConfig;
|
|
3290
|
+
if (key === "pluginConfig") return this.pluginConfig;
|
|
3291
|
+
}
|
|
3292
|
+
return Reflect.get(target, key, receiver);
|
|
3293
|
+
},
|
|
3294
|
+
/**
|
|
3295
|
+
* A trap for the `in` operator.
|
|
3296
|
+
* @param target - The original object which is being proxied.
|
|
3297
|
+
* @param key - The name or `Symbol` of the property to check for existence.
|
|
3298
|
+
*/
|
|
3299
|
+
has: (target, key) => {
|
|
3300
|
+
return Reflect.has(target, key) || UNRESOLVED_CONFIG_NAMES.includes(key.toString());
|
|
3301
|
+
},
|
|
3302
|
+
/**
|
|
3303
|
+
* A trap for `Reflect.ownKeys()`.
|
|
3304
|
+
* @param target - The original object which is being proxied.
|
|
3305
|
+
*/
|
|
3306
|
+
ownKeys: (target) => {
|
|
3307
|
+
return getUnique([...Reflect.ownKeys(target), ...UNRESOLVED_CONFIG_NAMES]);
|
|
3308
|
+
},
|
|
3309
|
+
/**
|
|
3310
|
+
* A trap for setting a property value.
|
|
3311
|
+
* @param target - The original object which is being proxied.
|
|
3312
|
+
* @param key - The name or `Symbol` of the property to set.
|
|
3313
|
+
* @param newValue - The new value to assign to the property.
|
|
3314
|
+
* @param receiver - The object to which the assignment was originally directed.
|
|
3315
|
+
* @returns A `boolean` indicating whether or not the property was set.
|
|
3316
|
+
*/
|
|
3317
|
+
set: (target, key, newValue, receiver) => {
|
|
3318
|
+
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.`);
|
|
3319
|
+
Reflect.set(this.overriddenConfig, key, newValue, receiver);
|
|
3320
|
+
return Reflect.set(target, key, newValue, receiver);
|
|
3321
|
+
}
|
|
3322
|
+
});
|
|
3293
3323
|
}
|
|
3294
3324
|
};
|
|
3295
3325
|
|
|
@@ -3434,7 +3464,7 @@ function createPluginContext(pluginId, plugin, environment) {
|
|
|
3434
3464
|
return {
|
|
3435
3465
|
meta: {
|
|
3436
3466
|
...isSetObject(message) ? message.meta : {},
|
|
3437
|
-
environment: environment.environment
|
|
3467
|
+
environment: environment.config.environment.name,
|
|
3438
3468
|
plugin: plugin.name
|
|
3439
3469
|
},
|
|
3440
3470
|
message: isString(message) ? message : message.message
|
|
@@ -3457,6 +3487,8 @@ function createPluginContext(pluginId, plugin, environment) {
|
|
|
3457
3487
|
callHook: callHookFn,
|
|
3458
3488
|
meta
|
|
3459
3489
|
};
|
|
3490
|
+
if (prop === "api") return environment.$$internal.api;
|
|
3491
|
+
if (prop === "environment") return environment;
|
|
3460
3492
|
if (prop === "id") return pluginId;
|
|
3461
3493
|
if (prop === "logger") return logger;
|
|
3462
3494
|
if (prop === "log") return (type, message) => {
|
|
@@ -3509,6 +3541,15 @@ function createPluginContext(pluginId, plugin, environment) {
|
|
|
3509
3541
|
//#endregion
|
|
3510
3542
|
//#region src/context/environment-context.ts
|
|
3511
3543
|
var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends PowerlinesContext {
|
|
3544
|
+
/**
|
|
3545
|
+
* Internal references storage
|
|
3546
|
+
*
|
|
3547
|
+
* @danger
|
|
3548
|
+
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
3549
|
+
*
|
|
3550
|
+
* @internal
|
|
3551
|
+
*/
|
|
3552
|
+
#internal = {};
|
|
3512
3553
|
/**
|
|
3513
3554
|
* The hooks registered by plugins in this environment
|
|
3514
3555
|
*/
|
|
@@ -3518,29 +3559,50 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
|
|
|
3518
3559
|
*
|
|
3519
3560
|
* @param options - The resolved execution options.
|
|
3520
3561
|
* @param config - The user configuration options.
|
|
3521
|
-
* @
|
|
3562
|
+
* @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.
|
|
3563
|
+
* @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.
|
|
3564
|
+
* @returns A promise that resolves to an instance of the PowerlinesEnvironmentContext class, initialized with the provided configuration and environment data.
|
|
3522
3565
|
*/
|
|
3523
|
-
static async
|
|
3524
|
-
const context = new PowerlinesEnvironmentContext(options, config,
|
|
3525
|
-
await context.
|
|
3526
|
-
const powerlinesPath = await resolvePackage("powerlines");
|
|
3527
|
-
if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
|
|
3528
|
-
context.powerlinesPath = powerlinesPath;
|
|
3566
|
+
static async createEnvironment(options, config, overriddenConfig, environment) {
|
|
3567
|
+
const context = new PowerlinesEnvironmentContext(options, config, overriddenConfig);
|
|
3568
|
+
await context.setEnvironmentConfig(environment);
|
|
3529
3569
|
return context;
|
|
3530
3570
|
}
|
|
3531
3571
|
/**
|
|
3532
|
-
* The
|
|
3572
|
+
* The configuration options provided by plugins added by the user (and other plugins)
|
|
3533
3573
|
*/
|
|
3534
|
-
|
|
3574
|
+
environmentConfig = {};
|
|
3535
3575
|
/**
|
|
3536
3576
|
* The list of plugins applied to this environment
|
|
3537
3577
|
*/
|
|
3538
3578
|
plugins = [];
|
|
3539
3579
|
/**
|
|
3540
|
-
*
|
|
3580
|
+
* Internal context fields and methods
|
|
3581
|
+
*
|
|
3582
|
+
* @danger
|
|
3583
|
+
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
3584
|
+
*
|
|
3585
|
+
* @internal
|
|
3541
3586
|
*/
|
|
3542
|
-
get
|
|
3543
|
-
return this
|
|
3587
|
+
get $$internal() {
|
|
3588
|
+
return this.#internal;
|
|
3589
|
+
}
|
|
3590
|
+
/**
|
|
3591
|
+
* Internal context fields and methods
|
|
3592
|
+
*
|
|
3593
|
+
* @danger
|
|
3594
|
+
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
3595
|
+
*
|
|
3596
|
+
* @internal
|
|
3597
|
+
*/
|
|
3598
|
+
set $$internal(value) {
|
|
3599
|
+
this.#internal = value;
|
|
3600
|
+
}
|
|
3601
|
+
/**
|
|
3602
|
+
* 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.
|
|
3603
|
+
*/
|
|
3604
|
+
get id() {
|
|
3605
|
+
return this.config.environment.id;
|
|
3544
3606
|
}
|
|
3545
3607
|
/**
|
|
3546
3608
|
* The hooks registered by plugins in this environment
|
|
@@ -3549,6 +3611,20 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
|
|
|
3549
3611
|
return this.#hooks;
|
|
3550
3612
|
}
|
|
3551
3613
|
/**
|
|
3614
|
+
* 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.
|
|
3615
|
+
*
|
|
3616
|
+
* @param config - The environment configuration values to set.
|
|
3617
|
+
* @returns A promise that resolves when the environment configuration values have been set.
|
|
3618
|
+
*/
|
|
3619
|
+
async setEnvironmentConfig(config) {
|
|
3620
|
+
this.logger.debug({
|
|
3621
|
+
meta: { category: "config" },
|
|
3622
|
+
message: `Updating environment configuration object: \n${this.logConfig(config)}`
|
|
3623
|
+
});
|
|
3624
|
+
this.environmentConfig = config;
|
|
3625
|
+
await this.resolveConfig();
|
|
3626
|
+
}
|
|
3627
|
+
/**
|
|
3552
3628
|
* Create a new logger instance
|
|
3553
3629
|
*
|
|
3554
3630
|
* @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.
|
|
@@ -3558,7 +3634,7 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
|
|
|
3558
3634
|
createLogger(options, logFn) {
|
|
3559
3635
|
return super.createLogger({
|
|
3560
3636
|
...options,
|
|
3561
|
-
environment: this.environment?.name
|
|
3637
|
+
environment: this.config.environment?.name
|
|
3562
3638
|
}, logFn);
|
|
3563
3639
|
}
|
|
3564
3640
|
/**
|
|
@@ -3570,47 +3646,21 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
|
|
|
3570
3646
|
extendLogger(options) {
|
|
3571
3647
|
return super.extendLogger({
|
|
3572
3648
|
...options,
|
|
3573
|
-
environment: this.environment?.name
|
|
3649
|
+
environment: this.config.environment?.name
|
|
3574
3650
|
});
|
|
3575
3651
|
}
|
|
3576
|
-
/**
|
|
3577
|
-
* 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.
|
|
3578
|
-
*
|
|
3579
|
-
* @remarks
|
|
3580
|
-
* 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.
|
|
3581
|
-
*
|
|
3582
|
-
* @returns A promise that resolves to the cloned context.
|
|
3583
|
-
*/
|
|
3584
|
-
async clone() {
|
|
3585
|
-
const context = await PowerlinesEnvironmentContext.fromConfig(deepClone(this.options), deepClone(this.config), deepClone(this.environment));
|
|
3586
|
-
return this.copyTo(context);
|
|
3587
|
-
}
|
|
3588
|
-
/**
|
|
3589
|
-
* Initialize the context with the provided configuration options
|
|
3590
|
-
*/
|
|
3591
|
-
async setup() {
|
|
3592
|
-
this.resolvedConfig = mergeConfig({
|
|
3593
|
-
name: this.config.name,
|
|
3594
|
-
title: this.config.title
|
|
3595
|
-
}, getConfigProps({
|
|
3596
|
-
...this.environment,
|
|
3597
|
-
root: this.options.root,
|
|
3598
|
-
cwd: this.options.cwd
|
|
3599
|
-
}), this.config);
|
|
3600
|
-
await this.innerSetup();
|
|
3601
|
-
}
|
|
3602
3652
|
async addPlugin(plugin) {
|
|
3603
3653
|
let resolvedPlugin = plugin;
|
|
3604
3654
|
if (isFunction(plugin.applyToEnvironment)) {
|
|
3605
|
-
const result = await Promise.resolve(plugin.applyToEnvironment(this.environment));
|
|
3655
|
+
const result = await Promise.resolve(plugin.applyToEnvironment(this.config.environment));
|
|
3606
3656
|
if (!result || isObject(result) && Object.keys(result).length === 0) return;
|
|
3607
3657
|
if (isPluginConfig(result)) return this.$$internal.addPlugin(result);
|
|
3608
3658
|
resolvedPlugin = isPlugin(result) ? result : plugin;
|
|
3609
3659
|
}
|
|
3610
|
-
const
|
|
3611
|
-
const context = createPluginContext(
|
|
3660
|
+
const id = uuid();
|
|
3661
|
+
const context = createPluginContext(id, resolvedPlugin, this);
|
|
3612
3662
|
this.plugins.push({
|
|
3613
|
-
|
|
3663
|
+
id,
|
|
3614
3664
|
plugin: resolvedPlugin,
|
|
3615
3665
|
context
|
|
3616
3666
|
});
|
|
@@ -3653,29 +3703,51 @@ var PowerlinesEnvironmentContext = class PowerlinesEnvironmentContext extends Po
|
|
|
3653
3703
|
}
|
|
3654
3704
|
return result;
|
|
3655
3705
|
}
|
|
3656
|
-
constructor(options, config,
|
|
3657
|
-
super(options);
|
|
3658
|
-
this.
|
|
3659
|
-
this.
|
|
3706
|
+
constructor(options, config, overriddenConfig) {
|
|
3707
|
+
super(options, config.initialConfig);
|
|
3708
|
+
this.userConfig = config.userConfig ?? {};
|
|
3709
|
+
this.inlineConfig = config.inlineConfig ?? {};
|
|
3710
|
+
this.pluginConfig = config.pluginConfig ?? {};
|
|
3711
|
+
this.overriddenConfig = overriddenConfig;
|
|
3660
3712
|
}
|
|
3661
3713
|
/**
|
|
3662
|
-
*
|
|
3714
|
+
* 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.
|
|
3663
3715
|
*
|
|
3664
|
-
* @
|
|
3665
|
-
* 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.
|
|
3666
|
-
*
|
|
3667
|
-
* @returns The cloned context.
|
|
3716
|
+
* @returns The merged configuration object that combines the initial, user, inline, and plugin configurations.
|
|
3668
3717
|
*/
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3718
|
+
mergeConfig() {
|
|
3719
|
+
return mergeConfig({
|
|
3720
|
+
...omit(this.environmentConfig ?? {}, [
|
|
3721
|
+
"ssr",
|
|
3722
|
+
"preview",
|
|
3723
|
+
"consumer",
|
|
3724
|
+
"runtime"
|
|
3725
|
+
]),
|
|
3726
|
+
environment: { name: this.environmentConfig?.name || DEFAULT_ENVIRONMENT },
|
|
3727
|
+
environmentConfig: this.environmentConfig ?? {}
|
|
3728
|
+
}, super.mergeConfig());
|
|
3672
3729
|
}
|
|
3673
3730
|
};
|
|
3674
3731
|
|
|
3675
3732
|
//#endregion
|
|
3676
3733
|
//#region src/context/execution-context.ts
|
|
3677
3734
|
var PowerlinesExecutionContext = class PowerlinesExecutionContext extends PowerlinesContext {
|
|
3735
|
+
/**
|
|
3736
|
+
* Internal references storage
|
|
3737
|
+
*
|
|
3738
|
+
* @danger
|
|
3739
|
+
* This field is for internal use only and should not be accessed or modified directly. It is unstable and can be changed at anytime.
|
|
3740
|
+
*
|
|
3741
|
+
* @internal
|
|
3742
|
+
*/
|
|
3743
|
+
#internal = {};
|
|
3744
|
+
/**
|
|
3745
|
+
* A record of all environments by name
|
|
3746
|
+
*/
|
|
3678
3747
|
#environments = {};
|
|
3748
|
+
/**
|
|
3749
|
+
* 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.
|
|
3750
|
+
*/
|
|
3679
3751
|
#plugins = [];
|
|
3680
3752
|
/**
|
|
3681
3753
|
* Create a new Storm context from the workspace root and user config.
|
|
@@ -3683,13 +3755,9 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3683
3755
|
* @param options - The options for resolving the context.
|
|
3684
3756
|
* @returns A promise that resolves to the new context.
|
|
3685
3757
|
*/
|
|
3686
|
-
static async
|
|
3687
|
-
const context = new PowerlinesExecutionContext(options);
|
|
3688
|
-
await context.init(
|
|
3689
|
-
const powerlinesPath = await resolvePackage("powerlines");
|
|
3690
|
-
if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
|
|
3691
|
-
context.powerlinesPath = powerlinesPath;
|
|
3692
|
-
await context.setup();
|
|
3758
|
+
static async fromInitialConfig(options, initialConfig) {
|
|
3759
|
+
const context = new PowerlinesExecutionContext(options, initialConfig);
|
|
3760
|
+
await context.init();
|
|
3693
3761
|
return context;
|
|
3694
3762
|
}
|
|
3695
3763
|
/**
|
|
@@ -3698,19 +3766,10 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3698
3766
|
* @param options - The options for resolving the context.
|
|
3699
3767
|
* @returns A promise that resolves to the new context.
|
|
3700
3768
|
*/
|
|
3701
|
-
static async
|
|
3702
|
-
const context = new PowerlinesExecutionContext(options);
|
|
3703
|
-
await context.init(
|
|
3704
|
-
context.
|
|
3705
|
-
if (context.config.inlineConfig.command === "new") {
|
|
3706
|
-
const workspacePackageJsonPath = joinPaths$1(context.config.cwd, "package.json");
|
|
3707
|
-
if (!existsSync(workspacePackageJsonPath)) throw new Error(`The workspace package.json file could not be found at ${workspacePackageJsonPath}`);
|
|
3708
|
-
context.packageJson = await readJsonFile(workspacePackageJsonPath);
|
|
3709
|
-
}
|
|
3710
|
-
await context.setup();
|
|
3711
|
-
const powerlinesPath = await resolvePackage("powerlines");
|
|
3712
|
-
if (!powerlinesPath) throw new Error("Could not resolve `powerlines` package location.");
|
|
3713
|
-
context.powerlinesPath = powerlinesPath;
|
|
3769
|
+
static async fromInlineConfig(options, initialConfig, inlineConfig) {
|
|
3770
|
+
const context = new PowerlinesExecutionContext(options, initialConfig);
|
|
3771
|
+
await context.init();
|
|
3772
|
+
await context.setInlineConfig(inlineConfig);
|
|
3714
3773
|
return context;
|
|
3715
3774
|
}
|
|
3716
3775
|
/**
|
|
@@ -3722,7 +3781,7 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3722
3781
|
* @internal
|
|
3723
3782
|
*/
|
|
3724
3783
|
get $$internal() {
|
|
3725
|
-
return
|
|
3784
|
+
return this.#internal;
|
|
3726
3785
|
}
|
|
3727
3786
|
/**
|
|
3728
3787
|
* Internal context fields and methods
|
|
@@ -3733,8 +3792,8 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3733
3792
|
* @internal
|
|
3734
3793
|
*/
|
|
3735
3794
|
set $$internal(value) {
|
|
3736
|
-
|
|
3737
|
-
for (const environment of Object.values(this.environments)) environment.$$internal =
|
|
3795
|
+
this.#internal = value;
|
|
3796
|
+
for (const environment of Object.values(this.environments)) environment.$$internal = value;
|
|
3738
3797
|
}
|
|
3739
3798
|
/**
|
|
3740
3799
|
* 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.
|
|
@@ -3755,9 +3814,26 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3755
3814
|
* Creates a new instance.
|
|
3756
3815
|
*
|
|
3757
3816
|
* @param options - The options to use for creating the context, including the resolved configuration and workspace settings.
|
|
3817
|
+
* @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.
|
|
3818
|
+
*/
|
|
3819
|
+
constructor(options, initialConfig = {}) {
|
|
3820
|
+
super(options, initialConfig);
|
|
3821
|
+
this.initialOptions = options;
|
|
3822
|
+
this.initialConfig = initialConfig;
|
|
3823
|
+
}
|
|
3824
|
+
/**
|
|
3825
|
+
* 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.
|
|
3826
|
+
*
|
|
3827
|
+
* @param config - The inline configuration values to set.
|
|
3828
|
+
* @returns A promise that resolves when the inline configuration values have been set.
|
|
3758
3829
|
*/
|
|
3759
|
-
|
|
3760
|
-
super(
|
|
3830
|
+
async setInlineConfig(config) {
|
|
3831
|
+
await super.setInlineConfig(config);
|
|
3832
|
+
if (this.inlineConfig.command === "new") {
|
|
3833
|
+
const workspacePackageJsonPath = joinPaths$1(this.config.cwd, "package.json");
|
|
3834
|
+
if (!existsSync(workspacePackageJsonPath)) throw new Error(`The workspace package.json file could not be found at ${workspacePackageJsonPath}`);
|
|
3835
|
+
this.packageJson = await readJsonFile(workspacePackageJsonPath);
|
|
3836
|
+
}
|
|
3761
3837
|
}
|
|
3762
3838
|
/**
|
|
3763
3839
|
* Create a new logger instance
|
|
@@ -3787,42 +3863,45 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3787
3863
|
});
|
|
3788
3864
|
}
|
|
3789
3865
|
/**
|
|
3790
|
-
* 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.
|
|
3791
|
-
*
|
|
3792
|
-
* @remarks
|
|
3793
|
-
* 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.
|
|
3794
|
-
*
|
|
3795
|
-
* @returns A promise that resolves to the cloned context.
|
|
3796
|
-
*/
|
|
3797
|
-
async clone() {
|
|
3798
|
-
const clone = await PowerlinesExecutionContext.init(this.options, this.initialConfig);
|
|
3799
|
-
clone.config.userConfig = deepClone(this.config.userConfig);
|
|
3800
|
-
clone.config.initialConfig = deepClone(this.config.initialConfig);
|
|
3801
|
-
clone.config.inlineConfig = deepClone(this.config.inlineConfig);
|
|
3802
|
-
clone.config.pluginConfig = deepClone(this.config.pluginConfig);
|
|
3803
|
-
await clone.setup();
|
|
3804
|
-
clone.$$internal = this.$$internal;
|
|
3805
|
-
return this.copyTo(clone);
|
|
3806
|
-
}
|
|
3807
|
-
/**
|
|
3808
3866
|
* A function to copy the context and update the fields for a specific environment
|
|
3809
3867
|
*
|
|
3810
3868
|
* @param environment - The environment configuration to use.
|
|
3811
3869
|
* @returns A new context instance with the updated environment.
|
|
3812
3870
|
*/
|
|
3813
|
-
async
|
|
3814
|
-
const context =
|
|
3871
|
+
async createEnvironment(environment) {
|
|
3872
|
+
const context = await PowerlinesEnvironmentContext.createEnvironment(deepClone(this.options), deepClone(this.config), deepClone(this.overriddenConfig), deepClone(environment));
|
|
3873
|
+
context.$$internal = this.$$internal;
|
|
3874
|
+
context.dependencies = deepClone(this.dependencies);
|
|
3875
|
+
context.devDependencies = deepClone(this.devDependencies);
|
|
3876
|
+
context.persistedMeta = deepClone(this.persistedMeta);
|
|
3877
|
+
context.resolvePatterns = deepClone(this.resolvePatterns);
|
|
3878
|
+
context.powerlinesPath ??= this.powerlinesPath;
|
|
3879
|
+
context.resolver ??= this.resolver;
|
|
3815
3880
|
context.plugins = [];
|
|
3816
3881
|
for (const plugin of this.plugins) await context.addPlugin(plugin);
|
|
3882
|
+
for (const [key, value] of Object.entries(this)) if (![
|
|
3883
|
+
"fs",
|
|
3884
|
+
"$$internal",
|
|
3885
|
+
"dependencies",
|
|
3886
|
+
"devDependencies",
|
|
3887
|
+
"persistedMeta",
|
|
3888
|
+
"packageJson",
|
|
3889
|
+
"projectJson",
|
|
3890
|
+
"tsconfig",
|
|
3891
|
+
"resolver",
|
|
3892
|
+
"plugins",
|
|
3893
|
+
"environments"
|
|
3894
|
+
].includes(key)) if (isObject(value) || Array.isArray(value)) context[key] = deepClone(value);
|
|
3895
|
+
else context[key] = value;
|
|
3817
3896
|
return context;
|
|
3818
3897
|
}
|
|
3819
3898
|
/**
|
|
3820
3899
|
* Update the context using a new inline configuration options
|
|
3821
3900
|
*/
|
|
3822
|
-
async
|
|
3823
|
-
await super.
|
|
3901
|
+
async resolveConfig() {
|
|
3902
|
+
await super.resolveConfig();
|
|
3824
3903
|
await Promise.all(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) => {
|
|
3825
|
-
this.#environments[env.name] = await this.
|
|
3904
|
+
this.#environments[env.name] = await this.createEnvironment(env);
|
|
3826
3905
|
}));
|
|
3827
3906
|
}
|
|
3828
3907
|
/**
|
|
@@ -3847,12 +3926,20 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3847
3926
|
if (name) environment = this.environments[name];
|
|
3848
3927
|
if (Object.keys(this.environments).length === 1) {
|
|
3849
3928
|
environment = this.environments[Object.keys(this.environments)[0]];
|
|
3850
|
-
this.
|
|
3929
|
+
this.trace({
|
|
3930
|
+
meta: { category: "plugins" },
|
|
3931
|
+
message: `Applying the only configured environment: ${chalk.bold.cyanBright(environment?.config.environment?.name)}`
|
|
3932
|
+
});
|
|
3851
3933
|
}
|
|
3852
3934
|
if (!environment) {
|
|
3853
3935
|
if (name) throw new Error(`Environment "${name}" not found.`);
|
|
3854
|
-
environment = await this.
|
|
3855
|
-
|
|
3936
|
+
environment = await PowerlinesEnvironmentContext.createEnvironment(deepClone(this.options), deepClone(this.config), deepClone(this.overriddenConfig), deepClone(createDefaultEnvironment(this.config)));
|
|
3937
|
+
environment.plugins = [];
|
|
3938
|
+
for (const plugin of this.plugins) await environment.addPlugin(plugin);
|
|
3939
|
+
this.warn({
|
|
3940
|
+
meta: { category: "plugins" },
|
|
3941
|
+
message: `No environment specified, and no default environment found. Using a temporary default environment: ${chalk.bold.cyanBright(environment.config.environment?.name)}`
|
|
3942
|
+
});
|
|
3856
3943
|
}
|
|
3857
3944
|
return environment;
|
|
3858
3945
|
}
|
|
@@ -3880,8 +3967,11 @@ var PowerlinesExecutionContext = class PowerlinesExecutionContext extends Powerl
|
|
|
3880
3967
|
async toEnvironment() {
|
|
3881
3968
|
let environment;
|
|
3882
3969
|
if (Object.keys(this.environments).length > 1) {
|
|
3883
|
-
environment = await this.
|
|
3884
|
-
this.debug(
|
|
3970
|
+
environment = await this.createEnvironment(createEnvironment(GLOBAL_ENVIRONMENT, this.config));
|
|
3971
|
+
this.debug({
|
|
3972
|
+
meta: { category: "plugins" },
|
|
3973
|
+
message: `Combined all ${Object.keys(this.environments).length} environments into a single global context.`
|
|
3974
|
+
});
|
|
3885
3975
|
} else environment = await this.getEnvironment();
|
|
3886
3976
|
return environment;
|
|
3887
3977
|
}
|
|
@@ -4301,11 +4391,11 @@ async function installDependencies(context) {
|
|
|
4301
4391
|
//#endregion
|
|
4302
4392
|
//#region src/_internal/helpers/resolve-tsconfig.ts
|
|
4303
4393
|
function getTsconfigDtsPath(context) {
|
|
4304
|
-
return joinPaths(relativePath(joinPaths(context.
|
|
4394
|
+
return joinPaths(relativePath(joinPaths(context.config.cwd, context.config.root), findFilePath(context.typesPath)), findFileName(context.typesPath));
|
|
4305
4395
|
}
|
|
4306
4396
|
async function resolveTsconfigChanges(context) {
|
|
4307
|
-
const tsconfig = getParsedTypeScriptConfig(context.
|
|
4308
|
-
const tsconfigJson = await readJsonFile(getTsconfigFilePath(context.
|
|
4397
|
+
const tsconfig = getParsedTypeScriptConfig(context.config.cwd, context.config.root, context.config.tsconfig, context.config.tsconfigRaw);
|
|
4398
|
+
const tsconfigJson = await readJsonFile(getTsconfigFilePath(context.config.cwd, context.config.root, context.config.tsconfig));
|
|
4309
4399
|
tsconfigJson.compilerOptions ??= {};
|
|
4310
4400
|
if (context.config.output.dts !== false) {
|
|
4311
4401
|
const dtsRelativePath = getTsconfigDtsPath(context);
|
|
@@ -4395,353 +4485,86 @@ var PowerlinesExecution = class PowerlinesExecution {
|
|
|
4395
4485
|
* The Powerlines context
|
|
4396
4486
|
*/
|
|
4397
4487
|
#context;
|
|
4398
|
-
async #handleBuild(context) {
|
|
4399
|
-
await this.callHook("build", {
|
|
4400
|
-
environment: context,
|
|
4401
|
-
order: "pre"
|
|
4402
|
-
});
|
|
4403
|
-
context.debug("Formatting the generated entry files before the build process starts.");
|
|
4404
|
-
await formatFolder(context, context.entryPath);
|
|
4405
|
-
await this.callHook("build", {
|
|
4406
|
-
environment: context,
|
|
4407
|
-
order: "normal"
|
|
4408
|
-
});
|
|
4409
|
-
if (context.config.output.copy) {
|
|
4410
|
-
context.debug("Copying project's files from build output directory.");
|
|
4411
|
-
const destinationPath = isParentPath(appendPath(context.config.output.path, context.config.cwd), appendPath(context.config.root, context.config.cwd)) ? joinPaths(context.config.output.copy.path, relativePath(appendPath(context.config.root, context.config.cwd), appendPath(context.config.output.path, context.config.cwd))) : joinPaths(context.config.output.copy.path, "dist");
|
|
4412
|
-
const sourcePath = context.config.output.path;
|
|
4413
|
-
if (existsSync(sourcePath) && sourcePath !== destinationPath) {
|
|
4414
|
-
context.debug(`Copying files from project's build output directory (${context.config.output.path}) to the project's copy/publish directory (${destinationPath}).`);
|
|
4415
|
-
await copyFiles(sourcePath, destinationPath);
|
|
4416
|
-
} else context.warn(`The source path for the copy operation ${!existsSync(sourcePath) ? "does not exist" : "is the same as the destination path"}. Source: ${sourcePath}, Destination: ${destinationPath}. Skipping copying of build output files.`);
|
|
4417
|
-
if (context.config.output.copy.assets && Array.isArray(context.config.output.copy.assets)) await Promise.all(context.config.output.copy.assets.map(async (asset) => {
|
|
4418
|
-
context.trace(`Copying asset(s): ${chalk.redBright(context.config.cwd === asset.input ? asset.glob : appendPath(asset.glob, replacePath(asset.input, context.config.cwd)))} -> ${chalk.greenBright(appendPath(asset.glob, replacePath(asset.output, context.config.cwd)))} ${Array.isArray(asset.ignore) && asset.ignore.length > 0 ? ` (ignoring: ${asset.ignore.map((i) => chalk.yellowBright(i)).join(", ")})` : ""}`);
|
|
4419
|
-
await context.fs.copy(asset, asset.output);
|
|
4420
|
-
}));
|
|
4421
|
-
} else context.debug("No copy configuration found for the project output. Skipping the copying of build output files.");
|
|
4422
|
-
await this.callHook("build", {
|
|
4423
|
-
environment: context,
|
|
4424
|
-
order: "post"
|
|
4425
|
-
});
|
|
4426
|
-
}
|
|
4427
4488
|
/**
|
|
4428
|
-
*
|
|
4489
|
+
* Initialize a Powerlines API instance
|
|
4429
4490
|
*
|
|
4430
|
-
* @
|
|
4491
|
+
* @param options - The options to initialize the API with
|
|
4492
|
+
* @returns A new instance of the Powerlines API
|
|
4431
4493
|
*/
|
|
4432
|
-
async
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
}
|
|
4437
|
-
this.context.debug(`Found ${Object.keys(this.context.config.environments).length} configured environment(s) for this Powerlines project.`);
|
|
4438
|
-
return (await Promise.all(Object.entries(this.context.config.environments).map(async ([name, config]) => {
|
|
4439
|
-
if (!await this.context.getEnvironmentSafe(name)) {
|
|
4440
|
-
const resolvedEnvironment = await this.callHook("configEnvironment", { environment: name }, name, config);
|
|
4441
|
-
if (resolvedEnvironment) this.context.environments[name] = await this.context.in(resolvedEnvironment);
|
|
4442
|
-
}
|
|
4443
|
-
return this.context.environments[name];
|
|
4444
|
-
}))).filter((context) => isSet(context));
|
|
4494
|
+
static async from(options, initialConfig) {
|
|
4495
|
+
const api = new PowerlinesExecution(await PowerlinesExecutionContext.fromInitialConfig(options, initialConfig ?? {}));
|
|
4496
|
+
await api.init();
|
|
4497
|
+
return api;
|
|
4445
4498
|
}
|
|
4446
4499
|
/**
|
|
4447
|
-
*
|
|
4448
|
-
*
|
|
4449
|
-
* @param handle - The handler function to execute for each environment
|
|
4500
|
+
* The Powerlines context
|
|
4450
4501
|
*/
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
return Promise.resolve(handle(context));
|
|
4454
|
-
}));
|
|
4502
|
+
get context() {
|
|
4503
|
+
return this.#context;
|
|
4455
4504
|
}
|
|
4456
4505
|
/**
|
|
4457
|
-
*
|
|
4506
|
+
* Generate the Powerlines typescript declaration file
|
|
4458
4507
|
*
|
|
4459
|
-
* @
|
|
4460
|
-
*
|
|
4461
|
-
*
|
|
4508
|
+
* @remarks
|
|
4509
|
+
* 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.
|
|
4510
|
+
*
|
|
4511
|
+
* @param inlineConfig - The inline configuration for the types command
|
|
4462
4512
|
*/
|
|
4463
|
-
async
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
plugins
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
if (
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
} else if (isFunction(pluginConfig)) plugins = toArray(await Promise.resolve(pluginConfig(pluginOptions)));
|
|
4499
|
-
else if (Array.isArray(pluginConfig) && pluginConfig.every(isPlugin)) plugins = pluginConfig;
|
|
4500
|
-
else if (isPlugin(pluginConfig)) plugins = toArray(pluginConfig);
|
|
4501
|
-
}
|
|
4502
|
-
if (!plugins) throw new Error(`The plugin configuration ${JSON.stringify(awaited)} is invalid. This configuration must point to a valid Powerlines plugin module.`);
|
|
4503
|
-
if (plugins.length > 0 && !plugins.every(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.`);
|
|
4504
|
-
const result = [];
|
|
4505
|
-
for (const plugin of plugins) if (isDuplicate(plugin, this.context.plugins)) this.context.trace(`Duplicate ${chalk.bold.cyanBright(plugin.name)} plugin dependency detected - Skipping initialization.`);
|
|
4506
|
-
else {
|
|
4507
|
-
result.push(plugin);
|
|
4508
|
-
this.context.trace(`Initializing the ${chalk.bold.cyanBright(plugin.name)} plugin...`);
|
|
4509
|
-
}
|
|
4510
|
-
return result;
|
|
4511
|
-
}
|
|
4512
|
-
async #resolvePlugin(pluginPath) {
|
|
4513
|
-
if (pluginPath.startsWith("@") && pluginPath.split("/").filter(Boolean).length > 2) {
|
|
4514
|
-
const splits = pluginPath.split("/").filter(Boolean);
|
|
4515
|
-
pluginPath = `${splits[0]}/${splits[1]}`;
|
|
4516
|
-
}
|
|
4517
|
-
const isInstalled = isPackageExists(pluginPath, { paths: [this.context.config.cwd, this.context.config.root] });
|
|
4518
|
-
if (!isInstalled && this.context.config.autoInstall) {
|
|
4519
|
-
this.#context.warn(`The plugin package "${pluginPath}" is not installed. It will be installed automatically.`);
|
|
4520
|
-
const result = await install(pluginPath, { cwd: this.context.config.root });
|
|
4521
|
-
if (isNumber(result.exitCode) && result.exitCode > 0) {
|
|
4522
|
-
this.#context.error(result.stderr);
|
|
4523
|
-
throw new Error(`An error occurred while installing the build plugin package "${pluginPath}" `);
|
|
4524
|
-
}
|
|
4525
|
-
}
|
|
4526
|
-
try {
|
|
4527
|
-
const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve(joinPaths(pluginPath, "plugin")));
|
|
4528
|
-
const result = module.plugin ?? module.default;
|
|
4529
|
-
if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
|
|
4530
|
-
return result;
|
|
4531
|
-
} catch (error) {
|
|
4532
|
-
try {
|
|
4533
|
-
const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve(pluginPath));
|
|
4534
|
-
const result = module.plugin ?? module.default;
|
|
4535
|
-
if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
|
|
4536
|
-
return result;
|
|
4537
|
-
} catch {
|
|
4538
|
-
if (!isInstalled) throw new Error(`The plugin package "${pluginPath}" is not installed. Please install the package using the command: "npm install ${pluginPath} --save-dev"`);
|
|
4539
|
-
else throw new Error(`An error occurred while importing the build plugin package "${pluginPath}":
|
|
4540
|
-
${isError(error) ? error.message : String(error)}
|
|
4541
|
-
|
|
4542
|
-
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\`.`);
|
|
4513
|
+
async types(inlineConfig = { command: "types" }) {
|
|
4514
|
+
this.context.debug(" Aggregating configuration options for the Powerlines project");
|
|
4515
|
+
inlineConfig.command ??= "types";
|
|
4516
|
+
await this.context.setInlineConfig(inlineConfig);
|
|
4517
|
+
await this.executeEnvironments(async (context) => {
|
|
4518
|
+
context.debug(`Initializing the processing options for the Powerlines project.`);
|
|
4519
|
+
await this.callHook("configResolved", {
|
|
4520
|
+
environment: context,
|
|
4521
|
+
order: "pre"
|
|
4522
|
+
});
|
|
4523
|
+
await initializeTsconfig(context);
|
|
4524
|
+
await this.callHook("configResolved", {
|
|
4525
|
+
environment: context,
|
|
4526
|
+
order: "normal"
|
|
4527
|
+
});
|
|
4528
|
+
if (context.entry.length > 0) context.debug(`The configuration provided ${isObject(context.config.input) ? Object.keys(context.config.input).length : 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")}` : ""}`);
|
|
4529
|
+
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.`);
|
|
4530
|
+
await resolveTsconfig(context);
|
|
4531
|
+
await installDependencies(context);
|
|
4532
|
+
await this.callHook("configResolved", {
|
|
4533
|
+
environment: context,
|
|
4534
|
+
order: "post"
|
|
4535
|
+
});
|
|
4536
|
+
context.trace(`Powerlines configuration has been resolved: \n\n${formatLogMessage({
|
|
4537
|
+
...context.config,
|
|
4538
|
+
userConfig: isSetObject(context.config.userConfig) ? omit(context.config.userConfig, ["plugins"]) : void 0,
|
|
4539
|
+
inlineConfig: isSetObject(context.config.inlineConfig) ? omit(context.config.inlineConfig, ["plugins"]) : void 0,
|
|
4540
|
+
plugins: context.plugins.map((plugin) => plugin.plugin.name)
|
|
4541
|
+
})}`);
|
|
4542
|
+
if (!context.fs.existsSync(context.cachePath)) await createDirectory(context.cachePath);
|
|
4543
|
+
if (!context.fs.existsSync(context.dataPath)) await createDirectory(context.dataPath);
|
|
4544
|
+
if (context.config.skipCache === true || context.persistedMeta?.checksum !== context.meta.checksum) context.debug(`Using previously prepared files as the meta checksum has not changed.`);
|
|
4545
|
+
else {
|
|
4546
|
+
context.info(`Running \`prepare\` command as the meta checksum has changed since the last run.`);
|
|
4547
|
+
await this.prepare(defu({ output: { types: false } }, inlineConfig));
|
|
4543
4548
|
}
|
|
4544
|
-
|
|
4549
|
+
await this.handleTypes(context);
|
|
4550
|
+
this.context.debug("Formatting files generated during the types step.");
|
|
4551
|
+
await format(context, context.typesPath, await context.fs.read(context.typesPath) ?? "");
|
|
4552
|
+
await writeMetaFile(context);
|
|
4553
|
+
context.persistedMeta = context.meta;
|
|
4554
|
+
});
|
|
4545
4555
|
}
|
|
4546
4556
|
/**
|
|
4547
|
-
*
|
|
4557
|
+
* Prepare the Powerlines API
|
|
4548
4558
|
*
|
|
4549
4559
|
* @remarks
|
|
4550
|
-
* This method will
|
|
4560
|
+
* This method will prepare the Powerlines API for use, initializing any necessary resources.
|
|
4551
4561
|
*
|
|
4552
|
-
* @param
|
|
4553
|
-
* @returns A promise that resolves when the TypeScript declaration file has been generated
|
|
4554
|
-
*/
|
|
4555
|
-
async #types(context) {
|
|
4556
|
-
context.debug(`Preparing the TypeScript definitions for the Powerlines project.`);
|
|
4557
|
-
if (context.fs.existsSync(context.typesPath)) await context.fs.remove(context.typesPath);
|
|
4558
|
-
if (!await resolvePackage("typescript")) throw new Error("Could not resolve TypeScript package location. Please ensure TypeScript is installed.");
|
|
4559
|
-
context.debug("Running TypeScript compiler for built-in runtime module files.");
|
|
4560
|
-
let { code, directives } = await emitBuiltinTypes(context, (await context.getBuiltins()).reduce((ret, builtin) => {
|
|
4561
|
-
const formatted = replacePath(builtin.path, context.config.cwd);
|
|
4562
|
-
if (!ret.includes(formatted)) ret.push(formatted);
|
|
4563
|
-
return ret;
|
|
4564
|
-
}, []));
|
|
4565
|
-
context.debug(`Generating TypeScript declaration file ${context.typesPath}.`);
|
|
4566
|
-
const merge = async (currentResult, previousResult) => {
|
|
4567
|
-
if (!isSetString(currentResult) && !isSetObject(currentResult) && !isSetString(previousResult) && !isSetObject(previousResult)) return {
|
|
4568
|
-
code,
|
|
4569
|
-
directives
|
|
4570
|
-
};
|
|
4571
|
-
const previous = (await format(context, context.typesPath, isSetString(previousResult) ? previousResult : isSetObject(previousResult) ? previousResult.code : "")).trim().replace(code, "").trim();
|
|
4572
|
-
const current = (await format(context, context.typesPath, isSetString(currentResult) ? currentResult : isSetObject(currentResult) ? currentResult.code : "")).trim().replace(previous, "").trim().replace(code, "").trim();
|
|
4573
|
-
return {
|
|
4574
|
-
directives: [...isSetObject(currentResult) && currentResult.directives ? currentResult.directives : [], ...isSetObject(previousResult) && previousResult.directives ? previousResult.directives : []],
|
|
4575
|
-
code: await format(context, context.typesPath, `${!previous.includes(getTypescriptFileHeader(context)) && !current.includes(getTypescriptFileHeader(context)) ? `${code}\n` : ""}${previous}\n${current}`.trim())
|
|
4576
|
-
};
|
|
4577
|
-
};
|
|
4578
|
-
const asNextParam = (previousResult) => isObject(previousResult) ? previousResult.code : previousResult;
|
|
4579
|
-
let result = await this.callHook("types", {
|
|
4580
|
-
environment: context,
|
|
4581
|
-
sequential: true,
|
|
4582
|
-
order: "pre",
|
|
4583
|
-
result: "merge",
|
|
4584
|
-
merge,
|
|
4585
|
-
asNextParam
|
|
4586
|
-
}, code);
|
|
4587
|
-
if (result) {
|
|
4588
|
-
if (isSetObject(result)) {
|
|
4589
|
-
code = result.code;
|
|
4590
|
-
if (Array.isArray(result.directives) && result.directives.length > 0) directives = getUnique([...directives, ...result.directives]).filter(Boolean);
|
|
4591
|
-
} else if (isSetString(result)) code = result;
|
|
4592
|
-
}
|
|
4593
|
-
result = await this.callHook("types", {
|
|
4594
|
-
environment: context,
|
|
4595
|
-
sequential: true,
|
|
4596
|
-
order: "normal",
|
|
4597
|
-
result: "merge",
|
|
4598
|
-
merge,
|
|
4599
|
-
asNextParam
|
|
4600
|
-
}, code);
|
|
4601
|
-
if (result) {
|
|
4602
|
-
if (isSetObject(result)) {
|
|
4603
|
-
code = result.code;
|
|
4604
|
-
if (Array.isArray(result.directives) && result.directives.length > 0) directives = getUnique([...directives, ...result.directives]).filter(Boolean);
|
|
4605
|
-
} else if (isSetString(result)) code = result;
|
|
4606
|
-
}
|
|
4607
|
-
result = await this.callHook("types", {
|
|
4608
|
-
environment: context,
|
|
4609
|
-
sequential: true,
|
|
4610
|
-
order: "post",
|
|
4611
|
-
result: "merge",
|
|
4612
|
-
merge,
|
|
4613
|
-
asNextParam
|
|
4614
|
-
}, code);
|
|
4615
|
-
if (result) {
|
|
4616
|
-
if (isSetObject(result)) {
|
|
4617
|
-
code = result.code;
|
|
4618
|
-
if (Array.isArray(result.directives) && result.directives.length > 0) directives = getUnique([...directives, ...result.directives]).filter(Boolean);
|
|
4619
|
-
} else if (isSetString(result)) code = result;
|
|
4620
|
-
}
|
|
4621
|
-
if (isSetString(code?.trim()) || directives.length > 0) await context.fs.write(context.typesPath, `${directives.length > 0 ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
|
|
4622
|
-
|
|
4623
|
-
` : ""}${getTypescriptFileHeader(context, {
|
|
4624
|
-
directive: null,
|
|
4625
|
-
prettierIgnore: false
|
|
4626
|
-
})}
|
|
4627
|
-
|
|
4628
|
-
${formatTypes(code)}
|
|
4629
|
-
`);
|
|
4630
|
-
}
|
|
4631
|
-
/**
|
|
4632
|
-
* Initialize a Powerlines API instance
|
|
4633
|
-
*
|
|
4634
|
-
* @param options - The options to initialize the API with
|
|
4635
|
-
* @returns A new instance of the Powerlines API
|
|
4636
|
-
*/
|
|
4637
|
-
static async init(options, initialConfig) {
|
|
4638
|
-
const api = new PowerlinesExecution(await PowerlinesExecutionContext.init(options, initialConfig ?? {}));
|
|
4639
|
-
api.#context.config.initialConfig = initialConfig ?? {};
|
|
4640
|
-
await api.setup();
|
|
4641
|
-
return api;
|
|
4642
|
-
}
|
|
4643
|
-
/**
|
|
4644
|
-
* The Powerlines context
|
|
4645
|
-
*/
|
|
4646
|
-
get context() {
|
|
4647
|
-
return this.#context;
|
|
4648
|
-
}
|
|
4649
|
-
/**
|
|
4650
|
-
* Initialize the execution API with the provided configuration options
|
|
4651
|
-
*/
|
|
4652
|
-
async setup() {
|
|
4653
|
-
await this.#context.setup();
|
|
4654
|
-
this.#context.$$internal = {
|
|
4655
|
-
api: this,
|
|
4656
|
-
addPlugin: this.addPlugin.bind(this)
|
|
4657
|
-
};
|
|
4658
|
-
const timer = this.#context.timer("Initialization");
|
|
4659
|
-
for (const plugin of this.#context.config.plugins.flatMap((p) => toArray(p)) ?? []) await this.addPlugin(plugin);
|
|
4660
|
-
if (this.#context.plugins.length === 0) this.#context.warn({
|
|
4661
|
-
meta: { category: "plugins" },
|
|
4662
|
-
message: "No Powerlines plugins were specified in the options. Please ensure this is correct, as it is generally not recommended."
|
|
4663
|
-
});
|
|
4664
|
-
else this.#context.info({
|
|
4665
|
-
meta: { category: "plugins" },
|
|
4666
|
-
message: `Loaded ${this.#context.plugins.length} ${titleCase(this.#context.config.framework)} plugin${this.#context.plugins.length > 1 ? "s" : ""}: \n${this.#context.plugins.map((plugin, index) => ` ${index + 1}. ${colorText(plugin.name)}`).join("\n")}`
|
|
4667
|
-
});
|
|
4668
|
-
const pluginConfig = await this.callHook("config", {
|
|
4669
|
-
environment: await this.#context.getEnvironment(),
|
|
4670
|
-
sequential: true,
|
|
4671
|
-
result: "merge",
|
|
4672
|
-
merge: mergeConfigs
|
|
4673
|
-
});
|
|
4674
|
-
if (pluginConfig) {
|
|
4675
|
-
this.#context.config.pluginConfig = pluginConfig;
|
|
4676
|
-
await this.#context.setup();
|
|
4677
|
-
}
|
|
4678
|
-
timer();
|
|
4679
|
-
}
|
|
4680
|
-
/**
|
|
4681
|
-
* Generate the Powerlines typescript declaration file
|
|
4682
|
-
*
|
|
4683
|
-
* @remarks
|
|
4684
|
-
* 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.
|
|
4685
|
-
*
|
|
4686
|
-
* @param inlineConfig - The inline configuration for the types command
|
|
4687
|
-
*/
|
|
4688
|
-
async types(inlineConfig = { command: "types" }) {
|
|
4689
|
-
this.context.debug(" Aggregating configuration options for the Powerlines project");
|
|
4690
|
-
inlineConfig.command ??= "types";
|
|
4691
|
-
this.context.config.inlineConfig = inlineConfig;
|
|
4692
|
-
await this.setup();
|
|
4693
|
-
await this.#executeEnvironments(async (context) => {
|
|
4694
|
-
context.debug(`Initializing the processing options for the Powerlines project.`);
|
|
4695
|
-
await this.callHook("configResolved", {
|
|
4696
|
-
environment: context,
|
|
4697
|
-
order: "pre"
|
|
4698
|
-
});
|
|
4699
|
-
await initializeTsconfig(context);
|
|
4700
|
-
await this.callHook("configResolved", {
|
|
4701
|
-
environment: context,
|
|
4702
|
-
order: "normal"
|
|
4703
|
-
});
|
|
4704
|
-
if (context.entry.length > 0) context.debug(`The configuration provided ${isObject(context.config.input) ? Object.keys(context.config.input).length : 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")}` : ""}`);
|
|
4705
|
-
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.`);
|
|
4706
|
-
await resolveTsconfig(context);
|
|
4707
|
-
await installDependencies(context);
|
|
4708
|
-
await this.callHook("configResolved", {
|
|
4709
|
-
environment: context,
|
|
4710
|
-
order: "post"
|
|
4711
|
-
});
|
|
4712
|
-
context.trace(`Powerlines configuration has been resolved: \n\n${formatLogMessage({
|
|
4713
|
-
...context.config,
|
|
4714
|
-
userConfig: isSetObject(context.config.userConfig) ? omit(context.config.userConfig, ["plugins"]) : void 0,
|
|
4715
|
-
inlineConfig: isSetObject(context.config.inlineConfig) ? omit(context.config.inlineConfig, ["plugins"]) : void 0,
|
|
4716
|
-
plugins: context.plugins.map((plugin) => plugin.plugin.name)
|
|
4717
|
-
})}`);
|
|
4718
|
-
if (!context.fs.existsSync(context.cachePath)) await createDirectory(context.cachePath);
|
|
4719
|
-
if (!context.fs.existsSync(context.dataPath)) await createDirectory(context.dataPath);
|
|
4720
|
-
if (context.config.skipCache === true || context.persistedMeta?.checksum !== context.meta.checksum) context.debug(`Using previously prepared files as the meta checksum has not changed.`);
|
|
4721
|
-
else {
|
|
4722
|
-
context.info(`Running \`prepare\` command as the meta checksum has changed since the last run.`);
|
|
4723
|
-
await this.prepare(defu({ output: { types: false } }, inlineConfig));
|
|
4724
|
-
}
|
|
4725
|
-
await this.#types(context);
|
|
4726
|
-
this.context.debug("Formatting files generated during the types step.");
|
|
4727
|
-
await format(context, context.typesPath, await context.fs.read(context.typesPath) ?? "");
|
|
4728
|
-
await writeMetaFile(context);
|
|
4729
|
-
context.persistedMeta = context.meta;
|
|
4730
|
-
});
|
|
4731
|
-
}
|
|
4732
|
-
/**
|
|
4733
|
-
* Prepare the Powerlines API
|
|
4734
|
-
*
|
|
4735
|
-
* @remarks
|
|
4736
|
-
* This method will prepare the Powerlines API for use, initializing any necessary resources.
|
|
4737
|
-
*
|
|
4738
|
-
* @param inlineConfig - The inline configuration for the prepare command
|
|
4562
|
+
* @param inlineConfig - The inline configuration for the prepare command
|
|
4739
4563
|
*/
|
|
4740
4564
|
async prepare(inlineConfig = { command: "prepare" }) {
|
|
4741
4565
|
inlineConfig.command ??= "prepare";
|
|
4742
|
-
this.context.
|
|
4743
|
-
await this.
|
|
4744
|
-
await this.#executeEnvironments(async (context) => {
|
|
4566
|
+
await this.context.setInlineConfig(inlineConfig);
|
|
4567
|
+
await this.executeEnvironments(async (context) => {
|
|
4745
4568
|
context.debug(`Initializing the processing options for the Powerlines project.`);
|
|
4746
4569
|
await this.callHook("configResolved", {
|
|
4747
4570
|
environment: context,
|
|
@@ -4791,7 +4614,7 @@ ${formatTypes(code)}
|
|
|
4791
4614
|
environment: context,
|
|
4792
4615
|
order: "post"
|
|
4793
4616
|
});
|
|
4794
|
-
if (context.config.output.types !== false) await this
|
|
4617
|
+
if (context.config.output.types !== false) await this.handleTypes(context);
|
|
4795
4618
|
this.context.debug("Formatting files generated during the prepare step.");
|
|
4796
4619
|
await Promise.all([formatFolder(context, context.builtinsPath), formatFolder(context, context.entryPath)]);
|
|
4797
4620
|
await writeMetaFile(context);
|
|
@@ -4810,7 +4633,7 @@ ${formatTypes(code)}
|
|
|
4810
4633
|
async new(inlineConfig) {
|
|
4811
4634
|
inlineConfig.command ??= "new";
|
|
4812
4635
|
await this.prepare(inlineConfig);
|
|
4813
|
-
await this
|
|
4636
|
+
await this.executeEnvironments(async (context) => {
|
|
4814
4637
|
context.debug("Initializing the processing options for the Powerlines project.");
|
|
4815
4638
|
await this.callHook("new", {
|
|
4816
4639
|
environment: context,
|
|
@@ -4859,7 +4682,7 @@ ${formatTypes(code)}
|
|
|
4859
4682
|
async clean(inlineConfig = { command: "clean" }) {
|
|
4860
4683
|
inlineConfig.command ??= "clean";
|
|
4861
4684
|
await this.prepare(inlineConfig);
|
|
4862
|
-
await this
|
|
4685
|
+
await this.executeEnvironments(async (context) => {
|
|
4863
4686
|
context.debug("Cleaning the project's dist and artifacts directories.");
|
|
4864
4687
|
await context.fs.remove(joinPaths(context.config.cwd, context.config.output.path));
|
|
4865
4688
|
await context.fs.remove(joinPaths(context.config.cwd, context.config.root, context.config.output.artifactsPath));
|
|
@@ -4878,7 +4701,7 @@ ${formatTypes(code)}
|
|
|
4878
4701
|
async lint(inlineConfig = { command: "lint" }) {
|
|
4879
4702
|
inlineConfig.command ??= "lint";
|
|
4880
4703
|
await this.prepare(inlineConfig);
|
|
4881
|
-
await this
|
|
4704
|
+
await this.executeEnvironments(async (context) => {
|
|
4882
4705
|
await this.callHook("lint", {
|
|
4883
4706
|
environment: context,
|
|
4884
4707
|
sequential: false
|
|
@@ -4894,7 +4717,7 @@ ${formatTypes(code)}
|
|
|
4894
4717
|
async test(inlineConfig = { command: "test" }) {
|
|
4895
4718
|
inlineConfig.command ??= "test";
|
|
4896
4719
|
await this.prepare(inlineConfig);
|
|
4897
|
-
await this
|
|
4720
|
+
await this.executeEnvironments(async (context) => {
|
|
4898
4721
|
await this.callHook("test", {
|
|
4899
4722
|
environment: context,
|
|
4900
4723
|
sequential: false
|
|
@@ -4912,17 +4735,15 @@ ${formatTypes(code)}
|
|
|
4912
4735
|
*/
|
|
4913
4736
|
async build(inlineConfig = { command: "build" }) {
|
|
4914
4737
|
inlineConfig.command ??= "build";
|
|
4738
|
+
await this.context.setInlineConfig(inlineConfig);
|
|
4915
4739
|
await this.context.generateChecksum();
|
|
4916
4740
|
if (this.context.meta.checksum !== this.context.persistedMeta?.checksum || this.context.config.skipCache) {
|
|
4917
4741
|
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.");
|
|
4918
4742
|
await this.prepare(inlineConfig);
|
|
4919
|
-
} else {
|
|
4920
|
-
this.context.config.inlineConfig = inlineConfig;
|
|
4921
|
-
await this.context.setup();
|
|
4922
4743
|
}
|
|
4923
|
-
if (this.context.config.singleBuild) await this
|
|
4924
|
-
else await this
|
|
4925
|
-
await this
|
|
4744
|
+
if (this.context.config.singleBuild) await this.handleBuild(await this.#context.toEnvironment());
|
|
4745
|
+
else await this.executeEnvironments(async (context) => {
|
|
4746
|
+
await this.handleBuild(context);
|
|
4926
4747
|
});
|
|
4927
4748
|
}
|
|
4928
4749
|
/**
|
|
@@ -4933,8 +4754,9 @@ ${formatTypes(code)}
|
|
|
4933
4754
|
*/
|
|
4934
4755
|
async docs(inlineConfig = { command: "docs" }) {
|
|
4935
4756
|
inlineConfig.command ??= "docs";
|
|
4757
|
+
await this.context.setInlineConfig(inlineConfig);
|
|
4936
4758
|
await this.prepare(inlineConfig);
|
|
4937
|
-
await this
|
|
4759
|
+
await this.executeEnvironments(async (context) => {
|
|
4938
4760
|
context.debug("Writing documentation for the Powerlines project artifacts.");
|
|
4939
4761
|
await this.callHook("docs", { environment: context });
|
|
4940
4762
|
});
|
|
@@ -4949,8 +4771,9 @@ ${formatTypes(code)}
|
|
|
4949
4771
|
*/
|
|
4950
4772
|
async deploy(inlineConfig = { command: "deploy" }) {
|
|
4951
4773
|
inlineConfig.command ??= "deploy";
|
|
4774
|
+
await this.context.setInlineConfig(inlineConfig);
|
|
4952
4775
|
await this.prepare(inlineConfig);
|
|
4953
|
-
await this
|
|
4776
|
+
await this.executeEnvironments(async (context) => {
|
|
4954
4777
|
await this.callHook("deploy", { environment: context });
|
|
4955
4778
|
});
|
|
4956
4779
|
}
|
|
@@ -4963,7 +4786,7 @@ ${formatTypes(code)}
|
|
|
4963
4786
|
* @returns A promise that resolves when the finalization process has completed
|
|
4964
4787
|
*/
|
|
4965
4788
|
async finalize() {
|
|
4966
|
-
await this
|
|
4789
|
+
await this.executeEnvironments(async (context) => {
|
|
4967
4790
|
await this.callHook("finalize", { environment: context });
|
|
4968
4791
|
await context.fs.dispose();
|
|
4969
4792
|
if (existsSync(context.cachePath) && !(await listFiles(joinPaths(context.cachePath, "**/*")))?.length) await removeDirectory(context.cachePath);
|
|
@@ -4995,13 +4818,40 @@ ${formatTypes(code)}
|
|
|
4995
4818
|
this.#context = context;
|
|
4996
4819
|
}
|
|
4997
4820
|
/**
|
|
4821
|
+
* Initialize the execution API with the provided configuration options
|
|
4822
|
+
*/
|
|
4823
|
+
async init() {
|
|
4824
|
+
this.#context.$$internal = {
|
|
4825
|
+
api: this,
|
|
4826
|
+
addPlugin: this.addPlugin.bind(this)
|
|
4827
|
+
};
|
|
4828
|
+
const timer = this.#context.timer("Initialization");
|
|
4829
|
+
for (const plugin of this.#context.config.plugins.flatMap((p) => toArray(p)) ?? []) await this.addPlugin(plugin);
|
|
4830
|
+
if (this.#context.plugins.length === 0) this.#context.warn({
|
|
4831
|
+
meta: { category: "plugins" },
|
|
4832
|
+
message: "No Powerlines plugins were specified in the options. Please ensure this is correct, as it is generally not recommended."
|
|
4833
|
+
});
|
|
4834
|
+
else this.#context.info({
|
|
4835
|
+
meta: { category: "plugins" },
|
|
4836
|
+
message: `Loaded ${this.#context.plugins.length} ${titleCase(this.#context.config.framework)} plugin${this.#context.plugins.length > 1 ? "s" : ""}: \n${this.#context.plugins.map((plugin, index) => ` ${index + 1}. ${colorText(plugin.name)}`).join("\n")}`
|
|
4837
|
+
});
|
|
4838
|
+
const pluginConfig = await this.callHook("config", {
|
|
4839
|
+
environment: await this.#context.getEnvironment(),
|
|
4840
|
+
sequential: true,
|
|
4841
|
+
result: "merge",
|
|
4842
|
+
merge: mergeConfigs
|
|
4843
|
+
});
|
|
4844
|
+
if (pluginConfig) await this.context.setPluginConfig(pluginConfig);
|
|
4845
|
+
timer();
|
|
4846
|
+
}
|
|
4847
|
+
/**
|
|
4998
4848
|
* Add a Powerlines plugin used in the build process
|
|
4999
4849
|
*
|
|
5000
4850
|
* @param config - The import path of the plugin to add
|
|
5001
4851
|
*/
|
|
5002
4852
|
async addPlugin(config) {
|
|
5003
4853
|
if (config) {
|
|
5004
|
-
const result = await this
|
|
4854
|
+
const result = await this.initPlugin(config);
|
|
5005
4855
|
if (!result) return;
|
|
5006
4856
|
for (const plugin of result) {
|
|
5007
4857
|
this.context.debug({
|
|
@@ -5012,33 +4862,266 @@ ${formatTypes(code)}
|
|
|
5012
4862
|
}
|
|
5013
4863
|
}
|
|
5014
4864
|
}
|
|
4865
|
+
/**
|
|
4866
|
+
* Get the configured environments
|
|
4867
|
+
*
|
|
4868
|
+
* @returns The configured environments
|
|
4869
|
+
*/
|
|
4870
|
+
async getEnvironments() {
|
|
4871
|
+
if (!this.context.config.environments || Object.keys(this.context.config.environments).length <= 1) {
|
|
4872
|
+
this.context.debug("No environments are configured for this Powerlines project. Using the default environment.");
|
|
4873
|
+
return [await this.context.getEnvironment()];
|
|
4874
|
+
}
|
|
4875
|
+
this.context.debug(`Found ${Object.keys(this.context.config.environments).length} configured environment(s) for this Powerlines project.`);
|
|
4876
|
+
return (await Promise.all(Object.entries(this.context.config.environments).map(async ([name, config]) => {
|
|
4877
|
+
if (!await this.context.getEnvironmentSafe(name)) {
|
|
4878
|
+
const resolvedEnvironment = await this.callHook("configEnvironment", { environment: name }, name, config);
|
|
4879
|
+
if (resolvedEnvironment) this.context.environments[name] = await this.context.createEnvironment(resolvedEnvironment);
|
|
4880
|
+
}
|
|
4881
|
+
return this.context.environments[name];
|
|
4882
|
+
}))).filter((context) => isSet(context));
|
|
4883
|
+
}
|
|
4884
|
+
/**
|
|
4885
|
+
* Execute a handler function for each environment
|
|
4886
|
+
*
|
|
4887
|
+
* @param handle - The handler function to execute for each environment
|
|
4888
|
+
*/
|
|
4889
|
+
async executeEnvironments(handle) {
|
|
4890
|
+
await Promise.all((await this.getEnvironments()).map(async (context) => {
|
|
4891
|
+
return Promise.resolve(handle(context));
|
|
4892
|
+
}));
|
|
4893
|
+
}
|
|
4894
|
+
/**
|
|
4895
|
+
* Initialize a Powerlines plugin
|
|
4896
|
+
*
|
|
4897
|
+
* @param config - The configuration for the plugin
|
|
4898
|
+
* @returns The initialized plugin instance, or null if the plugin was a duplicate
|
|
4899
|
+
* @throws Will throw an error if the plugin cannot be found or is invalid
|
|
4900
|
+
*/
|
|
4901
|
+
async initPlugin(config) {
|
|
4902
|
+
let awaited = config;
|
|
4903
|
+
if (isPromiseLike(config)) awaited = await Promise.resolve(config);
|
|
4904
|
+
if (!isPluginConfig(awaited)) {
|
|
4905
|
+
const invalid = findInvalidPluginConfig(awaited);
|
|
4906
|
+
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`);
|
|
4907
|
+
}
|
|
4908
|
+
let plugins;
|
|
4909
|
+
if (isPlugin(awaited)) plugins = [awaited];
|
|
4910
|
+
else if (isFunction(awaited)) plugins = toArray(await Promise.resolve(awaited()));
|
|
4911
|
+
else if (isString(awaited)) {
|
|
4912
|
+
const resolved = await this.resolvePlugin(awaited);
|
|
4913
|
+
if (isFunction(resolved)) plugins = toArray(await Promise.resolve(resolved()));
|
|
4914
|
+
else plugins = toArray(resolved);
|
|
4915
|
+
} else if (Array.isArray(awaited) && awaited.every(isPlugin)) plugins = awaited;
|
|
4916
|
+
else if (Array.isArray(awaited) && awaited.every(isPluginConfig)) {
|
|
4917
|
+
plugins = [];
|
|
4918
|
+
for (const pluginConfig of awaited) {
|
|
4919
|
+
const initialized = await this.initPlugin(pluginConfig);
|
|
4920
|
+
if (initialized) plugins.push(...initialized);
|
|
4921
|
+
}
|
|
4922
|
+
} else if (isPluginConfigTuple(awaited) || isPluginConfigObject(awaited)) {
|
|
4923
|
+
let pluginConfig;
|
|
4924
|
+
let pluginOptions;
|
|
4925
|
+
if (isPluginConfigTuple(awaited)) {
|
|
4926
|
+
pluginConfig = awaited[0];
|
|
4927
|
+
pluginOptions = awaited?.length === 2 ? awaited[1] : void 0;
|
|
4928
|
+
} else {
|
|
4929
|
+
pluginConfig = awaited.plugin;
|
|
4930
|
+
pluginOptions = awaited.options;
|
|
4931
|
+
}
|
|
4932
|
+
if (isSetString(pluginConfig)) {
|
|
4933
|
+
const resolved = await this.resolvePlugin(pluginConfig);
|
|
4934
|
+
if (isFunction(resolved)) plugins = toArray(await Promise.resolve(pluginOptions ? resolved(pluginOptions) : resolved()));
|
|
4935
|
+
else plugins = toArray(resolved);
|
|
4936
|
+
} else if (isFunction(pluginConfig)) plugins = toArray(await Promise.resolve(pluginConfig(pluginOptions)));
|
|
4937
|
+
else if (Array.isArray(pluginConfig) && pluginConfig.every(isPlugin)) plugins = pluginConfig;
|
|
4938
|
+
else if (isPlugin(pluginConfig)) plugins = toArray(pluginConfig);
|
|
4939
|
+
}
|
|
4940
|
+
if (!plugins) throw new Error(`The plugin configuration ${JSON.stringify(awaited)} is invalid. This configuration must point to a valid Powerlines plugin module.`);
|
|
4941
|
+
if (plugins.length > 0 && !plugins.every(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.`);
|
|
4942
|
+
const result = [];
|
|
4943
|
+
for (const plugin of plugins) if (isDuplicate(plugin, this.context.plugins)) this.context.trace(`Duplicate ${chalk.bold.cyanBright(plugin.name)} plugin dependency detected - Skipping initialization.`);
|
|
4944
|
+
else {
|
|
4945
|
+
result.push(plugin);
|
|
4946
|
+
this.context.trace(`Initializing the ${chalk.bold.cyanBright(plugin.name)} plugin...`);
|
|
4947
|
+
}
|
|
4948
|
+
return result;
|
|
4949
|
+
}
|
|
4950
|
+
async resolvePlugin(pluginPath) {
|
|
4951
|
+
if (pluginPath.startsWith("@") && pluginPath.split("/").filter(Boolean).length > 2) {
|
|
4952
|
+
const splits = pluginPath.split("/").filter(Boolean);
|
|
4953
|
+
pluginPath = `${splits[0]}/${splits[1]}`;
|
|
4954
|
+
}
|
|
4955
|
+
const isInstalled = isPackageExists(pluginPath, { paths: [this.context.config.cwd, this.context.config.root] });
|
|
4956
|
+
if (!isInstalled && this.context.config.autoInstall) {
|
|
4957
|
+
this.#context.warn(`The plugin package "${pluginPath}" is not installed. It will be installed automatically.`);
|
|
4958
|
+
const result = await install(pluginPath, { cwd: this.context.config.root });
|
|
4959
|
+
if (isNumber(result.exitCode) && result.exitCode > 0) {
|
|
4960
|
+
this.#context.error(result.stderr);
|
|
4961
|
+
throw new Error(`An error occurred while installing the build plugin package "${pluginPath}" `);
|
|
4962
|
+
}
|
|
4963
|
+
}
|
|
4964
|
+
try {
|
|
4965
|
+
const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve(joinPaths(pluginPath, "plugin")));
|
|
4966
|
+
const result = module.plugin ?? module.default;
|
|
4967
|
+
if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
|
|
4968
|
+
return result;
|
|
4969
|
+
} catch (error) {
|
|
4970
|
+
try {
|
|
4971
|
+
const module = await this.context.resolver.plugin.import(this.context.resolver.plugin.esmResolve(pluginPath));
|
|
4972
|
+
const result = module.plugin ?? module.default;
|
|
4973
|
+
if (!result) throw new Error(`The plugin package "${pluginPath}" does not export a valid module.`);
|
|
4974
|
+
return result;
|
|
4975
|
+
} catch {
|
|
4976
|
+
if (!isInstalled) throw new Error(`The plugin package "${pluginPath}" is not installed. Please install the package using the command: "npm install ${pluginPath} --save-dev"`);
|
|
4977
|
+
else throw new Error(`An error occurred while importing the build plugin package "${pluginPath}":
|
|
4978
|
+
${isError(error) ? error.message : String(error)}
|
|
4979
|
+
|
|
4980
|
+
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\`.`);
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
async handleBuild(context) {
|
|
4985
|
+
await this.callHook("build", {
|
|
4986
|
+
environment: context,
|
|
4987
|
+
order: "pre"
|
|
4988
|
+
});
|
|
4989
|
+
context.debug("Formatting the generated entry files before the build process starts.");
|
|
4990
|
+
await formatFolder(context, context.entryPath);
|
|
4991
|
+
await this.callHook("build", {
|
|
4992
|
+
environment: context,
|
|
4993
|
+
order: "normal"
|
|
4994
|
+
});
|
|
4995
|
+
if (context.config.output.copy) {
|
|
4996
|
+
context.debug("Copying project's files from build output directory.");
|
|
4997
|
+
const destinationPath = isParentPath(appendPath(context.config.output.path, context.config.cwd), appendPath(context.config.root, context.config.cwd)) ? joinPaths(context.config.output.copy.path, relativePath(appendPath(context.config.root, context.config.cwd), appendPath(context.config.output.path, context.config.cwd))) : joinPaths(context.config.output.copy.path, "dist");
|
|
4998
|
+
const sourcePath = context.config.output.path;
|
|
4999
|
+
if (existsSync(sourcePath) && sourcePath !== destinationPath) {
|
|
5000
|
+
context.debug(`Copying files from project's build output directory (${context.config.output.path}) to the project's copy/publish directory (${destinationPath}).`);
|
|
5001
|
+
await copyFiles(sourcePath, destinationPath);
|
|
5002
|
+
} else context.warn(`The source path for the copy operation ${!existsSync(sourcePath) ? "does not exist" : "is the same as the destination path"}. Source: ${sourcePath}, Destination: ${destinationPath}. Skipping copying of build output files.`);
|
|
5003
|
+
if (context.config.output.copy.assets && Array.isArray(context.config.output.copy.assets)) await Promise.all(context.config.output.copy.assets.map(async (asset) => {
|
|
5004
|
+
context.trace(`Copying asset(s): ${chalk.redBright(context.config.cwd === asset.input ? asset.glob : appendPath(asset.glob, replacePath(asset.input, context.config.cwd)))} -> ${chalk.greenBright(appendPath(asset.glob, replacePath(asset.output, context.config.cwd)))} ${Array.isArray(asset.ignore) && asset.ignore.length > 0 ? ` (ignoring: ${asset.ignore.map((i) => chalk.yellowBright(i)).join(", ")})` : ""}`);
|
|
5005
|
+
await context.fs.copy(asset, asset.output);
|
|
5006
|
+
}));
|
|
5007
|
+
} else context.debug("No copy configuration found for the project output. Skipping the copying of build output files.");
|
|
5008
|
+
await this.callHook("build", {
|
|
5009
|
+
environment: context,
|
|
5010
|
+
order: "post"
|
|
5011
|
+
});
|
|
5012
|
+
}
|
|
5013
|
+
/**
|
|
5014
|
+
* Generate the Powerlines TypeScript declaration file
|
|
5015
|
+
*
|
|
5016
|
+
* @remarks
|
|
5017
|
+
* This method will generate the TypeScript declaration file for the Powerlines project, including any types provided by plugins.
|
|
5018
|
+
*
|
|
5019
|
+
* @param context - The environment context to use for generating the TypeScript declaration file
|
|
5020
|
+
* @returns A promise that resolves when the TypeScript declaration file has been generated
|
|
5021
|
+
*/
|
|
5022
|
+
async handleTypes(context) {
|
|
5023
|
+
context.debug(`Preparing the TypeScript definitions for the Powerlines project.`);
|
|
5024
|
+
if (context.fs.existsSync(context.typesPath)) await context.fs.remove(context.typesPath);
|
|
5025
|
+
if (!await resolvePackage("typescript")) throw new Error("Could not resolve TypeScript package location. Please ensure TypeScript is installed.");
|
|
5026
|
+
context.debug("Running TypeScript compiler for built-in runtime module files.");
|
|
5027
|
+
let { code, directives } = await emitBuiltinTypes(context, (await context.getBuiltins()).reduce((ret, builtin) => {
|
|
5028
|
+
const formatted = replacePath(builtin.path, context.config.cwd);
|
|
5029
|
+
if (!ret.includes(formatted)) ret.push(formatted);
|
|
5030
|
+
return ret;
|
|
5031
|
+
}, []));
|
|
5032
|
+
context.debug(`Generating TypeScript declaration file ${context.typesPath}.`);
|
|
5033
|
+
const merge = async (currentResult, previousResult) => {
|
|
5034
|
+
if (!isSetString(currentResult) && !isSetObject(currentResult) && !isSetString(previousResult) && !isSetObject(previousResult)) return {
|
|
5035
|
+
code,
|
|
5036
|
+
directives
|
|
5037
|
+
};
|
|
5038
|
+
const previous = (await format(context, context.typesPath, isSetString(previousResult) ? previousResult : isSetObject(previousResult) ? previousResult.code : "")).trim().replace(code, "").trim();
|
|
5039
|
+
const current = (await format(context, context.typesPath, isSetString(currentResult) ? currentResult : isSetObject(currentResult) ? currentResult.code : "")).trim().replace(previous, "").trim().replace(code, "").trim();
|
|
5040
|
+
return {
|
|
5041
|
+
directives: [...isSetObject(currentResult) && currentResult.directives ? currentResult.directives : [], ...isSetObject(previousResult) && previousResult.directives ? previousResult.directives : []],
|
|
5042
|
+
code: await format(context, context.typesPath, `${!previous.includes(getTypescriptFileHeader(context)) && !current.includes(getTypescriptFileHeader(context)) ? `${code}\n` : ""}${previous}\n${current}`.trim())
|
|
5043
|
+
};
|
|
5044
|
+
};
|
|
5045
|
+
const asNextParam = (previousResult) => isObject(previousResult) ? previousResult.code : previousResult;
|
|
5046
|
+
let result = await this.callHook("types", {
|
|
5047
|
+
environment: context,
|
|
5048
|
+
sequential: true,
|
|
5049
|
+
order: "pre",
|
|
5050
|
+
result: "merge",
|
|
5051
|
+
merge,
|
|
5052
|
+
asNextParam
|
|
5053
|
+
}, code);
|
|
5054
|
+
if (result) {
|
|
5055
|
+
if (isSetObject(result)) {
|
|
5056
|
+
code = result.code;
|
|
5057
|
+
if (Array.isArray(result.directives) && result.directives.length > 0) directives = getUnique([...directives, ...result.directives]).filter(Boolean);
|
|
5058
|
+
} else if (isSetString(result)) code = result;
|
|
5059
|
+
}
|
|
5060
|
+
result = await this.callHook("types", {
|
|
5061
|
+
environment: context,
|
|
5062
|
+
sequential: true,
|
|
5063
|
+
order: "normal",
|
|
5064
|
+
result: "merge",
|
|
5065
|
+
merge,
|
|
5066
|
+
asNextParam
|
|
5067
|
+
}, code);
|
|
5068
|
+
if (result) {
|
|
5069
|
+
if (isSetObject(result)) {
|
|
5070
|
+
code = result.code;
|
|
5071
|
+
if (Array.isArray(result.directives) && result.directives.length > 0) directives = getUnique([...directives, ...result.directives]).filter(Boolean);
|
|
5072
|
+
} else if (isSetString(result)) code = result;
|
|
5073
|
+
}
|
|
5074
|
+
result = await this.callHook("types", {
|
|
5075
|
+
environment: context,
|
|
5076
|
+
sequential: true,
|
|
5077
|
+
order: "post",
|
|
5078
|
+
result: "merge",
|
|
5079
|
+
merge,
|
|
5080
|
+
asNextParam
|
|
5081
|
+
}, code);
|
|
5082
|
+
if (result) {
|
|
5083
|
+
if (isSetObject(result)) {
|
|
5084
|
+
code = result.code;
|
|
5085
|
+
if (Array.isArray(result.directives) && result.directives.length > 0) directives = getUnique([...directives, ...result.directives]).filter(Boolean);
|
|
5086
|
+
} else if (isSetString(result)) code = result;
|
|
5087
|
+
}
|
|
5088
|
+
if (isSetString(code?.trim()) || directives.length > 0) await context.fs.write(context.typesPath, `${directives.length > 0 ? `${directives.map((directive) => `/// <reference types="${directive}" />`).join("\n")}
|
|
5089
|
+
|
|
5090
|
+
` : ""}${getTypescriptFileHeader(context, {
|
|
5091
|
+
directive: null,
|
|
5092
|
+
prettierIgnore: false
|
|
5093
|
+
})}
|
|
5094
|
+
|
|
5095
|
+
${formatTypes(code)}
|
|
5096
|
+
`);
|
|
5097
|
+
}
|
|
5015
5098
|
};
|
|
5016
5099
|
|
|
5017
5100
|
//#endregion
|
|
5018
5101
|
//#region src/_internal/worker.ts
|
|
5019
5102
|
async function clean({ options, initialConfig, inlineConfig }) {
|
|
5020
|
-
await (await PowerlinesExecution.
|
|
5103
|
+
await (await PowerlinesExecution.from(options, initialConfig)).clean(inlineConfig);
|
|
5021
5104
|
}
|
|
5022
5105
|
async function prepare({ options, initialConfig, inlineConfig }) {
|
|
5023
|
-
await (await PowerlinesExecution.
|
|
5106
|
+
await (await PowerlinesExecution.from(options, initialConfig)).prepare(inlineConfig);
|
|
5024
5107
|
}
|
|
5025
5108
|
async function types({ options, initialConfig, inlineConfig }) {
|
|
5026
|
-
await (await PowerlinesExecution.
|
|
5109
|
+
await (await PowerlinesExecution.from(options, initialConfig)).types(inlineConfig);
|
|
5027
5110
|
}
|
|
5028
5111
|
async function lint({ options, initialConfig, inlineConfig }) {
|
|
5029
|
-
await (await PowerlinesExecution.
|
|
5112
|
+
await (await PowerlinesExecution.from(options, initialConfig)).lint(inlineConfig);
|
|
5030
5113
|
}
|
|
5031
5114
|
async function test({ options, initialConfig, inlineConfig }) {
|
|
5032
|
-
await (await PowerlinesExecution.
|
|
5115
|
+
await (await PowerlinesExecution.from(options, initialConfig)).test(inlineConfig);
|
|
5033
5116
|
}
|
|
5034
5117
|
async function build({ options, initialConfig, inlineConfig }) {
|
|
5035
|
-
await (await PowerlinesExecution.
|
|
5118
|
+
await (await PowerlinesExecution.from(options, initialConfig)).build(inlineConfig);
|
|
5036
5119
|
}
|
|
5037
5120
|
async function docs({ options, initialConfig, inlineConfig }) {
|
|
5038
|
-
await (await PowerlinesExecution.
|
|
5121
|
+
await (await PowerlinesExecution.from(options, initialConfig)).docs(inlineConfig);
|
|
5039
5122
|
}
|
|
5040
5123
|
async function deploy({ options, initialConfig, inlineConfig }) {
|
|
5041
|
-
await (await PowerlinesExecution.
|
|
5124
|
+
await (await PowerlinesExecution.from(options, initialConfig)).deploy(inlineConfig);
|
|
5042
5125
|
}
|
|
5043
5126
|
|
|
5044
5127
|
//#endregion
|