@bamboocss/config 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,630 @@
1
+ import {
2
+ diffConfigs
3
+ } from "./chunk-6TQW6KOI.mjs";
4
+ import {
5
+ SEP,
6
+ formatPath,
7
+ getReferences,
8
+ isTokenReference,
9
+ isValidToken,
10
+ mergeConfigs,
11
+ mergeHooks,
12
+ serializeTokenValue
13
+ } from "./chunk-RIBK22OM.mjs";
14
+ import {
15
+ resolveTsPathPattern
16
+ } from "./chunk-RPIVZP2I.mjs";
17
+
18
+ // src/bundle-config.ts
19
+ import { logger } from "@bamboocss/logger";
20
+ import { BambooError as BambooError2 } from "@bamboocss/shared";
21
+ import { bundleNRequire } from "bundle-n-require";
22
+
23
+ // src/find-config.ts
24
+ import { BambooError } from "@bamboocss/shared";
25
+ import findUp from "escalade/sync";
26
+ import { resolve } from "path";
27
+
28
+ // src/is-bamboo-config.ts
29
+ var configName = "bamboo";
30
+ var bambooConfigFiles = /* @__PURE__ */ new Set([
31
+ `${configName}.config.ts`,
32
+ `${configName}.config.js`,
33
+ `${configName}.config.mts`,
34
+ `${configName}.config.mjs`,
35
+ `${configName}.config.cts`,
36
+ `${configName}.config.cjs`
37
+ ]);
38
+ var isBambooConfig = (file) => bambooConfigFiles.has(file);
39
+
40
+ // src/find-config.ts
41
+ function findConfig(options) {
42
+ const { cwd = process.cwd(), file } = options;
43
+ if (file) {
44
+ return resolve(cwd, file);
45
+ }
46
+ const configPath = findUp(cwd, (_dir, paths) => paths.find(isBambooConfig));
47
+ if (!configPath) {
48
+ throw new BambooError(
49
+ "CONFIG_NOT_FOUND",
50
+ `Cannot find config file \`bamboo.config.{ts,js,mjs,mts}\`. Did you forget to run \`bamboo init\`?`
51
+ );
52
+ }
53
+ return configPath;
54
+ }
55
+
56
+ // src/bundle-config.ts
57
+ async function bundle(filepath, cwd) {
58
+ const { mod, dependencies } = await bundleNRequire(filepath, {
59
+ cwd,
60
+ interopDefault: true
61
+ });
62
+ const config = mod?.default ?? mod;
63
+ return {
64
+ config,
65
+ dependencies
66
+ };
67
+ }
68
+ async function bundleConfig(options) {
69
+ const { cwd, file } = options;
70
+ const filePath = findConfig({ cwd, file });
71
+ logger.debug("config:path", filePath);
72
+ const result = await bundle(filePath, cwd);
73
+ if (typeof result.config !== "object") {
74
+ throw new BambooError2("CONFIG_ERROR", `\u{1F4A5} Config must export or return an object.`);
75
+ }
76
+ result.config.outdir ??= "styled-system";
77
+ result.config.validation ??= "warn";
78
+ return {
79
+ ...result,
80
+ config: result.config,
81
+ path: filePath
82
+ };
83
+ }
84
+
85
+ // src/get-mod-deps.ts
86
+ import fs from "fs";
87
+ import path from "path";
88
+ import ts from "typescript";
89
+
90
+ // src/ts-config-paths.ts
91
+ import { resolve as resolve2 } from "path";
92
+ function convertTsPathsToRegexes(paths, baseUrl) {
93
+ const sortedPatterns = Object.keys(paths).sort((a, b) => getPrefixLength(b) - getPrefixLength(a));
94
+ const resolved = [];
95
+ for (let pattern of sortedPatterns) {
96
+ const relativePaths = paths[pattern];
97
+ pattern = escapeStringRegexp(pattern).replace(/\*/g, "(.+)");
98
+ resolved.push({
99
+ pattern: new RegExp("^" + pattern + "$"),
100
+ paths: relativePaths.map((relativePath) => resolve2(baseUrl, relativePath))
101
+ });
102
+ }
103
+ return resolved;
104
+ }
105
+ function getPrefixLength(pattern) {
106
+ const prefixLength = pattern.indexOf("*");
107
+ return pattern.substr(0, prefixLength).length;
108
+ }
109
+ function escapeStringRegexp(string) {
110
+ return string.replace(/[|\\{}()[\]^$+?.]/g, "\\$&").replace(/-/g, "\\x2d");
111
+ }
112
+
113
+ // src/get-mod-deps.ts
114
+ var jsExtensions = [".js", ".cjs", ".mjs"];
115
+ var jsResolutionOrder = ["", ".js", ".cjs", ".mjs", ".ts", ".cts", ".mts", ".jsx", ".tsx"];
116
+ var tsResolutionOrder = ["", ".ts", ".cts", ".mts", ".tsx", ".js", ".cjs", ".mjs", ".jsx"];
117
+ function resolveWithExtension(file, extensions) {
118
+ for (const ext of extensions) {
119
+ const full = `${file}${ext}`;
120
+ if (fs.existsSync(full) && fs.statSync(full).isFile()) {
121
+ return full;
122
+ }
123
+ }
124
+ for (const ext of extensions) {
125
+ const full = `${file}/index${ext}`;
126
+ if (fs.existsSync(full)) {
127
+ return full;
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ var importRegex = /import[\s\S]*?['"](.{3,}?)['"]/gi;
133
+ var importFromRegex = /import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi;
134
+ var requireRegex = /require\(['"`](.+)['"`]\)/gi;
135
+ var exportRegex = /export[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi;
136
+ function getDeps(opts, fromAlias) {
137
+ const { filename, seen } = opts;
138
+ const { moduleResolution: _, ...compilerOptions } = opts.compilerOptions ?? {};
139
+ const absoluteFile = resolveWithExtension(
140
+ path.resolve(opts.cwd, filename),
141
+ jsExtensions.includes(opts.ext) ? jsResolutionOrder : tsResolutionOrder
142
+ );
143
+ if (absoluteFile === null) return;
144
+ if (fromAlias) {
145
+ opts.foundModuleAliases.set(fromAlias, absoluteFile);
146
+ }
147
+ if (seen.size > 1 && seen.has(absoluteFile)) return;
148
+ seen.add(absoluteFile);
149
+ const contents = fs.readFileSync(absoluteFile, "utf-8");
150
+ const fileDeps = [
151
+ ...contents.matchAll(importRegex),
152
+ ...contents.matchAll(importFromRegex),
153
+ ...contents.matchAll(requireRegex),
154
+ ...contents.matchAll(exportRegex)
155
+ ];
156
+ if (!fileDeps.length) return;
157
+ const nextOpts = {
158
+ // Resolve new base for new imports/requires
159
+ cwd: path.dirname(absoluteFile),
160
+ ext: path.extname(absoluteFile),
161
+ seen,
162
+ baseUrl: opts.baseUrl,
163
+ pathMappings: opts.pathMappings,
164
+ foundModuleAliases: opts.foundModuleAliases
165
+ };
166
+ fileDeps.forEach((match) => {
167
+ const mod = match[1];
168
+ if (mod[0] === ".") {
169
+ getDeps(Object.assign({}, nextOpts, { filename: mod }));
170
+ return;
171
+ }
172
+ try {
173
+ const found = ts.resolveModuleName(mod, absoluteFile, compilerOptions, ts.sys).resolvedModule;
174
+ if (found && found.extension.endsWith("ts")) {
175
+ getDeps(Object.assign({}, nextOpts, { filename: found.resolvedFileName }));
176
+ return;
177
+ }
178
+ if (!opts.pathMappings) return;
179
+ const filename2 = resolveTsPathPattern(opts.pathMappings, mod);
180
+ if (!filename2) return;
181
+ getDeps(Object.assign({}, nextOpts, { filename: filename2 }), mod);
182
+ } catch {
183
+ }
184
+ });
185
+ }
186
+ function getConfigDependencies(filePath, tsOptions = { pathMappings: [] }, compilerOptions) {
187
+ if (filePath === null) return { deps: /* @__PURE__ */ new Set(), aliases: /* @__PURE__ */ new Map() };
188
+ const foundModuleAliases = /* @__PURE__ */ new Map();
189
+ const deps = /* @__PURE__ */ new Set();
190
+ deps.add(filePath);
191
+ getDeps({
192
+ filename: filePath,
193
+ ext: path.extname(filePath),
194
+ cwd: path.dirname(filePath),
195
+ seen: deps,
196
+ baseUrl: tsOptions.baseUrl,
197
+ pathMappings: tsOptions.pathMappings ?? [],
198
+ foundModuleAliases,
199
+ compilerOptions
200
+ });
201
+ return { deps, aliases: foundModuleAliases };
202
+ }
203
+
204
+ // src/get-resolved-config.ts
205
+ import { omit, pick, traverse } from "@bamboocss/shared";
206
+ var hookUtils = {
207
+ omit,
208
+ pick,
209
+ traverse
210
+ };
211
+ async function getResolvedConfig(config, cwd, hooks) {
212
+ const stack = [config];
213
+ const configs = [];
214
+ while (stack.length > 0) {
215
+ const current = stack.pop();
216
+ const subPresets = current.presets ?? [];
217
+ for (const subPreset of subPresets) {
218
+ let presetConfig;
219
+ let presetName;
220
+ if (typeof subPreset === "string") {
221
+ const presetModule = await bundle(subPreset, cwd);
222
+ presetConfig = presetModule.config;
223
+ presetName = subPreset;
224
+ } else {
225
+ presetConfig = await subPreset;
226
+ presetName = presetConfig.name || "unknown-preset";
227
+ }
228
+ if (hooks?.["preset:resolved"]) {
229
+ const resolvedPreset = await hooks["preset:resolved"]({
230
+ preset: presetConfig,
231
+ name: presetName,
232
+ utils: hookUtils
233
+ });
234
+ if (resolvedPreset !== void 0) {
235
+ presetConfig = resolvedPreset;
236
+ }
237
+ }
238
+ stack.push(presetConfig);
239
+ }
240
+ configs.unshift(current);
241
+ }
242
+ const merged = mergeConfigs(configs);
243
+ merged.presets = configs.slice(0, -1);
244
+ return merged;
245
+ }
246
+
247
+ // src/resolve-config.ts
248
+ import { logger as logger3 } from "@bamboocss/logger";
249
+ import { BAMBOO_CONFIG_NAME, omit as omit2, parseJson, pick as pick2, stringifyJson, traverse as traverse2 } from "@bamboocss/shared";
250
+
251
+ // src/bundled-preset.ts
252
+ import { preset as presetBase } from "@bamboocss/preset-base";
253
+ import { preset as presetBamboo } from "@bamboocss/preset-bamboo";
254
+ var bundledPresets = {
255
+ "@bamboocss/preset-base": presetBase,
256
+ "@bamboocss/preset-bamboo": presetBamboo,
257
+ "@bamboocss/dev/presets": presetBamboo
258
+ };
259
+ var bundledPresetsNames = Object.keys(bundledPresets);
260
+ var isBundledPreset = (preset) => bundledPresetsNames.includes(preset);
261
+ var getBundledPreset = (preset) => {
262
+ return typeof preset === "string" && isBundledPreset(preset) ? bundledPresets[preset] : void 0;
263
+ };
264
+
265
+ // src/validate-config.ts
266
+ import { logger as logger2 } from "@bamboocss/logger";
267
+ import { BambooError as BambooError3 } from "@bamboocss/shared";
268
+
269
+ // src/validation/validate-artifact.ts
270
+ var validateArtifactNames = (names, addError) => {
271
+ names.recipes.forEach((recipeName) => {
272
+ if (names.slotRecipes.has(recipeName)) {
273
+ addError("recipes", `This recipe name is already used in \`theme.slotRecipes\`: ${recipeName}`);
274
+ }
275
+ if (names.patterns.has(recipeName)) {
276
+ addError("recipes", `This recipe name is already used in \`patterns\`: \`${recipeName}\``);
277
+ }
278
+ });
279
+ names.slotRecipes.forEach((recipeName) => {
280
+ if (names.patterns.has(recipeName)) {
281
+ addError("recipes", `This recipe name is already used in \`patterns\`: ${recipeName}`);
282
+ }
283
+ });
284
+ };
285
+
286
+ // src/validation/validate-breakpoints.ts
287
+ import { getUnit } from "@bamboocss/shared";
288
+ var validateBreakpoints = (breakpoints, addError) => {
289
+ if (!breakpoints) return;
290
+ const units = /* @__PURE__ */ new Set();
291
+ const values = Object.values(breakpoints);
292
+ for (const value of values) {
293
+ const unit = getUnit(value) ?? "px";
294
+ units.add(unit);
295
+ }
296
+ if (units.size > 1) {
297
+ addError("breakpoints", `All breakpoints must use the same unit: \`${values.join(", ")}\``);
298
+ }
299
+ };
300
+
301
+ // src/validation/validate-condition.ts
302
+ import { isString } from "@bamboocss/shared";
303
+ var validateObjectCondition = (obj, addError) => {
304
+ let hasSlot = false;
305
+ for (const [key, value] of Object.entries(obj)) {
306
+ if (!key.startsWith("@") && !key.includes("&")) {
307
+ addError("conditions", `Selectors should contain the \`&\` character: \`${key}\``);
308
+ }
309
+ if (value === "@slot") {
310
+ hasSlot = true;
311
+ continue;
312
+ }
313
+ if (typeof value === "string") {
314
+ addError(
315
+ "conditions",
316
+ `Object condition leaves must be the literal string \`'@slot'\`, got \`${JSON.stringify(value)}\` at \`${key}\``
317
+ );
318
+ continue;
319
+ }
320
+ if (typeof value === "object" && value !== null) {
321
+ const nested = validateObjectCondition(value, addError);
322
+ if (nested.hasSlot) hasSlot = true;
323
+ }
324
+ }
325
+ return { hasSlot };
326
+ };
327
+ var validateConditions = (conditions, addError) => {
328
+ if (!conditions) return;
329
+ Object.values(conditions).forEach((condition) => {
330
+ if (isString(condition)) {
331
+ if (!condition.startsWith("@") && !condition.includes("&")) {
332
+ addError("conditions", `Selectors should contain the \`&\` character: \`${condition}\``);
333
+ }
334
+ return;
335
+ }
336
+ if (Array.isArray(condition)) {
337
+ condition.forEach((c) => {
338
+ if (!c.startsWith("@") && !c.includes("&")) {
339
+ addError("conditions", `Selectors should contain the \`&\` character: \`${c}\``);
340
+ }
341
+ });
342
+ return;
343
+ }
344
+ const { hasSlot } = validateObjectCondition(condition, addError);
345
+ if (!hasSlot) {
346
+ addError("conditions", `Object conditions must contain at least one \`'@slot'\` marker`);
347
+ }
348
+ });
349
+ };
350
+
351
+ // src/validation/validate-patterns.ts
352
+ var validatePatterns = (patterns, names) => {
353
+ if (!patterns) return;
354
+ Object.keys(patterns).forEach((patternName) => {
355
+ names.patterns.add(patternName);
356
+ });
357
+ };
358
+
359
+ // src/validation/validate-recipes.ts
360
+ var validateRecipes = (options) => {
361
+ const {
362
+ config: { theme },
363
+ artifacts
364
+ } = options;
365
+ if (!theme) return;
366
+ if (theme.recipes) {
367
+ Object.keys(theme.recipes).forEach((recipeName) => {
368
+ artifacts.recipes.add(recipeName);
369
+ });
370
+ }
371
+ if (theme.slotRecipes) {
372
+ Object.keys(theme.slotRecipes).forEach((recipeName) => {
373
+ artifacts.slotRecipes.add(recipeName);
374
+ });
375
+ }
376
+ return artifacts;
377
+ };
378
+
379
+ // src/validation/validate-tokens.ts
380
+ import { isObject, walkObject } from "@bamboocss/shared";
381
+
382
+ // src/validation/validate-token-references.ts
383
+ var validateTokenReferences = (props) => {
384
+ const { valueAtPath, refsByPath, addError, typeByPath } = props;
385
+ refsByPath.forEach((refs, path2) => {
386
+ if (refs.has(path2)) {
387
+ addError("tokens", `Self token reference: \`${path2}\``);
388
+ }
389
+ const stack = [path2];
390
+ while (stack.length > 0) {
391
+ let currentPath = stack.pop();
392
+ if (currentPath.includes("/")) {
393
+ const [tokenPath] = currentPath.split("/");
394
+ currentPath = tokenPath;
395
+ }
396
+ const value = valueAtPath.get(currentPath);
397
+ if (!value) {
398
+ const configKey = typeByPath.get(path2);
399
+ addError("tokens", `Missing token: \`${currentPath}\` used in \`theme.${configKey}.${path2}\``);
400
+ }
401
+ if (isTokenReference(value) && !refsByPath.has(value)) {
402
+ addError("tokens", `Unknown token reference: \`${currentPath}\` used in \`${value}\``);
403
+ }
404
+ const deps = refsByPath.get(currentPath);
405
+ if (!deps) continue;
406
+ for (const transitiveDep of deps) {
407
+ if (path2 === transitiveDep) {
408
+ addError(
409
+ "tokens",
410
+ `Circular token reference: \`${transitiveDep}\` -> \`${currentPath}\` -> ... -> \`${path2}\``
411
+ );
412
+ break;
413
+ }
414
+ stack.push(transitiveDep);
415
+ }
416
+ }
417
+ });
418
+ };
419
+
420
+ // src/validation/validate-tokens.ts
421
+ var validateTokens = (options) => {
422
+ const {
423
+ config: { theme },
424
+ tokens,
425
+ addError
426
+ } = options;
427
+ if (!theme) return;
428
+ const { tokenNames, semanticTokenNames, valueAtPath, refsByPath, typeByPath } = tokens;
429
+ if (theme.tokens) {
430
+ const tokenPaths = /* @__PURE__ */ new Set();
431
+ walkObject(
432
+ theme.tokens,
433
+ (value, paths) => {
434
+ const path2 = paths.join(SEP);
435
+ tokenNames.add(path2);
436
+ tokenPaths.add(path2);
437
+ valueAtPath.set(path2, value);
438
+ if (path2.includes("DEFAULT")) {
439
+ valueAtPath.set(path2.replace(SEP + "DEFAULT", ""), value);
440
+ }
441
+ },
442
+ {
443
+ stop: isValidToken
444
+ }
445
+ );
446
+ tokenPaths.forEach((path2) => {
447
+ const itemValue = valueAtPath.get(path2);
448
+ const formattedPath = formatPath(path2);
449
+ typeByPath.set(formattedPath, "tokens");
450
+ if (!isValidToken(itemValue)) {
451
+ addError("tokens", `Token must contain 'value': \`theme.tokens.${formattedPath}\``);
452
+ return;
453
+ }
454
+ if (path2.includes(" ")) {
455
+ addError("tokens", `Token key must not contain spaces: \`theme.tokens.${formattedPath}\``);
456
+ return;
457
+ }
458
+ const valueStr = serializeTokenValue(itemValue.value || itemValue);
459
+ if (isTokenReference(valueStr)) {
460
+ refsByPath.set(formattedPath, /* @__PURE__ */ new Set([]));
461
+ }
462
+ const references = refsByPath.get(formattedPath);
463
+ if (!references) return;
464
+ getReferences(valueStr).forEach((reference) => {
465
+ references.add(reference);
466
+ });
467
+ });
468
+ }
469
+ if (theme.semanticTokens) {
470
+ const tokenPaths = /* @__PURE__ */ new Set();
471
+ walkObject(
472
+ theme.semanticTokens,
473
+ (value, paths) => {
474
+ const path2 = paths.join(SEP);
475
+ semanticTokenNames.add(path2);
476
+ valueAtPath.set(path2, value);
477
+ tokenPaths.add(path2);
478
+ if (path2.includes("DEFAULT")) {
479
+ valueAtPath.set(path2.replace(SEP + "DEFAULT", ""), value);
480
+ }
481
+ if (!isValidToken(value)) return;
482
+ walkObject(value, (itemValue, paths2) => {
483
+ const valuePath = paths2.join(SEP);
484
+ const formattedPath = formatPath(path2);
485
+ typeByPath.set(formattedPath, "semanticTokens");
486
+ const fullPath = formattedPath + "." + paths2.join(SEP);
487
+ if (valuePath.includes("value" + SEP + "value")) {
488
+ addError("tokens", `You used \`value\` twice resulting in an invalid token \`theme.tokens.${fullPath}\``);
489
+ }
490
+ const valueStr = serializeTokenValue(itemValue.value || itemValue);
491
+ if (isTokenReference(valueStr)) {
492
+ if (!refsByPath.has(formattedPath)) {
493
+ refsByPath.set(formattedPath, /* @__PURE__ */ new Set());
494
+ }
495
+ const references = refsByPath.get(formattedPath);
496
+ if (!references) return;
497
+ getReferences(valueStr).forEach((reference) => {
498
+ references.add(reference);
499
+ });
500
+ }
501
+ });
502
+ },
503
+ {
504
+ stop: isValidToken
505
+ }
506
+ );
507
+ tokenPaths.forEach((path2) => {
508
+ const formattedPath = formatPath(path2);
509
+ const value = valueAtPath.get(path2);
510
+ if (path2.includes(" ")) {
511
+ addError("tokens", `Token key must not contain spaces: \`theme.tokens.${formattedPath}\``);
512
+ return;
513
+ }
514
+ if (!isObject(value) && !path2.includes("value")) {
515
+ addError("tokens", `Token must contain 'value': \`theme.semanticTokens.${formattedPath}\``);
516
+ }
517
+ });
518
+ }
519
+ validateTokenReferences({ valueAtPath, refsByPath, addError, typeByPath });
520
+ };
521
+
522
+ // src/validate-config.ts
523
+ var validateConfig = (config) => {
524
+ if (config.validation === "none") return;
525
+ const warnings = /* @__PURE__ */ new Set();
526
+ const addError = (scope, message) => {
527
+ warnings.add(`[${scope}] ` + message);
528
+ };
529
+ validateBreakpoints(config.theme?.breakpoints, addError);
530
+ validateConditions(config.conditions, addError);
531
+ const artifacts = {
532
+ recipes: /* @__PURE__ */ new Set(),
533
+ slotRecipes: /* @__PURE__ */ new Set(),
534
+ patterns: /* @__PURE__ */ new Set()
535
+ };
536
+ const tokens = {
537
+ tokenNames: /* @__PURE__ */ new Set(),
538
+ semanticTokenNames: /* @__PURE__ */ new Set(),
539
+ valueAtPath: /* @__PURE__ */ new Map(),
540
+ refsByPath: /* @__PURE__ */ new Map(),
541
+ typeByPath: /* @__PURE__ */ new Map()
542
+ };
543
+ if (config.theme) {
544
+ validateTokens({ config, tokens, addError });
545
+ validateRecipes({ config, tokens, artifacts, addError });
546
+ }
547
+ validatePatterns(config.patterns, artifacts);
548
+ validateArtifactNames(artifacts, addError);
549
+ if (warnings.size) {
550
+ const errors = `\u26A0\uFE0F Invalid config:
551
+ ${Array.from(warnings).map((err) => "- " + err).join("\n")}
552
+ `;
553
+ if (config.validation === "error") {
554
+ throw new BambooError3("CONFIG_ERROR", errors);
555
+ }
556
+ logger2.warn("config", errors);
557
+ return warnings;
558
+ }
559
+ };
560
+
561
+ // src/resolve-config.ts
562
+ var hookUtils2 = {
563
+ omit: omit2,
564
+ pick: pick2,
565
+ traverse: traverse2
566
+ };
567
+ async function resolveConfig(result, cwd) {
568
+ const presets = /* @__PURE__ */ new Set();
569
+ if (!result.config.eject) {
570
+ presets.add(presetBase);
571
+ }
572
+ if (result.config.presets) {
573
+ result.config.presets.forEach((preset) => {
574
+ presets.add(getBundledPreset(preset) ?? preset);
575
+ });
576
+ } else if (!result.config.eject) {
577
+ presets.add(presetBamboo);
578
+ }
579
+ result.config.presets = Array.from(presets);
580
+ const userConfig = result.config;
581
+ const pluginHooks = userConfig.plugins ?? [];
582
+ if (userConfig.hooks) {
583
+ pluginHooks.push({ name: BAMBOO_CONFIG_NAME, hooks: userConfig.hooks });
584
+ }
585
+ const earlyHooks = mergeHooks(pluginHooks);
586
+ const mergedConfig = await getResolvedConfig(result.config, cwd, earlyHooks);
587
+ const hooks = mergedConfig.hooks ?? {};
588
+ if (mergedConfig.logLevel) {
589
+ logger3.level = mergedConfig.logLevel;
590
+ }
591
+ validateConfig(mergedConfig);
592
+ const loadConfigResult = {
593
+ ...result,
594
+ config: mergedConfig
595
+ };
596
+ if (hooks["config:resolved"]) {
597
+ const result2 = await hooks["config:resolved"]({
598
+ config: loadConfigResult.config,
599
+ path: loadConfigResult.path,
600
+ dependencies: loadConfigResult.dependencies,
601
+ utils: hookUtils2
602
+ });
603
+ if (result2) {
604
+ loadConfigResult.config = result2;
605
+ }
606
+ }
607
+ const serialized = stringifyJson(
608
+ Object.assign({}, loadConfigResult.config, { name: BAMBOO_CONFIG_NAME, presets: [] })
609
+ );
610
+ const deserialize = () => parseJson(serialized);
611
+ return { ...loadConfigResult, serialized, deserialize, hooks };
612
+ }
613
+
614
+ // src/load-config.ts
615
+ async function loadConfig(options) {
616
+ const result = await bundleConfig(options);
617
+ return resolveConfig(result, options.cwd);
618
+ }
619
+ export {
620
+ bundleConfig,
621
+ convertTsPathsToRegexes,
622
+ diffConfigs,
623
+ findConfig,
624
+ getConfigDependencies,
625
+ getResolvedConfig,
626
+ loadConfig,
627
+ mergeConfigs,
628
+ mergeHooks,
629
+ resolveConfig
630
+ };