@storm-software/linting-tools 1.106.2 → 1.106.3

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/README.md CHANGED
@@ -21,7 +21,7 @@ This package is part of the <b>⚡Storm-Ops</b> monorepo. The Storm-Ops packages
21
21
 
22
22
  <h3 align="center">💻 Visit <a href="https://stormsoftware.com" target="_blank">stormsoftware.com</a> to stay up to date with this developer</h3><br />
23
23
 
24
- [![Version](https://img.shields.io/badge/version-1.106.1-1fb2a6.svg?style=for-the-badge&color=1fb2a6)](https://prettier.io/)&nbsp;[![Nx](https://img.shields.io/badge/Nx-17.0.2-lightgrey?style=for-the-badge&logo=nx&logoWidth=20&&color=1fb2a6)](http://nx.dev/)&nbsp;[![NextJs](https://img.shields.io/badge/Next.js-14.0.2-lightgrey?style=for-the-badge&logo=nextdotjs&logoWidth=20&color=1fb2a6)](https://nextjs.org/)&nbsp;[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=for-the-badge&logo=commitlint&color=1fb2a6)](http://commitizen.github.io/cz-cli/)&nbsp;![Semantic-Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=for-the-badge&color=1fb2a6)&nbsp;[![documented with Fumadocs](https://img.shields.io/badge/documented_with-fumadocs-success.svg?style=for-the-badge&logo=readthedocs&color=1fb2a6)](https://fumadocs.vercel.app/)&nbsp;![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/storm-software/storm-ops/cr.yml?style=for-the-badge&logo=github-actions&color=1fb2a6)
24
+ [![Version](https://img.shields.io/badge/version-1.106.2-1fb2a6.svg?style=for-the-badge&color=1fb2a6)](https://prettier.io/)&nbsp;[![Nx](https://img.shields.io/badge/Nx-17.0.2-lightgrey?style=for-the-badge&logo=nx&logoWidth=20&&color=1fb2a6)](http://nx.dev/)&nbsp;[![NextJs](https://img.shields.io/badge/Next.js-14.0.2-lightgrey?style=for-the-badge&logo=nextdotjs&logoWidth=20&color=1fb2a6)](https://nextjs.org/)&nbsp;[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=for-the-badge&logo=commitlint&color=1fb2a6)](http://commitizen.github.io/cz-cli/)&nbsp;![Semantic-Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=for-the-badge&color=1fb2a6)&nbsp;[![documented with Fumadocs](https://img.shields.io/badge/documented_with-fumadocs-success.svg?style=for-the-badge&logo=readthedocs&color=1fb2a6)](https://fumadocs.vercel.app/)&nbsp;![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/storm-software/storm-ops/cr.yml?style=for-the-badge&logo=github-actions&color=1fb2a6)
25
25
 
26
26
  <!-- prettier-ignore-start -->
27
27
  <!-- markdownlint-disable -->
package/bin/lint.cjs CHANGED
@@ -140,6 +140,8 @@ var ColorConfigMapSchema = import_zod.default.union([
140
140
  }),
141
141
  import_zod.default.record(import_zod.default.string(), ColorConfigSchema)
142
142
  ]);
143
+ var ExtendsItemSchema = import_zod.default.string().trim().describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
144
+ var ExtendsSchema = ExtendsItemSchema.or(import_zod.default.array(ExtendsItemSchema)).describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
143
145
  var WorkspaceBotConfigSchema = import_zod.default.object({
144
146
  name: import_zod.default.string().trim().default("Stormie-Bot").describe("The workspace bot user's name (this is the bot that will be used to perform various tasks)"),
145
147
  email: import_zod.default.string().trim().email().default("bot@stormsoftware.com").describe("The email of the workspace bot")
@@ -154,11 +156,11 @@ var WorkspaceDirectoryConfigSchema = import_zod.default.object({
154
156
  }).describe("Various directories used by the workspace to store data, cache, and configuration files");
155
157
  var StormConfigSchema = import_zod.default.object({
156
158
  $schema: import_zod.default.string().trim().default("https://cdn.jsdelivr.net/npm/@storm-software/config/schemas/storm.schema.json").optional().nullish().describe("The URL to the JSON schema file that describes the Storm configuration file"),
157
- extends: import_zod.default.string().trim().optional().describe("The path to a base JSON file to use as a configuration preset file"),
159
+ extends: ExtendsSchema.optional(),
158
160
  name: import_zod.default.string().trim().toLowerCase().optional().describe("The name of the service/package/scope using this configuration"),
159
161
  namespace: import_zod.default.string().trim().toLowerCase().optional().describe("The namespace of the package"),
160
162
  organization: import_zod.default.string().trim().default("storm-software").describe("The organization of the workspace"),
161
- repository: import_zod.default.string().trim().url().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
163
+ repository: import_zod.default.string().trim().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
162
164
  license: import_zod.default.string().trim().default("Apache-2.0").describe("The license type of the package"),
163
165
  homepage: import_zod.default.string().trim().url().default(STORM_DEFAULT_HOMEPAGE).describe("The homepage of the workspace"),
164
166
  docs: import_zod.default.string().trim().url().default(STORM_DEFAULT_DOCS).describe("The base documentation site for the workspace"),
@@ -222,6 +224,7 @@ var COLOR_KEYS = [
222
224
 
223
225
  // ../config-tools/src/utilities/get-default-config.ts
224
226
  var import_node_fs2 = require("fs");
227
+ var import_promises = require("fs/promises");
225
228
  var import_node_path2 = require("path");
226
229
 
227
230
  // ../config-tools/src/utilities/correct-paths.ts
@@ -343,17 +346,15 @@ var DEFAULT_COLOR_CONFIG = {
343
346
  "negative": "#dc2626"
344
347
  }
345
348
  };
346
- var getDefaultConfig = /* @__PURE__ */ __name((root) => {
349
+ var getDefaultConfig = /* @__PURE__ */ __name(async (root) => {
347
350
  let license = STORM_DEFAULT_LICENSE;
348
351
  let homepage = STORM_DEFAULT_HOMEPAGE;
349
- let name;
350
- let namespace;
351
- let repository;
352
+ let name = void 0;
353
+ let namespace = void 0;
354
+ let repository = void 0;
352
355
  const workspaceRoot = findWorkspaceRoot(root);
353
356
  if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(workspaceRoot, "package.json"))) {
354
- const file = (0, import_node_fs2.readFileSync)((0, import_node_path2.join)(workspaceRoot, "package.json"), {
355
- encoding: "utf8"
356
- });
357
+ const file = await (0, import_promises.readFile)(joinPaths(workspaceRoot, "package.json"), "utf8");
357
358
  if (file) {
358
359
  const packageJson = JSON.parse(file);
359
360
  if (packageJson.name) {
@@ -362,8 +363,12 @@ var getDefaultConfig = /* @__PURE__ */ __name((root) => {
362
363
  if (packageJson.namespace) {
363
364
  namespace = packageJson.namespace;
364
365
  }
365
- if (packageJson.repository?.url) {
366
- repository = packageJson.repository?.url;
366
+ if (packageJson.repository) {
367
+ if (typeof packageJson.repository === "string") {
368
+ repository = packageJson.repository;
369
+ } else if (packageJson.repository.url) {
370
+ repository = packageJson.repository.url;
371
+ }
367
372
  }
368
373
  if (packageJson.license) {
369
374
  license = packageJson.license;
@@ -568,7 +573,6 @@ var writeInfo = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.IN
568
573
  var writeSuccess = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.SUCCESS, config)(message), "writeSuccess");
569
574
  var writeDebug = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.DEBUG, config)(message), "writeDebug");
570
575
  var writeTrace = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.TRACE, config)(message), "writeTrace");
571
- var writeSystem = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.ALL, config)(message), "writeSystem");
572
576
  var MAX_DEPTH = 4;
573
577
  var formatLogMessage = /* @__PURE__ */ __name((message, options = {}, depth2 = 0) => {
574
578
  if (depth2 > MAX_DEPTH) {
@@ -631,19 +635,19 @@ Stacktrace: ${error.stack}`, config);
631
635
  // ../config-tools/src/config-file/get-config-file.ts
632
636
  var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, options = {}) => {
633
637
  const workspacePath = filePath || findWorkspaceRoot(filePath);
634
- let config = await (0, import_c12.loadConfig)({
635
- cwd: workspacePath,
636
- packageJson: true,
637
- name: fileName,
638
- envName: fileName?.toUpperCase(),
639
- jitiOptions: {
640
- debug: false,
641
- fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
642
- },
643
- ...options
644
- });
645
- if (!config || Object.keys(config).length === 0) {
646
- config = await (0, import_c12.loadConfig)({
638
+ const configs = await Promise.all([
639
+ (0, import_c12.loadConfig)({
640
+ cwd: workspacePath,
641
+ packageJson: true,
642
+ name: fileName,
643
+ envName: fileName?.toUpperCase(),
644
+ jitiOptions: {
645
+ debug: false,
646
+ fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
647
+ },
648
+ ...options
649
+ }),
650
+ (0, import_c12.loadConfig)({
647
651
  cwd: workspacePath,
648
652
  packageJson: true,
649
653
  name: fileName,
@@ -654,9 +658,9 @@ var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, opti
654
658
  },
655
659
  configFile: fileName,
656
660
  ...options
657
- });
658
- }
659
- return config;
661
+ })
662
+ ]);
663
+ return (0, import_defu.default)(configs[0] ?? {}, configs[1] ?? {});
660
664
  }, "getConfigFileByName");
661
665
  var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames = []) => {
662
666
  const workspacePath = filePath ? filePath : findWorkspaceRoot(filePath);
@@ -664,7 +668,7 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
664
668
  let config = result.config;
665
669
  const configFile = result.configFile;
666
670
  if (config && configFile && Object.keys(config).length > 0) {
667
- writeSystem(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
671
+ writeTrace(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
668
672
  logLevel: "all"
669
673
  });
670
674
  }
@@ -672,7 +676,7 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
672
676
  const results = await Promise.all(additionalFileNames.map((fileName) => getConfigFileByName(fileName, workspacePath)));
673
677
  for (const result2 of results) {
674
678
  if (result2?.config && result2?.configFile && Object.keys(result2.config).length > 0) {
675
- writeSystem(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
679
+ writeTrace(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
676
680
  logLevel: "all"
677
681
  });
678
682
  config = (0, import_defu.default)(result2.config ?? {}, config ?? {});
@@ -690,6 +694,16 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
690
694
  var import_defu2 = __toESM(require("defu"), 1);
691
695
 
692
696
  // ../config-tools/src/env/get-env.ts
697
+ var getExtensionEnv = /* @__PURE__ */ __name((extensionName) => {
698
+ const prefix = `STORM_EXTENSION_${extensionName.toUpperCase()}_`;
699
+ return Object.keys(process.env).filter((key) => key.startsWith(prefix)).reduce((ret, key) => {
700
+ const name = key.replace(prefix, "").split("_").map((i) => i.length > 0 ? i.trim().charAt(0).toUpperCase() + i.trim().slice(1) : "").join("");
701
+ if (name) {
702
+ ret[name] = process.env[key];
703
+ }
704
+ return ret;
705
+ }, {});
706
+ }, "getExtensionEnv");
693
707
  var getConfigEnv = /* @__PURE__ */ __name(() => {
694
708
  const prefix = "STORM_";
695
709
  let config = {
@@ -849,7 +863,7 @@ var setExtensionEnv = /* @__PURE__ */ __name((extensionName, extension) => {
849
863
  var setConfigEnv = /* @__PURE__ */ __name((config) => {
850
864
  const prefix = "STORM_";
851
865
  if (config.extends) {
852
- process.env[`${prefix}EXTENDS`] = config.extends;
866
+ process.env[`${prefix}EXTENDS`] = Array.isArray(config.extends) ? JSON.stringify(config.extends) : config.extends;
853
867
  }
854
868
  if (config.name) {
855
869
  process.env[`${prefix}NAME`] = config.name;
@@ -1079,30 +1093,69 @@ var setBaseThemeColorConfigEnv = /* @__PURE__ */ __name((prefix, config) => {
1079
1093
  }, "setBaseThemeColorConfigEnv");
1080
1094
 
1081
1095
  // ../config-tools/src/create-storm-config.ts
1096
+ var _extension_cache = /* @__PURE__ */ new WeakMap();
1082
1097
  var _static_cache = void 0;
1083
- var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot) => {
1084
- let config = {};
1085
- if (_static_cache?.data && _static_cache?.timestamp && _static_cache.timestamp >= Date.now() + 3e4) {
1086
- writeTrace(`Configuration cache hit - ${_static_cache.timestamp}`, _static_cache.data);
1087
- return _static_cache.data;
1088
- }
1089
- let _workspaceRoot = workspaceRoot;
1090
- if (!_workspaceRoot) {
1091
- _workspaceRoot = findWorkspaceRoot();
1092
- }
1093
- const configFile = await getConfigFile(_workspaceRoot);
1094
- if (!configFile) {
1095
- writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1096
- logLevel: "all"
1097
- });
1098
+ var createStormConfig = /* @__PURE__ */ __name(async (extensionName, schema, workspaceRoot, skipLogs = false) => {
1099
+ let result;
1100
+ if (!_static_cache?.data || !_static_cache?.timestamp || _static_cache.timestamp < Date.now() - 8e3) {
1101
+ let _workspaceRoot = workspaceRoot;
1102
+ if (!_workspaceRoot) {
1103
+ _workspaceRoot = findWorkspaceRoot();
1104
+ }
1105
+ const configEnv = getConfigEnv();
1106
+ const defaultConfig = await getDefaultConfig(_workspaceRoot);
1107
+ const configFile = await getConfigFile(_workspaceRoot);
1108
+ if (!configFile && !skipLogs) {
1109
+ writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1110
+ logLevel: "all"
1111
+ });
1112
+ }
1113
+ result = await StormConfigSchema.parseAsync((0, import_defu2.default)(configEnv, configFile, defaultConfig));
1114
+ result.workspaceRoot ??= _workspaceRoot;
1115
+ } else {
1116
+ result = _static_cache.data;
1098
1117
  }
1099
- config = (0, import_defu2.default)(getConfigEnv(), configFile, getDefaultConfig(_workspaceRoot));
1118
+ if (schema && extensionName) {
1119
+ result.extensions = {
1120
+ ...result.extensions,
1121
+ [extensionName]: createConfigExtension(extensionName, schema)
1122
+ };
1123
+ }
1124
+ _static_cache = {
1125
+ timestamp: Date.now(),
1126
+ data: result
1127
+ };
1128
+ return result;
1129
+ }, "createStormConfig");
1130
+ var createConfigExtension = /* @__PURE__ */ __name((extensionName, schema) => {
1131
+ const extension_cache_key = {
1132
+ extensionName
1133
+ };
1134
+ if (_extension_cache.has(extension_cache_key)) {
1135
+ return _extension_cache.get(extension_cache_key);
1136
+ }
1137
+ let extension = getExtensionEnv(extensionName);
1138
+ if (schema) {
1139
+ extension = schema.parse(extension);
1140
+ }
1141
+ _extension_cache.set(extension_cache_key, extension);
1142
+ return extension;
1143
+ }, "createConfigExtension");
1144
+ var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot, skipLogs = false) => {
1145
+ const config = await createStormConfig(void 0, void 0, workspaceRoot, skipLogs);
1100
1146
  setConfigEnv(config);
1101
- writeTrace(`\u2699\uFE0F Using Storm configuration:
1147
+ if (!skipLogs) {
1148
+ writeTrace(`\u2699\uFE0F Using Storm configuration:
1102
1149
  ${formatLogMessage(config)}`, config);
1150
+ }
1103
1151
  return config;
1104
1152
  }, "loadStormConfig");
1105
1153
 
1154
+ // ../config-tools/src/get-config.ts
1155
+ var getConfig = /* @__PURE__ */ __name((workspaceRoot, skipLogs = false) => {
1156
+ return loadStormConfig(workspaceRoot, skipLogs);
1157
+ }, "getConfig");
1158
+
1106
1159
  // src/cli/index.ts
1107
1160
  var import_check_dependency_version_consistency = require("check-dependency-version-consistency");
1108
1161
  var import_commander = require("commander");
@@ -1198,7 +1251,7 @@ var import_fs_extra = __toESM(require("fs-extra"), 1);
1198
1251
  var import_octokit = require("octokit");
1199
1252
  var import_path = require("path");
1200
1253
  async function runCodeowners() {
1201
- const config = await loadStormConfig();
1254
+ const config = await getConfig();
1202
1255
  if (!config) {
1203
1256
  throw new Error("Failed to load storm config.");
1204
1257
  }
@@ -1653,7 +1706,7 @@ __name(manypkgAction, "manypkgAction");
1653
1706
  // bin/lint.ts
1654
1707
  Error.stackTraceLimit = Infinity;
1655
1708
  void (async () => {
1656
- const config = await loadStormConfig();
1709
+ const config = await getConfig();
1657
1710
  try {
1658
1711
  handleProcess(config);
1659
1712
  const program = await createProgram(config);
package/bin/lint.js CHANGED
@@ -119,6 +119,8 @@ var ColorConfigMapSchema = z.union([
119
119
  }),
120
120
  z.record(z.string(), ColorConfigSchema)
121
121
  ]);
122
+ var ExtendsItemSchema = z.string().trim().describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
123
+ var ExtendsSchema = ExtendsItemSchema.or(z.array(ExtendsItemSchema)).describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
122
124
  var WorkspaceBotConfigSchema = z.object({
123
125
  name: z.string().trim().default("Stormie-Bot").describe("The workspace bot user's name (this is the bot that will be used to perform various tasks)"),
124
126
  email: z.string().trim().email().default("bot@stormsoftware.com").describe("The email of the workspace bot")
@@ -133,11 +135,11 @@ var WorkspaceDirectoryConfigSchema = z.object({
133
135
  }).describe("Various directories used by the workspace to store data, cache, and configuration files");
134
136
  var StormConfigSchema = z.object({
135
137
  $schema: z.string().trim().default("https://cdn.jsdelivr.net/npm/@storm-software/config/schemas/storm.schema.json").optional().nullish().describe("The URL to the JSON schema file that describes the Storm configuration file"),
136
- extends: z.string().trim().optional().describe("The path to a base JSON file to use as a configuration preset file"),
138
+ extends: ExtendsSchema.optional(),
137
139
  name: z.string().trim().toLowerCase().optional().describe("The name of the service/package/scope using this configuration"),
138
140
  namespace: z.string().trim().toLowerCase().optional().describe("The namespace of the package"),
139
141
  organization: z.string().trim().default("storm-software").describe("The organization of the workspace"),
140
- repository: z.string().trim().url().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
142
+ repository: z.string().trim().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
141
143
  license: z.string().trim().default("Apache-2.0").describe("The license type of the package"),
142
144
  homepage: z.string().trim().url().default(STORM_DEFAULT_HOMEPAGE).describe("The homepage of the workspace"),
143
145
  docs: z.string().trim().url().default(STORM_DEFAULT_DOCS).describe("The base documentation site for the workspace"),
@@ -200,7 +202,8 @@ var COLOR_KEYS = [
200
202
  ];
201
203
 
202
204
  // ../config-tools/src/utilities/get-default-config.ts
203
- import { existsSync as existsSync2, readFileSync } from "node:fs";
205
+ import { existsSync as existsSync2 } from "node:fs";
206
+ import { readFile } from "node:fs/promises";
204
207
  import { join as join2 } from "node:path";
205
208
 
206
209
  // ../config-tools/src/utilities/correct-paths.ts
@@ -322,17 +325,15 @@ var DEFAULT_COLOR_CONFIG = {
322
325
  "negative": "#dc2626"
323
326
  }
324
327
  };
325
- var getDefaultConfig = /* @__PURE__ */ __name((root) => {
328
+ var getDefaultConfig = /* @__PURE__ */ __name(async (root) => {
326
329
  let license = STORM_DEFAULT_LICENSE;
327
330
  let homepage = STORM_DEFAULT_HOMEPAGE;
328
- let name;
329
- let namespace;
330
- let repository;
331
+ let name = void 0;
332
+ let namespace = void 0;
333
+ let repository = void 0;
331
334
  const workspaceRoot = findWorkspaceRoot(root);
332
335
  if (existsSync2(join2(workspaceRoot, "package.json"))) {
333
- const file = readFileSync(join2(workspaceRoot, "package.json"), {
334
- encoding: "utf8"
335
- });
336
+ const file = await readFile(joinPaths(workspaceRoot, "package.json"), "utf8");
336
337
  if (file) {
337
338
  const packageJson = JSON.parse(file);
338
339
  if (packageJson.name) {
@@ -341,8 +342,12 @@ var getDefaultConfig = /* @__PURE__ */ __name((root) => {
341
342
  if (packageJson.namespace) {
342
343
  namespace = packageJson.namespace;
343
344
  }
344
- if (packageJson.repository?.url) {
345
- repository = packageJson.repository?.url;
345
+ if (packageJson.repository) {
346
+ if (typeof packageJson.repository === "string") {
347
+ repository = packageJson.repository;
348
+ } else if (packageJson.repository.url) {
349
+ repository = packageJson.repository.url;
350
+ }
346
351
  }
347
352
  if (packageJson.license) {
348
353
  license = packageJson.license;
@@ -547,7 +552,6 @@ var writeInfo = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.IN
547
552
  var writeSuccess = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.SUCCESS, config)(message), "writeSuccess");
548
553
  var writeDebug = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.DEBUG, config)(message), "writeDebug");
549
554
  var writeTrace = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.TRACE, config)(message), "writeTrace");
550
- var writeSystem = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.ALL, config)(message), "writeSystem");
551
555
  var MAX_DEPTH = 4;
552
556
  var formatLogMessage = /* @__PURE__ */ __name((message, options = {}, depth2 = 0) => {
553
557
  if (depth2 > MAX_DEPTH) {
@@ -610,19 +614,19 @@ Stacktrace: ${error.stack}`, config);
610
614
  // ../config-tools/src/config-file/get-config-file.ts
611
615
  var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, options = {}) => {
612
616
  const workspacePath = filePath || findWorkspaceRoot(filePath);
613
- let config = await loadConfig({
614
- cwd: workspacePath,
615
- packageJson: true,
616
- name: fileName,
617
- envName: fileName?.toUpperCase(),
618
- jitiOptions: {
619
- debug: false,
620
- fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
621
- },
622
- ...options
623
- });
624
- if (!config || Object.keys(config).length === 0) {
625
- config = await loadConfig({
617
+ const configs = await Promise.all([
618
+ loadConfig({
619
+ cwd: workspacePath,
620
+ packageJson: true,
621
+ name: fileName,
622
+ envName: fileName?.toUpperCase(),
623
+ jitiOptions: {
624
+ debug: false,
625
+ fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
626
+ },
627
+ ...options
628
+ }),
629
+ loadConfig({
626
630
  cwd: workspacePath,
627
631
  packageJson: true,
628
632
  name: fileName,
@@ -633,9 +637,9 @@ var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, opti
633
637
  },
634
638
  configFile: fileName,
635
639
  ...options
636
- });
637
- }
638
- return config;
640
+ })
641
+ ]);
642
+ return defu(configs[0] ?? {}, configs[1] ?? {});
639
643
  }, "getConfigFileByName");
640
644
  var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames = []) => {
641
645
  const workspacePath = filePath ? filePath : findWorkspaceRoot(filePath);
@@ -643,7 +647,7 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
643
647
  let config = result.config;
644
648
  const configFile = result.configFile;
645
649
  if (config && configFile && Object.keys(config).length > 0) {
646
- writeSystem(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
650
+ writeTrace(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
647
651
  logLevel: "all"
648
652
  });
649
653
  }
@@ -651,7 +655,7 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
651
655
  const results = await Promise.all(additionalFileNames.map((fileName) => getConfigFileByName(fileName, workspacePath)));
652
656
  for (const result2 of results) {
653
657
  if (result2?.config && result2?.configFile && Object.keys(result2.config).length > 0) {
654
- writeSystem(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
658
+ writeTrace(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
655
659
  logLevel: "all"
656
660
  });
657
661
  config = defu(result2.config ?? {}, config ?? {});
@@ -669,6 +673,16 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
669
673
  import defu2 from "defu";
670
674
 
671
675
  // ../config-tools/src/env/get-env.ts
676
+ var getExtensionEnv = /* @__PURE__ */ __name((extensionName) => {
677
+ const prefix = `STORM_EXTENSION_${extensionName.toUpperCase()}_`;
678
+ return Object.keys(process.env).filter((key) => key.startsWith(prefix)).reduce((ret, key) => {
679
+ const name = key.replace(prefix, "").split("_").map((i) => i.length > 0 ? i.trim().charAt(0).toUpperCase() + i.trim().slice(1) : "").join("");
680
+ if (name) {
681
+ ret[name] = process.env[key];
682
+ }
683
+ return ret;
684
+ }, {});
685
+ }, "getExtensionEnv");
672
686
  var getConfigEnv = /* @__PURE__ */ __name(() => {
673
687
  const prefix = "STORM_";
674
688
  let config = {
@@ -828,7 +842,7 @@ var setExtensionEnv = /* @__PURE__ */ __name((extensionName, extension) => {
828
842
  var setConfigEnv = /* @__PURE__ */ __name((config) => {
829
843
  const prefix = "STORM_";
830
844
  if (config.extends) {
831
- process.env[`${prefix}EXTENDS`] = config.extends;
845
+ process.env[`${prefix}EXTENDS`] = Array.isArray(config.extends) ? JSON.stringify(config.extends) : config.extends;
832
846
  }
833
847
  if (config.name) {
834
848
  process.env[`${prefix}NAME`] = config.name;
@@ -1058,30 +1072,69 @@ var setBaseThemeColorConfigEnv = /* @__PURE__ */ __name((prefix, config) => {
1058
1072
  }, "setBaseThemeColorConfigEnv");
1059
1073
 
1060
1074
  // ../config-tools/src/create-storm-config.ts
1075
+ var _extension_cache = /* @__PURE__ */ new WeakMap();
1061
1076
  var _static_cache = void 0;
1062
- var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot) => {
1063
- let config = {};
1064
- if (_static_cache?.data && _static_cache?.timestamp && _static_cache.timestamp >= Date.now() + 3e4) {
1065
- writeTrace(`Configuration cache hit - ${_static_cache.timestamp}`, _static_cache.data);
1066
- return _static_cache.data;
1067
- }
1068
- let _workspaceRoot = workspaceRoot;
1069
- if (!_workspaceRoot) {
1070
- _workspaceRoot = findWorkspaceRoot();
1071
- }
1072
- const configFile = await getConfigFile(_workspaceRoot);
1073
- if (!configFile) {
1074
- writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1075
- logLevel: "all"
1076
- });
1077
+ var createStormConfig = /* @__PURE__ */ __name(async (extensionName, schema, workspaceRoot, skipLogs = false) => {
1078
+ let result;
1079
+ if (!_static_cache?.data || !_static_cache?.timestamp || _static_cache.timestamp < Date.now() - 8e3) {
1080
+ let _workspaceRoot = workspaceRoot;
1081
+ if (!_workspaceRoot) {
1082
+ _workspaceRoot = findWorkspaceRoot();
1083
+ }
1084
+ const configEnv = getConfigEnv();
1085
+ const defaultConfig = await getDefaultConfig(_workspaceRoot);
1086
+ const configFile = await getConfigFile(_workspaceRoot);
1087
+ if (!configFile && !skipLogs) {
1088
+ writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1089
+ logLevel: "all"
1090
+ });
1091
+ }
1092
+ result = await StormConfigSchema.parseAsync(defu2(configEnv, configFile, defaultConfig));
1093
+ result.workspaceRoot ??= _workspaceRoot;
1094
+ } else {
1095
+ result = _static_cache.data;
1077
1096
  }
1078
- config = defu2(getConfigEnv(), configFile, getDefaultConfig(_workspaceRoot));
1097
+ if (schema && extensionName) {
1098
+ result.extensions = {
1099
+ ...result.extensions,
1100
+ [extensionName]: createConfigExtension(extensionName, schema)
1101
+ };
1102
+ }
1103
+ _static_cache = {
1104
+ timestamp: Date.now(),
1105
+ data: result
1106
+ };
1107
+ return result;
1108
+ }, "createStormConfig");
1109
+ var createConfigExtension = /* @__PURE__ */ __name((extensionName, schema) => {
1110
+ const extension_cache_key = {
1111
+ extensionName
1112
+ };
1113
+ if (_extension_cache.has(extension_cache_key)) {
1114
+ return _extension_cache.get(extension_cache_key);
1115
+ }
1116
+ let extension = getExtensionEnv(extensionName);
1117
+ if (schema) {
1118
+ extension = schema.parse(extension);
1119
+ }
1120
+ _extension_cache.set(extension_cache_key, extension);
1121
+ return extension;
1122
+ }, "createConfigExtension");
1123
+ var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot, skipLogs = false) => {
1124
+ const config = await createStormConfig(void 0, void 0, workspaceRoot, skipLogs);
1079
1125
  setConfigEnv(config);
1080
- writeTrace(`\u2699\uFE0F Using Storm configuration:
1126
+ if (!skipLogs) {
1127
+ writeTrace(`\u2699\uFE0F Using Storm configuration:
1081
1128
  ${formatLogMessage(config)}`, config);
1129
+ }
1082
1130
  return config;
1083
1131
  }, "loadStormConfig");
1084
1132
 
1133
+ // ../config-tools/src/get-config.ts
1134
+ var getConfig = /* @__PURE__ */ __name((workspaceRoot, skipLogs = false) => {
1135
+ return loadStormConfig(workspaceRoot, skipLogs);
1136
+ }, "getConfig");
1137
+
1085
1138
  // src/cli/index.ts
1086
1139
  import { CDVC } from "check-dependency-version-consistency";
1087
1140
  import { Command, Option } from "commander";
@@ -1177,7 +1230,7 @@ import fs from "fs-extra";
1177
1230
  import { Octokit } from "octokit";
1178
1231
  import { join as join3 } from "path";
1179
1232
  async function runCodeowners() {
1180
- const config = await loadStormConfig();
1233
+ const config = await getConfig();
1181
1234
  if (!config) {
1182
1235
  throw new Error("Failed to load storm config.");
1183
1236
  }
@@ -1632,7 +1685,7 @@ __name(manypkgAction, "manypkgAction");
1632
1685
  // bin/lint.ts
1633
1686
  Error.stackTraceLimit = Infinity;
1634
1687
  void (async () => {
1635
- const config = await loadStormConfig();
1688
+ const config = await getConfig();
1636
1689
  try {
1637
1690
  handleProcess(config);
1638
1691
  const program = await createProgram(config);
package/dist/index.cjs CHANGED
@@ -118,6 +118,8 @@ var ColorConfigMapSchema = _zod2.default.union([
118
118
  }),
119
119
  _zod2.default.record(_zod2.default.string(), ColorConfigSchema)
120
120
  ]);
121
+ var ExtendsItemSchema = _zod2.default.string().trim().describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
122
+ var ExtendsSchema = ExtendsItemSchema.or(_zod2.default.array(ExtendsItemSchema)).describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
121
123
  var WorkspaceBotConfigSchema = _zod2.default.object({
122
124
  name: _zod2.default.string().trim().default("Stormie-Bot").describe("The workspace bot user's name (this is the bot that will be used to perform various tasks)"),
123
125
  email: _zod2.default.string().trim().email().default("bot@stormsoftware.com").describe("The email of the workspace bot")
@@ -132,11 +134,11 @@ var WorkspaceDirectoryConfigSchema = _zod2.default.object({
132
134
  }).describe("Various directories used by the workspace to store data, cache, and configuration files");
133
135
  var StormConfigSchema = _zod2.default.object({
134
136
  $schema: _zod2.default.string().trim().default("https://cdn.jsdelivr.net/npm/@storm-software/config/schemas/storm.schema.json").optional().nullish().describe("The URL to the JSON schema file that describes the Storm configuration file"),
135
- extends: _zod2.default.string().trim().optional().describe("The path to a base JSON file to use as a configuration preset file"),
137
+ extends: ExtendsSchema.optional(),
136
138
  name: _zod2.default.string().trim().toLowerCase().optional().describe("The name of the service/package/scope using this configuration"),
137
139
  namespace: _zod2.default.string().trim().toLowerCase().optional().describe("The namespace of the package"),
138
140
  organization: _zod2.default.string().trim().default("storm-software").describe("The organization of the workspace"),
139
- repository: _zod2.default.string().trim().url().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
141
+ repository: _zod2.default.string().trim().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
140
142
  license: _zod2.default.string().trim().default("Apache-2.0").describe("The license type of the package"),
141
143
  homepage: _zod2.default.string().trim().url().default(STORM_DEFAULT_HOMEPAGE).describe("The homepage of the workspace"),
142
144
  docs: _zod2.default.string().trim().url().default(STORM_DEFAULT_DOCS).describe("The base documentation site for the workspace"),
@@ -200,6 +202,7 @@ var COLOR_KEYS = [
200
202
 
201
203
  // ../config-tools/src/utilities/get-default-config.ts
202
204
  var _fs = require('fs');
205
+ var _promises = require('fs/promises');
203
206
  var _path = require('path');
204
207
 
205
208
  // ../config-tools/src/utilities/correct-paths.ts
@@ -321,17 +324,15 @@ var DEFAULT_COLOR_CONFIG = {
321
324
  "negative": "#dc2626"
322
325
  }
323
326
  };
324
- var getDefaultConfig = /* @__PURE__ */ __name((root) => {
327
+ var getDefaultConfig = /* @__PURE__ */ __name(async (root) => {
325
328
  let license = STORM_DEFAULT_LICENSE;
326
329
  let homepage = STORM_DEFAULT_HOMEPAGE;
327
- let name;
328
- let namespace;
329
- let repository;
330
+ let name = void 0;
331
+ let namespace = void 0;
332
+ let repository = void 0;
330
333
  const workspaceRoot = findWorkspaceRoot(root);
331
334
  if (_fs.existsSync.call(void 0, _path.join.call(void 0, workspaceRoot, "package.json"))) {
332
- const file = _fs.readFileSync.call(void 0, _path.join.call(void 0, workspaceRoot, "package.json"), {
333
- encoding: "utf8"
334
- });
335
+ const file = await _promises.readFile.call(void 0, joinPaths(workspaceRoot, "package.json"), "utf8");
335
336
  if (file) {
336
337
  const packageJson = JSON.parse(file);
337
338
  if (packageJson.name) {
@@ -340,8 +341,12 @@ var getDefaultConfig = /* @__PURE__ */ __name((root) => {
340
341
  if (packageJson.namespace) {
341
342
  namespace = packageJson.namespace;
342
343
  }
343
- if (_optionalChain([packageJson, 'access', _2 => _2.repository, 'optionalAccess', _3 => _3.url])) {
344
- repository = _optionalChain([packageJson, 'access', _4 => _4.repository, 'optionalAccess', _5 => _5.url]);
344
+ if (packageJson.repository) {
345
+ if (typeof packageJson.repository === "string") {
346
+ repository = packageJson.repository;
347
+ } else if (packageJson.repository.url) {
348
+ repository = packageJson.repository.url;
349
+ }
345
350
  }
346
351
  if (packageJson.license) {
347
352
  license = packageJson.license;
@@ -386,7 +391,7 @@ var chalkDefault = {
386
391
  };
387
392
  var getChalk = /* @__PURE__ */ __name(() => {
388
393
  let _chalk = _chalk3.default;
389
- if (!_optionalChain([_chalk, 'optionalAccess', _6 => _6.hex]) || !_optionalChain([_chalk, 'optionalAccess', _7 => _7.bold, 'optionalAccess', _8 => _8.hex]) || !_optionalChain([_chalk, 'optionalAccess', _9 => _9.bgHex]) || !_optionalChain([_chalk, 'optionalAccess', _10 => _10.whiteBright])) {
394
+ if (!_optionalChain([_chalk, 'optionalAccess', _2 => _2.hex]) || !_optionalChain([_chalk, 'optionalAccess', _3 => _3.bold, 'optionalAccess', _4 => _4.hex]) || !_optionalChain([_chalk, 'optionalAccess', _5 => _5.bgHex]) || !_optionalChain([_chalk, 'optionalAccess', _6 => _6.whiteBright])) {
390
395
  _chalk = chalkDefault;
391
396
  }
392
397
  return _chalk;
@@ -478,7 +483,7 @@ var getLogLevelLabel = /* @__PURE__ */ __name((logLevel = LogLevel.INFO) => {
478
483
 
479
484
  // ../config-tools/src/logger/console.ts
480
485
  var getLogFn = /* @__PURE__ */ __name((logLevel = LogLevel.INFO, config = {}, _chalk = getChalk()) => {
481
- const colors = !_optionalChain([config, 'access', _11 => _11.colors, 'optionalAccess', _12 => _12.dark]) && !_optionalChain([config, 'access', _13 => _13.colors, 'optionalAccess', _14 => _14["base"]]) && !_optionalChain([config, 'access', _15 => _15.colors, 'optionalAccess', _16 => _16["base"], 'optionalAccess', _17 => _17.dark]) ? DEFAULT_COLOR_CONFIG : _optionalChain([config, 'access', _18 => _18.colors, 'optionalAccess', _19 => _19.dark]) && typeof config.colors.dark === "string" ? config.colors : _optionalChain([config, 'access', _20 => _20.colors, 'optionalAccess', _21 => _21["base"], 'optionalAccess', _22 => _22.dark]) && typeof config.colors["base"].dark === "string" ? config.colors["base"].dark : _optionalChain([config, 'access', _23 => _23.colors, 'optionalAccess', _24 => _24["base"]]) ? _optionalChain([config, 'access', _25 => _25.colors, 'optionalAccess', _26 => _26["base"]]) : DEFAULT_COLOR_CONFIG;
486
+ const colors = !_optionalChain([config, 'access', _7 => _7.colors, 'optionalAccess', _8 => _8.dark]) && !_optionalChain([config, 'access', _9 => _9.colors, 'optionalAccess', _10 => _10["base"]]) && !_optionalChain([config, 'access', _11 => _11.colors, 'optionalAccess', _12 => _12["base"], 'optionalAccess', _13 => _13.dark]) ? DEFAULT_COLOR_CONFIG : _optionalChain([config, 'access', _14 => _14.colors, 'optionalAccess', _15 => _15.dark]) && typeof config.colors.dark === "string" ? config.colors : _optionalChain([config, 'access', _16 => _16.colors, 'optionalAccess', _17 => _17["base"], 'optionalAccess', _18 => _18.dark]) && typeof config.colors["base"].dark === "string" ? config.colors["base"].dark : _optionalChain([config, 'access', _19 => _19.colors, 'optionalAccess', _20 => _20["base"]]) ? _optionalChain([config, 'access', _21 => _21.colors, 'optionalAccess', _22 => _22["base"]]) : DEFAULT_COLOR_CONFIG;
482
487
  const configLogLevel = config.logLevel || process.env.STORM_LOG_LEVEL || LogLevelLabel.INFO;
483
488
  if (logLevel > getLogLevel(configLogLevel) || logLevel <= LogLevel.SILENT || getLogLevel(configLogLevel) <= LogLevel.SILENT) {
484
489
  return (_) => {
@@ -546,7 +551,6 @@ var writeInfo = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.IN
546
551
  var writeSuccess = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.SUCCESS, config)(message), "writeSuccess");
547
552
  var writeDebug = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.DEBUG, config)(message), "writeDebug");
548
553
  var writeTrace = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.TRACE, config)(message), "writeTrace");
549
- var writeSystem = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.ALL, config)(message), "writeSystem");
550
554
  var MAX_DEPTH = 4;
551
555
  var formatLogMessage = /* @__PURE__ */ __name((message, options = {}, depth2 = 0) => {
552
556
  if (depth2 > MAX_DEPTH) {
@@ -566,7 +570,7 @@ ${Object.keys(message).filter((key) => !skip.includes(key)).map((key) => ` ${pre
566
570
  }, "formatLogMessage");
567
571
  var _isFunction = /* @__PURE__ */ __name((value) => {
568
572
  try {
569
- return value instanceof Function || typeof value === "function" || !!(_optionalChain([value, 'optionalAccess', _27 => _27.constructor]) && _optionalChain([value, 'optionalAccess', _28 => _28.call]) && _optionalChain([value, 'optionalAccess', _29 => _29.apply]));
573
+ return value instanceof Function || typeof value === "function" || !!(_optionalChain([value, 'optionalAccess', _23 => _23.constructor]) && _optionalChain([value, 'optionalAccess', _24 => _24.call]) && _optionalChain([value, 'optionalAccess', _25 => _25.apply]));
570
574
  } catch (e) {
571
575
  return false;
572
576
  }
@@ -575,32 +579,32 @@ var _isFunction = /* @__PURE__ */ __name((value) => {
575
579
  // ../config-tools/src/config-file/get-config-file.ts
576
580
  var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, options = {}) => {
577
581
  const workspacePath = filePath || findWorkspaceRoot(filePath);
578
- let config = await _c12.loadConfig.call(void 0, {
579
- cwd: workspacePath,
580
- packageJson: true,
581
- name: fileName,
582
- envName: _optionalChain([fileName, 'optionalAccess', _30 => _30.toUpperCase, 'call', _31 => _31()]),
583
- jitiOptions: {
584
- debug: false,
585
- fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
586
- },
587
- ...options
588
- });
589
- if (!config || Object.keys(config).length === 0) {
590
- config = await _c12.loadConfig.call(void 0, {
582
+ const configs = await Promise.all([
583
+ _c12.loadConfig.call(void 0, {
591
584
  cwd: workspacePath,
592
585
  packageJson: true,
593
586
  name: fileName,
594
- envName: _optionalChain([fileName, 'optionalAccess', _32 => _32.toUpperCase, 'call', _33 => _33()]),
587
+ envName: _optionalChain([fileName, 'optionalAccess', _26 => _26.toUpperCase, 'call', _27 => _27()]),
588
+ jitiOptions: {
589
+ debug: false,
590
+ fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
591
+ },
592
+ ...options
593
+ }),
594
+ _c12.loadConfig.call(void 0, {
595
+ cwd: workspacePath,
596
+ packageJson: true,
597
+ name: fileName,
598
+ envName: _optionalChain([fileName, 'optionalAccess', _28 => _28.toUpperCase, 'call', _29 => _29()]),
595
599
  jitiOptions: {
596
600
  debug: false,
597
601
  fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
598
602
  },
599
603
  configFile: fileName,
600
604
  ...options
601
- });
602
- }
603
- return config;
605
+ })
606
+ ]);
607
+ return _defu2.default.call(void 0, _nullishCoalesce(configs[0], () => ( {})), _nullishCoalesce(configs[1], () => ( {})));
604
608
  }, "getConfigFileByName");
605
609
  var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames = []) => {
606
610
  const workspacePath = filePath ? filePath : findWorkspaceRoot(filePath);
@@ -608,15 +612,15 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
608
612
  let config = result.config;
609
613
  const configFile = result.configFile;
610
614
  if (config && configFile && Object.keys(config).length > 0) {
611
- writeSystem(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
615
+ writeTrace(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
612
616
  logLevel: "all"
613
617
  });
614
618
  }
615
619
  if (additionalFileNames && additionalFileNames.length > 0) {
616
620
  const results = await Promise.all(additionalFileNames.map((fileName) => getConfigFileByName(fileName, workspacePath)));
617
621
  for (const result2 of results) {
618
- if (_optionalChain([result2, 'optionalAccess', _34 => _34.config]) && _optionalChain([result2, 'optionalAccess', _35 => _35.configFile]) && Object.keys(result2.config).length > 0) {
619
- writeSystem(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
622
+ if (_optionalChain([result2, 'optionalAccess', _30 => _30.config]) && _optionalChain([result2, 'optionalAccess', _31 => _31.configFile]) && Object.keys(result2.config).length > 0) {
623
+ writeTrace(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
620
624
  logLevel: "all"
621
625
  });
622
626
  config = _defu2.default.call(void 0, _nullishCoalesce(result2.config, () => ( {})), _nullishCoalesce(config, () => ( {})));
@@ -634,6 +638,16 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
634
638
 
635
639
 
636
640
  // ../config-tools/src/env/get-env.ts
641
+ var getExtensionEnv = /* @__PURE__ */ __name((extensionName) => {
642
+ const prefix = `STORM_EXTENSION_${extensionName.toUpperCase()}_`;
643
+ return Object.keys(process.env).filter((key) => key.startsWith(prefix)).reduce((ret, key) => {
644
+ const name = key.replace(prefix, "").split("_").map((i) => i.length > 0 ? i.trim().charAt(0).toUpperCase() + i.trim().slice(1) : "").join("");
645
+ if (name) {
646
+ ret[name] = process.env[key];
647
+ }
648
+ return ret;
649
+ }, {});
650
+ }, "getExtensionEnv");
637
651
  var getConfigEnv = /* @__PURE__ */ __name(() => {
638
652
  const prefix = "STORM_";
639
653
  let config = {
@@ -774,13 +788,13 @@ var getBaseThemeColorConfigEnv = /* @__PURE__ */ __name((prefix) => {
774
788
  var setExtensionEnv = /* @__PURE__ */ __name((extensionName, extension) => {
775
789
  for (const key of Object.keys(_nullishCoalesce(extension, () => ( {})))) {
776
790
  if (extension[key]) {
777
- const result = _nullishCoalesce(_optionalChain([key, 'optionalAccess', _36 => _36.replace, 'call', _37 => _37(/([A-Z])+/g, (input) => input ? _optionalChain([input, 'access', _38 => _38[0], 'optionalAccess', _39 => _39.toUpperCase, 'call', _40 => _40()]) + input.slice(1) : ""), 'access', _41 => _41.split, 'call', _42 => _42(/(?=[A-Z])|[.\-\s_]/), 'access', _43 => _43.map, 'call', _44 => _44((x) => x.toLowerCase())]), () => ( []));
791
+ const result = _nullishCoalesce(_optionalChain([key, 'optionalAccess', _32 => _32.replace, 'call', _33 => _33(/([A-Z])+/g, (input) => input ? _optionalChain([input, 'access', _34 => _34[0], 'optionalAccess', _35 => _35.toUpperCase, 'call', _36 => _36()]) + input.slice(1) : ""), 'access', _37 => _37.split, 'call', _38 => _38(/(?=[A-Z])|[.\-\s_]/), 'access', _39 => _39.map, 'call', _40 => _40((x) => x.toLowerCase())]), () => ( []));
778
792
  let extensionKey;
779
793
  if (result.length === 0) {
780
794
  return;
781
795
  }
782
796
  if (result.length === 1) {
783
- extensionKey = _nullishCoalesce(_optionalChain([result, 'access', _45 => _45[0], 'optionalAccess', _46 => _46.toUpperCase, 'call', _47 => _47()]), () => ( ""));
797
+ extensionKey = _nullishCoalesce(_optionalChain([result, 'access', _41 => _41[0], 'optionalAccess', _42 => _42.toUpperCase, 'call', _43 => _43()]), () => ( ""));
784
798
  } else {
785
799
  extensionKey = result.reduce((ret, part) => {
786
800
  return `${ret}_${part.toLowerCase()}`;
@@ -793,7 +807,7 @@ var setExtensionEnv = /* @__PURE__ */ __name((extensionName, extension) => {
793
807
  var setConfigEnv = /* @__PURE__ */ __name((config) => {
794
808
  const prefix = "STORM_";
795
809
  if (config.extends) {
796
- process.env[`${prefix}EXTENDS`] = config.extends;
810
+ process.env[`${prefix}EXTENDS`] = Array.isArray(config.extends) ? JSON.stringify(config.extends) : config.extends;
797
811
  }
798
812
  if (config.name) {
799
813
  process.env[`${prefix}NAME`] = config.name;
@@ -877,7 +891,7 @@ var setConfigEnv = /* @__PURE__ */ __name((config) => {
877
891
  process.env.NODE_ENV = config.env;
878
892
  process.env.ENVIRONMENT = config.env;
879
893
  }
880
- if (_optionalChain([config, 'access', _48 => _48.colors, 'optionalAccess', _49 => _49.base, 'optionalAccess', _50 => _50.light]) || _optionalChain([config, 'access', _51 => _51.colors, 'optionalAccess', _52 => _52.base, 'optionalAccess', _53 => _53.dark])) {
894
+ if (_optionalChain([config, 'access', _44 => _44.colors, 'optionalAccess', _45 => _45.base, 'optionalAccess', _46 => _46.light]) || _optionalChain([config, 'access', _47 => _47.colors, 'optionalAccess', _48 => _48.base, 'optionalAccess', _49 => _49.dark])) {
881
895
  for (const key of Object.keys(config.colors)) {
882
896
  setThemeColorConfigEnv(`${prefix}COLOR_${key}_`, config.colors[key]);
883
897
  }
@@ -925,7 +939,7 @@ var setConfigEnv = /* @__PURE__ */ __name((config) => {
925
939
  }
926
940
  }, "setConfigEnv");
927
941
  var setThemeColorConfigEnv = /* @__PURE__ */ __name((prefix, config) => {
928
- return _optionalChain([config, 'optionalAccess', _54 => _54.light, 'optionalAccess', _55 => _55.brand]) || _optionalChain([config, 'optionalAccess', _56 => _56.dark, 'optionalAccess', _57 => _57.brand]) ? setMultiThemeColorConfigEnv(prefix, config) : setSingleThemeColorConfigEnv(prefix, config);
942
+ return _optionalChain([config, 'optionalAccess', _50 => _50.light, 'optionalAccess', _51 => _51.brand]) || _optionalChain([config, 'optionalAccess', _52 => _52.dark, 'optionalAccess', _53 => _53.brand]) ? setMultiThemeColorConfigEnv(prefix, config) : setSingleThemeColorConfigEnv(prefix, config);
929
943
  }, "setThemeColorConfigEnv");
930
944
  var setSingleThemeColorConfigEnv = /* @__PURE__ */ __name((prefix, config) => {
931
945
  if (config.dark) {
@@ -1023,30 +1037,69 @@ var setBaseThemeColorConfigEnv = /* @__PURE__ */ __name((prefix, config) => {
1023
1037
  }, "setBaseThemeColorConfigEnv");
1024
1038
 
1025
1039
  // ../config-tools/src/create-storm-config.ts
1040
+ var _extension_cache = /* @__PURE__ */ new WeakMap();
1026
1041
  var _static_cache = void 0;
1027
- var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot) => {
1028
- let config = {};
1029
- if (_optionalChain([_static_cache, 'optionalAccess', _58 => _58.data]) && _optionalChain([_static_cache, 'optionalAccess', _59 => _59.timestamp]) && _static_cache.timestamp >= Date.now() + 3e4) {
1030
- writeTrace(`Configuration cache hit - ${_static_cache.timestamp}`, _static_cache.data);
1031
- return _static_cache.data;
1032
- }
1033
- let _workspaceRoot = workspaceRoot;
1034
- if (!_workspaceRoot) {
1035
- _workspaceRoot = findWorkspaceRoot();
1036
- }
1037
- const configFile = await getConfigFile(_workspaceRoot);
1038
- if (!configFile) {
1039
- writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1040
- logLevel: "all"
1041
- });
1042
+ var createStormConfig = /* @__PURE__ */ __name(async (extensionName, schema, workspaceRoot, skipLogs = false) => {
1043
+ let result;
1044
+ if (!_optionalChain([_static_cache, 'optionalAccess', _54 => _54.data]) || !_optionalChain([_static_cache, 'optionalAccess', _55 => _55.timestamp]) || _static_cache.timestamp < Date.now() - 8e3) {
1045
+ let _workspaceRoot = workspaceRoot;
1046
+ if (!_workspaceRoot) {
1047
+ _workspaceRoot = findWorkspaceRoot();
1048
+ }
1049
+ const configEnv = getConfigEnv();
1050
+ const defaultConfig = await getDefaultConfig(_workspaceRoot);
1051
+ const configFile = await getConfigFile(_workspaceRoot);
1052
+ if (!configFile && !skipLogs) {
1053
+ writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1054
+ logLevel: "all"
1055
+ });
1056
+ }
1057
+ result = await StormConfigSchema.parseAsync(_defu2.default.call(void 0, configEnv, configFile, defaultConfig));
1058
+ result.workspaceRoot ??= _workspaceRoot;
1059
+ } else {
1060
+ result = _static_cache.data;
1042
1061
  }
1043
- config = _defu2.default.call(void 0, getConfigEnv(), configFile, getDefaultConfig(_workspaceRoot));
1062
+ if (schema && extensionName) {
1063
+ result.extensions = {
1064
+ ...result.extensions,
1065
+ [extensionName]: createConfigExtension(extensionName, schema)
1066
+ };
1067
+ }
1068
+ _static_cache = {
1069
+ timestamp: Date.now(),
1070
+ data: result
1071
+ };
1072
+ return result;
1073
+ }, "createStormConfig");
1074
+ var createConfigExtension = /* @__PURE__ */ __name((extensionName, schema) => {
1075
+ const extension_cache_key = {
1076
+ extensionName
1077
+ };
1078
+ if (_extension_cache.has(extension_cache_key)) {
1079
+ return _extension_cache.get(extension_cache_key);
1080
+ }
1081
+ let extension = getExtensionEnv(extensionName);
1082
+ if (schema) {
1083
+ extension = schema.parse(extension);
1084
+ }
1085
+ _extension_cache.set(extension_cache_key, extension);
1086
+ return extension;
1087
+ }, "createConfigExtension");
1088
+ var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot, skipLogs = false) => {
1089
+ const config = await createStormConfig(void 0, void 0, workspaceRoot, skipLogs);
1044
1090
  setConfigEnv(config);
1045
- writeTrace(`\u2699\uFE0F Using Storm configuration:
1091
+ if (!skipLogs) {
1092
+ writeTrace(`\u2699\uFE0F Using Storm configuration:
1046
1093
  ${formatLogMessage(config)}`, config);
1094
+ }
1047
1095
  return config;
1048
1096
  }, "loadStormConfig");
1049
1097
 
1098
+ // ../config-tools/src/get-config.ts
1099
+ var getConfig = /* @__PURE__ */ __name((workspaceRoot, skipLogs = false) => {
1100
+ return loadStormConfig(workspaceRoot, skipLogs);
1101
+ }, "getConfig");
1102
+
1050
1103
  // src/cli/index.ts
1051
1104
  var _checkdependencyversionconsistency = require('check-dependency-version-consistency');
1052
1105
  var _commander = require('commander');
@@ -1142,7 +1195,7 @@ var _fsextra = require('fs-extra'); var _fsextra2 = _interopRequireDefault(_fsex
1142
1195
  var _octokit = require('octokit');
1143
1196
 
1144
1197
  async function runCodeowners() {
1145
- const config = await loadStormConfig();
1198
+ const config = await getConfig();
1146
1199
  if (!config) {
1147
1200
  throw new Error("Failed to load storm config.");
1148
1201
  }
@@ -1349,7 +1402,7 @@ async function runManypkg(manypkgType = "fix", manypkgArgs) {
1349
1402
  const { packages, rootPackage, rootDir } = await _getpackages.getPackages.call(void 0, process.env.STORM_WORKSPACE_ROOT ? process.env.STORM_WORKSPACE_ROOT : process.cwd());
1350
1403
  const options = {
1351
1404
  ...defaultOptions,
1352
- ..._optionalChain([rootPackage, 'optionalAccess', _60 => _60.packageJson, 'access', _61 => _61.manypkg])
1405
+ ..._optionalChain([rootPackage, 'optionalAccess', _56 => _56.packageJson, 'access', _57 => _57.manypkg])
1353
1406
  };
1354
1407
  const packagesByName = new Map(packages.map((x) => [
1355
1408
  x.packageJson.name,
package/dist/index.d.cts CHANGED
@@ -6,7 +6,7 @@ import { Command } from 'commander';
6
6
  */
7
7
  declare const StormConfigSchema: z.ZodObject<{
8
8
  $schema: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodDefault<z.ZodString>>>>;
9
- extends: z.ZodOptional<z.ZodString>;
9
+ extends: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
10
10
  name: z.ZodOptional<z.ZodString>;
11
11
  namespace: z.ZodOptional<z.ZodString>;
12
12
  organization: z.ZodDefault<z.ZodString>;
@@ -980,7 +980,7 @@ declare const StormConfigSchema: z.ZodObject<{
980
980
  extensions: Record<string, any>;
981
981
  name?: string | undefined;
982
982
  $schema?: string | null | undefined;
983
- extends?: string | undefined;
983
+ extends?: string | string[] | undefined;
984
984
  namespace?: string | undefined;
985
985
  repository?: string | undefined;
986
986
  preid?: string | undefined;
@@ -1146,7 +1146,7 @@ declare const StormConfigSchema: z.ZodObject<{
1146
1146
  }>;
1147
1147
  name?: string | undefined;
1148
1148
  $schema?: string | null | undefined;
1149
- extends?: string | undefined;
1149
+ extends?: string | string[] | undefined;
1150
1150
  namespace?: string | undefined;
1151
1151
  organization?: string | undefined;
1152
1152
  repository?: string | undefined;
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ import { Command } from 'commander';
6
6
  */
7
7
  declare const StormConfigSchema: z.ZodObject<{
8
8
  $schema: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodDefault<z.ZodString>>>>;
9
- extends: z.ZodOptional<z.ZodString>;
9
+ extends: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
10
10
  name: z.ZodOptional<z.ZodString>;
11
11
  namespace: z.ZodOptional<z.ZodString>;
12
12
  organization: z.ZodDefault<z.ZodString>;
@@ -980,7 +980,7 @@ declare const StormConfigSchema: z.ZodObject<{
980
980
  extensions: Record<string, any>;
981
981
  name?: string | undefined;
982
982
  $schema?: string | null | undefined;
983
- extends?: string | undefined;
983
+ extends?: string | string[] | undefined;
984
984
  namespace?: string | undefined;
985
985
  repository?: string | undefined;
986
986
  preid?: string | undefined;
@@ -1146,7 +1146,7 @@ declare const StormConfigSchema: z.ZodObject<{
1146
1146
  }>;
1147
1147
  name?: string | undefined;
1148
1148
  $schema?: string | null | undefined;
1149
- extends?: string | undefined;
1149
+ extends?: string | string[] | undefined;
1150
1150
  namespace?: string | undefined;
1151
1151
  organization?: string | undefined;
1152
1152
  repository?: string | undefined;
package/dist/index.js CHANGED
@@ -118,6 +118,8 @@ var ColorConfigMapSchema = z.union([
118
118
  }),
119
119
  z.record(z.string(), ColorConfigSchema)
120
120
  ]);
121
+ var ExtendsItemSchema = z.string().trim().describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
122
+ var ExtendsSchema = ExtendsItemSchema.or(z.array(ExtendsItemSchema)).describe("The path to a base config file to use as a configuration preset file. Documentation can be found at https://github.com/unjs/c12#extending-configuration.");
121
123
  var WorkspaceBotConfigSchema = z.object({
122
124
  name: z.string().trim().default("Stormie-Bot").describe("The workspace bot user's name (this is the bot that will be used to perform various tasks)"),
123
125
  email: z.string().trim().email().default("bot@stormsoftware.com").describe("The email of the workspace bot")
@@ -132,11 +134,11 @@ var WorkspaceDirectoryConfigSchema = z.object({
132
134
  }).describe("Various directories used by the workspace to store data, cache, and configuration files");
133
135
  var StormConfigSchema = z.object({
134
136
  $schema: z.string().trim().default("https://cdn.jsdelivr.net/npm/@storm-software/config/schemas/storm.schema.json").optional().nullish().describe("The URL to the JSON schema file that describes the Storm configuration file"),
135
- extends: z.string().trim().optional().describe("The path to a base JSON file to use as a configuration preset file"),
137
+ extends: ExtendsSchema.optional(),
136
138
  name: z.string().trim().toLowerCase().optional().describe("The name of the service/package/scope using this configuration"),
137
139
  namespace: z.string().trim().toLowerCase().optional().describe("The namespace of the package"),
138
140
  organization: z.string().trim().default("storm-software").describe("The organization of the workspace"),
139
- repository: z.string().trim().url().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
141
+ repository: z.string().trim().optional().describe("The repo URL of the workspace (i.e. GitHub)"),
140
142
  license: z.string().trim().default("Apache-2.0").describe("The license type of the package"),
141
143
  homepage: z.string().trim().url().default(STORM_DEFAULT_HOMEPAGE).describe("The homepage of the workspace"),
142
144
  docs: z.string().trim().url().default(STORM_DEFAULT_DOCS).describe("The base documentation site for the workspace"),
@@ -199,7 +201,8 @@ var COLOR_KEYS = [
199
201
  ];
200
202
 
201
203
  // ../config-tools/src/utilities/get-default-config.ts
202
- import { existsSync as existsSync2, readFileSync } from "node:fs";
204
+ import { existsSync as existsSync2 } from "node:fs";
205
+ import { readFile } from "node:fs/promises";
203
206
  import { join as join2 } from "node:path";
204
207
 
205
208
  // ../config-tools/src/utilities/correct-paths.ts
@@ -321,17 +324,15 @@ var DEFAULT_COLOR_CONFIG = {
321
324
  "negative": "#dc2626"
322
325
  }
323
326
  };
324
- var getDefaultConfig = /* @__PURE__ */ __name((root) => {
327
+ var getDefaultConfig = /* @__PURE__ */ __name(async (root) => {
325
328
  let license = STORM_DEFAULT_LICENSE;
326
329
  let homepage = STORM_DEFAULT_HOMEPAGE;
327
- let name;
328
- let namespace;
329
- let repository;
330
+ let name = void 0;
331
+ let namespace = void 0;
332
+ let repository = void 0;
330
333
  const workspaceRoot = findWorkspaceRoot(root);
331
334
  if (existsSync2(join2(workspaceRoot, "package.json"))) {
332
- const file = readFileSync(join2(workspaceRoot, "package.json"), {
333
- encoding: "utf8"
334
- });
335
+ const file = await readFile(joinPaths(workspaceRoot, "package.json"), "utf8");
335
336
  if (file) {
336
337
  const packageJson = JSON.parse(file);
337
338
  if (packageJson.name) {
@@ -340,8 +341,12 @@ var getDefaultConfig = /* @__PURE__ */ __name((root) => {
340
341
  if (packageJson.namespace) {
341
342
  namespace = packageJson.namespace;
342
343
  }
343
- if (packageJson.repository?.url) {
344
- repository = packageJson.repository?.url;
344
+ if (packageJson.repository) {
345
+ if (typeof packageJson.repository === "string") {
346
+ repository = packageJson.repository;
347
+ } else if (packageJson.repository.url) {
348
+ repository = packageJson.repository.url;
349
+ }
345
350
  }
346
351
  if (packageJson.license) {
347
352
  license = packageJson.license;
@@ -546,7 +551,6 @@ var writeInfo = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.IN
546
551
  var writeSuccess = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.SUCCESS, config)(message), "writeSuccess");
547
552
  var writeDebug = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.DEBUG, config)(message), "writeDebug");
548
553
  var writeTrace = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.TRACE, config)(message), "writeTrace");
549
- var writeSystem = /* @__PURE__ */ __name((message, config) => getLogFn(LogLevel.ALL, config)(message), "writeSystem");
550
554
  var MAX_DEPTH = 4;
551
555
  var formatLogMessage = /* @__PURE__ */ __name((message, options = {}, depth2 = 0) => {
552
556
  if (depth2 > MAX_DEPTH) {
@@ -575,19 +579,19 @@ var _isFunction = /* @__PURE__ */ __name((value) => {
575
579
  // ../config-tools/src/config-file/get-config-file.ts
576
580
  var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, options = {}) => {
577
581
  const workspacePath = filePath || findWorkspaceRoot(filePath);
578
- let config = await loadConfig({
579
- cwd: workspacePath,
580
- packageJson: true,
581
- name: fileName,
582
- envName: fileName?.toUpperCase(),
583
- jitiOptions: {
584
- debug: false,
585
- fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
586
- },
587
- ...options
588
- });
589
- if (!config || Object.keys(config).length === 0) {
590
- config = await loadConfig({
582
+ const configs = await Promise.all([
583
+ loadConfig({
584
+ cwd: workspacePath,
585
+ packageJson: true,
586
+ name: fileName,
587
+ envName: fileName?.toUpperCase(),
588
+ jitiOptions: {
589
+ debug: false,
590
+ fsCache: process.env.STORM_SKIP_CACHE === "true" ? false : joinPaths(process.env.STORM_CACHE_DIR || "node_modules/.cache/storm", "jiti")
591
+ },
592
+ ...options
593
+ }),
594
+ loadConfig({
591
595
  cwd: workspacePath,
592
596
  packageJson: true,
593
597
  name: fileName,
@@ -598,9 +602,9 @@ var getConfigFileByName = /* @__PURE__ */ __name(async (fileName, filePath, opti
598
602
  },
599
603
  configFile: fileName,
600
604
  ...options
601
- });
602
- }
603
- return config;
605
+ })
606
+ ]);
607
+ return defu(configs[0] ?? {}, configs[1] ?? {});
604
608
  }, "getConfigFileByName");
605
609
  var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames = []) => {
606
610
  const workspacePath = filePath ? filePath : findWorkspaceRoot(filePath);
@@ -608,7 +612,7 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
608
612
  let config = result.config;
609
613
  const configFile = result.configFile;
610
614
  if (config && configFile && Object.keys(config).length > 0) {
611
- writeSystem(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
615
+ writeTrace(`Found Storm configuration file "${configFile.includes(`${workspacePath}/`) ? configFile.replace(`${workspacePath}/`, "") : configFile}" at "${workspacePath}"`, {
612
616
  logLevel: "all"
613
617
  });
614
618
  }
@@ -616,7 +620,7 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
616
620
  const results = await Promise.all(additionalFileNames.map((fileName) => getConfigFileByName(fileName, workspacePath)));
617
621
  for (const result2 of results) {
618
622
  if (result2?.config && result2?.configFile && Object.keys(result2.config).length > 0) {
619
- writeSystem(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
623
+ writeTrace(`Found alternative configuration file "${result2.configFile.includes(`${workspacePath}/`) ? result2.configFile.replace(`${workspacePath}/`, "") : result2.configFile}" at "${workspacePath}"`, {
620
624
  logLevel: "all"
621
625
  });
622
626
  config = defu(result2.config ?? {}, config ?? {});
@@ -634,6 +638,16 @@ var getConfigFile = /* @__PURE__ */ __name(async (filePath, additionalFileNames
634
638
  import defu2 from "defu";
635
639
 
636
640
  // ../config-tools/src/env/get-env.ts
641
+ var getExtensionEnv = /* @__PURE__ */ __name((extensionName) => {
642
+ const prefix = `STORM_EXTENSION_${extensionName.toUpperCase()}_`;
643
+ return Object.keys(process.env).filter((key) => key.startsWith(prefix)).reduce((ret, key) => {
644
+ const name = key.replace(prefix, "").split("_").map((i) => i.length > 0 ? i.trim().charAt(0).toUpperCase() + i.trim().slice(1) : "").join("");
645
+ if (name) {
646
+ ret[name] = process.env[key];
647
+ }
648
+ return ret;
649
+ }, {});
650
+ }, "getExtensionEnv");
637
651
  var getConfigEnv = /* @__PURE__ */ __name(() => {
638
652
  const prefix = "STORM_";
639
653
  let config = {
@@ -793,7 +807,7 @@ var setExtensionEnv = /* @__PURE__ */ __name((extensionName, extension) => {
793
807
  var setConfigEnv = /* @__PURE__ */ __name((config) => {
794
808
  const prefix = "STORM_";
795
809
  if (config.extends) {
796
- process.env[`${prefix}EXTENDS`] = config.extends;
810
+ process.env[`${prefix}EXTENDS`] = Array.isArray(config.extends) ? JSON.stringify(config.extends) : config.extends;
797
811
  }
798
812
  if (config.name) {
799
813
  process.env[`${prefix}NAME`] = config.name;
@@ -1023,30 +1037,69 @@ var setBaseThemeColorConfigEnv = /* @__PURE__ */ __name((prefix, config) => {
1023
1037
  }, "setBaseThemeColorConfigEnv");
1024
1038
 
1025
1039
  // ../config-tools/src/create-storm-config.ts
1040
+ var _extension_cache = /* @__PURE__ */ new WeakMap();
1026
1041
  var _static_cache = void 0;
1027
- var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot) => {
1028
- let config = {};
1029
- if (_static_cache?.data && _static_cache?.timestamp && _static_cache.timestamp >= Date.now() + 3e4) {
1030
- writeTrace(`Configuration cache hit - ${_static_cache.timestamp}`, _static_cache.data);
1031
- return _static_cache.data;
1032
- }
1033
- let _workspaceRoot = workspaceRoot;
1034
- if (!_workspaceRoot) {
1035
- _workspaceRoot = findWorkspaceRoot();
1036
- }
1037
- const configFile = await getConfigFile(_workspaceRoot);
1038
- if (!configFile) {
1039
- writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1040
- logLevel: "all"
1041
- });
1042
+ var createStormConfig = /* @__PURE__ */ __name(async (extensionName, schema, workspaceRoot, skipLogs = false) => {
1043
+ let result;
1044
+ if (!_static_cache?.data || !_static_cache?.timestamp || _static_cache.timestamp < Date.now() - 8e3) {
1045
+ let _workspaceRoot = workspaceRoot;
1046
+ if (!_workspaceRoot) {
1047
+ _workspaceRoot = findWorkspaceRoot();
1048
+ }
1049
+ const configEnv = getConfigEnv();
1050
+ const defaultConfig = await getDefaultConfig(_workspaceRoot);
1051
+ const configFile = await getConfigFile(_workspaceRoot);
1052
+ if (!configFile && !skipLogs) {
1053
+ writeWarning("No Storm config file found in the current workspace. Please ensure this is the expected behavior - you can add a `storm.json` file to the root of your workspace if it is not.\n", {
1054
+ logLevel: "all"
1055
+ });
1056
+ }
1057
+ result = await StormConfigSchema.parseAsync(defu2(configEnv, configFile, defaultConfig));
1058
+ result.workspaceRoot ??= _workspaceRoot;
1059
+ } else {
1060
+ result = _static_cache.data;
1042
1061
  }
1043
- config = defu2(getConfigEnv(), configFile, getDefaultConfig(_workspaceRoot));
1062
+ if (schema && extensionName) {
1063
+ result.extensions = {
1064
+ ...result.extensions,
1065
+ [extensionName]: createConfigExtension(extensionName, schema)
1066
+ };
1067
+ }
1068
+ _static_cache = {
1069
+ timestamp: Date.now(),
1070
+ data: result
1071
+ };
1072
+ return result;
1073
+ }, "createStormConfig");
1074
+ var createConfigExtension = /* @__PURE__ */ __name((extensionName, schema) => {
1075
+ const extension_cache_key = {
1076
+ extensionName
1077
+ };
1078
+ if (_extension_cache.has(extension_cache_key)) {
1079
+ return _extension_cache.get(extension_cache_key);
1080
+ }
1081
+ let extension = getExtensionEnv(extensionName);
1082
+ if (schema) {
1083
+ extension = schema.parse(extension);
1084
+ }
1085
+ _extension_cache.set(extension_cache_key, extension);
1086
+ return extension;
1087
+ }, "createConfigExtension");
1088
+ var loadStormConfig = /* @__PURE__ */ __name(async (workspaceRoot, skipLogs = false) => {
1089
+ const config = await createStormConfig(void 0, void 0, workspaceRoot, skipLogs);
1044
1090
  setConfigEnv(config);
1045
- writeTrace(`\u2699\uFE0F Using Storm configuration:
1091
+ if (!skipLogs) {
1092
+ writeTrace(`\u2699\uFE0F Using Storm configuration:
1046
1093
  ${formatLogMessage(config)}`, config);
1094
+ }
1047
1095
  return config;
1048
1096
  }, "loadStormConfig");
1049
1097
 
1098
+ // ../config-tools/src/get-config.ts
1099
+ var getConfig = /* @__PURE__ */ __name((workspaceRoot, skipLogs = false) => {
1100
+ return loadStormConfig(workspaceRoot, skipLogs);
1101
+ }, "getConfig");
1102
+
1050
1103
  // src/cli/index.ts
1051
1104
  import { CDVC } from "check-dependency-version-consistency";
1052
1105
  import { Command, Option } from "commander";
@@ -1142,7 +1195,7 @@ import fs from "fs-extra";
1142
1195
  import { Octokit } from "octokit";
1143
1196
  import { join as join3 } from "path";
1144
1197
  async function runCodeowners() {
1145
- const config = await loadStormConfig();
1198
+ const config = await getConfig();
1146
1199
  if (!config) {
1147
1200
  throw new Error("Failed to load storm config.");
1148
1201
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storm-software/linting-tools",
3
- "version": "1.106.2",
3
+ "version": "1.106.3",
4
4
  "type": "module",
5
5
  "description": "⚡ A package containing various linting tools used to validate syntax, enforce design standards, and format code in a Storm workspace.",
6
6
  "repository": {
@@ -133,7 +133,7 @@
133
133
  "vfile-reporter": "8.1.1"
134
134
  },
135
135
  "devDependencies": {
136
- "@storm-software/cspell": "0.8.2",
136
+ "@storm-software/cspell": "0.8.3",
137
137
  "@types/node": "^22.10.2",
138
138
  "cspell": "8.8.4",
139
139
  "tsup": "8.3.5"