@powerlines/core 0.48.45 → 0.48.46
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/context/context.mjs.map +1 -1
- package/dist/context/environment-context.mjs.map +1 -1
- package/dist/context/execution-context.mjs.map +1 -1
- package/dist/context/plugin-context.mjs.map +1 -1
- package/dist/lib/config.mjs.map +1 -1
- package/dist/lib/context-helpers.mjs.map +1 -1
- package/dist/lib/entry.mjs.map +1 -1
- package/dist/lib/environment.mjs.map +1 -1
- package/dist/lib/events.mjs.map +1 -1
- package/dist/lib/generate-types.mjs.map +1 -1
- package/dist/lib/hooks.mjs.map +1 -1
- package/dist/lib/install-dependencies.mjs.map +1 -1
- package/dist/lib/plugins.mjs.map +1 -1
- package/dist/lib/typescript/ts-morph.mjs.map +1 -1
- package/dist/lib/typescript/tsconfig.mjs.map +1 -1
- package/dist/lib/utilities/file-header.mjs.map +1 -1
- package/dist/lib/utilities/format.mjs.map +1 -1
- package/dist/lib/vfs.mjs.map +1 -1
- package/dist/plugin-base.mjs.map +1 -1
- package/dist/plugin-utils/build-helpers.mjs.map +1 -1
- package/dist/plugin-utils/combine-plugins.mjs.map +1 -1
- package/dist/plugin-utils/context-helpers.mjs.map +1 -1
- package/dist/plugin-utils/enable-plugin.mjs.map +1 -1
- package/dist/plugin-utils/extend.mjs.map +1 -1
- package/dist/plugin-utils/filter.mjs.map +1 -1
- package/dist/plugin-utils/format.mjs.map +1 -1
- package/dist/plugin-utils/helpers.mjs.map +1 -1
- package/dist/plugin-utils/logging.mjs.map +1 -1
- package/dist/plugin-utils/merge.mjs.map +1 -1
- package/dist/plugin-utils/modules.mjs.map +1 -1
- package/dist/plugin-utils/paths.mjs.map +1 -1
- package/dist/storage/base.mjs.map +1 -1
- package/dist/storage/file-system.mjs.map +1 -1
- package/dist/storage/virtual.mjs.map +1 -1
- package/package.json +2 -2
package/dist/lib/hooks.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.mjs","names":["defu"],"sources":["../../src/lib/hooks.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { getField } from \"@stryke/helpers/get-field\";\nimport { isFunction } from \"@stryke/type-checks/is-function\";\nimport { isObject } from \"@stryke/type-checks/is-object\";\nimport { isSet } from \"@stryke/type-checks/is-set\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { ArrayValues } from \"@stryke/types/array\";\nimport { AnyFunction } from \"@stryke/types/base\";\nimport chalk from \"chalk\";\nimport { defu } from \"defu\";\nimport {\n addPluginHook,\n colorText,\n isPluginHook,\n isPluginHookField,\n mergeConfig\n} from \"../plugin-utils\";\nimport type {\n CallHookOptions,\n EnvironmentContext,\n ExecutionContext,\n HookListOrders,\n HooksList,\n HooksListItem,\n InferHookParameters,\n InferHookReturnType,\n Plugin,\n PluginContext,\n PluginHookFields,\n ResolvedConfig\n} from \"../types\";\n\n/**\n * Merges the current hook result with the previous results based on their types.\n *\n * @param currentResult - The current hook result to merge with the previous results.\n * @param previousResults - The previous hook results to merge with the current result.\n * @returns The merged result.\n */\nexport function mergeResults<\n T extends Record<string | number | symbol, any> | string\n>(currentResult: T, previousResults: T[]): T[] {\n if (!previousResults || previousResults.length === 0) {\n return [currentResult];\n }\n\n if (isSetString(currentResult)) {\n previousResults = [\n `${isSetString(previousResults[0]) ? previousResults[0] || \"\" : \"\"}\\n${\n isSetString(previousResults[0])\n ? currentResult.replace(previousResults[0], \"\")\n : currentResult\n }`.trim() as T\n ];\n } else if (isObject(currentResult)) {\n previousResults =\n previousResults.length > 0\n ? [defu(currentResult, previousResults[0])]\n : [currentResult];\n }\n\n return previousResults;\n}\n\n/**\n * Merges multiple hook results together, with special handling for string values and object values.\n *\n * @param currentResult - The current hook result to merge with the previous results.\n * @param previousResults - The previous hook results to merge with the current result.\n * @returns The merged result.\n */\nexport function mergeConfigs<T>(currentResult: T, previousResults: T): T {\n if (isString(currentResult)) {\n previousResults =\n `${isString(previousResults) ? previousResults || \"\" : \"\"}\\n${\n currentResult || \"\"\n }`.trim() as T;\n } else if (isObject(currentResult)) {\n previousResults = mergeConfig(currentResult, previousResults ?? {}) as T;\n }\n\n return previousResults;\n}\n\n/**\n * Calls a hook with the given context, options, and arguments.\n *\n * @param context - The context to use when calling the hook.\n * @param key - The hook to call.\n * @param options - Options for calling the hook.\n * @param args - Arguments to pass to the hook.\n * @returns The return value of the hook.\n */\nasync function _callHook<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TKey extends string\n>(\n context: EnvironmentContext<TResolvedConfig, TSystemContext>,\n key: TKey,\n options: CallHookOptions,\n ...args: InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n): Promise<\n | InferHookReturnType<PluginContext<TResolvedConfig, TSystemContext>, TKey>\n | undefined\n> {\n const hooks = context.selectHooks(key, options);\n if (hooks.length > 0) {\n const logger = context.extendLogger({ category: \"hooks\" });\n const pluginNumberWidth =\n hooks.length >= 10 ? String(hooks.length).length : 1;\n\n logger.debug(\n `🧩 Calling ${hooks.length} ${chalk.bold.cyanBright(\n `${key}${options?.order ? ` (${options.order})` : \"\"}`\n )} plugin hook${hooks.length > 1 ? \"s\" : \"\"}:\\n${hooks\n .map(\n (hook, index) =>\n `${String(index + 1).padStart(\n pluginNumberWidth,\n \"0\"\n )}. ${colorText(hook.plugin.name)}`\n )\n .join(\"\\n\")}`\n );\n\n const invokeHook = async (\n hook: ArrayValues<typeof hooks>,\n hookArgs: InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n ) => {\n return Reflect.apply(hook.handler as AnyFunction, hook.context, hookArgs);\n };\n\n let results = [] as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >[];\n if (options?.sequential === false) {\n results = (await Promise.all(\n hooks.map(async hook => {\n if (!isFunction(hook.handler)) {\n throw new Error(\n `Plugin hook handler for hook \"${key}\" is not a function.`\n );\n }\n\n return invokeHook(hook, [...args]);\n })\n )) as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >[];\n } else {\n for (const hook of hooks) {\n if (!isFunction(hook.handler)) {\n throw new Error(\n `Plugin hook handler for hook \"${key}\" is not a function.`\n );\n }\n\n if (options?.result === \"first\" || options?.asNextParam === false) {\n results.push(\n (await Promise.resolve(\n invokeHook(hook, [...args])\n )) as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n );\n if (\n options?.result === \"first\" &&\n isSet(results[results.length - 1])\n ) {\n break;\n }\n } else {\n const sequenceArgs = [...args];\n if (results.length > 0 && sequenceArgs.length > 0) {\n sequenceArgs[0] = isFunction(options.asNextParam)\n ? await Promise.resolve(options.asNextParam(results[0]))\n : results[0];\n }\n\n const result = await Promise.resolve(\n invokeHook(hook, [...sequenceArgs] as InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >)\n );\n if (result) {\n if (options.result === \"last\") {\n results = [result];\n } else if (options.result === \"merge\" && options.merge) {\n results = [\n results.length > 0 && results[0]\n ? await Promise.resolve(options.merge(result, results[0]))\n : result\n ];\n } else {\n results = mergeResults(result, results);\n }\n }\n }\n }\n }\n\n const definedResults = results.filter(\n (\n result\n ): result is NonNullable<\n InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n > => isSet(result)\n );\n\n if (definedResults.length > 0) {\n let mergedResult = undefined as\n | InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n | undefined;\n\n for (const result of definedResults) {\n mergedResult = defu(\n result as Record<string, unknown>,\n mergedResult ?? {}\n ) as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >;\n }\n\n return mergedResult;\n }\n }\n\n return undefined;\n}\n\nexport function extractHooks<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown\n>(\n context: PluginContext<TResolvedConfig, TSystemContext>,\n hooks: Record<\n string,\n HooksList<PluginContext<TResolvedConfig, TSystemContext>>\n >,\n plugin: Plugin<PluginContext<TResolvedConfig, TSystemContext>>,\n key: string,\n parentKey?: string\n): Record<string, HooksList<PluginContext<TResolvedConfig, TSystemContext>>> {\n const combinedKey = parentKey ? `${parentKey}:${key}` : key;\n const pluginField = getField(plugin, combinedKey.replace(/:/g, \".\"));\n if (\n isPluginHookField<PluginContext<TResolvedConfig, TSystemContext>>(\n combinedKey\n ) &&\n isPluginHook(pluginField)\n ) {\n const pluginHook = pluginField;\n if (!isPluginHook(pluginHook)) {\n return hooks;\n }\n\n hooks[combinedKey] ??= {\n preEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n preOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n normal: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[]\n };\n\n if (plugin.enforce) {\n const hookListOrder = `${plugin.enforce}Enforced` as HookListOrders;\n hooks[combinedKey][hookListOrder] ??= [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[];\n\n hooks[combinedKey][hookListOrder] = addPluginHook<\n PluginContext<TResolvedConfig, TSystemContext>,\n PluginHookFields<PluginContext<TResolvedConfig, TSystemContext>>\n >(context, plugin, pluginHook, hooks[combinedKey][hookListOrder]);\n\n return hooks;\n }\n\n if (isFunction(pluginHook) || !pluginHook.order) {\n hooks[combinedKey].normal ??= [];\n\n hooks[combinedKey].normal = addPluginHook<\n PluginContext<TResolvedConfig, TSystemContext>,\n PluginHookFields<PluginContext<TResolvedConfig, TSystemContext>>\n >(context, plugin, pluginHook, hooks[combinedKey].normal);\n\n return hooks;\n }\n\n const hookListOrder = `${pluginHook.order}Ordered` as HookListOrders;\n hooks[combinedKey][hookListOrder] ??= [];\n\n hooks[combinedKey][hookListOrder] = addPluginHook<\n PluginContext<TResolvedConfig, TSystemContext>,\n PluginHookFields<PluginContext<TResolvedConfig, TSystemContext>>\n >(context, plugin, pluginHook, hooks[combinedKey][hookListOrder]);\n\n return hooks;\n } else if (isSetObject(pluginField)) {\n return Object.keys(pluginField)\n .map(pluginKey =>\n extractHooks(context, hooks, plugin, pluginKey, combinedKey)\n )\n .reduce((ret, current) => {\n Object.keys(current).forEach(key => {\n ret[key] ??= {\n preEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n preOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n normal: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[]\n };\n\n [\n \"preEnforced\",\n \"preOrdered\",\n \"normal\",\n \"postEnforced\",\n \"postOrdered\"\n ].forEach(order => {\n if (\n current[key]?.[\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ]\n ) {\n ret[key]![\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ] ??= [];\n ret[key]![\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ] = ret[key]![\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ]!.concat(\n current[key][\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ]!\n );\n }\n });\n });\n\n return ret;\n }, hooks);\n }\n\n return hooks;\n}\n\nexport async function callHook<\n TKey extends string,\n TResolvedConfig extends ResolvedConfig,\n TSystemContext = unknown\n>(\n context: ExecutionContext<TResolvedConfig, TSystemContext>,\n key: TKey,\n options: CallHookOptions & {\n environment?: string | EnvironmentContext<TResolvedConfig, TSystemContext>;\n },\n ...args: InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n) {\n return _callHook<TResolvedConfig, TSystemContext, TKey>(\n isSetObject(options?.environment)\n ? options.environment\n : await context.getEnvironment(options?.environment),\n key,\n { sequential: true, ...options },\n ...args\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hooks.mjs","names":["defu"],"sources":["../../src/lib/hooks.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { getField } from \"@stryke/helpers/get-field\";\nimport { isFunction } from \"@stryke/type-checks/is-function\";\nimport { isObject } from \"@stryke/type-checks/is-object\";\nimport { isSet } from \"@stryke/type-checks/is-set\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { ArrayValues } from \"@stryke/types/array\";\nimport { AnyFunction } from \"@stryke/types/base\";\nimport chalk from \"chalk\";\nimport { defu } from \"defu\";\nimport {\n addPluginHook,\n colorText,\n isPluginHook,\n isPluginHookField,\n mergeConfig\n} from \"../plugin-utils\";\nimport type {\n CallHookOptions,\n EnvironmentContext,\n ExecutionContext,\n HookListOrders,\n HooksList,\n HooksListItem,\n InferHookParameters,\n InferHookReturnType,\n Plugin,\n PluginContext,\n PluginHookFields,\n ResolvedConfig\n} from \"../types\";\n\n/**\n * Merges the current hook result with the previous results based on their types.\n *\n * @param currentResult - The current hook result to merge with the previous results.\n * @param previousResults - The previous hook results to merge with the current result.\n * @returns The merged result.\n */\nexport function mergeResults<\n T extends Record<string | number | symbol, any> | string\n>(currentResult: T, previousResults: T[]): T[] {\n if (!previousResults || previousResults.length === 0) {\n return [currentResult];\n }\n\n if (isSetString(currentResult)) {\n previousResults = [\n `${isSetString(previousResults[0]) ? previousResults[0] || \"\" : \"\"}\\n${\n isSetString(previousResults[0])\n ? currentResult.replace(previousResults[0], \"\")\n : currentResult\n }`.trim() as T\n ];\n } else if (isObject(currentResult)) {\n previousResults =\n previousResults.length > 0\n ? [defu(currentResult, previousResults[0])]\n : [currentResult];\n }\n\n return previousResults;\n}\n\n/**\n * Merges multiple hook results together, with special handling for string values and object values.\n *\n * @param currentResult - The current hook result to merge with the previous results.\n * @param previousResults - The previous hook results to merge with the current result.\n * @returns The merged result.\n */\nexport function mergeConfigs<T>(currentResult: T, previousResults: T): T {\n if (isString(currentResult)) {\n previousResults =\n `${isString(previousResults) ? previousResults || \"\" : \"\"}\\n${\n currentResult || \"\"\n }`.trim() as T;\n } else if (isObject(currentResult)) {\n previousResults = mergeConfig(currentResult, previousResults ?? {}) as T;\n }\n\n return previousResults;\n}\n\n/**\n * Calls a hook with the given context, options, and arguments.\n *\n * @param context - The context to use when calling the hook.\n * @param key - The hook to call.\n * @param options - Options for calling the hook.\n * @param args - Arguments to pass to the hook.\n * @returns The return value of the hook.\n */\nasync function _callHook<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TKey extends string\n>(\n context: EnvironmentContext<TResolvedConfig, TSystemContext>,\n key: TKey,\n options: CallHookOptions,\n ...args: InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n): Promise<\n | InferHookReturnType<PluginContext<TResolvedConfig, TSystemContext>, TKey>\n | undefined\n> {\n const hooks = context.selectHooks(key, options);\n if (hooks.length > 0) {\n const logger = context.extendLogger({ category: \"hooks\" });\n const pluginNumberWidth =\n hooks.length >= 10 ? String(hooks.length).length : 1;\n\n logger.debug(\n `🧩 Calling ${hooks.length} ${chalk.bold.cyanBright(\n `${key}${options?.order ? ` (${options.order})` : \"\"}`\n )} plugin hook${hooks.length > 1 ? \"s\" : \"\"}:\\n${hooks\n .map(\n (hook, index) =>\n `${String(index + 1).padStart(\n pluginNumberWidth,\n \"0\"\n )}. ${colorText(hook.plugin.name)}`\n )\n .join(\"\\n\")}`\n );\n\n const invokeHook = async (\n hook: ArrayValues<typeof hooks>,\n hookArgs: InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n ) => {\n return Reflect.apply(hook.handler as AnyFunction, hook.context, hookArgs);\n };\n\n let results = [] as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >[];\n if (options?.sequential === false) {\n results = (await Promise.all(\n hooks.map(async hook => {\n if (!isFunction(hook.handler)) {\n throw new Error(\n `Plugin hook handler for hook \"${key}\" is not a function.`\n );\n }\n\n return invokeHook(hook, [...args]);\n })\n )) as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >[];\n } else {\n for (const hook of hooks) {\n if (!isFunction(hook.handler)) {\n throw new Error(\n `Plugin hook handler for hook \"${key}\" is not a function.`\n );\n }\n\n if (options?.result === \"first\" || options?.asNextParam === false) {\n results.push(\n (await Promise.resolve(\n invokeHook(hook, [...args])\n )) as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n );\n if (\n options?.result === \"first\" &&\n isSet(results[results.length - 1])\n ) {\n break;\n }\n } else {\n const sequenceArgs = [...args];\n if (results.length > 0 && sequenceArgs.length > 0) {\n sequenceArgs[0] = isFunction(options.asNextParam)\n ? await Promise.resolve(options.asNextParam(results[0]))\n : results[0];\n }\n\n const result = await Promise.resolve(\n invokeHook(hook, [...sequenceArgs] as InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >)\n );\n if (result) {\n if (options.result === \"last\") {\n results = [result];\n } else if (options.result === \"merge\" && options.merge) {\n results = [\n results.length > 0 && results[0]\n ? await Promise.resolve(options.merge(result, results[0]))\n : result\n ];\n } else {\n results = mergeResults(result, results);\n }\n }\n }\n }\n }\n\n const definedResults = results.filter(\n (\n result\n ): result is NonNullable<\n InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n > => isSet(result)\n );\n\n if (definedResults.length > 0) {\n let mergedResult = undefined as\n | InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n | undefined;\n\n for (const result of definedResults) {\n mergedResult = defu(\n result as Record<string, unknown>,\n mergedResult ?? {}\n ) as InferHookReturnType<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >;\n }\n\n return mergedResult;\n }\n }\n\n return undefined;\n}\n\nexport function extractHooks<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown\n>(\n context: PluginContext<TResolvedConfig, TSystemContext>,\n hooks: Record<\n string,\n HooksList<PluginContext<TResolvedConfig, TSystemContext>>\n >,\n plugin: Plugin<PluginContext<TResolvedConfig, TSystemContext>>,\n key: string,\n parentKey?: string\n): Record<string, HooksList<PluginContext<TResolvedConfig, TSystemContext>>> {\n const combinedKey = parentKey ? `${parentKey}:${key}` : key;\n const pluginField = getField(plugin, combinedKey.replace(/:/g, \".\"));\n if (\n isPluginHookField<PluginContext<TResolvedConfig, TSystemContext>>(\n combinedKey\n ) &&\n isPluginHook(pluginField)\n ) {\n const pluginHook = pluginField;\n if (!isPluginHook(pluginHook)) {\n return hooks;\n }\n\n hooks[combinedKey] ??= {\n preEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n preOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n normal: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[]\n };\n\n if (plugin.enforce) {\n const hookListOrder = `${plugin.enforce}Enforced` as HookListOrders;\n hooks[combinedKey][hookListOrder] ??= [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[];\n\n hooks[combinedKey][hookListOrder] = addPluginHook<\n PluginContext<TResolvedConfig, TSystemContext>,\n PluginHookFields<PluginContext<TResolvedConfig, TSystemContext>>\n >(context, plugin, pluginHook, hooks[combinedKey][hookListOrder]);\n\n return hooks;\n }\n\n if (isFunction(pluginHook) || !pluginHook.order) {\n hooks[combinedKey].normal ??= [];\n\n hooks[combinedKey].normal = addPluginHook<\n PluginContext<TResolvedConfig, TSystemContext>,\n PluginHookFields<PluginContext<TResolvedConfig, TSystemContext>>\n >(context, plugin, pluginHook, hooks[combinedKey].normal);\n\n return hooks;\n }\n\n const hookListOrder = `${pluginHook.order}Ordered` as HookListOrders;\n hooks[combinedKey][hookListOrder] ??= [];\n\n hooks[combinedKey][hookListOrder] = addPluginHook<\n PluginContext<TResolvedConfig, TSystemContext>,\n PluginHookFields<PluginContext<TResolvedConfig, TSystemContext>>\n >(context, plugin, pluginHook, hooks[combinedKey][hookListOrder]);\n\n return hooks;\n } else if (isSetObject(pluginField)) {\n return Object.keys(pluginField)\n .map(pluginKey =>\n extractHooks(context, hooks, plugin, pluginKey, combinedKey)\n )\n .reduce((ret, current) => {\n Object.keys(current).forEach(key => {\n ret[key] ??= {\n preEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n preOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n normal: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postEnforced: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[],\n postOrdered: [] as HooksListItem<\n PluginContext<TResolvedConfig, TSystemContext>\n >[]\n };\n\n [\n \"preEnforced\",\n \"preOrdered\",\n \"normal\",\n \"postEnforced\",\n \"postOrdered\"\n ].forEach(order => {\n if (\n current[key]?.[\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ]\n ) {\n ret[key]![\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ] ??= [];\n ret[key]![\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ] = ret[key]![\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ]!.concat(\n current[key][\n order as keyof HooksList<\n PluginContext<TResolvedConfig, TSystemContext>\n >\n ]!\n );\n }\n });\n });\n\n return ret;\n }, hooks);\n }\n\n return hooks;\n}\n\nexport async function callHook<\n TKey extends string,\n TResolvedConfig extends ResolvedConfig,\n TSystemContext = unknown\n>(\n context: ExecutionContext<TResolvedConfig, TSystemContext>,\n key: TKey,\n options: CallHookOptions & {\n environment?: string | EnvironmentContext<TResolvedConfig, TSystemContext>;\n },\n ...args: InferHookParameters<\n PluginContext<TResolvedConfig, TSystemContext>,\n TKey\n >\n) {\n return _callHook<TResolvedConfig, TSystemContext, TKey>(\n isSetObject(options?.environment)\n ? options.environment\n : await context.getEnvironment(options?.environment),\n key,\n { sequential: true, ...options },\n ...args\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-dependencies.mjs","names":[],"sources":["../../src/lib/install-dependencies.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { getPackageName } from \"@stryke/string-format/package\";\nimport { installPackage } from \"../plugin-utils/install\";\nimport type { Context } from \"../types/context\";\n\n/**\n * Install missing project dependencies.\n *\n * @param context - The build context.\n */\nexport async function installDependencies<TContext extends Context = Context>(\n context: TContext\n): Promise<void> {\n context.debug(`Checking and installing missing project dependencies.`);\n\n context.dependencies ??= {};\n context.devDependencies ??= {};\n\n if (\n Object.keys(context.dependencies).length === 0 &&\n Object.keys(context.devDependencies).length === 0\n ) {\n context.debug(\n `No dependencies or devDependencies to install. Skipping installation step.`\n );\n return;\n }\n\n context.debug(\n `The following packages are required: \\nDependencies: \\n${Object.entries(\n context.dependencies\n )\n .map(([name, version]) => `- ${name}@${String(version)}`)\n .join(\" \\n\")}\\n\\nDevDependencies: \\n${Object.entries(\n context.devDependencies\n )\n .map(([name, version]) => `- ${name}@${String(version)}`)\n .join(\" \\n\")}`\n );\n\n await Promise.all([\n Promise.all(\n Object.entries(context.dependencies).map(async ([name, version]) =>\n installPackage(\n context,\n `${getPackageName(name)}@${String(version)}`,\n false\n )\n )\n ),\n Promise.all(\n Object.entries(context.devDependencies).map(async ([name, version]) =>\n installPackage(\n context,\n `${getPackageName(name)}@${String(version)}`,\n true\n )\n )\n )\n ]);\n}\n"],"mappings":";;;;;;;;;AA2BA,eAAsB,oBACpB,SACe;CACf,QAAQ,MAAM,uDAAuD;CAErE,QAAQ,iBAAiB,CAAC;CAC1B,QAAQ,oBAAoB,CAAC;CAE7B,IACE,OAAO,KAAK,QAAQ,YAAY,
|
|
1
|
+
{"version":3,"file":"install-dependencies.mjs","names":[],"sources":["../../src/lib/install-dependencies.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { getPackageName } from \"@stryke/string-format/package\";\nimport { installPackage } from \"../plugin-utils/install\";\nimport type { Context } from \"../types/context\";\n\n/**\n * Install missing project dependencies.\n *\n * @param context - The build context.\n */\nexport async function installDependencies<TContext extends Context = Context>(\n context: TContext\n): Promise<void> {\n context.debug(`Checking and installing missing project dependencies.`);\n\n context.dependencies ??= {};\n context.devDependencies ??= {};\n\n if (\n Object.keys(context.dependencies).length === 0 &&\n Object.keys(context.devDependencies).length === 0\n ) {\n context.debug(\n `No dependencies or devDependencies to install. Skipping installation step.`\n );\n return;\n }\n\n context.debug(\n `The following packages are required: \\nDependencies: \\n${Object.entries(\n context.dependencies\n )\n .map(([name, version]) => `- ${name}@${String(version)}`)\n .join(\" \\n\")}\\n\\nDevDependencies: \\n${Object.entries(\n context.devDependencies\n )\n .map(([name, version]) => `- ${name}@${String(version)}`)\n .join(\" \\n\")}`\n );\n\n await Promise.all([\n Promise.all(\n Object.entries(context.dependencies).map(async ([name, version]) =>\n installPackage(\n context,\n `${getPackageName(name)}@${String(version)}`,\n false\n )\n )\n ),\n Promise.all(\n Object.entries(context.devDependencies).map(async ([name, version]) =>\n installPackage(\n context,\n `${getPackageName(name)}@${String(version)}`,\n true\n )\n )\n )\n ]);\n}\n"],"mappings":";;;;;;;;;AA2BA,eAAsB,oBACpB,SACe;CACf,QAAQ,MAAM,uDAAuD;CAErE,QAAQ,iBAAiB,CAAC;CAC1B,QAAQ,oBAAoB,CAAC;CAE7B,IACE,OAAO,KAAK,QAAQ,YAAY,CAAC,CAAC,WAAW,KAC7C,OAAO,KAAK,QAAQ,eAAe,CAAC,CAAC,WAAW,GAChD;EACA,QAAQ,MACN,4EACF;EACA;CACF;CAEA,QAAQ,MACN,0DAA0D,OAAO,QAC/D,QAAQ,YACV,CAAC,CACE,KAAK,CAAC,MAAM,aAAa,KAAK,KAAK,GAAG,OAAO,OAAO,GAAG,CAAC,CACxD,KAAK,KAAK,EAAE,yBAAyB,OAAO,QAC7C,QAAQ,eACV,CAAC,CACE,KAAK,CAAC,MAAM,aAAa,KAAK,KAAK,GAAG,OAAO,OAAO,GAAG,CAAC,CACxD,KAAK,KAAK,GACf;CAEA,MAAM,QAAQ,IAAI,CAChB,QAAQ,IACN,OAAO,QAAQ,QAAQ,YAAY,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,aACrD,eACE,SACA,GAAG,eAAe,IAAI,EAAE,GAAG,OAAO,OAAO,KACzC,KACF,CACF,CACF,GACA,QAAQ,IACN,OAAO,QAAQ,QAAQ,eAAe,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,aACxD,eACE,SACA,GAAG,eAAe,IAAI,EAAE,GAAG,OAAO,OAAO,KACzC,IACF,CACF,CACF,CACF,CAAC;AACH"}
|
package/dist/lib/plugins.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.mjs","names":[],"sources":["../../src/lib/plugins.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { install } from \"@stryke/fs/install\";\nimport { isPackageExists } from \"@stryke/fs/package-fns\";\nimport { joinPaths } from \"@stryke/path/join\";\nimport { isError } from \"@stryke/type-checks/is-error\";\nimport { isFunction } from \"@stryke/type-checks/is-function\";\nimport { isNumber } from \"@stryke/type-checks/is-number\";\nimport { isPromiseLike } from \"@stryke/type-checks/is-promise\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { MaybePromise } from \"@stryke/types/base\";\nimport chalk from \"chalk\";\nimport {\n findInvalidPluginConfig,\n isDuplicate,\n isPlugin,\n isPluginConfig,\n isPluginConfigObject,\n isPluginConfigTuple\n} from \"../plugin-utils\";\nimport type {\n EnvironmentContext,\n ExecutionContext,\n Plugin,\n PluginConfig,\n PluginConfigTuple,\n PluginContext,\n PluginFactory,\n ResolvedConfig\n} from \"../types\";\n\n/**\n * Resolve a plugin module based on the provided plugin path. This function checks if the plugin package is installed, attempts to import the plugin module, and handles various error cases such as missing packages or invalid module exports. It supports both direct plugin exports and plugins exported from a \"plugin\" subdirectory within the package.\n *\n * @param context - The execution context in which the plugin will be initialized. This context provides access to configuration, logging, and other utilities that may be needed during plugin initialization.\n * @param pluginPath - The path to the plugin module. This can be a package name, a scoped package name, or a path to a local module.\n * @returns A promise that resolves to the plugin module, which can be a plugin instance, a factory function that returns a plugin, or an array of plugins.\n */\nexport async function resolvePlugin<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TContext extends\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext> =\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext>,\n TPluginContext extends PluginContext<TResolvedConfig, TSystemContext> =\n PluginContext<TResolvedConfig, TSystemContext>\n>(\n context: TContext,\n pluginPath: string\n): Promise<\n | Plugin<TPluginContext>\n | Plugin<TPluginContext>[]\n | ((\n options?: any\n ) => MaybePromise<Plugin<TPluginContext> | Plugin<TPluginContext>[]>)\n> {\n if (\n pluginPath.startsWith(\"@\") &&\n pluginPath.split(\"/\").filter(Boolean).length > 2\n ) {\n const splits = pluginPath.split(\"/\").filter(Boolean);\n pluginPath = `${splits[0]}/${splits[1]}`;\n }\n\n const isInstalled = isPackageExists(pluginPath, {\n paths: [context.config.cwd, context.config.root]\n });\n if (!isInstalled && context.config.autoInstall) {\n context.warn(\n `The plugin package \"${\n pluginPath\n }\" is not installed. It will be installed automatically.`\n );\n\n const result = await install(pluginPath, {\n cwd: context.config.root\n });\n if (isNumber(result.exitCode) && result.exitCode > 0) {\n context.error(result.stderr);\n\n throw new Error(\n `An error occurred while installing the build plugin package \"${\n pluginPath\n }\" `\n );\n }\n }\n\n try {\n // First check if the package has a \"plugin\" subdirectory - @scope/package/plugin\n const module = await context.resolver.plugin.import<{\n plugin?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n default?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n }>(context.resolver.plugin.esmResolve(joinPaths(pluginPath, \"plugin\")));\n\n const result = module.plugin ?? module.default;\n if (!result) {\n throw new Error(\n `The plugin package \"${pluginPath}\" does not export a valid module.`\n );\n }\n\n return result;\n } catch (error) {\n try {\n const module = await context.resolver.plugin.import<{\n plugin?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n default?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n }>(context.resolver.plugin.esmResolve(pluginPath));\n\n const result = module.plugin ?? module.default;\n if (!result) {\n throw new Error(\n `The plugin package \"${pluginPath}\" does not export a valid module.`\n );\n }\n\n return result;\n } catch {\n if (!isInstalled) {\n throw new Error(\n `The plugin package \"${\n pluginPath\n }\" is not installed. Please install the package using the command: \"npm install ${\n pluginPath\n } --save-dev\"`\n );\n } else {\n throw new Error(\n `An error occurred while importing the build plugin package \"${\n pluginPath\n }\":\n${isError(error) ? error.message : String(error)}\n\nNote: 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\\`.`\n );\n }\n }\n }\n}\n\n/**\n * Initialize a plugin based on the provided plugin configuration. This function handles various forms of plugin configurations, including direct plugin instances, factory functions, string paths to plugins, and arrays of plugins or plugin configurations. It validates the plugin configuration, resolves any plugin paths, and returns an array of initialized plugins.\n *\n * @param context - The execution context in which the plugin will be initialized. This context provides access to configuration, logging, and other utilities that may be needed during plugin initialization.\n * @param config - The plugin configuration, which can be in various forms such as a direct plugin instance, a string path to a plugin, a factory function that returns a plugin, or an array of plugins or plugin configurations. This configuration will be processed and validated to initialize the appropriate plugins.\n * @returns A promise that resolves to an array of initialized plugins based on the provided configuration. If the configuration is invalid, an error will be thrown with details about the issue.\n */\nexport async function initPlugin<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TContext extends\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext> =\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext>,\n TPluginContext extends PluginContext<TResolvedConfig, TSystemContext> =\n PluginContext<TResolvedConfig, TSystemContext>\n>(\n context: TContext,\n config: PluginConfig<TPluginContext>,\n options: ResolvePluginsOptions = {}\n): Promise<Plugin<TPluginContext>[] | null> {\n const { skipLogging = false } = options;\n\n let awaited = config;\n if (isPromiseLike(config)) {\n awaited = (await Promise.resolve(\n config as Promise<any>\n )) as PluginConfig<TPluginContext>;\n }\n\n if (!isPluginConfig<TPluginContext>(awaited)) {\n const invalid = findInvalidPluginConfig(awaited);\n\n throw new Error(\n `Invalid ${\n invalid && invalid.length > 1 ? \"plugins\" : \"plugin\"\n } specified in the configuration - ${\n invalid && invalid.length > 0\n ? JSON.stringify(awaited)\n : invalid?.join(\"\\n\\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`\n );\n }\n\n let plugins!: Plugin<TPluginContext>[];\n if (isPlugin<TPluginContext>(awaited)) {\n plugins = [awaited];\n } else if (isFunction(awaited)) {\n plugins = toArray(await Promise.resolve(awaited()));\n } else if (isString(awaited)) {\n const resolved = await resolvePlugin<\n TResolvedConfig,\n TSystemContext,\n TContext\n >(context, awaited);\n if (isFunction(resolved)) {\n plugins = toArray(await Promise.resolve(resolved()));\n } else {\n plugins = toArray(resolved);\n }\n } else if (\n Array.isArray(awaited) &&\n (awaited as TPluginContext[]).every(isPlugin<TPluginContext>)\n ) {\n plugins = awaited as Plugin<TPluginContext>[];\n } else if (\n Array.isArray(awaited) &&\n (awaited as PluginConfig<TPluginContext>[]).every(\n isPluginConfig<TPluginContext>\n )\n ) {\n plugins = [];\n for (const pluginConfig of awaited as PluginConfig<TPluginContext>[]) {\n const initialized = await initPlugin<\n TResolvedConfig,\n TSystemContext,\n TContext,\n TPluginContext\n >(context, pluginConfig);\n if (initialized) {\n plugins.push(...initialized);\n }\n }\n } else if (\n isPluginConfigTuple<TPluginContext>(awaited) ||\n isPluginConfigObject<TPluginContext>(awaited)\n ) {\n let pluginConfig!:\n | string\n | PluginFactory<TPluginContext>\n | Plugin<TPluginContext>;\n let pluginOptions: any;\n\n if (isPluginConfigTuple<TPluginContext>(awaited)) {\n pluginConfig = awaited[0] as Plugin<TPluginContext>;\n pluginOptions =\n (awaited as PluginConfigTuple)?.length === 2 ? awaited[1] : undefined;\n } else {\n pluginConfig = awaited.plugin as Plugin<TPluginContext>;\n pluginOptions = awaited.options;\n }\n\n if (isSetString(pluginConfig)) {\n const resolved = await resolvePlugin<\n TResolvedConfig,\n TSystemContext,\n TContext,\n TPluginContext\n >(context, pluginConfig);\n if (isFunction(resolved)) {\n plugins = toArray(\n await Promise.resolve(\n pluginOptions ? resolved(pluginOptions) : resolved()\n )\n );\n } else {\n plugins = toArray(resolved);\n }\n } else if (isFunction(pluginConfig)) {\n plugins = toArray(await Promise.resolve(pluginConfig(pluginOptions)));\n } else if (\n Array.isArray(pluginConfig) &&\n pluginConfig.every(isPlugin<TPluginContext>)\n ) {\n plugins = pluginConfig;\n } else if (isPlugin<TPluginContext>(pluginConfig)) {\n plugins = toArray(pluginConfig);\n }\n }\n\n if (!plugins) {\n throw new Error(\n `The plugin configuration ${JSON.stringify(awaited)} is invalid. This configuration must point to a valid Powerlines plugin module.`\n );\n }\n\n if (plugins.length > 0 && !plugins.every(isPlugin<TPluginContext>)) {\n throw new Error(\n `The plugin option ${JSON.stringify(plugins)} does not export a valid module. This configuration must point to a valid Powerlines plugin module.`\n );\n }\n\n const result = [] as Plugin<TPluginContext>[];\n for (const plugin of plugins) {\n if (isDuplicate<TPluginContext>(plugin, context.plugins)) {\n if (!skipLogging) {\n context.trace({\n meta: {\n category: \"plugins\"\n },\n message: `Duplicate ${chalk.bold.cyanBright(\n plugin.name\n )} plugin dependency detected - Skipping initialization.`\n });\n }\n } else {\n result.push(plugin);\n\n if (!skipLogging) {\n context.trace({\n meta: {\n category: \"plugins\"\n },\n message: `Initializing the ${chalk.bold.cyanBright(plugin.name)} plugin...`\n });\n }\n }\n }\n\n return result;\n}\n\nexport interface ResolvePluginsOptions {\n /**\n * If true, the plugin resolution process will skip logging messages about the plugin initialization. This can be useful in scenarios where you want to suppress plugin-related logs, such as when running in a non-interactive environment or when you want to reduce log verbosity. By default, this option is false, and plugin initialization messages will be logged using the context's logger.\n */\n skipLogging?: boolean;\n}\n\n/**\n * Initialize a plugin based on the provided plugin configuration. This function handles various forms of plugin configurations, including direct plugin instances, plugin names, factory functions, and arrays of plugins. It validates the configuration, resolves plugin modules if necessary, and returns an array of initialized plugins ready to be added to the execution context.\n *\n * @param context - The execution context in which the plugin will be initialized. This context provides access to configuration, logging, and other utilities that may be needed during plugin initialization.\n * @param config - The plugin configuration, which can be in various forms such as a plugin instance, a plugin name string, a factory function that returns a plugin or an array of plugins, or an array of plugin configurations. The function will handle the resolution and initialization of the plugin(s) based on the provided configuration.\n * @returns A promise that resolves to an array of initialized plugins that can be added to the execution context, or null if the configuration is invalid or results in no plugins being initialized.\n */\nexport async function resolvePlugins<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TContext extends\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext> =\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext>,\n TPluginContext extends PluginContext<TResolvedConfig, TSystemContext> =\n PluginContext<TResolvedConfig, TSystemContext>\n>(\n context: TContext,\n config: PluginConfig<TPluginContext>,\n options: ResolvePluginsOptions = {}\n) {\n const { skipLogging = false } = options;\n\n const plugins = [] as Plugin<TPluginContext>[];\n if (config) {\n const result = await initPlugin<\n TResolvedConfig,\n TSystemContext,\n TContext,\n TPluginContext\n >(context, config);\n if (result) {\n for (const plugin of result) {\n if (!skipLogging) {\n context.trace({\n meta: {\n category: \"plugins\"\n },\n message: `Successfully initialized the ${chalk.bold.cyanBright(\n plugin.name\n )} plugin`\n });\n }\n\n plugins.push(plugin);\n }\n }\n }\n\n return plugins;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugins.mjs","names":[],"sources":["../../src/lib/plugins.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { install } from \"@stryke/fs/install\";\nimport { isPackageExists } from \"@stryke/fs/package-fns\";\nimport { joinPaths } from \"@stryke/path/join\";\nimport { isError } from \"@stryke/type-checks/is-error\";\nimport { isFunction } from \"@stryke/type-checks/is-function\";\nimport { isNumber } from \"@stryke/type-checks/is-number\";\nimport { isPromiseLike } from \"@stryke/type-checks/is-promise\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { MaybePromise } from \"@stryke/types/base\";\nimport chalk from \"chalk\";\nimport {\n findInvalidPluginConfig,\n isDuplicate,\n isPlugin,\n isPluginConfig,\n isPluginConfigObject,\n isPluginConfigTuple\n} from \"../plugin-utils\";\nimport type {\n EnvironmentContext,\n ExecutionContext,\n Plugin,\n PluginConfig,\n PluginConfigTuple,\n PluginContext,\n PluginFactory,\n ResolvedConfig\n} from \"../types\";\n\n/**\n * Resolve a plugin module based on the provided plugin path. This function checks if the plugin package is installed, attempts to import the plugin module, and handles various error cases such as missing packages or invalid module exports. It supports both direct plugin exports and plugins exported from a \"plugin\" subdirectory within the package.\n *\n * @param context - The execution context in which the plugin will be initialized. This context provides access to configuration, logging, and other utilities that may be needed during plugin initialization.\n * @param pluginPath - The path to the plugin module. This can be a package name, a scoped package name, or a path to a local module.\n * @returns A promise that resolves to the plugin module, which can be a plugin instance, a factory function that returns a plugin, or an array of plugins.\n */\nexport async function resolvePlugin<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TContext extends\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext> =\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext>,\n TPluginContext extends PluginContext<TResolvedConfig, TSystemContext> =\n PluginContext<TResolvedConfig, TSystemContext>\n>(\n context: TContext,\n pluginPath: string\n): Promise<\n | Plugin<TPluginContext>\n | Plugin<TPluginContext>[]\n | ((\n options?: any\n ) => MaybePromise<Plugin<TPluginContext> | Plugin<TPluginContext>[]>)\n> {\n if (\n pluginPath.startsWith(\"@\") &&\n pluginPath.split(\"/\").filter(Boolean).length > 2\n ) {\n const splits = pluginPath.split(\"/\").filter(Boolean);\n pluginPath = `${splits[0]}/${splits[1]}`;\n }\n\n const isInstalled = isPackageExists(pluginPath, {\n paths: [context.config.cwd, context.config.root]\n });\n if (!isInstalled && context.config.autoInstall) {\n context.warn(\n `The plugin package \"${\n pluginPath\n }\" is not installed. It will be installed automatically.`\n );\n\n const result = await install(pluginPath, {\n cwd: context.config.root\n });\n if (isNumber(result.exitCode) && result.exitCode > 0) {\n context.error(result.stderr);\n\n throw new Error(\n `An error occurred while installing the build plugin package \"${\n pluginPath\n }\" `\n );\n }\n }\n\n try {\n // First check if the package has a \"plugin\" subdirectory - @scope/package/plugin\n const module = await context.resolver.plugin.import<{\n plugin?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n default?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n }>(context.resolver.plugin.esmResolve(joinPaths(pluginPath, \"plugin\")));\n\n const result = module.plugin ?? module.default;\n if (!result) {\n throw new Error(\n `The plugin package \"${pluginPath}\" does not export a valid module.`\n );\n }\n\n return result;\n } catch (error) {\n try {\n const module = await context.resolver.plugin.import<{\n plugin?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n default?:\n | Plugin<TPluginContext>\n | ((options?: any) => MaybePromise<Plugin<TPluginContext>>);\n }>(context.resolver.plugin.esmResolve(pluginPath));\n\n const result = module.plugin ?? module.default;\n if (!result) {\n throw new Error(\n `The plugin package \"${pluginPath}\" does not export a valid module.`\n );\n }\n\n return result;\n } catch {\n if (!isInstalled) {\n throw new Error(\n `The plugin package \"${\n pluginPath\n }\" is not installed. Please install the package using the command: \"npm install ${\n pluginPath\n } --save-dev\"`\n );\n } else {\n throw new Error(\n `An error occurred while importing the build plugin package \"${\n pluginPath\n }\":\n${isError(error) ? error.message : String(error)}\n\nNote: 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\\`.`\n );\n }\n }\n }\n}\n\n/**\n * Initialize a plugin based on the provided plugin configuration. This function handles various forms of plugin configurations, including direct plugin instances, factory functions, string paths to plugins, and arrays of plugins or plugin configurations. It validates the plugin configuration, resolves any plugin paths, and returns an array of initialized plugins.\n *\n * @param context - The execution context in which the plugin will be initialized. This context provides access to configuration, logging, and other utilities that may be needed during plugin initialization.\n * @param config - The plugin configuration, which can be in various forms such as a direct plugin instance, a string path to a plugin, a factory function that returns a plugin, or an array of plugins or plugin configurations. This configuration will be processed and validated to initialize the appropriate plugins.\n * @returns A promise that resolves to an array of initialized plugins based on the provided configuration. If the configuration is invalid, an error will be thrown with details about the issue.\n */\nexport async function initPlugin<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TContext extends\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext> =\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext>,\n TPluginContext extends PluginContext<TResolvedConfig, TSystemContext> =\n PluginContext<TResolvedConfig, TSystemContext>\n>(\n context: TContext,\n config: PluginConfig<TPluginContext>,\n options: ResolvePluginsOptions = {}\n): Promise<Plugin<TPluginContext>[] | null> {\n const { skipLogging = false } = options;\n\n let awaited = config;\n if (isPromiseLike(config)) {\n awaited = (await Promise.resolve(\n config as Promise<any>\n )) as PluginConfig<TPluginContext>;\n }\n\n if (!isPluginConfig<TPluginContext>(awaited)) {\n const invalid = findInvalidPluginConfig(awaited);\n\n throw new Error(\n `Invalid ${\n invalid && invalid.length > 1 ? \"plugins\" : \"plugin\"\n } specified in the configuration - ${\n invalid && invalid.length > 0\n ? JSON.stringify(awaited)\n : invalid?.join(\"\\n\\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`\n );\n }\n\n let plugins!: Plugin<TPluginContext>[];\n if (isPlugin<TPluginContext>(awaited)) {\n plugins = [awaited];\n } else if (isFunction(awaited)) {\n plugins = toArray(await Promise.resolve(awaited()));\n } else if (isString(awaited)) {\n const resolved = await resolvePlugin<\n TResolvedConfig,\n TSystemContext,\n TContext\n >(context, awaited);\n if (isFunction(resolved)) {\n plugins = toArray(await Promise.resolve(resolved()));\n } else {\n plugins = toArray(resolved);\n }\n } else if (\n Array.isArray(awaited) &&\n (awaited as TPluginContext[]).every(isPlugin<TPluginContext>)\n ) {\n plugins = awaited as Plugin<TPluginContext>[];\n } else if (\n Array.isArray(awaited) &&\n (awaited as PluginConfig<TPluginContext>[]).every(\n isPluginConfig<TPluginContext>\n )\n ) {\n plugins = [];\n for (const pluginConfig of awaited as PluginConfig<TPluginContext>[]) {\n const initialized = await initPlugin<\n TResolvedConfig,\n TSystemContext,\n TContext,\n TPluginContext\n >(context, pluginConfig);\n if (initialized) {\n plugins.push(...initialized);\n }\n }\n } else if (\n isPluginConfigTuple<TPluginContext>(awaited) ||\n isPluginConfigObject<TPluginContext>(awaited)\n ) {\n let pluginConfig!:\n | string\n | PluginFactory<TPluginContext>\n | Plugin<TPluginContext>;\n let pluginOptions: any;\n\n if (isPluginConfigTuple<TPluginContext>(awaited)) {\n pluginConfig = awaited[0] as Plugin<TPluginContext>;\n pluginOptions =\n (awaited as PluginConfigTuple)?.length === 2 ? awaited[1] : undefined;\n } else {\n pluginConfig = awaited.plugin as Plugin<TPluginContext>;\n pluginOptions = awaited.options;\n }\n\n if (isSetString(pluginConfig)) {\n const resolved = await resolvePlugin<\n TResolvedConfig,\n TSystemContext,\n TContext,\n TPluginContext\n >(context, pluginConfig);\n if (isFunction(resolved)) {\n plugins = toArray(\n await Promise.resolve(\n pluginOptions ? resolved(pluginOptions) : resolved()\n )\n );\n } else {\n plugins = toArray(resolved);\n }\n } else if (isFunction(pluginConfig)) {\n plugins = toArray(await Promise.resolve(pluginConfig(pluginOptions)));\n } else if (\n Array.isArray(pluginConfig) &&\n pluginConfig.every(isPlugin<TPluginContext>)\n ) {\n plugins = pluginConfig;\n } else if (isPlugin<TPluginContext>(pluginConfig)) {\n plugins = toArray(pluginConfig);\n }\n }\n\n if (!plugins) {\n throw new Error(\n `The plugin configuration ${JSON.stringify(awaited)} is invalid. This configuration must point to a valid Powerlines plugin module.`\n );\n }\n\n if (plugins.length > 0 && !plugins.every(isPlugin<TPluginContext>)) {\n throw new Error(\n `The plugin option ${JSON.stringify(plugins)} does not export a valid module. This configuration must point to a valid Powerlines plugin module.`\n );\n }\n\n const result = [] as Plugin<TPluginContext>[];\n for (const plugin of plugins) {\n if (isDuplicate<TPluginContext>(plugin, context.plugins)) {\n if (!skipLogging) {\n context.trace({\n meta: {\n category: \"plugins\"\n },\n message: `Duplicate ${chalk.bold.cyanBright(\n plugin.name\n )} plugin dependency detected - Skipping initialization.`\n });\n }\n } else {\n result.push(plugin);\n\n if (!skipLogging) {\n context.trace({\n meta: {\n category: \"plugins\"\n },\n message: `Initializing the ${chalk.bold.cyanBright(plugin.name)} plugin...`\n });\n }\n }\n }\n\n return result;\n}\n\nexport interface ResolvePluginsOptions {\n /**\n * If true, the plugin resolution process will skip logging messages about the plugin initialization. This can be useful in scenarios where you want to suppress plugin-related logs, such as when running in a non-interactive environment or when you want to reduce log verbosity. By default, this option is false, and plugin initialization messages will be logged using the context's logger.\n */\n skipLogging?: boolean;\n}\n\n/**\n * Initialize a plugin based on the provided plugin configuration. This function handles various forms of plugin configurations, including direct plugin instances, plugin names, factory functions, and arrays of plugins. It validates the configuration, resolves plugin modules if necessary, and returns an array of initialized plugins ready to be added to the execution context.\n *\n * @param context - The execution context in which the plugin will be initialized. This context provides access to configuration, logging, and other utilities that may be needed during plugin initialization.\n * @param config - The plugin configuration, which can be in various forms such as a plugin instance, a plugin name string, a factory function that returns a plugin or an array of plugins, or an array of plugin configurations. The function will handle the resolution and initialization of the plugin(s) based on the provided configuration.\n * @returns A promise that resolves to an array of initialized plugins that can be added to the execution context, or null if the configuration is invalid or results in no plugins being initialized.\n */\nexport async function resolvePlugins<\n TResolvedConfig extends ResolvedConfig,\n TSystemContext,\n TContext extends\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext> =\n | EnvironmentContext<TResolvedConfig, TSystemContext>\n | ExecutionContext<TResolvedConfig, TSystemContext>,\n TPluginContext extends PluginContext<TResolvedConfig, TSystemContext> =\n PluginContext<TResolvedConfig, TSystemContext>\n>(\n context: TContext,\n config: PluginConfig<TPluginContext>,\n options: ResolvePluginsOptions = {}\n) {\n const { skipLogging = false } = options;\n\n const plugins = [] as Plugin<TPluginContext>[];\n if (config) {\n const result = await initPlugin<\n TResolvedConfig,\n TSystemContext,\n TContext,\n TPluginContext\n >(context, config);\n if (result) {\n for (const plugin of result) {\n if (!skipLogging) {\n context.trace({\n meta: {\n category: \"plugins\"\n },\n message: `Successfully initialized the ${chalk.bold.cyanBright(\n plugin.name\n )} plugin`\n });\n }\n\n plugins.push(plugin);\n }\n }\n }\n\n return plugins;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts-morph.mjs","names":["#context"],"sources":["../../../src/lib/typescript/ts-morph.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport defu from \"defu\";\nimport {\n CompilerOptions,\n FileSystemHost,\n InMemoryFileSystemHost,\n Project,\n ProjectOptions,\n RuntimeDirEntry\n} from \"ts-morph\";\nimport type { Context } from \"../../types/context\";\n\nexport class VirtualFileSystemHost\n extends InMemoryFileSystemHost\n implements FileSystemHost\n{\n #context: Context;\n\n public constructor(context: Context) {\n super();\n\n this.#context = context;\n }\n\n public override deleteSync(path: string) {\n this.#context.fs.removeSync(path);\n }\n\n public override readDirSync(dirPath: string): RuntimeDirEntry[] {\n if (!this.#context.fs.isDirectorySync(dirPath)) {\n return [];\n }\n\n return this.#context.fs.listSync(dirPath).reduce((ret, entry) => {\n const fullPath = this.#context.fs.resolveSync(entry);\n if (fullPath) {\n ret.push({\n name: entry,\n isDirectory: this.#context.fs.isDirectorySync(fullPath),\n isFile: this.#context.fs.isFileSync(fullPath),\n isSymlink: false\n });\n }\n\n return ret;\n }, [] as RuntimeDirEntry[]);\n }\n\n public override async readFile(filePath: string) {\n if (!this.#context.fs.isFileSync(filePath)) {\n return \"\";\n }\n\n return (await this.#context.fs.read(filePath))!;\n }\n\n public override readFileSync(filePath: string) {\n if (!this.#context.fs.isFileSync(filePath)) {\n return \"\";\n }\n\n return this.#context.fs.readSync(filePath)!;\n }\n\n public override async writeFile(filePath: string, fileText: string) {\n return this.#context.fs.write(filePath, fileText);\n }\n\n public override writeFileSync(filePath: string, fileText: string) {\n this.#context.fs.writeSync(filePath, fileText);\n }\n\n public override async mkdir(dirPath: string) {\n await this.#context.fs.mkdir(dirPath);\n }\n\n public override mkdirSync(dirPath: string) {\n this.#context.fs.mkdirSync(dirPath);\n }\n\n public override async move(srcPath: string, destPath: string) {\n await this.#context.fs.move(srcPath, destPath);\n }\n\n public override moveSync(srcPath: string, destPath: string) {\n this.#context.fs.moveSync(srcPath, destPath);\n }\n\n public override async copy(srcPath: string, destPath: string) {\n await this.#context.fs.copy(srcPath, destPath);\n }\n\n public override copySync(srcPath: string, destPath: string) {\n this.#context.fs.copySync(srcPath, destPath);\n }\n\n public override async fileExists(filePath: string) {\n return this.#context.fs.isFile(filePath);\n }\n\n public override fileExistsSync(filePath: string) {\n return this.#context.fs.isFileSync(filePath);\n }\n\n public override async directoryExists(dirPath: string) {\n return this.#context.fs.isDirectory(dirPath);\n }\n\n public override directoryExistsSync(dirPath: string): boolean {\n return this.#context.fs.isDirectorySync(dirPath);\n }\n\n public override realpathSync(path: string) {\n return this.#context.fs.resolveSync(path) || path;\n }\n\n public override getCurrentDirectory() {\n return this.#context.config.cwd;\n }\n\n public override async glob(\n patterns: ReadonlyArray<string>\n ): Promise<string[]> {\n return this.#context.fs.glob(patterns as string[]);\n }\n\n public override globSync(patterns: ReadonlyArray<string>): string[] {\n return this.#context.fs.globSync(patterns as string[]);\n }\n}\n\n/**\n * Create a ts-morph {@link Project} instance used for type reflection and module manipulation during processing\n *\n * @param context - The Powerlines context\n * @returns A ts-morph {@link Project} instance\n */\nexport function createProgram(\n context: Context,\n override: Partial<ProjectOptions>\n): Project {\n context.debug(\n `Creating ts-morph Project instance with configuration from: ${\n context.tsconfig.tsconfigFilePath\n }.`\n );\n\n const project = new Project(\n defu(override ?? {}, {\n skipAddingFilesFromTsConfig: false,\n tsConfigFilePath: context.tsconfig.tsconfigFilePath,\n fileSystem: new VirtualFileSystemHost(context),\n compilerOptions: defu(context.tsconfig.options ?? {}, {\n lib: [\"lib.esnext.full.d.ts\"]\n }) as CompilerOptions\n })\n );\n\n return project;\n}\n"],"mappings":";;;;AA6BA,IAAa,wBAAb,cACU,uBAEV;CACE;CAEA,AAAO,YAAY,SAAkB;EACnC,MAAM;EAEN,KAAKA,WAAW;CAClB;CAEA,AAAgB,WAAW,MAAc;EACvC,KAAKA,SAAS,GAAG,WAAW,IAAI;CAClC;CAEA,AAAgB,YAAY,SAAoC;EAC9D,IAAI,CAAC,KAAKA,SAAS,GAAG,gBAAgB,OAAO,GAC3C,OAAO,CAAC;EAGV,OAAO,KAAKA,SAAS,GAAG,SAAS,OAAO,
|
|
1
|
+
{"version":3,"file":"ts-morph.mjs","names":["#context"],"sources":["../../../src/lib/typescript/ts-morph.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport defu from \"defu\";\nimport {\n CompilerOptions,\n FileSystemHost,\n InMemoryFileSystemHost,\n Project,\n ProjectOptions,\n RuntimeDirEntry\n} from \"ts-morph\";\nimport type { Context } from \"../../types/context\";\n\nexport class VirtualFileSystemHost\n extends InMemoryFileSystemHost\n implements FileSystemHost\n{\n #context: Context;\n\n public constructor(context: Context) {\n super();\n\n this.#context = context;\n }\n\n public override deleteSync(path: string) {\n this.#context.fs.removeSync(path);\n }\n\n public override readDirSync(dirPath: string): RuntimeDirEntry[] {\n if (!this.#context.fs.isDirectorySync(dirPath)) {\n return [];\n }\n\n return this.#context.fs.listSync(dirPath).reduce((ret, entry) => {\n const fullPath = this.#context.fs.resolveSync(entry);\n if (fullPath) {\n ret.push({\n name: entry,\n isDirectory: this.#context.fs.isDirectorySync(fullPath),\n isFile: this.#context.fs.isFileSync(fullPath),\n isSymlink: false\n });\n }\n\n return ret;\n }, [] as RuntimeDirEntry[]);\n }\n\n public override async readFile(filePath: string) {\n if (!this.#context.fs.isFileSync(filePath)) {\n return \"\";\n }\n\n return (await this.#context.fs.read(filePath))!;\n }\n\n public override readFileSync(filePath: string) {\n if (!this.#context.fs.isFileSync(filePath)) {\n return \"\";\n }\n\n return this.#context.fs.readSync(filePath)!;\n }\n\n public override async writeFile(filePath: string, fileText: string) {\n return this.#context.fs.write(filePath, fileText);\n }\n\n public override writeFileSync(filePath: string, fileText: string) {\n this.#context.fs.writeSync(filePath, fileText);\n }\n\n public override async mkdir(dirPath: string) {\n await this.#context.fs.mkdir(dirPath);\n }\n\n public override mkdirSync(dirPath: string) {\n this.#context.fs.mkdirSync(dirPath);\n }\n\n public override async move(srcPath: string, destPath: string) {\n await this.#context.fs.move(srcPath, destPath);\n }\n\n public override moveSync(srcPath: string, destPath: string) {\n this.#context.fs.moveSync(srcPath, destPath);\n }\n\n public override async copy(srcPath: string, destPath: string) {\n await this.#context.fs.copy(srcPath, destPath);\n }\n\n public override copySync(srcPath: string, destPath: string) {\n this.#context.fs.copySync(srcPath, destPath);\n }\n\n public override async fileExists(filePath: string) {\n return this.#context.fs.isFile(filePath);\n }\n\n public override fileExistsSync(filePath: string) {\n return this.#context.fs.isFileSync(filePath);\n }\n\n public override async directoryExists(dirPath: string) {\n return this.#context.fs.isDirectory(dirPath);\n }\n\n public override directoryExistsSync(dirPath: string): boolean {\n return this.#context.fs.isDirectorySync(dirPath);\n }\n\n public override realpathSync(path: string) {\n return this.#context.fs.resolveSync(path) || path;\n }\n\n public override getCurrentDirectory() {\n return this.#context.config.cwd;\n }\n\n public override async glob(\n patterns: ReadonlyArray<string>\n ): Promise<string[]> {\n return this.#context.fs.glob(patterns as string[]);\n }\n\n public override globSync(patterns: ReadonlyArray<string>): string[] {\n return this.#context.fs.globSync(patterns as string[]);\n }\n}\n\n/**\n * Create a ts-morph {@link Project} instance used for type reflection and module manipulation during processing\n *\n * @param context - The Powerlines context\n * @returns A ts-morph {@link Project} instance\n */\nexport function createProgram(\n context: Context,\n override: Partial<ProjectOptions>\n): Project {\n context.debug(\n `Creating ts-morph Project instance with configuration from: ${\n context.tsconfig.tsconfigFilePath\n }.`\n );\n\n const project = new Project(\n defu(override ?? {}, {\n skipAddingFilesFromTsConfig: false,\n tsConfigFilePath: context.tsconfig.tsconfigFilePath,\n fileSystem: new VirtualFileSystemHost(context),\n compilerOptions: defu(context.tsconfig.options ?? {}, {\n lib: [\"lib.esnext.full.d.ts\"]\n }) as CompilerOptions\n })\n );\n\n return project;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsconfig.mjs","names":[],"sources":["../../../src/lib/typescript/tsconfig.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { Diff, ObjectData } from \"@donedeal0/superdiff\";\nimport { getObjectDiff } from \"@donedeal0/superdiff\";\nimport { existsSync } from \"@stryke/fs/exists\";\nimport { readJsonFile, readJsonFileSync } from \"@stryke/fs/json\";\nimport { isPackageExists } from \"@stryke/fs/package-fns\";\nimport { StormJSON } from \"@stryke/json/storm-json\";\nimport { appendPath } from \"@stryke/path/append\";\nimport {\n findFileName,\n findFilePath,\n relativePath\n} from \"@stryke/path/file-path-fns\";\nimport { joinPaths } from \"@stryke/path/join-paths\";\nimport { titleCase } from \"@stryke/string-format/title-case\";\nimport { FilterPattern } from \"@stryke/types/file\";\nimport { TsConfigJson } from \"@stryke/types/tsconfig\";\nimport chalk from \"chalk\";\nimport defu from \"defu\";\nimport ts from \"typescript\";\nimport { ResolvedConfig } from \"../../types/config\";\nimport { EnvironmentContext } from \"../../types/context\";\nimport type { ParsedTypeScriptConfig, TSConfig } from \"../../types/tsconfig\";\n\nexport function getTsconfigDtsPath<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown\n>(context: EnvironmentContext<TResolvedConfig, TSystemContext>): string {\n const dtsRelativePath = joinPaths(\n relativePath(\n joinPaths(context.config.cwd, context.config.root),\n findFilePath(context.typesPath)\n ),\n findFileName(context.typesPath)\n );\n\n return dtsRelativePath;\n}\n\nasync function resolveTsconfigChanges<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown\n>(\n context: EnvironmentContext<TResolvedConfig, TSystemContext>\n): Promise<TsConfigJson> {\n const tsconfig = getParsedTypeScriptConfig(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig,\n context.config.tsconfigRaw\n );\n\n const tsconfigFilePath = getTsconfigFilePath(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig\n );\n\n const tsconfigJson = await readJsonFile<TsConfigJson>(tsconfigFilePath);\n tsconfigJson.compilerOptions ??= {};\n\n if (context.config.output.dts !== false) {\n const dtsRelativePath = getTsconfigDtsPath(context);\n\n if (\n !tsconfigJson.include?.some(filePattern =>\n isIncludeMatchFound(filePattern, [context.typesPath, dtsRelativePath])\n )\n ) {\n tsconfigJson.include ??= [];\n tsconfigJson.include.push(\n dtsRelativePath.startsWith(\"./\")\n ? dtsRelativePath.slice(2)\n : dtsRelativePath\n );\n }\n }\n\n if (\n !tsconfig.options.lib?.some(lib =>\n [\n \"lib.esnext.d.ts\",\n \"lib.es2021.d.ts\",\n \"lib.es2022.d.ts\",\n \"lib.es2023.d.ts\"\n ].includes(lib.toLowerCase())\n )\n ) {\n tsconfigJson.compilerOptions.lib ??= [];\n tsconfigJson.compilerOptions.lib.push(\"esnext\");\n }\n\n // if (tsconfig.options.module !== ts.ModuleKind.ESNext) {\n // tsconfigJson.compilerOptions.module = \"ESNext\";\n // }\n\n // if (\n // !tsconfig.options.target ||\n // ![\n // ts.ScriptTarget.ESNext,\n // ts.ScriptTarget.ES2024,\n // ts.ScriptTarget.ES2023,\n // ts.ScriptTarget.ES2022,\n // ts.ScriptTarget.ES2021\n // ].includes(tsconfig.options.target)\n // ) {\n // tsconfigJson.compilerOptions.target = \"ESNext\";\n // }\n\n // if (tsconfig.options.moduleResolution !== ts.ModuleResolutionKind.Bundler) {\n // tsconfigJson.compilerOptions.moduleResolution = \"Bundler\";\n // }\n\n // if (tsconfig.options.moduleDetection !== ts.ModuleDetectionKind.Force) {\n // tsconfigJson.compilerOptions.moduleDetection = \"force\";\n // }\n\n // if (tsconfig.options.allowSyntheticDefaultImports !== true) {\n // tsconfigJson.compilerOptions.allowSyntheticDefaultImports = true;\n // }\n\n // if (tsconfig.options.noImplicitOverride !== true) {\n // tsconfigJson.compilerOptions.noImplicitOverride = true;\n // }\n\n // if (tsconfig.options.noUncheckedIndexedAccess !== true) {\n // tsconfigJson.compilerOptions.noUncheckedIndexedAccess = true;\n // }\n\n // if (tsconfig.options.skipLibCheck !== true) {\n // tsconfigJson.compilerOptions.skipLibCheck = true;\n // }\n\n // if (tsconfig.options.resolveJsonModule !== true) {\n // tsconfigJson.compilerOptions.resolveJsonModule = true;\n // }\n\n // if (tsconfig.options.verbatimModuleSyntax !== false) {\n // tsconfigJson.compilerOptions.verbatimModuleSyntax = false;\n // }\n\n // if (tsconfig.options.allowJs !== true) {\n // tsconfigJson.compilerOptions.allowJs = true;\n // }\n\n // if (tsconfig.options.declaration !== true) {\n // tsconfigJson.compilerOptions.declaration = true;\n // }\n\n if (tsconfig.options.esModuleInterop !== true) {\n tsconfigJson.compilerOptions.esModuleInterop = true;\n }\n\n if (tsconfig.options.isolatedModules !== true) {\n tsconfigJson.compilerOptions.isolatedModules = true;\n }\n\n if (context.config.platform === \"node\") {\n if (\n !tsconfig.options.types?.some(\n type =>\n type.toLowerCase() === \"node\" || type.toLowerCase() === \"@types/node\"\n )\n ) {\n tsconfigJson.compilerOptions.types ??= [];\n tsconfigJson.compilerOptions.types.push(\"node\");\n }\n }\n\n return tsconfigJson;\n}\n\nexport async function initializeTsconfig<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown,\n TContext extends EnvironmentContext<TResolvedConfig, TSystemContext> =\n EnvironmentContext<TResolvedConfig, TSystemContext>\n>(context: TContext): Promise<void> {\n context.debug(\n \"Initializing TypeScript configuration (tsconfig.json) for the Powerlines project.\"\n );\n\n if (!isPackageExists(\"typescript\")) {\n throw new Error(\n 'The TypeScript package is not installed. Please install the package using the command: \"npm install typescript --save-dev\"'\n );\n }\n\n const tsconfigFilePath = getTsconfigFilePath(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig\n );\n\n context.tsconfig.originalTsconfigJson =\n await readJsonFile<TsConfigJson>(tsconfigFilePath);\n\n context.tsconfig.tsconfigJson = await resolveTsconfigChanges<\n TResolvedConfig,\n TSystemContext\n >(context);\n\n context.debug(\n \"Writing updated TypeScript configuration (tsconfig.json) file to disk.\"\n );\n\n await context.fs.write(\n tsconfigFilePath,\n StormJSON.stringify(context.tsconfig.tsconfigJson)\n );\n\n context.tsconfig = getParsedTypeScriptConfig(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig,\n context.config.tsconfigRaw,\n context.tsconfig.originalTsconfigJson\n );\n}\n\nexport async function resolveTsconfig<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown,\n TContext extends EnvironmentContext<TResolvedConfig, TSystemContext> =\n EnvironmentContext<TResolvedConfig, TSystemContext>\n>(context: TContext): Promise<void> {\n const updateTsconfigJson = await readJsonFile<TsConfigJson>(\n context.tsconfig.tsconfigFilePath\n );\n if (\n updateTsconfigJson?.compilerOptions?.types &&\n Array.isArray(updateTsconfigJson.compilerOptions.types) &&\n !updateTsconfigJson.compilerOptions.types.length\n ) {\n // If the types array is empty, we can safely remove it\n delete updateTsconfigJson.compilerOptions.types;\n }\n\n const result = getObjectDiff(\n context.tsconfig.originalTsconfigJson as NonNullable<ObjectData>,\n updateTsconfigJson as ObjectData,\n {\n ignoreArrayOrder: true,\n showOnly: {\n statuses: [\"added\", \"deleted\", \"updated\"],\n granularity: \"deep\"\n }\n }\n );\n\n const changes = [] as {\n field: string;\n status: \"added\" | \"deleted\" | \"updated\";\n previous: string;\n current: string;\n }[];\n const getChanges = (difference: Diff, property?: string) => {\n if (\n difference.status === \"added\" ||\n difference.status === \"deleted\" ||\n difference.status === \"updated\"\n ) {\n if (difference.diff) {\n for (const diff of difference.diff) {\n getChanges(\n diff,\n property\n ? `${property}.${difference.property}`\n : difference.property\n );\n }\n } else {\n changes.push({\n field: property\n ? `${property}.${difference.property}`\n : difference.property,\n status: difference.status,\n previous:\n difference.status === \"added\"\n ? \"---\"\n : StormJSON.stringify(difference.previousValue),\n current:\n difference.status === \"deleted\"\n ? \"---\"\n : StormJSON.stringify(difference.currentValue)\n });\n }\n }\n };\n\n for (const diff of result.diff) {\n getChanges(diff);\n }\n\n if (changes.length > 0) {\n context.warn(\n `Updating the following configuration values in \"${context.tsconfig.tsconfigFilePath}\" file:\n\n ${changes\n .map(\n (change, i) => `${chalk.bold.whiteBright(\n `${i + 1}. ${titleCase(change.status)} the ${change.field} field: `\n )}\n ${chalk.red(` - Previous: ${change.previous} `)}\n ${chalk.green(` - Updated: ${change.current} `)}\n `\n )\n .join(\"\\n\")}\n `\n );\n }\n\n await context.fs.write(\n context.tsconfig.tsconfigFilePath,\n StormJSON.stringify(updateTsconfigJson)\n );\n\n context.tsconfig = getParsedTypeScriptConfig(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig\n );\n if (!context.tsconfig) {\n throw new Error(\"Failed to parse the TypeScript configuration file.\");\n }\n}\n\n/**\n * Get the path to the tsconfig.json file.\n *\n * @param cwd - The root directory of the workspace.\n * @param root - The root directory of the project.\n * @param tsconfig - The path to the tsconfig.json file.\n * @returns The absolute path to the tsconfig.json file.\n * @throws If the tsconfig.json file does not exist.\n */\nexport function getTsconfigFilePath(\n cwd: string,\n root: string,\n tsconfig?: string\n): string {\n let tsconfigFilePath: string | undefined;\n if (tsconfig) {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, tsconfig);\n } else {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, \"tsconfig.app.json\");\n if (!tsconfigFilePath) {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, \"tsconfig.lib.json\");\n if (!tsconfigFilePath) {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, \"tsconfig.json\");\n }\n }\n }\n\n if (!tsconfigFilePath) {\n throw new Error(\n `Cannot find the \\`tsconfig.json\\` configuration file for the project at ${\n root\n }.`\n );\n }\n\n return tsconfigFilePath;\n}\n\n/**\n * Get the path to the tsconfig.json file.\n *\n * @param cwd - The root directory of the workspace.\n * @param root - The root directory of the project.\n * @param tsconfig - The path to the tsconfig.json file.\n * @returns The absolute path to the tsconfig.json file.\n * @throws If the tsconfig.json file does not exist.\n */\nexport function tryTsconfigFilePath(\n cwd: string,\n root: string,\n tsconfig: string\n): string | undefined {\n let tsconfigFilePath = tsconfig;\n if (!existsSync(tsconfigFilePath)) {\n tsconfigFilePath = appendPath(tsconfig, root);\n if (!existsSync(tsconfigFilePath)) {\n tsconfigFilePath = appendPath(tsconfig, appendPath(root, cwd));\n if (!existsSync(tsconfigFilePath)) {\n return undefined;\n }\n }\n }\n\n return tsconfigFilePath;\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function findMatch(\n tsconfigType: string | RegExp | null,\n types: (string | RegExp | null)[],\n extensions: string[] = [\".ts\", \".tsx\", \".d.ts\"]\n): string | RegExp | null | undefined {\n return types.find(\n type =>\n tsconfigType?.toString().toLowerCase() ===\n type?.toString().toLowerCase() ||\n tsconfigType?.toString().toLowerCase() ===\n `./${type?.toString().toLowerCase()}` ||\n `./${tsconfigType?.toString().toLowerCase()}` ===\n type?.toString().toLowerCase() ||\n extensions.some(\n ext =>\n `${tsconfigType?.toString().toLowerCase()}${ext}` ===\n type?.toString().toLowerCase() ||\n `${tsconfigType?.toString().toLowerCase()}${ext}` ===\n `./${type?.toString().toLowerCase()}` ||\n `${type?.toString().toLowerCase()}${ext}` ===\n `./${tsconfigType?.toString().toLowerCase()}` ||\n tsconfigType?.toString().toLowerCase() ===\n `${type?.toString().toLowerCase()}${ext}` ||\n tsconfigType?.toString().toLowerCase() ===\n `./${type?.toString().toLowerCase()}${ext}` ||\n type?.toString().toLowerCase() ===\n `./${tsconfigType?.toString().toLowerCase()}${ext}`\n )\n );\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function findIncludeMatch(\n tsconfigType: string | RegExp | null,\n types: (string | RegExp | null)[]\n): string | RegExp | null | undefined {\n return findMatch(tsconfigType, types, [\n \".ts\",\n \".tsx\",\n \".d.ts\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".mts\",\n \".cts\",\n \"/*.ts\",\n \"/*.tsx\",\n \"/*.d.ts\",\n \"/*.js\",\n \"/*.jsx\",\n \"/*.mjs\",\n \"/*.cjs\",\n \"/*.mts\",\n \"/*.cts\",\n \"/**/*.ts\",\n \"/**/*.tsx\",\n \"/**/*.d.ts\",\n \"/**/*.js\",\n \"/**/*.jsx\",\n \"/**/*.mjs\",\n \"/**/*.cjs\",\n \"/**/*.mts\",\n \"/**/*.cts\"\n ]);\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function isMatchFound(\n tsconfigType: string | RegExp | null,\n types: (string | RegExp | null)[]\n): boolean {\n return findMatch(tsconfigType, types) !== undefined;\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function isIncludeMatchFound(\n tsconfigType: FilterPattern,\n types: FilterPattern[]\n): boolean {\n return (\n findIncludeMatch(\n tsconfigType as string | RegExp | null,\n types as (string | RegExp | null)[]\n ) !== undefined\n );\n}\n\n/**\n * Get the parsed TypeScript configuration.\n *\n * @param workspaceRoot - The root directory of the workspace.\n * @param projectRoot - The root directory of the project.\n * @param tsconfig - The path to the tsconfig.json file.\n * @param tsconfigRaw - The raw tsconfig.json content.\n * @param originalTsconfigJson - The original tsconfig.json content.\n * @param host - The TypeScript parse config host.\n * @returns The resolved TypeScript configuration.\n */\nexport function getParsedTypeScriptConfig(\n workspaceRoot: string,\n projectRoot: string,\n tsconfig?: string,\n tsconfigRaw: TSConfig = {},\n originalTsconfigJson?: TSConfig,\n host: ts.ParseConfigHost = ts.sys\n): ParsedTypeScriptConfig {\n const tsconfigFilePath = getTsconfigFilePath(\n workspaceRoot,\n projectRoot,\n tsconfig\n );\n const tsconfigJson = readJsonFileSync<TSConfig>(tsconfigFilePath);\n if (!tsconfigJson) {\n throw new Error(\n `Cannot find the \\`tsconfig.json\\` configuration file at ${joinPaths(\n projectRoot,\n tsconfig ?? \"tsconfig.json\"\n )}`\n );\n }\n\n const parsedCommandLine = ts.parseJsonConfigFileContent(\n defu(tsconfigRaw ?? {}, tsconfigJson),\n host,\n appendPath(projectRoot, workspaceRoot)\n );\n if (parsedCommandLine.errors.length > 0) {\n const errorMessage = `Cannot parse the TypeScript compiler options. Please investigate the following issues:\n${parsedCommandLine.errors\n .map(\n error =>\n `- ${\n (error.category !== undefined && error.code\n ? `[${error.category}-${error.code}]: `\n : \"\") + error.messageText.toString()\n }`\n )\n .join(\"\\n\")}\n `;\n\n throw new Error(errorMessage);\n }\n\n return {\n ...parsedCommandLine,\n originalTsconfigJson: (originalTsconfigJson ??\n tsconfigJson) as TsConfigJson,\n tsconfigJson,\n tsconfigFilePath\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tsconfig.mjs","names":[],"sources":["../../../src/lib/typescript/tsconfig.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { Diff, ObjectData } from \"@donedeal0/superdiff\";\nimport { getObjectDiff } from \"@donedeal0/superdiff\";\nimport { existsSync } from \"@stryke/fs/exists\";\nimport { readJsonFile, readJsonFileSync } from \"@stryke/fs/json\";\nimport { isPackageExists } from \"@stryke/fs/package-fns\";\nimport { StormJSON } from \"@stryke/json/storm-json\";\nimport { appendPath } from \"@stryke/path/append\";\nimport {\n findFileName,\n findFilePath,\n relativePath\n} from \"@stryke/path/file-path-fns\";\nimport { joinPaths } from \"@stryke/path/join-paths\";\nimport { titleCase } from \"@stryke/string-format/title-case\";\nimport { FilterPattern } from \"@stryke/types/file\";\nimport { TsConfigJson } from \"@stryke/types/tsconfig\";\nimport chalk from \"chalk\";\nimport defu from \"defu\";\nimport ts from \"typescript\";\nimport { ResolvedConfig } from \"../../types/config\";\nimport { EnvironmentContext } from \"../../types/context\";\nimport type { ParsedTypeScriptConfig, TSConfig } from \"../../types/tsconfig\";\n\nexport function getTsconfigDtsPath<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown\n>(context: EnvironmentContext<TResolvedConfig, TSystemContext>): string {\n const dtsRelativePath = joinPaths(\n relativePath(\n joinPaths(context.config.cwd, context.config.root),\n findFilePath(context.typesPath)\n ),\n findFileName(context.typesPath)\n );\n\n return dtsRelativePath;\n}\n\nasync function resolveTsconfigChanges<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown\n>(\n context: EnvironmentContext<TResolvedConfig, TSystemContext>\n): Promise<TsConfigJson> {\n const tsconfig = getParsedTypeScriptConfig(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig,\n context.config.tsconfigRaw\n );\n\n const tsconfigFilePath = getTsconfigFilePath(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig\n );\n\n const tsconfigJson = await readJsonFile<TsConfigJson>(tsconfigFilePath);\n tsconfigJson.compilerOptions ??= {};\n\n if (context.config.output.dts !== false) {\n const dtsRelativePath = getTsconfigDtsPath(context);\n\n if (\n !tsconfigJson.include?.some(filePattern =>\n isIncludeMatchFound(filePattern, [context.typesPath, dtsRelativePath])\n )\n ) {\n tsconfigJson.include ??= [];\n tsconfigJson.include.push(\n dtsRelativePath.startsWith(\"./\")\n ? dtsRelativePath.slice(2)\n : dtsRelativePath\n );\n }\n }\n\n if (\n !tsconfig.options.lib?.some(lib =>\n [\n \"lib.esnext.d.ts\",\n \"lib.es2021.d.ts\",\n \"lib.es2022.d.ts\",\n \"lib.es2023.d.ts\"\n ].includes(lib.toLowerCase())\n )\n ) {\n tsconfigJson.compilerOptions.lib ??= [];\n tsconfigJson.compilerOptions.lib.push(\"esnext\");\n }\n\n // if (tsconfig.options.module !== ts.ModuleKind.ESNext) {\n // tsconfigJson.compilerOptions.module = \"ESNext\";\n // }\n\n // if (\n // !tsconfig.options.target ||\n // ![\n // ts.ScriptTarget.ESNext,\n // ts.ScriptTarget.ES2024,\n // ts.ScriptTarget.ES2023,\n // ts.ScriptTarget.ES2022,\n // ts.ScriptTarget.ES2021\n // ].includes(tsconfig.options.target)\n // ) {\n // tsconfigJson.compilerOptions.target = \"ESNext\";\n // }\n\n // if (tsconfig.options.moduleResolution !== ts.ModuleResolutionKind.Bundler) {\n // tsconfigJson.compilerOptions.moduleResolution = \"Bundler\";\n // }\n\n // if (tsconfig.options.moduleDetection !== ts.ModuleDetectionKind.Force) {\n // tsconfigJson.compilerOptions.moduleDetection = \"force\";\n // }\n\n // if (tsconfig.options.allowSyntheticDefaultImports !== true) {\n // tsconfigJson.compilerOptions.allowSyntheticDefaultImports = true;\n // }\n\n // if (tsconfig.options.noImplicitOverride !== true) {\n // tsconfigJson.compilerOptions.noImplicitOverride = true;\n // }\n\n // if (tsconfig.options.noUncheckedIndexedAccess !== true) {\n // tsconfigJson.compilerOptions.noUncheckedIndexedAccess = true;\n // }\n\n // if (tsconfig.options.skipLibCheck !== true) {\n // tsconfigJson.compilerOptions.skipLibCheck = true;\n // }\n\n // if (tsconfig.options.resolveJsonModule !== true) {\n // tsconfigJson.compilerOptions.resolveJsonModule = true;\n // }\n\n // if (tsconfig.options.verbatimModuleSyntax !== false) {\n // tsconfigJson.compilerOptions.verbatimModuleSyntax = false;\n // }\n\n // if (tsconfig.options.allowJs !== true) {\n // tsconfigJson.compilerOptions.allowJs = true;\n // }\n\n // if (tsconfig.options.declaration !== true) {\n // tsconfigJson.compilerOptions.declaration = true;\n // }\n\n if (tsconfig.options.esModuleInterop !== true) {\n tsconfigJson.compilerOptions.esModuleInterop = true;\n }\n\n if (tsconfig.options.isolatedModules !== true) {\n tsconfigJson.compilerOptions.isolatedModules = true;\n }\n\n if (context.config.platform === \"node\") {\n if (\n !tsconfig.options.types?.some(\n type =>\n type.toLowerCase() === \"node\" || type.toLowerCase() === \"@types/node\"\n )\n ) {\n tsconfigJson.compilerOptions.types ??= [];\n tsconfigJson.compilerOptions.types.push(\"node\");\n }\n }\n\n return tsconfigJson;\n}\n\nexport async function initializeTsconfig<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown,\n TContext extends EnvironmentContext<TResolvedConfig, TSystemContext> =\n EnvironmentContext<TResolvedConfig, TSystemContext>\n>(context: TContext): Promise<void> {\n context.debug(\n \"Initializing TypeScript configuration (tsconfig.json) for the Powerlines project.\"\n );\n\n if (!isPackageExists(\"typescript\")) {\n throw new Error(\n 'The TypeScript package is not installed. Please install the package using the command: \"npm install typescript --save-dev\"'\n );\n }\n\n const tsconfigFilePath = getTsconfigFilePath(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig\n );\n\n context.tsconfig.originalTsconfigJson =\n await readJsonFile<TsConfigJson>(tsconfigFilePath);\n\n context.tsconfig.tsconfigJson = await resolveTsconfigChanges<\n TResolvedConfig,\n TSystemContext\n >(context);\n\n context.debug(\n \"Writing updated TypeScript configuration (tsconfig.json) file to disk.\"\n );\n\n await context.fs.write(\n tsconfigFilePath,\n StormJSON.stringify(context.tsconfig.tsconfigJson)\n );\n\n context.tsconfig = getParsedTypeScriptConfig(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig,\n context.config.tsconfigRaw,\n context.tsconfig.originalTsconfigJson\n );\n}\n\nexport async function resolveTsconfig<\n TResolvedConfig extends ResolvedConfig = ResolvedConfig,\n TSystemContext = unknown,\n TContext extends EnvironmentContext<TResolvedConfig, TSystemContext> =\n EnvironmentContext<TResolvedConfig, TSystemContext>\n>(context: TContext): Promise<void> {\n const updateTsconfigJson = await readJsonFile<TsConfigJson>(\n context.tsconfig.tsconfigFilePath\n );\n if (\n updateTsconfigJson?.compilerOptions?.types &&\n Array.isArray(updateTsconfigJson.compilerOptions.types) &&\n !updateTsconfigJson.compilerOptions.types.length\n ) {\n // If the types array is empty, we can safely remove it\n delete updateTsconfigJson.compilerOptions.types;\n }\n\n const result = getObjectDiff(\n context.tsconfig.originalTsconfigJson as NonNullable<ObjectData>,\n updateTsconfigJson as ObjectData,\n {\n ignoreArrayOrder: true,\n showOnly: {\n statuses: [\"added\", \"deleted\", \"updated\"],\n granularity: \"deep\"\n }\n }\n );\n\n const changes = [] as {\n field: string;\n status: \"added\" | \"deleted\" | \"updated\";\n previous: string;\n current: string;\n }[];\n const getChanges = (difference: Diff, property?: string) => {\n if (\n difference.status === \"added\" ||\n difference.status === \"deleted\" ||\n difference.status === \"updated\"\n ) {\n if (difference.diff) {\n for (const diff of difference.diff) {\n getChanges(\n diff,\n property\n ? `${property}.${difference.property}`\n : difference.property\n );\n }\n } else {\n changes.push({\n field: property\n ? `${property}.${difference.property}`\n : difference.property,\n status: difference.status,\n previous:\n difference.status === \"added\"\n ? \"---\"\n : StormJSON.stringify(difference.previousValue),\n current:\n difference.status === \"deleted\"\n ? \"---\"\n : StormJSON.stringify(difference.currentValue)\n });\n }\n }\n };\n\n for (const diff of result.diff) {\n getChanges(diff);\n }\n\n if (changes.length > 0) {\n context.warn(\n `Updating the following configuration values in \"${context.tsconfig.tsconfigFilePath}\" file:\n\n ${changes\n .map(\n (change, i) => `${chalk.bold.whiteBright(\n `${i + 1}. ${titleCase(change.status)} the ${change.field} field: `\n )}\n ${chalk.red(` - Previous: ${change.previous} `)}\n ${chalk.green(` - Updated: ${change.current} `)}\n `\n )\n .join(\"\\n\")}\n `\n );\n }\n\n await context.fs.write(\n context.tsconfig.tsconfigFilePath,\n StormJSON.stringify(updateTsconfigJson)\n );\n\n context.tsconfig = getParsedTypeScriptConfig(\n context.config.cwd,\n context.config.root,\n context.config.tsconfig\n );\n if (!context.tsconfig) {\n throw new Error(\"Failed to parse the TypeScript configuration file.\");\n }\n}\n\n/**\n * Get the path to the tsconfig.json file.\n *\n * @param cwd - The root directory of the workspace.\n * @param root - The root directory of the project.\n * @param tsconfig - The path to the tsconfig.json file.\n * @returns The absolute path to the tsconfig.json file.\n * @throws If the tsconfig.json file does not exist.\n */\nexport function getTsconfigFilePath(\n cwd: string,\n root: string,\n tsconfig?: string\n): string {\n let tsconfigFilePath: string | undefined;\n if (tsconfig) {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, tsconfig);\n } else {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, \"tsconfig.app.json\");\n if (!tsconfigFilePath) {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, \"tsconfig.lib.json\");\n if (!tsconfigFilePath) {\n tsconfigFilePath = tryTsconfigFilePath(cwd, root, \"tsconfig.json\");\n }\n }\n }\n\n if (!tsconfigFilePath) {\n throw new Error(\n `Cannot find the \\`tsconfig.json\\` configuration file for the project at ${\n root\n }.`\n );\n }\n\n return tsconfigFilePath;\n}\n\n/**\n * Get the path to the tsconfig.json file.\n *\n * @param cwd - The root directory of the workspace.\n * @param root - The root directory of the project.\n * @param tsconfig - The path to the tsconfig.json file.\n * @returns The absolute path to the tsconfig.json file.\n * @throws If the tsconfig.json file does not exist.\n */\nexport function tryTsconfigFilePath(\n cwd: string,\n root: string,\n tsconfig: string\n): string | undefined {\n let tsconfigFilePath = tsconfig;\n if (!existsSync(tsconfigFilePath)) {\n tsconfigFilePath = appendPath(tsconfig, root);\n if (!existsSync(tsconfigFilePath)) {\n tsconfigFilePath = appendPath(tsconfig, appendPath(root, cwd));\n if (!existsSync(tsconfigFilePath)) {\n return undefined;\n }\n }\n }\n\n return tsconfigFilePath;\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function findMatch(\n tsconfigType: string | RegExp | null,\n types: (string | RegExp | null)[],\n extensions: string[] = [\".ts\", \".tsx\", \".d.ts\"]\n): string | RegExp | null | undefined {\n return types.find(\n type =>\n tsconfigType?.toString().toLowerCase() ===\n type?.toString().toLowerCase() ||\n tsconfigType?.toString().toLowerCase() ===\n `./${type?.toString().toLowerCase()}` ||\n `./${tsconfigType?.toString().toLowerCase()}` ===\n type?.toString().toLowerCase() ||\n extensions.some(\n ext =>\n `${tsconfigType?.toString().toLowerCase()}${ext}` ===\n type?.toString().toLowerCase() ||\n `${tsconfigType?.toString().toLowerCase()}${ext}` ===\n `./${type?.toString().toLowerCase()}` ||\n `${type?.toString().toLowerCase()}${ext}` ===\n `./${tsconfigType?.toString().toLowerCase()}` ||\n tsconfigType?.toString().toLowerCase() ===\n `${type?.toString().toLowerCase()}${ext}` ||\n tsconfigType?.toString().toLowerCase() ===\n `./${type?.toString().toLowerCase()}${ext}` ||\n type?.toString().toLowerCase() ===\n `./${tsconfigType?.toString().toLowerCase()}${ext}`\n )\n );\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function findIncludeMatch(\n tsconfigType: string | RegExp | null,\n types: (string | RegExp | null)[]\n): string | RegExp | null | undefined {\n return findMatch(tsconfigType, types, [\n \".ts\",\n \".tsx\",\n \".d.ts\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".mts\",\n \".cts\",\n \"/*.ts\",\n \"/*.tsx\",\n \"/*.d.ts\",\n \"/*.js\",\n \"/*.jsx\",\n \"/*.mjs\",\n \"/*.cjs\",\n \"/*.mts\",\n \"/*.cts\",\n \"/**/*.ts\",\n \"/**/*.tsx\",\n \"/**/*.d.ts\",\n \"/**/*.js\",\n \"/**/*.jsx\",\n \"/**/*.mjs\",\n \"/**/*.cjs\",\n \"/**/*.mts\",\n \"/**/*.cts\"\n ]);\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function isMatchFound(\n tsconfigType: string | RegExp | null,\n types: (string | RegExp | null)[]\n): boolean {\n return findMatch(tsconfigType, types) !== undefined;\n}\n\n/**\n * Check if the TypeScript configuration type matches any of the provided types.\n *\n * @param tsconfigType - The type from the TypeScript configuration.\n * @param types - An array of type names to check against.\n * @returns True if the TypeScript configuration type matches any of the provided types, false otherwise.\n */\nexport function isIncludeMatchFound(\n tsconfigType: FilterPattern,\n types: FilterPattern[]\n): boolean {\n return (\n findIncludeMatch(\n tsconfigType as string | RegExp | null,\n types as (string | RegExp | null)[]\n ) !== undefined\n );\n}\n\n/**\n * Get the parsed TypeScript configuration.\n *\n * @param workspaceRoot - The root directory of the workspace.\n * @param projectRoot - The root directory of the project.\n * @param tsconfig - The path to the tsconfig.json file.\n * @param tsconfigRaw - The raw tsconfig.json content.\n * @param originalTsconfigJson - The original tsconfig.json content.\n * @param host - The TypeScript parse config host.\n * @returns The resolved TypeScript configuration.\n */\nexport function getParsedTypeScriptConfig(\n workspaceRoot: string,\n projectRoot: string,\n tsconfig?: string,\n tsconfigRaw: TSConfig = {},\n originalTsconfigJson?: TSConfig,\n host: ts.ParseConfigHost = ts.sys\n): ParsedTypeScriptConfig {\n const tsconfigFilePath = getTsconfigFilePath(\n workspaceRoot,\n projectRoot,\n tsconfig\n );\n const tsconfigJson = readJsonFileSync<TSConfig>(tsconfigFilePath);\n if (!tsconfigJson) {\n throw new Error(\n `Cannot find the \\`tsconfig.json\\` configuration file at ${joinPaths(\n projectRoot,\n tsconfig ?? \"tsconfig.json\"\n )}`\n );\n }\n\n const parsedCommandLine = ts.parseJsonConfigFileContent(\n defu(tsconfigRaw ?? {}, tsconfigJson),\n host,\n appendPath(projectRoot, workspaceRoot)\n );\n if (parsedCommandLine.errors.length > 0) {\n const errorMessage = `Cannot parse the TypeScript compiler options. Please investigate the following issues:\n${parsedCommandLine.errors\n .map(\n error =>\n `- ${\n (error.category !== undefined && error.code\n ? `[${error.category}-${error.code}]: `\n : \"\") + error.messageText.toString()\n }`\n )\n .join(\"\\n\")}\n `;\n\n throw new Error(errorMessage);\n }\n\n return {\n ...parsedCommandLine,\n originalTsconfigJson: (originalTsconfigJson ??\n tsconfigJson) as TsConfigJson,\n tsconfigJson,\n tsconfigFilePath\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-header.mjs","names":[],"sources":["../../../src/lib/utilities/file-header.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { titleCase } from \"@stryke/string-format/title-case\";\nimport { Context } from \"../../types/context\";\n\nexport interface FileHeaderOptions {\n directive?: string | null;\n prettierIgnore?: boolean;\n}\n\n/**\n * Generates a file header comment with a warning about automatic overwriting.\n *\n * @param overwrite - Whether the file will be automatically overwritten. If `false`, the warning will indicate that the file will not be overwritten. If `true` or omitted, the warning will indicate that the file will be overwritten.\n * @param framework - The name of the framework to include in the warning message. Defaults to \"powerlines\".\n * @returns A string containing the file header warning message.\n */\nexport function getFileHeaderWarningText(\n overwrite = true,\n framework = \"powerlines\"\n): string {\n return overwrite !== false\n ? `Do not edit this file manually - it will be overwritten automatically. Automatic overwrites can be disabled by using the \\`output.overwrite\\` option.`\n : `This file was generated on ${new Date().toLocaleString()} - it will not be overwritten by ${titleCase(framework)} while the \\`output.overwrite\\` option is set to \\`true\\`.`;\n}\n\n/**\n * Generates a file header warning message based on the provided context.\n *\n * @param context - The Powerlines context.\n * @returns A string containing the file header warning message.\n */\nexport function getFileHeaderWarning(context: Context): string {\n return getFileHeaderWarningText(\n context.config.output?.overwrite,\n context.config.framework?.name\n );\n}\n\n/**\n * Generates a file header comment for a generated source file, including a warning about automatic overwriting.\n *\n * @param context - The Powerlines context.\n * @param comment - The comment syntax to use for the header (e.g., `//` for JavaScript/TypeScript, `#` for Python). Defaults to `//`.\n * @returns A string containing the file header comment.\n */\nexport function getFileHeader(context: Context, comment = \"//\"): string {\n return `\n${comment} Generated by ${titleCase(context.config.framework?.name) || \"Powerlines\"}\n${comment} ${getFileHeaderWarning(context)}\n`;\n}\n\n/**\n * Generates a file header comment for a generated TypeScript source file, including a warning about automatic overwriting.\n *\n * @param context - The Powerlines context.\n * @param options - Additional options for generating the file header, such as a directive to include and whether to add a Prettier ignore comment.\n * @returns A string containing the file header comment for a TypeScript file.\n */\nexport function getTypescriptFileHeader(\n context: Context,\n options: FileHeaderOptions = {}\n): string {\n const { directive = null, prettierIgnore = false } = options;\n\n return `/* eslint-disable */\n// biome-ignore lint: disable\n${prettierIgnore ? `// prettier-ignore` : \"\"}${directive ? `\\n\\n${directive}\\n` : \"\\n\"}\n${getFileHeader(context)}\n\n`;\n}\n"],"mappings":";;;;;;;;;;AAiCA,SAAgB,yBACd,YAAY,MACZ,YAAY,cACJ;CACR,OAAO,cAAc,QACjB,0JACA,+CAA8B,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"file-header.mjs","names":[],"sources":["../../../src/lib/utilities/file-header.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { titleCase } from \"@stryke/string-format/title-case\";\nimport { Context } from \"../../types/context\";\n\nexport interface FileHeaderOptions {\n directive?: string | null;\n prettierIgnore?: boolean;\n}\n\n/**\n * Generates a file header comment with a warning about automatic overwriting.\n *\n * @param overwrite - Whether the file will be automatically overwritten. If `false`, the warning will indicate that the file will not be overwritten. If `true` or omitted, the warning will indicate that the file will be overwritten.\n * @param framework - The name of the framework to include in the warning message. Defaults to \"powerlines\".\n * @returns A string containing the file header warning message.\n */\nexport function getFileHeaderWarningText(\n overwrite = true,\n framework = \"powerlines\"\n): string {\n return overwrite !== false\n ? `Do not edit this file manually - it will be overwritten automatically. Automatic overwrites can be disabled by using the \\`output.overwrite\\` option.`\n : `This file was generated on ${new Date().toLocaleString()} - it will not be overwritten by ${titleCase(framework)} while the \\`output.overwrite\\` option is set to \\`true\\`.`;\n}\n\n/**\n * Generates a file header warning message based on the provided context.\n *\n * @param context - The Powerlines context.\n * @returns A string containing the file header warning message.\n */\nexport function getFileHeaderWarning(context: Context): string {\n return getFileHeaderWarningText(\n context.config.output?.overwrite,\n context.config.framework?.name\n );\n}\n\n/**\n * Generates a file header comment for a generated source file, including a warning about automatic overwriting.\n *\n * @param context - The Powerlines context.\n * @param comment - The comment syntax to use for the header (e.g., `//` for JavaScript/TypeScript, `#` for Python). Defaults to `//`.\n * @returns A string containing the file header comment.\n */\nexport function getFileHeader(context: Context, comment = \"//\"): string {\n return `\n${comment} Generated by ${titleCase(context.config.framework?.name) || \"Powerlines\"}\n${comment} ${getFileHeaderWarning(context)}\n`;\n}\n\n/**\n * Generates a file header comment for a generated TypeScript source file, including a warning about automatic overwriting.\n *\n * @param context - The Powerlines context.\n * @param options - Additional options for generating the file header, such as a directive to include and whether to add a Prettier ignore comment.\n * @returns A string containing the file header comment for a TypeScript file.\n */\nexport function getTypescriptFileHeader(\n context: Context,\n options: FileHeaderOptions = {}\n): string {\n const { directive = null, prettierIgnore = false } = options;\n\n return `/* eslint-disable */\n// biome-ignore lint: disable\n${prettierIgnore ? `// prettier-ignore` : \"\"}${directive ? `\\n\\n${directive}\\n` : \"\\n\"}\n${getFileHeader(context)}\n\n`;\n}\n"],"mappings":";;;;;;;;;;AAiCA,SAAgB,yBACd,YAAY,MACZ,YAAY,cACJ;CACR,OAAO,cAAc,QACjB,0JACA,+CAA8B,IAAI,KAAK,EAAC,CAAC,eAAe,EAAE,mCAAmC,UAAU,SAAS,EAAE;AACxH;;;;;;;AAQA,SAAgB,qBAAqB,SAA0B;CAC7D,OAAO,yBACL,QAAQ,OAAO,QAAQ,WACvB,QAAQ,OAAO,WAAW,IAC5B;AACF;;;;;;;;AASA,SAAgB,cAAc,SAAkB,UAAU,MAAc;CACtE,OAAO;EACP,QAAQ,gBAAgB,UAAU,QAAQ,OAAO,WAAW,IAAI,KAAK,aAAa;EAClF,QAAQ,GAAG,qBAAqB,OAAO,EAAE;;AAE3C;;;;;;;;AASA,SAAgB,wBACd,SACA,UAA6B,CAAC,GACtB;CACR,MAAM,EAAE,YAAY,MAAM,iBAAiB,UAAU;CAErD,OAAO;;EAEP,iBAAiB,uBAAuB,KAAK,YAAY,OAAO,UAAU,MAAM,KAAK;EACrF,cAAc,OAAO,EAAE;;;AAGzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.mjs","names":["prettier","defu"],"sources":["../../../src/lib/utilities/format.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { listFiles } from \"@stryke/fs/list-files\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { findFileExtension } from \"@stryke/path/file-path-fns\";\nimport { isParentPath } from \"@stryke/path/is-parent-path\";\nimport { defu } from \"defu\";\nimport { format as prettier, resolveConfig } from \"prettier\";\nimport importsPlugin from \"prettier-plugin-organize-imports\";\nimport { Context } from \"../../types/context\";\n\n/**\n * Formats code using Prettier based on the file path.\n *\n * @param context - The Powerlines context.\n * @param path - The file path to use for resolving Prettier configuration.\n * @param data - The code string to format.\n * @param force - Whether to force formatting even for output/build paths.\n * @returns A promise that resolves to the formatted code string.\n */\nexport async function format(\n context: Context,\n path: string,\n data: string,\n force = false\n): Promise<string> {\n if (\n !force &&\n ((context.config.output.copy &&\n isParentPath(\n path,\n appendPath(context.config.output.copy.path, context.config.cwd)\n )) ||\n isParentPath(\n path,\n appendPath(context.config.output.path, context.config.cwd)\n ))\n ) {\n return data;\n }\n\n let code = data;\n try {\n const resolvedConfig = await resolveConfig(path);\n if (resolvedConfig) {\n code = await prettier(\n data,\n defu(\n {\n absolutePath: path,\n ...resolvedConfig\n },\n findFileExtension(path) === \"ts\" || findFileExtension(path) === \"tsx\"\n ? { plugins: [importsPlugin] }\n : {}\n )\n );\n }\n } catch (error) {\n throw new Error(\n `Failed to format file at ${path} with Prettier: ${\n (error as Error).message\n }`,\n { cause: error }\n );\n }\n\n return code;\n}\n\n/**\n * Formats all files in a folder using Prettier based on their file paths.\n *\n * @param context - The Powerlines context.\n * @param path - The folder path containing files to format.\n * @returns A promise that resolves when all files have been formatted.\n */\nexport async function formatFolder(context: Context, path: string) {\n if (\n !context.config.output.copy ||\n (!isParentPath(\n path,\n appendPath(context.config.output.copy.path, context.config.cwd)\n ) &&\n !isParentPath(\n path,\n appendPath(context.config.output.path, context.config.cwd)\n ))\n ) {\n await Promise.allSettled(\n (await listFiles(path)).map(async file => {\n if (\n (!context.config.output.copy ||\n !isParentPath(\n file,\n appendPath(context.config.output.copy.path, context.config.cwd)\n )) &&\n !isParentPath(\n file,\n appendPath(context.config.output.path, context.config.cwd)\n )\n ) {\n const data = await context.fs.read(file);\n if (data) {\n const formatted = await format(context, file, data);\n\n return context.fs.write(file, formatted);\n }\n }\n })\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoCA,eAAsB,OACpB,SACA,MACA,MACA,QAAQ,OACS;CACjB,IACE,CAAC,UACC,QAAQ,OAAO,OAAO,QACtB,aACE,MACA,WAAW,QAAQ,OAAO,OAAO,KAAK,MAAM,QAAQ,OAAO,GAAG,CAChE,KACA,aACE,MACA,WAAW,QAAQ,OAAO,OAAO,MAAM,QAAQ,OAAO,GAAG,CAC3D,IAEF,OAAO;CAGT,IAAI,OAAO;CACX,IAAI;EACF,MAAM,iBAAiB,MAAM,cAAc,IAAI;EAC/C,IAAI,gBACF,OAAO,MAAMA,SACX,MACAC,OACE;GACE,cAAc;GACd,GAAG;EACL,GACA,kBAAkB,IAAI,MAAM,QAAQ,kBAAkB,IAAI,MAAM,QAC5D,EAAE,SAAS,CAAC,aAAa,EAAE,IAC3B,CAAC,CACP,CACF;CAEJ,SAAS,OAAO;EACd,MAAM,IAAI,MACR,4BAA4B,KAAK,kBAC9B,MAAgB,WAEnB,EAAE,OAAO,MAAM,CACjB;CACF;CAEA,OAAO;AACT;;;;;;;;AASA,eAAsB,aAAa,SAAkB,MAAc;CACjE,IACE,CAAC,QAAQ,OAAO,OAAO,QACtB,CAAC,aACA,MACA,WAAW,QAAQ,OAAO,OAAO,KAAK,MAAM,QAAQ,OAAO,GAAG,CAChE,KACE,CAAC,aACC,MACA,WAAW,QAAQ,OAAO,OAAO,MAAM,QAAQ,OAAO,GAAG,CAC3D,GAEF,MAAM,QAAQ,YACX,MAAM,UAAU,IAAI,
|
|
1
|
+
{"version":3,"file":"format.mjs","names":["prettier","defu"],"sources":["../../../src/lib/utilities/format.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { listFiles } from \"@stryke/fs/list-files\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { findFileExtension } from \"@stryke/path/file-path-fns\";\nimport { isParentPath } from \"@stryke/path/is-parent-path\";\nimport { defu } from \"defu\";\nimport { format as prettier, resolveConfig } from \"prettier\";\nimport importsPlugin from \"prettier-plugin-organize-imports\";\nimport { Context } from \"../../types/context\";\n\n/**\n * Formats code using Prettier based on the file path.\n *\n * @param context - The Powerlines context.\n * @param path - The file path to use for resolving Prettier configuration.\n * @param data - The code string to format.\n * @param force - Whether to force formatting even for output/build paths.\n * @returns A promise that resolves to the formatted code string.\n */\nexport async function format(\n context: Context,\n path: string,\n data: string,\n force = false\n): Promise<string> {\n if (\n !force &&\n ((context.config.output.copy &&\n isParentPath(\n path,\n appendPath(context.config.output.copy.path, context.config.cwd)\n )) ||\n isParentPath(\n path,\n appendPath(context.config.output.path, context.config.cwd)\n ))\n ) {\n return data;\n }\n\n let code = data;\n try {\n const resolvedConfig = await resolveConfig(path);\n if (resolvedConfig) {\n code = await prettier(\n data,\n defu(\n {\n absolutePath: path,\n ...resolvedConfig\n },\n findFileExtension(path) === \"ts\" || findFileExtension(path) === \"tsx\"\n ? { plugins: [importsPlugin] }\n : {}\n )\n );\n }\n } catch (error) {\n throw new Error(\n `Failed to format file at ${path} with Prettier: ${\n (error as Error).message\n }`,\n { cause: error }\n );\n }\n\n return code;\n}\n\n/**\n * Formats all files in a folder using Prettier based on their file paths.\n *\n * @param context - The Powerlines context.\n * @param path - The folder path containing files to format.\n * @returns A promise that resolves when all files have been formatted.\n */\nexport async function formatFolder(context: Context, path: string) {\n if (\n !context.config.output.copy ||\n (!isParentPath(\n path,\n appendPath(context.config.output.copy.path, context.config.cwd)\n ) &&\n !isParentPath(\n path,\n appendPath(context.config.output.path, context.config.cwd)\n ))\n ) {\n await Promise.allSettled(\n (await listFiles(path)).map(async file => {\n if (\n (!context.config.output.copy ||\n !isParentPath(\n file,\n appendPath(context.config.output.copy.path, context.config.cwd)\n )) &&\n !isParentPath(\n file,\n appendPath(context.config.output.path, context.config.cwd)\n )\n ) {\n const data = await context.fs.read(file);\n if (data) {\n const formatted = await format(context, file, data);\n\n return context.fs.write(file, formatted);\n }\n }\n })\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoCA,eAAsB,OACpB,SACA,MACA,MACA,QAAQ,OACS;CACjB,IACE,CAAC,UACC,QAAQ,OAAO,OAAO,QACtB,aACE,MACA,WAAW,QAAQ,OAAO,OAAO,KAAK,MAAM,QAAQ,OAAO,GAAG,CAChE,KACA,aACE,MACA,WAAW,QAAQ,OAAO,OAAO,MAAM,QAAQ,OAAO,GAAG,CAC3D,IAEF,OAAO;CAGT,IAAI,OAAO;CACX,IAAI;EACF,MAAM,iBAAiB,MAAM,cAAc,IAAI;EAC/C,IAAI,gBACF,OAAO,MAAMA,SACX,MACAC,OACE;GACE,cAAc;GACd,GAAG;EACL,GACA,kBAAkB,IAAI,MAAM,QAAQ,kBAAkB,IAAI,MAAM,QAC5D,EAAE,SAAS,CAAC,aAAa,EAAE,IAC3B,CAAC,CACP,CACF;CAEJ,SAAS,OAAO;EACd,MAAM,IAAI,MACR,4BAA4B,KAAK,kBAC9B,MAAgB,WAEnB,EAAE,OAAO,MAAM,CACjB;CACF;CAEA,OAAO;AACT;;;;;;;;AASA,eAAsB,aAAa,SAAkB,MAAc;CACjE,IACE,CAAC,QAAQ,OAAO,OAAO,QACtB,CAAC,aACA,MACA,WAAW,QAAQ,OAAO,OAAO,KAAK,MAAM,QAAQ,OAAO,GAAG,CAChE,KACE,CAAC,aACC,MACA,WAAW,QAAQ,OAAO,OAAO,MAAM,QAAQ,OAAO,GAAG,CAC3D,GAEF,MAAM,QAAQ,YACX,MAAM,UAAU,IAAI,EAAC,CAAE,IAAI,OAAM,SAAQ;EACxC,KACG,CAAC,QAAQ,OAAO,OAAO,QACtB,CAAC,aACC,MACA,WAAW,QAAQ,OAAO,OAAO,KAAK,MAAM,QAAQ,OAAO,GAAG,CAChE,MACF,CAAC,aACC,MACA,WAAW,QAAQ,OAAO,OAAO,MAAM,QAAQ,OAAO,GAAG,CAC3D,GACA;GACA,MAAM,OAAO,MAAM,QAAQ,GAAG,KAAK,IAAI;GACvC,IAAI,MAAM;IACR,MAAM,YAAY,MAAM,OAAO,SAAS,MAAM,IAAI;IAElD,OAAO,QAAQ,GAAG,MAAM,MAAM,SAAS;GACzC;EACF;CACF,CAAC,CACH;AAEJ"}
|