@homepages/template-kit 0.8.0 → 0.8.1-dev-20260718224903

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.
@@ -0,0 +1,90 @@
1
+ import { resolveFromWorkspace } from "../check/resolve-tool.js";
2
+ import { existsSync, statSync } from "node:fs";
3
+ import { isAbsolute, join, resolve } from "node:path";
4
+
5
+ //#region src/cli/dev/tsconfig-paths-plugin.ts
6
+ const RESOLVE_EXTENSIONS = [
7
+ "",
8
+ ".ts",
9
+ ".tsx",
10
+ ".js",
11
+ ".jsx",
12
+ ".mjs",
13
+ ".cjs",
14
+ ".json"
15
+ ];
16
+ function toPattern(key, targets, baseUrl) {
17
+ const star = key.indexOf("*");
18
+ const hasWildcard = star !== -1;
19
+ return {
20
+ prefix: hasWildcard ? key.slice(0, star) : key,
21
+ suffix: hasWildcard ? key.slice(star + 1) : "",
22
+ hasWildcard,
23
+ targets: targets.map((target) => isAbsolute(target) ? target : join(baseUrl, target))
24
+ };
25
+ }
26
+ /** The wildcard capture for a match, `""` for a wildcard-free exact match, or `undefined` when `specifier` doesn't match. */
27
+ function matchPattern(pattern, specifier) {
28
+ if (!pattern.hasWildcard) return specifier === pattern.prefix ? "" : void 0;
29
+ if (!specifier.startsWith(pattern.prefix) || !specifier.endsWith(pattern.suffix)) return void 0;
30
+ return specifier.slice(pattern.prefix.length, specifier.length - pattern.suffix.length);
31
+ }
32
+ function isFile(path) {
33
+ try {
34
+ return existsSync(path) && statSync(path).isFile();
35
+ } catch {
36
+ return false;
37
+ }
38
+ }
39
+ /** `candidate` resolved as tsc would: itself, itself with a resolvable extension, or a directory index. */
40
+ function resolveCandidate(candidate) {
41
+ for (const ext of RESOLVE_EXTENSIONS) {
42
+ const withExt = candidate + ext;
43
+ if (isFile(withExt)) return withExt;
44
+ }
45
+ for (const ext of RESOLVE_EXTENSIONS.slice(1)) {
46
+ const indexFile = join(candidate, `index${ext}`);
47
+ if (isFile(indexFile)) return indexFile;
48
+ }
49
+ }
50
+ /**
51
+ * Builds a Vite `resolveId` plugin from `root`'s tsconfig `paths`, or returns
52
+ * `null` when the workspace has none configured, or its tsconfig/`typescript`
53
+ * can't be read at all — `check` already owns reporting a broken tsconfig
54
+ * cleanly; `dev` degrades to its pre-existing behavior (no `paths` support)
55
+ * rather than introduce a new startup failure mode over it.
56
+ */
57
+ async function createTsconfigPathsPlugin(root) {
58
+ try {
59
+ const ts = await resolveFromWorkspace(root, "typescript");
60
+ const configPath = join(root, "tsconfig.json");
61
+ const configFile = ts.readConfigFile(configPath, (file) => ts.sys.readFile(file));
62
+ if (configFile.error) return null;
63
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, root);
64
+ const rawPaths = parsed.options.paths;
65
+ if (!rawPaths || Object.keys(rawPaths).length === 0) return null;
66
+ const baseUrl = parsed.options.baseUrl ? resolve(root, parsed.options.baseUrl) : root;
67
+ const patterns = Object.entries(rawPaths).map(([key, targets]) => toPattern(key, targets, baseUrl)).sort((a, b) => b.prefix.length - a.prefix.length);
68
+ return {
69
+ name: "template-kit:tsconfig-paths",
70
+ enforce: "pre",
71
+ resolveId(source) {
72
+ if (source.startsWith(".") || isAbsolute(source)) return null;
73
+ for (const pattern of patterns) {
74
+ const matched = matchPattern(pattern, source);
75
+ if (matched === void 0) continue;
76
+ for (const target of pattern.targets) {
77
+ const resolved = resolveCandidate(pattern.hasWildcard ? target.replace("*", () => matched) : target);
78
+ if (resolved) return resolved;
79
+ }
80
+ }
81
+ return null;
82
+ }
83
+ };
84
+ } catch {
85
+ return null;
86
+ }
87
+ }
88
+
89
+ //#endregion
90
+ export { createTsconfigPathsPlugin };
@@ -1,15 +1,21 @@
1
1
  import { resolveFromWorkspace } from "../check/resolve-tool.js";
2
2
  import { islandTransformPlugin } from "./island-transform.js";
3
+ import { createTsconfigPathsPlugin } from "./tsconfig-paths-plugin.js";
3
4
 
4
5
  //#region src/cli/dev/vite-server.ts
5
6
  async function createDevViteServer(root, opts = {}) {
6
7
  const vite = await resolveFromWorkspace(root, "vite");
7
8
  const reactPlugin = await resolveFromWorkspace(root, "@vitejs/plugin-react");
9
+ const tsconfigPathsPlugin = await createTsconfigPathsPlugin(root);
8
10
  return vite.createServer({
9
11
  root,
10
12
  appType: "custom",
11
13
  configFile: false,
12
- plugins: [reactPlugin.default(), islandTransformPlugin({ root })],
14
+ plugins: [
15
+ reactPlugin.default(),
16
+ islandTransformPlugin({ root }),
17
+ ...tsconfigPathsPlugin ? [tsconfigPathsPlugin] : []
18
+ ],
13
19
  server: {
14
20
  middlewareMode: true,
15
21
  fs: { allow: [root] },