@kimesh/kit 0.2.6 → 0.2.7-nightly.20260124083945

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 CHANGED
@@ -8,7 +8,8 @@ import consola from "consola";
8
8
  import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
9
9
  import { dirname, isAbsolute, join, resolve } from "node:path";
10
10
  import fg from "fast-glob";
11
- import { basename, extname, isAbsolute as isAbsolute$1, join as join$1, relative, resolve as resolve$1 } from "pathe";
11
+ import { basename, dirname as dirname$1, extname, isAbsolute as isAbsolute$1, join as join$1, relative, resolve as resolve$1 } from "pathe";
12
+ import { resolveModulePath } from "exsolve";
12
13
  import ignore from "ignore";
13
14
  import pc from "picocolors";
14
15
  import { defu } from "defu";
@@ -97,18 +98,18 @@ function hasConfigPath(config, keys) {
97
98
  function getPossiblePaths(envKey) {
98
99
  const parts = envKey.toLowerCase().split("_");
99
100
  const paths = [];
100
- function generateGroupings(parts$1, current, start) {
101
- if (start >= parts$1.length) {
101
+ function generateGroupings(parts, current, start) {
102
+ if (start >= parts.length) {
102
103
  paths.push([...current]);
103
104
  return;
104
105
  }
105
- for (let end = start + 1; end <= parts$1.length; end++) {
106
- const segment = parts$1.slice(start, end).reduce((acc, part, i) => {
106
+ for (let end = start + 1; end <= parts.length; end++) {
107
+ const segment = parts.slice(start, end).reduce((acc, part, i) => {
107
108
  if (i === 0) return part;
108
109
  return acc + part.charAt(0).toUpperCase() + part.slice(1);
109
110
  }, "");
110
111
  current.push(segment);
111
- generateGroupings(parts$1, current, end);
112
+ generateGroupings(parts, current, end);
112
113
  current.pop();
113
114
  }
114
115
  }
@@ -949,11 +950,11 @@ function buildPluginGlobPattern(extensions) {
949
950
  async function scanPluginsDir(pluginsDir, options = {}) {
950
951
  if (!existsSync(pluginsDir)) return [];
951
952
  const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
952
- const ignore$1 = options.ignore ?? DEFAULT_IGNORE;
953
+ const ignore = options.ignore ?? DEFAULT_IGNORE;
953
954
  return (await fg(buildPluginGlobPattern(extensions), {
954
955
  cwd: pluginsDir,
955
956
  onlyFiles: true,
956
- ignore: ignore$1,
957
+ ignore,
957
958
  absolute: false
958
959
  })).map((file) => {
959
960
  const { name, order } = parsePluginFilename(file);
@@ -1031,7 +1032,7 @@ function generatePluginsTemplate(options) {
1031
1032
  imports.push("// Module-registered plugins");
1032
1033
  for (const plugin of pluginsWithSrc) {
1033
1034
  const varName = toVariableName(plugin.name || "module", index);
1034
- const importPath = plugin.src.startsWith("@") || plugin.src.startsWith(".") ? plugin.src : relative(buildDir, plugin.src).replace(/\.ts$/, "");
1035
+ const importPath = plugin.src.startsWith("@") || plugin.src.startsWith(".") || plugin.src.startsWith("#") || plugin.src.startsWith("kimesh/") ? plugin.src : relative(buildDir, plugin.src).replace(/\.ts$/, "");
1035
1036
  imports.push(`import ${varName} from '${importPath}'`);
1036
1037
  pluginVars.push(varName);
1037
1038
  index++;
@@ -1077,6 +1078,121 @@ function addPluginsTemplate(kimesh, discoveredPlugins) {
1077
1078
  });
1078
1079
  }
1079
1080
 
1081
+ //#endregion
1082
+ //#region src/kit/internal-alias-template.ts
1083
+ /**
1084
+ * Internal Alias Template Generator
1085
+ *
1086
+ * Generates wrapper templates for internal aliases (prefixed with #).
1087
+ * These templates re-export the actual package using **resolved absolute paths**,
1088
+ * which works correctly across all environments:
1089
+ * - Normal npm/pnpm/yarn/bun installs
1090
+ * - Workspace development with link:kimesh
1091
+ * - PR preview packages
1092
+ *
1093
+ * The key insight is that @kimesh/kit can resolve @kimesh/* packages because
1094
+ * they're peer dependencies. We resolve the paths at build time and generate
1095
+ * templates with absolute paths, avoiding the transitive dependency resolution
1096
+ * problem in pnpm's strict mode.
1097
+ *
1098
+ * @module internal-alias-template
1099
+ */
1100
+ /**
1101
+ * Internal aliases that should be resolved via generated templates.
1102
+ *
1103
+ * Each entry maps an internal alias (#kimesh/...) to the actual internal
1104
+ * package subpath export (@kimesh/...) that should be resolved and re-exported.
1105
+ */
1106
+ const INTERNAL_ALIASES = [{
1107
+ alias: "#kimesh/head/plugin",
1108
+ packageSpecifier: "@kimesh/head/plugin",
1109
+ filename: "head-plugin.mjs"
1110
+ }, {
1111
+ alias: "#kimesh/router-runtime/default-app",
1112
+ packageSpecifier: "@kimesh/router-runtime/default-app",
1113
+ filename: "router-runtime-default-app.mjs"
1114
+ }];
1115
+ /**
1116
+ * Resolve a package specifier to an absolute file path.
1117
+ * This uses exsolve/createRequire to find the package from @kimesh/kit's location.
1118
+ *
1119
+ * @param specifier - Package specifier like '@kimesh/head/plugin'
1120
+ * @returns Resolved absolute path or null if not found
1121
+ */
1122
+ function resolvePackagePath(specifier) {
1123
+ const fromUrl = import.meta.url;
1124
+ try {
1125
+ return resolveModulePath(specifier, {
1126
+ from: fromUrl,
1127
+ try: true
1128
+ }) || null;
1129
+ } catch {
1130
+ try {
1131
+ return createRequire(fromUrl).resolve(specifier);
1132
+ } catch {
1133
+ return null;
1134
+ }
1135
+ }
1136
+ }
1137
+ /**
1138
+ * Generate the content for an internal alias template file.
1139
+ *
1140
+ * The generated file re-exports everything from the **resolved absolute path**,
1141
+ * not from a package specifier. This ensures the import works correctly even
1142
+ * when the package is a transitive dependency that can't be directly resolved
1143
+ * from the host app.
1144
+ *
1145
+ * @param config - The internal alias configuration
1146
+ * @param resolvedPath - The resolved absolute path to the module
1147
+ * @returns Generated template content
1148
+ */
1149
+ function generateInternalAliasTemplate(config, resolvedPath) {
1150
+ return `/**
1151
+ * Kimesh Internal Alias - ${config.alias}
1152
+ * Auto-generated wrapper for ${config.packageSpecifier}
1153
+ * Resolved to: ${resolvedPath}
1154
+ * DO NOT EDIT - This file is regenerated by Kimesh
1155
+ */
1156
+
1157
+ export * from '${resolvedPath}'
1158
+ export { default } from '${resolvedPath}'
1159
+ `;
1160
+ }
1161
+ /**
1162
+ * Register internal alias templates with the Kimesh context.
1163
+ *
1164
+ * This function resolves the actual paths to @kimesh/* packages at build time
1165
+ * and generates templates that use those absolute paths. This ensures the
1166
+ * imports work correctly across all environments including PR preview packages.
1167
+ *
1168
+ * @param kimesh - The Kimesh context
1169
+ */
1170
+ function addInternalAliasTemplates(kimesh) {
1171
+ for (const config of INTERNAL_ALIASES) {
1172
+ const resolvedPath = resolvePackagePath(config.packageSpecifier);
1173
+ if (resolvedPath) kimesh._registries.templates.push({
1174
+ filename: config.filename,
1175
+ getContents: () => generateInternalAliasTemplate(config, resolvedPath)
1176
+ });
1177
+ else console.warn(`[Kimesh] Could not resolve internal alias ${config.alias} (${config.packageSpecifier})`);
1178
+ }
1179
+ }
1180
+ /**
1181
+ * Build a map of internal alias to generated template file path.
1182
+ *
1183
+ * This is used to configure Vite's resolve.alias so that imports
1184
+ * like '#kimesh/head/plugin' are resolved to the generated template
1185
+ * file in .kimesh/.
1186
+ *
1187
+ * @param buildDir - The .kimesh build directory path
1188
+ * @returns Record mapping alias to generated file path
1189
+ */
1190
+ function buildInternalAliasMap(buildDir) {
1191
+ const aliases = {};
1192
+ for (const config of INTERNAL_ALIASES) aliases[config.alias] = `${buildDir}/${config.filename}`;
1193
+ return aliases;
1194
+ }
1195
+
1080
1196
  //#endregion
1081
1197
  //#region src/types/config.ts
1082
1198
  /**
@@ -1178,9 +1294,9 @@ function toTsConfigPaths(aliases, rootDir) {
1178
1294
  * @param debug - Debug config from KimeshConfig (boolean or DebugConfig)
1179
1295
  * @returns Normalized DebugConfig
1180
1296
  */
1181
- function normalizeDebugConfig(debug$1) {
1182
- if (!debug$1) return {};
1183
- if (debug$1 === true) return {
1297
+ function normalizeDebugConfig(debug) {
1298
+ if (!debug) return {};
1299
+ if (debug === true) return {
1184
1300
  hooks: true,
1185
1301
  modules: true,
1186
1302
  layers: true,
@@ -1189,7 +1305,7 @@ function normalizeDebugConfig(debug$1) {
1189
1305
  routes: true,
1190
1306
  imports: true
1191
1307
  };
1192
- return debug$1;
1308
+ return debug;
1193
1309
  }
1194
1310
  /**
1195
1311
  * Check if a specific debug option is enabled
@@ -1198,10 +1314,10 @@ function normalizeDebugConfig(debug$1) {
1198
1314
  * @param option - Debug option to check
1199
1315
  * @returns Whether the option is enabled
1200
1316
  */
1201
- function isDebugEnabled(debug$1, option) {
1202
- if (!debug$1) return false;
1203
- if (debug$1 === true) return true;
1204
- return !!debug$1[option];
1317
+ function isDebugEnabled(debug, option) {
1318
+ if (!debug) return false;
1319
+ if (debug === true) return true;
1320
+ return !!debug[option];
1205
1321
  }
1206
1322
 
1207
1323
  //#endregion
@@ -1288,7 +1404,7 @@ function matchRoutePattern(pattern, routePath) {
1288
1404
  const normalizedPattern = pattern.replace(/\/+/g, "/").replace(/\/$/, "");
1289
1405
  const normalizedPath = routePath.replace(/\/+/g, "/").replace(/\/$/, "");
1290
1406
  let regexPattern = normalizedPattern.replace(/\/\*\*/g, "___DOUBLE_WILDCARD___").replace(/\*/g, "___SINGLE_WILDCARD___").replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/___DOUBLE_WILDCARD___/g, "(?:/.*)?").replace(/___SINGLE_WILDCARD___/g, "[^/]+");
1291
- return (/* @__PURE__ */ new RegExp(`^${regexPattern}$`)).test(normalizedPath);
1407
+ return new RegExp(`^${regexPattern}$`).test(normalizedPath);
1292
1408
  }
1293
1409
  /**
1294
1410
  * Find matching route rules for a given path
@@ -1579,6 +1695,46 @@ function writeTsConfig(options) {
1579
1695
  mkdirSync(buildDir, { recursive: true });
1580
1696
  const tsconfig = generateTsConfig(options);
1581
1697
  writeFileSync(join$1(buildDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2), "utf-8");
1698
+ writeFileSync(join$1(buildDir, "kimesh.d.ts"), generateKimeshDts(), "utf-8");
1699
+ }
1700
+ /**
1701
+ * Generate kimesh.d.ts content with global type declarations
1702
+ *
1703
+ * This file directly declares global types instead of using triple-slash references,
1704
+ * ensuring compatibility with various package manager setups (npm, pnpm, bun, workspace links).
1705
+ */
1706
+ function generateKimeshDts() {
1707
+ return `/* eslint-disable */
1708
+ /* prettier-ignore */
1709
+
1710
+ /**
1711
+ * Kimesh Framework Type Declarations
1712
+ *
1713
+ * This file provides global type declarations for the Kimesh framework.
1714
+ *
1715
+ * DO NOT EDIT - This file is auto-generated by Kimesh.
1716
+ */
1717
+
1718
+ export {}
1719
+
1720
+ declare global {
1721
+ /**
1722
+ * Define Kimesh configuration with type inference.
1723
+ * This function is available globally in kimesh.config.ts files.
1724
+ *
1725
+ * @example
1726
+ * \`\`\`ts
1727
+ * export default defineKmConfig({
1728
+ * name: 'my-app',
1729
+ * dev: {
1730
+ * port: 3000,
1731
+ * },
1732
+ * })
1733
+ * \`\`\`
1734
+ */
1735
+ const defineKmConfig: <T extends Record<string, unknown>>(config: T) => T
1736
+ }
1737
+ `;
1582
1738
  }
1583
1739
 
1584
1740
  //#endregion
@@ -1784,17 +1940,17 @@ function toViteWatchOptions(config) {
1784
1940
  * Generate the entry point code for a Kimesh app
1785
1941
  */
1786
1942
  function generateEntryCode(options) {
1787
- const { hasContext, hasPlugins: hasPlugins$1 } = options;
1943
+ const { hasContext, hasPlugins } = options;
1788
1944
  const imports = [
1789
1945
  `import { createKimeshApp } from '@kimesh/router-runtime'`,
1790
1946
  `import { routes } from '#kimesh/routes'`,
1791
1947
  `import App from '#kimesh/app'`
1792
1948
  ];
1793
1949
  if (hasContext) imports.push(`import createContext from '#kimesh/context'`);
1794
- if (hasPlugins$1) imports.push(`import { plugins } from '#kimesh/plugins'`);
1950
+ if (hasPlugins) imports.push(`import { plugins } from '#kimesh/plugins'`);
1795
1951
  const optionLines = [` runtimeConfig: __KIMESH_CONFIG__,`, ` layersConfig: __KIMESH_LAYERS_CONFIG__,`];
1796
1952
  if (hasContext) optionLines.push(` context: createContext(),`);
1797
- if (hasPlugins$1) optionLines.push(` plugins,`);
1953
+ if (hasPlugins) optionLines.push(` plugins,`);
1798
1954
  const optionsBlock = `\n${optionLines.join("\n")}`;
1799
1955
  return `${imports.join("\n")}
1800
1956
 
@@ -1877,9 +2033,9 @@ function generateHtml(title) {
1877
2033
  * Create HMR watcher for Kimesh layers
1878
2034
  */
1879
2035
  function createHMRWatcher(options) {
1880
- const { server, layers, debug: debug$1 } = options;
2036
+ const { server, layers, debug } = options;
1881
2037
  const log = (...args) => {
1882
- if (debug$1) consola.debug("[kimesh:hmr]", ...args);
2038
+ if (debug) consola.debug("[kimesh:hmr]", ...args);
1883
2039
  };
1884
2040
  /**
1885
2041
  * Detect which layer a file belongs to
@@ -2132,11 +2288,11 @@ function formatTiming(operation, timeMs, details) {
2132
2288
  /**
2133
2289
  * Create a timing logger
2134
2290
  */
2135
- function createTimer(operation, debug$1 = false) {
2291
+ function createTimer(operation, debug = false) {
2136
2292
  const start = performance.now();
2137
2293
  return { end(details) {
2138
2294
  const elapsed = performance.now() - start;
2139
- if (debug$1) console.log(formatTiming(operation, elapsed, details));
2295
+ if (debug) console.log(formatTiming(operation, elapsed, details));
2140
2296
  return elapsed;
2141
2297
  } };
2142
2298
  }
@@ -2163,12 +2319,233 @@ function findWorkspaceRoot(startDir) {
2163
2319
  return startDir;
2164
2320
  }
2165
2321
  /**
2322
+ * Try to resolve a package or subpath export using exsolve.
2323
+ * This handles various package manager layouts (npm, pnpm, bun, yarn)
2324
+ * and properly resolves subpath exports like "@kimesh/head/plugin"
2325
+ *
2326
+ * @param specifier - Full package specifier (e.g., "@kimesh/head" or "@kimesh/head/plugin")
2327
+ * @param fromDir - Directory to resolve from
2328
+ * @returns Resolved file path or null if not found
2329
+ */
2330
+ function tryResolveModule(specifier, fromUrl) {
2331
+ try {
2332
+ return resolveModulePath(specifier, {
2333
+ from: fromUrl,
2334
+ try: true
2335
+ }) || null;
2336
+ } catch {
2337
+ try {
2338
+ return createRequire(fromUrl).resolve(specifier);
2339
+ } catch {
2340
+ return null;
2341
+ }
2342
+ }
2343
+ }
2344
+ /**
2345
+ * Try to resolve a package directory (not a specific file).
2346
+ * Used for aliasing the base package.
2347
+ */
2348
+ function tryResolvePackage(packageName, fromUrl) {
2349
+ try {
2350
+ const resolved = resolveModulePath(packageName, {
2351
+ from: fromUrl,
2352
+ try: true
2353
+ });
2354
+ if (resolved) {
2355
+ const parts = resolved.split("/");
2356
+ const nodeModulesIndex = parts.lastIndexOf("node_modules");
2357
+ if (nodeModulesIndex !== -1) {
2358
+ const pkgPathLength = packageName.split("/")[0].startsWith("@") ? 2 : 1;
2359
+ return parts.slice(0, nodeModulesIndex + 1 + pkgPathLength).join("/");
2360
+ }
2361
+ return dirname$1(dirname$1(resolved));
2362
+ }
2363
+ } catch {}
2364
+ return null;
2365
+ }
2366
+ /**
2367
+ * Find the kimesh packages location.
2368
+ * This handles both installed packages (in node_modules) and workspace development.
2369
+ *
2370
+ * The search strategy:
2371
+ * 1. Check if we're in a workspace development setup (kimesh/packages/*)
2372
+ * 2. From @kimesh/kit's location, traverse up to find the parent "kimesh" package
2373
+ * 3. In pnpm/bun workspace: kit -> ../kimesh/node_modules
2374
+ * 4. In npm flat layout: kit is in node_modules/@kimesh/kit, umbrella is in node_modules/kimesh
2375
+ */
2376
+ function findKimeshPackagesLocation(kitPath, debug) {
2377
+ const kitDir = dirname$1(dirname$1(kitPath.replace(/^file:\/\//, "")));
2378
+ consola.debug(`[Kimesh] kitPath: ${kitPath}`);
2379
+ consola.debug(`[Kimesh] kitDir (after 2x dirname): ${kitDir}`);
2380
+ const packagesDir = dirname$1(kitDir);
2381
+ const headSibling = resolve$1(packagesDir, "head");
2382
+ const routerRuntimeSibling = resolve$1(packagesDir, "router-runtime");
2383
+ consola.debug(`[Kimesh] packagesDir: ${packagesDir}`);
2384
+ consola.debug(`[Kimesh] headSibling: ${headSibling}, exists: ${existsSync(headSibling)}`);
2385
+ consola.debug(`[Kimesh] routerRuntimeSibling: ${routerRuntimeSibling}, exists: ${existsSync(routerRuntimeSibling)}`);
2386
+ if (existsSync(headSibling) && existsSync(routerRuntimeSibling)) {
2387
+ const headPkgPath = join$1(headSibling, "package.json");
2388
+ const routerPkgPath = join$1(routerRuntimeSibling, "package.json");
2389
+ consola.debug(`[Kimesh] headPkgPath: ${headPkgPath}, exists: ${existsSync(headPkgPath)}`);
2390
+ consola.debug(`[Kimesh] routerPkgPath: ${routerPkgPath}, exists: ${existsSync(routerPkgPath)}`);
2391
+ if (existsSync(headPkgPath) && existsSync(routerPkgPath)) try {
2392
+ const headPkg = JSON.parse(readFileSync(headPkgPath, "utf-8"));
2393
+ const routerPkg = JSON.parse(readFileSync(routerPkgPath, "utf-8"));
2394
+ consola.debug(`[Kimesh] headPkg.name: ${headPkg.name}`);
2395
+ consola.debug(`[Kimesh] routerPkg.name: ${routerPkg.name}`);
2396
+ if (headPkg.name === "@kimesh/head" && routerPkg.name === "@kimesh/router-runtime") {
2397
+ consola.debug(`[Kimesh] Found workspace development (sibling packages): ${packagesDir}`);
2398
+ return {
2399
+ type: "workspace-packages",
2400
+ path: packagesDir
2401
+ };
2402
+ }
2403
+ } catch (e) {
2404
+ consola.warn(`[Kimesh] Error reading package.json: ${e}`);
2405
+ }
2406
+ }
2407
+ const workspaceUmbrella = resolve$1(kitDir, "..", "kimesh", "node_modules");
2408
+ if (existsSync(join$1(workspaceUmbrella, "@kimesh"))) {
2409
+ if (debug) consola.info(`[Kimesh] Found umbrella node_modules (workspace): ${workspaceUmbrella}`);
2410
+ return {
2411
+ type: "node_modules",
2412
+ path: workspaceUmbrella
2413
+ };
2414
+ }
2415
+ const parts = kitDir.split("/");
2416
+ const nmIndex = parts.lastIndexOf("node_modules");
2417
+ if (nmIndex !== -1) {
2418
+ const parentNodeModules = parts.slice(0, nmIndex + 1).join("/");
2419
+ if (existsSync(join$1(parentNodeModules, "@kimesh", "router-runtime"))) {
2420
+ if (debug) consola.info(`[Kimesh] Found umbrella node_modules (installed): ${parentNodeModules}`);
2421
+ return {
2422
+ type: "node_modules",
2423
+ path: parentNodeModules
2424
+ };
2425
+ }
2426
+ }
2427
+ if (debug) consola.warn(`[Kimesh] Could not find kimesh packages location from: ${kitDir}`);
2428
+ return null;
2429
+ }
2430
+ /**
2431
+ * Map from @kimesh/* package name to the directory name in kimesh/packages/
2432
+ * Most follow the pattern @kimesh/{name} -> {name}, but some differ
2433
+ */
2434
+ const PACKAGE_DIR_MAP = {
2435
+ "@kimesh/router-runtime": "router-runtime",
2436
+ "@kimesh/head": "head",
2437
+ "@kimesh/query": "query",
2438
+ "@kimesh/kit": "kit",
2439
+ "@kimesh/layers": "layers",
2440
+ "@kimesh/auto-import": "auto-import",
2441
+ "@kimesh/router-generator": "router-generator"
2442
+ };
2443
+ /**
2444
+ * Map subpath exports to their actual dist file paths
2445
+ *
2446
+ * This map is used for workspace development (link:kimesh) where we need to
2447
+ * resolve subpath exports directly to dist files since symlinked packages
2448
+ * don't resolve subpath exports correctly via Vite's alias system.
2449
+ *
2450
+ * NOTE: We now prefer using `kimesh/head/plugin` (umbrella package subpath)
2451
+ * over `@kimesh/head/plugin` (direct internal package) because the umbrella
2452
+ * package re-exports work correctly in PR preview packages and all setups.
2453
+ */
2454
+ const SUBPATH_EXPORT_MAP = {
2455
+ "@kimesh/head/plugin": {
2456
+ pkg: "head",
2457
+ file: "dist/plugin.mjs"
2458
+ },
2459
+ "@kimesh/router-runtime/default-app": {
2460
+ pkg: "router-runtime",
2461
+ file: "dist/default-app.mjs"
2462
+ },
2463
+ "kimesh/head/plugin": {
2464
+ pkg: "head",
2465
+ file: "dist/plugin.mjs"
2466
+ },
2467
+ "kimesh/router-runtime/default-app": {
2468
+ pkg: "router-runtime",
2469
+ file: "dist/default-app.mjs"
2470
+ }
2471
+ };
2472
+ /**
2473
+ * Build aliases for @kimesh/* packages and their subpath exports.
2474
+ * This ensures Vite can resolve these packages regardless of package manager.
2475
+ *
2476
+ * KEY INSIGHT: We find the "kimesh" umbrella package's node_modules, then
2477
+ * resolve all @kimesh/* packages from there. This works because:
2478
+ * 1. User's project depends on the umbrella "kimesh" package
2479
+ * 2. The umbrella package has @kimesh/kit, @kimesh/head, etc. as dependencies
2480
+ * 3. Those dependencies are installed in the umbrella's node_modules
2481
+ *
2482
+ * For workspace development (link:kimesh), we directly resolve from sibling packages.
2483
+ *
2484
+ * Unlike simple package aliases, this also handles subpath exports like:
2485
+ * - "@kimesh/head/plugin" -> actual file path
2486
+ * - "@kimesh/router-runtime/default-app" -> actual file path
2487
+ */
2488
+ function buildKimeshPackageAliases(_rootDir, debug) {
2489
+ const kitUrl = import.meta.url;
2490
+ const location = findKimeshPackagesLocation(kitUrl, debug);
2491
+ if (debug) consola.debug(`[Kimesh] Package location detected: type=${location?.type}, path=${location?.path}`);
2492
+ const aliases = {};
2493
+ const packages = Object.keys(PACKAGE_DIR_MAP);
2494
+ const subpathExports = Object.keys(SUBPATH_EXPORT_MAP);
2495
+ if (location?.type === "workspace-packages") {
2496
+ if (debug) consola.info(`[Kimesh] Resolving packages from workspace: ${location.path}`);
2497
+ for (const pkg of packages) {
2498
+ const dirName = PACKAGE_DIR_MAP[pkg];
2499
+ const pkgDir = join$1(location.path, dirName);
2500
+ if (existsSync(pkgDir)) {
2501
+ aliases[pkg] = pkgDir;
2502
+ if (debug) consola.debug(`[Kimesh] Resolved ${pkg} -> ${pkgDir}`);
2503
+ } else if (debug) consola.warn(`[Kimesh] Could not find workspace package: ${pkgDir}`);
2504
+ }
2505
+ for (const specifier of subpathExports) {
2506
+ const mapping = SUBPATH_EXPORT_MAP[specifier];
2507
+ const filePath = join$1(location.path, mapping.pkg, mapping.file);
2508
+ if (existsSync(filePath)) {
2509
+ aliases[specifier] = filePath;
2510
+ if (debug) consola.debug(`[Kimesh] Resolved subpath ${specifier} -> ${filePath}`);
2511
+ } else if (debug) consola.warn(`[Kimesh] Could not find workspace subpath: ${filePath}`);
2512
+ }
2513
+ if (debug) {
2514
+ consola.debug(`[Kimesh] Generated ${Object.keys(aliases).length} workspace aliases`);
2515
+ for (const [key, value] of Object.entries(aliases)) consola.debug(`[Kimesh] ${key} -> ${value}`);
2516
+ }
2517
+ return aliases;
2518
+ }
2519
+ let fromUrl;
2520
+ if (location?.type === "node_modules") fromUrl = "file://" + join$1(location.path, "package.json");
2521
+ else {
2522
+ fromUrl = kitUrl;
2523
+ if (debug) consola.warn(`[Kimesh] Falling back to kit location for package resolution`);
2524
+ }
2525
+ if (debug) consola.info(`[Kimesh] Resolving @kimesh/* packages from: ${fromUrl}`);
2526
+ for (const pkg of packages) {
2527
+ const resolved = tryResolvePackage(pkg, fromUrl);
2528
+ if (resolved) {
2529
+ aliases[pkg] = resolved;
2530
+ if (debug) consola.debug(`[Kimesh] Resolved ${pkg} -> ${resolved}`);
2531
+ } else if (debug) consola.warn(`[Kimesh] Could not resolve ${pkg}`);
2532
+ }
2533
+ for (const specifier of subpathExports) {
2534
+ const resolved = tryResolveModule(specifier, fromUrl);
2535
+ if (resolved) {
2536
+ aliases[specifier] = resolved;
2537
+ if (debug) consola.debug(`[Kimesh] Resolved subpath ${specifier} -> ${resolved}`);
2538
+ } else if (debug) consola.warn(`[Kimesh] Could not resolve subpath ${specifier}`);
2539
+ }
2540
+ return aliases;
2541
+ }
2542
+ /**
2166
2543
  * Process all configured modules using the new v2 system
2167
2544
  */
2168
- async function processModules(kimesh, debug$1) {
2545
+ async function processModules(kimesh, debug) {
2169
2546
  const modules = kimesh.options.config.modules;
2170
2547
  if (!modules || modules.length === 0) return;
2171
- const moduleTimer = createTimer("Module processing", debug$1);
2548
+ const moduleTimer = createTimer("Module processing", debug);
2172
2549
  try {
2173
2550
  await executeModules(modules, kimesh);
2174
2551
  moduleTimer.end({ count: modules.length });
@@ -2215,7 +2592,7 @@ ${imports}
2215
2592
  */
2216
2593
  function kimeshPlugin(options = {}) {
2217
2594
  const config = options.config || {};
2218
- const debug$1 = options.debug ?? false;
2595
+ const debug = options.debug ?? false;
2219
2596
  const { plugins: userPlugins = [], ...userViteOptions } = config.vite || {};
2220
2597
  const allUserPlugins = [...userPlugins, ...options.additionalPlugins || []];
2221
2598
  const state = {
@@ -2229,9 +2606,21 @@ function kimeshPlugin(options = {}) {
2229
2606
  enabled: options.layers?.enabled ?? config.layers?.enabled ?? "all",
2230
2607
  excluded: options.layers?.excluded ?? config.layers?.excluded ?? []
2231
2608
  };
2609
+ let kimeshPackagesPath = null;
2232
2610
  const mainPlugin = {
2233
2611
  name: "kimesh:main",
2234
2612
  enforce: "pre",
2613
+ resolveId(id) {
2614
+ if (kimeshPackagesPath && SUBPATH_EXPORT_MAP[id]) {
2615
+ const mapping = SUBPATH_EXPORT_MAP[id];
2616
+ const filePath = join$1(kimeshPackagesPath, mapping.pkg, mapping.file);
2617
+ if (existsSync(filePath)) {
2618
+ consola.debug(`[Kimesh:resolveId] Resolved ${id} -> ${filePath}`);
2619
+ return filePath;
2620
+ }
2621
+ }
2622
+ return null;
2623
+ },
2235
2624
  async config(viteConfig, { command, mode }) {
2236
2625
  consola.debug(`[Kimesh] Configuring for ${command} mode`);
2237
2626
  const configRoot = viteConfig.root || process.cwd();
@@ -2241,28 +2630,38 @@ function kimeshPlugin(options = {}) {
2241
2630
  const resolvedBuildConfig = resolveBuildConfig(config.build);
2242
2631
  const resolvedDevConfig = resolveDevConfig(config.dev);
2243
2632
  const resolvedWatchConfig = resolveWatchConfig(config.watch, config.watchers);
2244
- if (debug$1) {
2633
+ if (debug) {
2245
2634
  consola.info(`[Kimesh] Resolved directories:`);
2246
2635
  consola.info(` - srcDir: ${resolvedDirs.srcDir}`);
2247
2636
  consola.info(` - buildDir: ${resolvedDirs.buildDir}`);
2248
2637
  consola.info(` - pluginsDir: ${resolvedDirs.pluginsDir}`);
2249
2638
  }
2250
2639
  const envVars = loadEnv(mode, configRoot, "KIMESH_");
2251
- const layerTimer = createTimer("Layer resolution", debug$1);
2640
+ const layerTimer = createTimer("Layer resolution", debug);
2252
2641
  try {
2253
2642
  state.resolvedLayers = await prepareLayers$1(configRoot, {
2254
2643
  enabled: layersConfig.enabled,
2255
2644
  excluded: layersConfig.excluded
2256
2645
  });
2257
2646
  layerTimer.end({ count: state.resolvedLayers.length });
2258
- if (debug$1 || state.resolvedLayers.length > 1) {
2259
- consola.info(`[Kimesh] Resolved ${state.resolvedLayers.length} layers:`);
2260
- for (const layer of state.resolvedLayers) consola.info(` - ${layer.name} (priority: ${layer.priority}, path: ${layer.path})`);
2647
+ if (state.resolvedLayers.length > 1) {
2648
+ const layerNames = state.resolvedLayers.map((l) => l.name).join(", ");
2649
+ consola.info(`Layers: ${layerNames}`);
2650
+ }
2651
+ if (debug) {
2652
+ consola.debug(`[Kimesh] Resolved ${state.resolvedLayers.length} layers:`);
2653
+ for (const layer of state.resolvedLayers) consola.debug(` - ${layer.name} (priority: ${layer.priority}, path: ${layer.path})`);
2261
2654
  }
2262
2655
  } catch (error) {
2263
2656
  layerTimer.end({ error: true });
2264
2657
  consola.warn(`[Kimesh] Layer resolution failed: ${error}`);
2265
- state.resolvedLayers = [];
2658
+ state.resolvedLayers = [{
2659
+ name: "app",
2660
+ path: configRoot,
2661
+ priority: 0,
2662
+ isApp: true,
2663
+ config: {}
2664
+ }];
2266
2665
  }
2267
2666
  const layerAliases = generateLayerAliases$1(state.resolvedLayers);
2268
2667
  state.kimesh = createKimesh({
@@ -2272,15 +2671,18 @@ function kimeshPlugin(options = {}) {
2272
2671
  buildDir: state.generatedDir,
2273
2672
  dev: command === "serve"
2274
2673
  });
2275
- await processModules(state.kimesh, debug$1);
2674
+ addInternalAliasTemplates(state.kimesh);
2675
+ await processModules(state.kimesh, debug);
2676
+ const kitUrl = import.meta.url;
2677
+ const packagesLocation = findKimeshPackagesLocation(kitUrl, debug);
2276
2678
  if (config.app?.head) {
2277
- const headPluginSrc = "@kimesh/head/plugin";
2278
- if (!state.kimesh._registries.runtimePlugins.some((p) => p.src === headPluginSrc)) {
2679
+ const headPluginSrc = "#kimesh/head/plugin";
2680
+ if (!state.kimesh._registries.runtimePlugins.some((p) => p.src === headPluginSrc || p.src === "kimesh/head/plugin" || p.src === "@kimesh/head/plugin")) {
2279
2681
  state.kimesh._registries.runtimePlugins.unshift({
2280
2682
  src: headPluginSrc,
2281
2683
  name: "head"
2282
2684
  });
2283
- if (debug$1) consola.info("[Kimesh] Auto-registered @kimesh/head plugin (app.head configured)");
2685
+ if (debug) consola.info(`[Kimesh] Auto-registered head plugin (app.head configured), src: ${headPluginSrc}`);
2284
2686
  }
2285
2687
  }
2286
2688
  let discoveredPlugins = await scanPluginsDir(resolvedDirs.pluginsDir);
@@ -2292,7 +2694,7 @@ function kimeshPlugin(options = {}) {
2292
2694
  state.hasPlugins = discoveredPlugins.length > 0 || hasRegisteredPlugins;
2293
2695
  if (state.hasPlugins) {
2294
2696
  addPluginsTemplate(state.kimesh, discoveredPlugins);
2295
- if (debug$1) {
2697
+ if (debug) {
2296
2698
  consola.info(`[Kimesh] Found ${discoveredPlugins.length} auto-discovered plugins`);
2297
2699
  consola.info(`[Kimesh] Found ${state.kimesh._registries.runtimePlugins.length} module-registered plugins`);
2298
2700
  }
@@ -2300,6 +2702,8 @@ function kimeshPlugin(options = {}) {
2300
2702
  generateModulesTypeDeclaration(config.modules, state.generatedDir);
2301
2703
  await writeTemplates(state.kimesh);
2302
2704
  const userAliases = buildAliases(config, resolvedDirs.srcDir, configRoot);
2705
+ const kimeshPackageAliases = buildKimeshPackageAliases(configRoot, debug);
2706
+ if (packagesLocation?.type === "workspace-packages") kimeshPackagesPath = packagesLocation.path;
2303
2707
  const moduleAliases = {};
2304
2708
  for (const alias of state.kimesh._registries.aliases) if (typeof alias.find === "string") moduleAliases[alias.find] = alias.replacement;
2305
2709
  const appVuePath = resolve$1(resolvedDirs.srcDir, "app.vue");
@@ -2324,7 +2728,7 @@ function kimeshPlugin(options = {}) {
2324
2728
  ],
2325
2729
  exclude: ["../node_modules"]
2326
2730
  });
2327
- if (debug$1) consola.info(`[Kimesh] Generated .kimesh/tsconfig.json with ${Object.keys(userAliases).length} aliases`);
2731
+ if (debug) consola.info(`[Kimesh] Generated .kimesh/tsconfig.json with ${Object.keys(userAliases).length} aliases`);
2328
2732
  const layerDirs = state.resolvedLayers.map((layer) => layer.path);
2329
2733
  const workspaceRoot = findWorkspaceRoot(configRoot);
2330
2734
  const workspacePackages = resolve$1(workspaceRoot, "packages");
@@ -2352,6 +2756,8 @@ function kimeshPlugin(options = {}) {
2352
2756
  __KIMESH_LAYERS_CONFIG__: JSON.stringify(layerConfigMap)
2353
2757
  },
2354
2758
  resolve: { alias: {
2759
+ ...kimeshPackageAliases,
2760
+ ...buildInternalAliasMap(resolvedDirs.buildDir),
2355
2761
  "#kimesh/routes": join$1(resolvedDirs.buildDir, "routes.gen.ts"),
2356
2762
  "#kimesh/app": existsSync(appVuePath) ? appVuePath : "@kimesh/router-runtime/default-app",
2357
2763
  "#kimesh/context": join$1(resolvedDirs.srcDir, "app.context.ts"),
@@ -2370,7 +2776,8 @@ function kimeshPlugin(options = {}) {
2370
2776
  ...layerDirs,
2371
2777
  workspaceRoot,
2372
2778
  workspacePackages,
2373
- nodeModules
2779
+ nodeModules,
2780
+ ...kimeshPackagesPath ? [kimeshPackagesPath] : []
2374
2781
  ] },
2375
2782
  watch: toViteWatchOptions(resolvedWatchConfig)
2376
2783
  },
@@ -2401,19 +2808,40 @@ function kimeshPlugin(options = {}) {
2401
2808
  const contextTypesPath = join$1(state.generatedDir, "context.d.ts");
2402
2809
  writeFileSync(contextTypesPath, generateContextTypes(), "utf-8");
2403
2810
  consola.debug(`[Kimesh] Generated context types: ${contextTypesPath}`);
2404
- for (const layer of state.resolvedLayers) {
2405
- if (layer.isApp) continue;
2406
- let layerRoot = layer.path;
2407
- try {
2408
- layerRoot = realpathSync(layer.path);
2409
- } catch {}
2410
- const layerKimeshDir = join$1(layerRoot, ".kimesh");
2411
- if (!existsSync(layerKimeshDir)) mkdirSync(layerKimeshDir, { recursive: true });
2811
+ }
2812
+ for (const layer of state.resolvedLayers) {
2813
+ if (layer.isApp) continue;
2814
+ let layerRoot = layer.path;
2815
+ try {
2816
+ layerRoot = realpathSync(layer.path);
2817
+ } catch {}
2818
+ const layerKimeshDir = join$1(layerRoot, ".kimesh");
2819
+ if (!existsSync(layerKimeshDir)) mkdirSync(layerKimeshDir, { recursive: true });
2820
+ if (hasContext) {
2412
2821
  const hostContextPath = relative(layerKimeshDir, contextPath).replace(/\.ts$/, "");
2413
2822
  const layerContextTypesPath = join$1(layerKimeshDir, "context.d.ts");
2414
2823
  writeFileSync(layerContextTypesPath, generateLayerContextTypes(hostContextPath), "utf-8");
2415
2824
  consola.debug(`[Kimesh] Generated layer context types: ${layerContextTypesPath}`);
2416
2825
  }
2826
+ const layerTsConfigPath = join$1(layerKimeshDir, "tsconfig.json");
2827
+ writeFileSync(layerTsConfigPath, JSON.stringify({
2828
+ compilerOptions: {
2829
+ target: "ESNext",
2830
+ module: "ESNext",
2831
+ moduleResolution: "bundler",
2832
+ strict: true,
2833
+ jsx: "preserve",
2834
+ sourceMap: true,
2835
+ resolveJsonModule: true,
2836
+ esModuleInterop: true,
2837
+ lib: ["ESNext", "DOM"],
2838
+ skipLibCheck: true,
2839
+ noEmit: true
2840
+ },
2841
+ include: ["../src/**/*", "./**/*"],
2842
+ exclude: ["../node_modules"]
2843
+ }, null, 2), "utf-8");
2844
+ consola.debug(`[Kimesh] Generated layer tsconfig: ${layerTsConfigPath}`);
2417
2845
  }
2418
2846
  const htmlPath = join$1(state.generatedDir, "index.html");
2419
2847
  writeFileSync(htmlPath, generateHtml(config.name || "Kimesh App"), "utf-8");
@@ -2423,7 +2851,7 @@ function kimeshPlugin(options = {}) {
2423
2851
  const hmrWatcher = createHMRWatcher({
2424
2852
  server,
2425
2853
  layers: state.resolvedLayers,
2426
- debug: debug$1
2854
+ debug
2427
2855
  });
2428
2856
  for (const layer of state.resolvedLayers) if (!layer.isApp) {
2429
2857
  server.watcher.add(layer.path);
@@ -2453,7 +2881,7 @@ function kimeshPlugin(options = {}) {
2453
2881
  const routerPlugin = kimeshRouterGenerator({
2454
2882
  routesDir: config.router?.routesDir ?? "routes",
2455
2883
  importMode: config.router?.importMode ?? "async",
2456
- debug: debug$1,
2884
+ debug,
2457
2885
  getLayerRoutes: () => {
2458
2886
  return state.resolvedLayers.filter((l) => !l.isApp).map((layer) => {
2459
2887
  const routesFolder = layer.config.routes?.folder || "routes";
@@ -2500,42 +2928,42 @@ function kimeshPlugin(options = {}) {
2500
2928
  }));
2501
2929
  },
2502
2930
  dts: config.autoImport?.dts !== false ? state.generatedDir || ".kimesh" : false,
2503
- debug: debug$1
2931
+ debug
2504
2932
  }),
2505
2933
  vue(),
2506
2934
  routerPlugin
2507
2935
  ];
2508
2936
  const modulePluginsWrapper = {
2509
2937
  name: "kimesh:module-plugins-wrapper",
2510
- async resolveId(id, importer, options$1) {
2938
+ async resolveId(id, importer, options) {
2511
2939
  const modulePlugins = state.kimesh?._registries.vitePlugins ?? [];
2512
2940
  for (const entry of modulePlugins) {
2513
2941
  const plugin = entry.plugin;
2514
2942
  if (typeof plugin.resolveId === "function") {
2515
- const result = await plugin.resolveId.call(this, id, importer, options$1);
2943
+ const result = await plugin.resolveId.call(this, id, importer, options);
2516
2944
  if (result != null) return result;
2517
2945
  }
2518
2946
  }
2519
2947
  return null;
2520
2948
  },
2521
- async load(id, options$1) {
2949
+ async load(id, options) {
2522
2950
  const modulePlugins = state.kimesh?._registries.vitePlugins ?? [];
2523
2951
  for (const entry of modulePlugins) {
2524
2952
  const plugin = entry.plugin;
2525
2953
  if (typeof plugin.load === "function") {
2526
- const result = await plugin.load.call(this, id, options$1);
2954
+ const result = await plugin.load.call(this, id, options);
2527
2955
  if (result != null) return result;
2528
2956
  }
2529
2957
  }
2530
2958
  return null;
2531
2959
  },
2532
- async transform(code, id, options$1) {
2960
+ async transform(code, id, options) {
2533
2961
  let currentCode = code;
2534
2962
  const modulePlugins = state.kimesh?._registries.vitePlugins ?? [];
2535
2963
  for (const entry of modulePlugins) {
2536
2964
  const plugin = entry.plugin;
2537
2965
  if (typeof plugin.transform === "function") {
2538
- const result = await plugin.transform.call(this, currentCode, id, options$1);
2966
+ const result = await plugin.transform.call(this, currentCode, id, options);
2539
2967
  if (result != null) currentCode = typeof result === "string" ? result : result.code;
2540
2968
  }
2541
2969
  }
@@ -2555,13 +2983,20 @@ function kimeshPlugin(options = {}) {
2555
2983
  * Wrap a function with defineKmConfig injected into globalThis.
2556
2984
  * This allows kimesh.config.ts to use defineKmConfig without explicit import (like Nuxt).
2557
2985
  *
2986
+ * Unlike importing a real function, we use a simple passthrough function here.
2987
+ * This is necessary because c12/jiti evaluates config files in a sandboxed environment
2988
+ * that may not share globalThis with the parent Node.js process.
2989
+ *
2990
+ * Following Nuxt's approach: the function is just a passthrough identity function.
2991
+ * @see https://github.com/nuxt/nuxt/blob/main/packages/kit/src/loader/config.ts
2992
+ *
2558
2993
  * @internal
2559
2994
  */
2560
2995
  async function withDefineKmConfig(fn) {
2561
2996
  const key = "defineKmConfig";
2562
2997
  const globalSelf = globalThis;
2563
2998
  if (!globalSelf[key]) {
2564
- globalSelf[key] = defineKmConfig;
2999
+ globalSelf[key] = (c) => c;
2565
3000
  globalSelf[key].count = 0;
2566
3001
  }
2567
3002
  globalSelf[key].count++;
@@ -2813,4 +3248,4 @@ function extractModuleNames(modules) {
2813
3248
  }
2814
3249
 
2815
3250
  //#endregion
2816
- export { DEFAULT_ALIASES, DEFAULT_IGNORE_PATTERNS, addAlias, addBuildPlugin, addComponent, addComponentResolver, addComponentsDir, addImports, addImportsDir, addImportsPreset, addPluginsTemplate, addRuntimePlugin, addTemplate, addTypeTemplate, addVitePlugin, applyEnv, buildAliases, buildImportRegistry, createDebugLogger, createDefaultRuntimeConfig, createHMRWatcher, createIgnoreFilter, createIgnoreMatcher, createKimesh, createResolver, createTimer, debug, debugTable, defineKimeshModule, defineKimeshPlugin, defineKmConfig, envToKey, executeModule, executeModules, filterIgnored, findMatchingRules, formatConflictWarning, formatError, formatTiming, formatWarning, generateDts, generateLayerAliases, generatePluginsTemplate, generateRouteRulesManifest, getIgnorePatterns, getRedirectInfo, getRouteRule, getRuntimePlugins, hasPlugins, hasRuntimePlugin, isDebug, isDebugEnabled, keyToEnv, kimeshAutoImport, kimeshPlugin, loadConfig, matchRoutePattern, mergeLayerConfigs, mergeRouteRules, normalizeDebugConfig, normalizeModuleInput, prepare, prepareLayers, removeRuntimePlugin, resolveAlias, resolveAliasPath, resolveLayers, resolvePathFromBuild, resolvePathFromRoot, scanExports, scanPluginsDir, setDebugConfig, shouldIgnore, toTsConfigPaths, toViteAliases, tryUseKimesh, updateTemplates, useKimesh, writeTemplates };
3251
+ export { DEFAULT_ALIASES, DEFAULT_IGNORE_PATTERNS, INTERNAL_ALIASES, addAlias, addBuildPlugin, addComponent, addComponentResolver, addComponentsDir, addImports, addImportsDir, addImportsPreset, addInternalAliasTemplates, addPluginsTemplate, addRuntimePlugin, addTemplate, addTypeTemplate, addVitePlugin, applyEnv, buildAliases, buildImportRegistry, buildInternalAliasMap, createDebugLogger, createDefaultRuntimeConfig, createHMRWatcher, createIgnoreFilter, createIgnoreMatcher, createKimesh, createResolver, createTimer, debug, debugTable, defineKimeshModule, defineKimeshPlugin, defineKmConfig, envToKey, executeModule, executeModules, filterIgnored, findMatchingRules, formatConflictWarning, formatError, formatTiming, formatWarning, generateDts, generateInternalAliasTemplate, generateLayerAliases, generatePluginsTemplate, generateRouteRulesManifest, getIgnorePatterns, getRedirectInfo, getRouteRule, getRuntimePlugins, hasPlugins, hasRuntimePlugin, isDebug, isDebugEnabled, keyToEnv, kimeshAutoImport, kimeshPlugin, loadConfig, matchRoutePattern, mergeLayerConfigs, mergeRouteRules, normalizeDebugConfig, normalizeModuleInput, prepare, prepareLayers, removeRuntimePlugin, resolveAlias, resolveAliasPath, resolveLayers, resolvePathFromBuild, resolvePathFromRoot, scanExports, scanPluginsDir, setDebugConfig, shouldIgnore, toTsConfigPaths, toViteAliases, tryUseKimesh, updateTemplates, useKimesh, writeTemplates };