@jogak/core 0.1.0-alpha.1 → 0.1.0-alpha.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/CHANGELOG.md +21 -0
- package/dist/types.d.ts +15 -0
- package/dist/vite/index.js +9 -9
- package/dist/vite/index.mjs +183 -122
- package/dist/vite/resolve-paths.d.ts +32 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to Jogak packages are documented here. The repository follow
|
|
|
5
5
|
|
|
6
6
|
Version numbers apply to all packages in the workspace (synchronized release).
|
|
7
7
|
|
|
8
|
+
## [0.1.0-alpha.3] — 2026-05-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`@jogak/core`**: Vite plugin now auto-detects user `tsconfig.json` (and `tsconfig.app.json` for the Vite scaffold-default split-references layout) and converts `compilerOptions.paths` into `vite resolve.alias`. This makes `runHost`-driven dev/build work zero-config for projects that use path aliases (shadcn/ui's `@/lib/utils` etc.). Without this, `runHost` ignored the user's `vite.config.ts` (`configFile: false`) and any `@/...` import inside a user component failed to resolve.
|
|
13
|
+
- **`JogakPluginOptions.resolveAlias`**: explicit user-provided alias map for cases the auto-extraction can't handle (extends chains, complex glob patterns). Explicit entries override auto-extracted ones. Relative paths are resolved against the user root.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Path aliases declared in user `tsconfig` are now respected during `jogak dev` and `jogak build`. Previously, every `*.jogak.tsx` that imported a component using `@/`-style imports would fail with `Failed to resolve import "@/..."` in the browser dev overlay.
|
|
18
|
+
|
|
19
|
+
Other packages: no source changes; version bumped to keep the workspace synchronized.
|
|
20
|
+
|
|
21
|
+
## [0.1.0-alpha.2] — 2026-05-07
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **`@jogak/ui`**: Published package was missing `src/app/main.tsx` (referenced by `index.html` as the SPA entry), causing `jogak dev` to 404 on the entry script and `jogak build` to fail with `Failed to resolve /src/app/main.tsx`. The `files` field in `package.json` only included `dist/`, but `runHost` uses the package's `index.html` as the Vite root and resolves `/src/app/main.tsx` from source. Added `src/app`, `src/components`, `src/hooks`, `src/index.ts`, `src/vite-env.d.ts` to `files`. Internal `src/host` and `src/examples` remain excluded (host is consumed via the published `dist/host` build; examples are repository-only demos).
|
|
26
|
+
|
|
27
|
+
Other packages: no source changes; version bumped to keep the workspace synchronized.
|
|
28
|
+
|
|
8
29
|
## [0.1.0-alpha.1] — 2026-05-07
|
|
9
30
|
|
|
10
31
|
### Changed
|
package/dist/types.d.ts
CHANGED
|
@@ -139,4 +139,19 @@ export interface JogakPluginOptions {
|
|
|
139
139
|
* 또는 `--force`를 관리해야 한다.
|
|
140
140
|
*/
|
|
141
141
|
readonly disableCacheValidation?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* 사용자 명시 path alias. 미지정 시 사용자 tsconfig의 `compilerOptions.paths`를
|
|
144
|
+
* 자동으로 읽어 vite `resolve.alias`로 등록한다 (shadcn/ui 같이 `@/`를 쓰는
|
|
145
|
+
* 일반적 환경 대응).
|
|
146
|
+
*
|
|
147
|
+
* 자동 추출은 단순 prefix 매핑(`"@/*": ["./src/*"]`)만 처리하므로,
|
|
148
|
+
* `extends` 체인이나 복합 glob 패턴을 쓰는 경우 본 옵션으로 명시 전달한다.
|
|
149
|
+
* 본 옵션이 자동 추출 결과를 덮어쓴다.
|
|
150
|
+
*
|
|
151
|
+
* 값은 alias prefix → 절대 경로(또는 cwd 기준 상대 경로) 맵이다.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* jogak({ resolveAlias: { '@': './src', '@components': './src/components' } })
|
|
155
|
+
*/
|
|
156
|
+
readonly resolveAlias?: Readonly<Record<string, string>>;
|
|
142
157
|
}
|
package/dist/vite/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
"use strict";var V=Object.create;var N=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var V=Object.create;var N=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var q=(e,o,a,c)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of J(o))!K.call(e,s)&&s!==a&&N(e,s,{get:()=>o[s],enumerable:!(c=G(o,s))||c.enumerable});return e};var W=(e,o,a)=>(a=e!=null?V(B(e)):{},q(o||!e||!e.__esModule?N(a,"default",{value:e,enumerable:!0}):a,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("node:path"),_=require("node:fs"),w=require("node:fs/promises"),O=require("../extractor-client-CiWszHel.cjs"),X=["@jogak/core","@jogak/react","@jogak/web-components","@jogak/next"];async function P(e){try{const c=await w.stat(e);if(!c.isDirectory())return c.mtimeMs}catch{return 0}let o=0,a;try{a=await w.readdir(e)}catch{return 0}for(const c of a){const s=p.join(e,c);try{const u=await w.stat(s);if(u.isDirectory()){const y=await P(s);y>o&&(o=y)}else u.mtimeMs>o&&(o=u.mtimeMs)}catch{continue}}return o}async function Y(e){const o=p.resolve(e.root,"node_modules/.vite/deps");if(!_.existsSync(o))return{purged:!1};const a=p.join(o,"_metadata.json");if(!_.existsSync(a))return{purged:!1};let c;try{c=(await w.stat(a)).mtimeMs}catch(u){return e.logger.warn(`[jogak] cache validation: failed to stat _metadata.json (${u.message})`),{purged:!1}}const s=e.packages??X;for(const u of s){const y=p.resolve(e.root,"node_modules",u,"dist");if(!_.existsSync(y))continue;let n;try{n=await P(y)}catch(l){e.logger.warn(`[jogak] cache validation: failed to walk ${u}/dist (${l.message})`);continue}if(n>c+1e3)try{return await w.rm(o,{recursive:!0,force:!0}),e.logger.info(`[jogak] vite deps cache invalidated (stale): ${u} dist newer than cache`),{purged:!0,reason:u}}catch(l){return e.logger.warn(`[jogak] cache validation: failed to purge ${o} (${l.message})`),{purged:!1}}}return{purged:!1}}function H(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,"")}function z(e){if(_.existsSync(e))try{const o=_.readFileSync(e,"utf8");return JSON.parse(H(o))}catch{return}}function Q(e,o,a){if(!e.endsWith("/*")||!o.endsWith("/*"))return;const c=e.slice(0,-2),s=p.resolve(a,o.slice(0,-2));return[c,s]}function Z(e,o){var s,u;const a={},c=new Set([e,p.resolve(o,"tsconfig.app.json")]);for(const y of c){const n=z(y);if(n===void 0)continue;const l=(s=n.compilerOptions)==null?void 0:s.paths;if(l===void 0)continue;const S=((u=n.compilerOptions)==null?void 0:u.baseUrl)??".",j=p.resolve(p.dirname(y),S);for(const[x,T]of Object.entries(l)){const M=T[0];if(M===void 0)continue;const t=Q(x,M,j);if(t===void 0)continue;const[f,r]=t;a[f]===void 0&&(a[f]=r)}}return a}const $="virtual:jogak",C="\0"+$,F="virtual:jogak/entry/",A="\0"+F;function ee(e){return Buffer.from(e,"utf8").toString("base64url")}function te(e){return Buffer.from(e,"base64url").toString("utf8")}function R(e){return{title:e.title,jogakNamesKey:[...e.jogakNames].sort().join("|")}}function oe(e,o){return e!==void 0&&e.title===o.title&&e.jogakNamesKey===o.jogakNamesKey}function re(e={}){const{patterns:o=["src/**/*.jogak.ts","src/**/*.jogak.tsx"],codeTheme:a="vsDark"}=e,c=e.cwd,s=e.tsConfigFilePath,u=e.disableCacheValidation===!0,y=e.resolveAlias;let n,l,S;const j=new Map,x=new Map,T=new Map;async function M(){const{glob:t}=await import("glob"),f=S??process.cwd(),r=await t(o,{cwd:f,absolute:!0}),g=[];j.clear(),x.clear();for(const d of r){let v="";try{v=await w.readFile(d,"utf8")}catch{continue}let h={},i=null;if(l!==void 0){try{h=await l.extract(d)}catch{h={}}try{i=await l.extractMeta(d)}catch{i=null}}if(i===null)continue;const m=i.title;j.set(m,d),x.set(d,m);const k={id:m,title:i.title,jogakNames:i.jogakNames,autoArgTypes:h,userArgTypes:i.userArgTypes,source:v,filePath:d,metaExtras:i.metaExtras};T.set(d,R(k)),g.push({id:m,filePath:d,meta:k})}return g}return{name:"vite-plugin-jogak",config(){const t=c??process.cwd(),f=s??p.resolve(t,"tsconfig.json"),r=Z(f,t),g={};if(y!==void 0)for(const[v,h]of Object.entries(y))g[v]=p.resolve(t,h);const d={...r,...g};if(Object.keys(d).length!==0)return{resolve:{alias:d}}},async configResolved(t){S=c??t.root,t.command==="serve"&&!u&&await Y({root:t.root,logger:{info:r=>t.logger.info(r),warn:r=>t.logger.warn(r)}});const f=s??p.resolve(S,"tsconfig.json");l=_.existsSync(f)?O.createPropsExtractor({tsConfigFilePath:f}):O.createPropsExtractor()},configureServer(t){n=t},buildEnd(){l==null||l.releaseCache()},resolveId(t){if(t===$)return C;if(t.startsWith(F))return"\0"+t},async load(t){if(t===C){const r=(await M()).map(g=>g.meta);return`import { defaultRegistry } from '@jogak/core'
|
|
2
2
|
|
|
3
3
|
const _entryLoader = (slug) =>
|
|
4
4
|
import(/* @vite-ignore */ '/@id/__x00__virtual:jogak/entry/' + slug)
|
|
5
5
|
defaultRegistry.setEntryLoader((id) => {
|
|
6
|
-
const slug = ${
|
|
6
|
+
const slug = ${ae()}
|
|
7
7
|
return _entryLoader(slug(id))
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
const _metas = ${JSON.stringify(
|
|
10
|
+
const _metas = ${JSON.stringify(r)}
|
|
11
11
|
|
|
12
12
|
for (const m of _metas) defaultRegistry.registerMeta(m)
|
|
13
13
|
|
|
14
|
-
export const _jogakCodeTheme = ${JSON.stringify(
|
|
14
|
+
export const _jogakCodeTheme = ${JSON.stringify(a)}
|
|
15
15
|
export const _jogakMetas = _metas
|
|
16
|
-
`}if(t.startsWith(
|
|
16
|
+
`}if(t.startsWith(A)){const f=t.slice(A.length),r=te(f);let g=j.get(r);return g===void 0&&(await M(),g=j.get(r)),g===void 0?`// [jogak] unknown entry id: ${JSON.stringify(r)}
|
|
17
17
|
export {}
|
|
18
|
-
`:`import * as _user from ${JSON.stringify(
|
|
18
|
+
`:`import * as _user from ${JSON.stringify(g)}
|
|
19
19
|
import { defaultRegistry } from '@jogak/core'
|
|
20
20
|
|
|
21
21
|
const _meta = _user.default
|
|
@@ -24,18 +24,18 @@ delete _named.default
|
|
|
24
24
|
const _jogaks = Object.values(_named).filter(
|
|
25
25
|
(v) => v !== null && typeof v === 'object' && typeof v.name === 'string'
|
|
26
26
|
)
|
|
27
|
-
defaultRegistry.hydrateEntry(${JSON.stringify(
|
|
27
|
+
defaultRegistry.hydrateEntry(${JSON.stringify(r)}, _jogaks, _meta?.component)
|
|
28
28
|
|
|
29
29
|
if (import.meta.hot) {
|
|
30
30
|
import.meta.hot.accept()
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export {}
|
|
34
|
-
`}},async handleHotUpdate({file:t,modules:
|
|
34
|
+
`}},async handleHotUpdate({file:t,modules:f}){const r=/\.jogak\.(tsx?|jsx?)$/.test(t),g=/\.(tsx?|jsx?)$/.test(t)&&!r;if(!r&&!g||n===void 0||!r)return;const d=n.moduleGraph.getModuleById(C),v=x.get(t),h=v!==void 0?A+ee(v):void 0,i=h!==void 0?n.moduleGraph.getModuleById(h):void 0;let m=null,k={},E="";if(l!==void 0){try{m=await l.extractMeta(t)}catch{m=null}try{k=await l.extract(t)}catch{k={}}try{E=await w.readFile(t,"utf8")}catch{E=""}}if(m===null){d!==void 0&&n.moduleGraph.invalidateModule(d),i!==void 0&&n.moduleGraph.invalidateModule(i),n.ws.send({type:"full-reload"});return}const I=R(m),D=T.get(t),L=oe(D,I);if(T.set(t,I),!L||v===void 0){d!==void 0&&n.moduleGraph.invalidateModule(d),i!==void 0&&n.moduleGraph.invalidateModule(i),n.ws.send({type:"full-reload"});return}const U={id:v,title:m.title,jogakNames:m.jogakNames,autoArgTypes:k,userArgTypes:m.userArgTypes,source:E,filePath:t,metaExtras:m.metaExtras};i!==void 0&&n.moduleGraph.invalidateModule(i),n.ws.send({type:"custom",event:"jogak:meta-update",data:{id:v,meta:U}});const b=[...f];return i!==void 0&&!b.includes(i)&&b.push(i),b}}}function ae(){return`(rawId) => {
|
|
35
35
|
if (typeof Buffer !== 'undefined') return Buffer.from(rawId, 'utf8').toString('base64url')
|
|
36
36
|
// 브라우저 폴백: btoa는 binary string 기준이라 UTF-8을 한번 인코딩해야 한다.
|
|
37
37
|
const enc = new TextEncoder().encode(rawId)
|
|
38
38
|
let bin = ''
|
|
39
39
|
for (let i = 0; i < enc.length; i++) bin += String.fromCharCode(enc[i])
|
|
40
40
|
return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')
|
|
41
|
-
}`}exports.jogak=
|
|
41
|
+
}`}exports.jogak=re;
|
package/dist/vite/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { resolve as
|
|
2
|
-
import { existsSync as
|
|
3
|
-
import { stat as
|
|
1
|
+
import { resolve as h, join as $, dirname as G } from "node:path";
|
|
2
|
+
import { existsSync as S, readFileSync as J } from "node:fs";
|
|
3
|
+
import { stat as C, rm as B, readdir as K, readFile as N } from "node:fs/promises";
|
|
4
4
|
import { c as R } from "../extractor-client-CReBed7x.js";
|
|
5
|
-
const
|
|
5
|
+
const W = [
|
|
6
6
|
"@jogak/core",
|
|
7
7
|
"@jogak/react",
|
|
8
8
|
"@jogak/web-components",
|
|
@@ -10,107 +10,147 @@ const B = [
|
|
|
10
10
|
];
|
|
11
11
|
async function P(t) {
|
|
12
12
|
try {
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
15
|
-
return
|
|
13
|
+
const l = await C(t);
|
|
14
|
+
if (!l.isDirectory())
|
|
15
|
+
return l.mtimeMs;
|
|
16
16
|
} catch {
|
|
17
17
|
return 0;
|
|
18
18
|
}
|
|
19
|
-
let
|
|
19
|
+
let o = 0, f;
|
|
20
20
|
try {
|
|
21
|
-
|
|
21
|
+
f = await K(t);
|
|
22
22
|
} catch {
|
|
23
23
|
return 0;
|
|
24
24
|
}
|
|
25
|
-
for (const
|
|
26
|
-
const
|
|
25
|
+
for (const l of f) {
|
|
26
|
+
const m = $(t, l);
|
|
27
27
|
try {
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
} else
|
|
28
|
+
const c = await C(m);
|
|
29
|
+
if (c.isDirectory()) {
|
|
30
|
+
const p = await P(m);
|
|
31
|
+
p > o && (o = p);
|
|
32
|
+
} else c.mtimeMs > o && (o = c.mtimeMs);
|
|
33
33
|
} catch {
|
|
34
34
|
continue;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
return
|
|
37
|
+
return o;
|
|
38
38
|
}
|
|
39
|
-
async function
|
|
40
|
-
const
|
|
41
|
-
if (!
|
|
39
|
+
async function X(t) {
|
|
40
|
+
const o = h(t.root, "node_modules/.vite/deps");
|
|
41
|
+
if (!S(o))
|
|
42
42
|
return { purged: !1 };
|
|
43
|
-
const
|
|
44
|
-
if (!
|
|
43
|
+
const f = $(o, "_metadata.json");
|
|
44
|
+
if (!S(f))
|
|
45
45
|
return { purged: !1 };
|
|
46
|
-
let
|
|
46
|
+
let l;
|
|
47
47
|
try {
|
|
48
|
-
|
|
49
|
-
} catch (
|
|
48
|
+
l = (await C(f)).mtimeMs;
|
|
49
|
+
} catch (c) {
|
|
50
50
|
return t.logger.warn(
|
|
51
|
-
`[jogak] cache validation: failed to stat _metadata.json (${
|
|
51
|
+
`[jogak] cache validation: failed to stat _metadata.json (${c.message})`
|
|
52
52
|
), { purged: !1 };
|
|
53
53
|
}
|
|
54
|
-
const
|
|
55
|
-
for (const
|
|
56
|
-
const
|
|
57
|
-
if (!
|
|
58
|
-
let
|
|
54
|
+
const m = t.packages ?? W;
|
|
55
|
+
for (const c of m) {
|
|
56
|
+
const p = h(t.root, "node_modules", c, "dist");
|
|
57
|
+
if (!S(p)) continue;
|
|
58
|
+
let r;
|
|
59
59
|
try {
|
|
60
|
-
|
|
61
|
-
} catch (
|
|
60
|
+
r = await P(p);
|
|
61
|
+
} catch (i) {
|
|
62
62
|
t.logger.warn(
|
|
63
|
-
`[jogak] cache validation: failed to walk ${
|
|
63
|
+
`[jogak] cache validation: failed to walk ${c}/dist (${i.message})`
|
|
64
64
|
);
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
|
-
if (
|
|
67
|
+
if (r > l + 1e3)
|
|
68
68
|
try {
|
|
69
|
-
return await
|
|
70
|
-
`[jogak] vite deps cache invalidated (stale): ${
|
|
71
|
-
), { purged: !0, reason:
|
|
72
|
-
} catch (
|
|
69
|
+
return await B(o, { recursive: !0, force: !0 }), t.logger.info(
|
|
70
|
+
`[jogak] vite deps cache invalidated (stale): ${c} dist newer than cache`
|
|
71
|
+
), { purged: !0, reason: c };
|
|
72
|
+
} catch (i) {
|
|
73
73
|
return t.logger.warn(
|
|
74
|
-
`[jogak] cache validation: failed to purge ${
|
|
74
|
+
`[jogak] cache validation: failed to purge ${o} (${i.message})`
|
|
75
75
|
), { purged: !1 };
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
return { purged: !1 };
|
|
79
79
|
}
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
function Y(t) {
|
|
81
|
+
return t.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
|
|
82
|
+
}
|
|
83
|
+
function q(t) {
|
|
84
|
+
if (S(t))
|
|
85
|
+
try {
|
|
86
|
+
const o = J(t, "utf8");
|
|
87
|
+
return JSON.parse(Y(o));
|
|
88
|
+
} catch {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function H(t, o, f) {
|
|
93
|
+
if (!t.endsWith("/*") || !o.endsWith("/*")) return;
|
|
94
|
+
const l = t.slice(0, -2), m = h(f, o.slice(0, -2));
|
|
95
|
+
return [l, m];
|
|
96
|
+
}
|
|
97
|
+
function z(t, o) {
|
|
98
|
+
var m, c;
|
|
99
|
+
const f = {}, l = /* @__PURE__ */ new Set([
|
|
100
|
+
t,
|
|
101
|
+
h(o, "tsconfig.app.json")
|
|
102
|
+
]);
|
|
103
|
+
for (const p of l) {
|
|
104
|
+
const r = q(p);
|
|
105
|
+
if (r === void 0) continue;
|
|
106
|
+
const i = (m = r.compilerOptions) == null ? void 0 : m.paths;
|
|
107
|
+
if (i === void 0) continue;
|
|
108
|
+
const k = ((c = r.compilerOptions) == null ? void 0 : c.baseUrl) ?? ".", w = h(G(p), k);
|
|
109
|
+
for (const [_, T] of Object.entries(i)) {
|
|
110
|
+
const M = T[0];
|
|
111
|
+
if (M === void 0) continue;
|
|
112
|
+
const e = H(_, M, w);
|
|
113
|
+
if (e === void 0) continue;
|
|
114
|
+
const [d, a] = e;
|
|
115
|
+
f[d] === void 0 && (f[d] = a);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return f;
|
|
119
|
+
}
|
|
120
|
+
const D = "virtual:jogak", x = "\0" + D, F = "virtual:jogak/entry/", A = "\0" + F;
|
|
121
|
+
function Q(t) {
|
|
82
122
|
return Buffer.from(t, "utf8").toString("base64url");
|
|
83
123
|
}
|
|
84
|
-
function
|
|
124
|
+
function Z(t) {
|
|
85
125
|
return Buffer.from(t, "base64url").toString("utf8");
|
|
86
126
|
}
|
|
87
|
-
function
|
|
127
|
+
function O(t) {
|
|
88
128
|
return {
|
|
89
129
|
title: t.title,
|
|
90
130
|
jogakNamesKey: [...t.jogakNames].sort().join("|")
|
|
91
131
|
};
|
|
92
132
|
}
|
|
93
|
-
function
|
|
94
|
-
return t !== void 0 && t.title ===
|
|
133
|
+
function tt(t, o) {
|
|
134
|
+
return t !== void 0 && t.title === o.title && t.jogakNamesKey === o.jogakNamesKey;
|
|
95
135
|
}
|
|
96
|
-
function
|
|
136
|
+
function it(t = {}) {
|
|
97
137
|
const {
|
|
98
|
-
patterns:
|
|
99
|
-
codeTheme:
|
|
100
|
-
} = t,
|
|
101
|
-
let
|
|
102
|
-
const w = /* @__PURE__ */ new Map(),
|
|
103
|
-
async function
|
|
104
|
-
const { glob: e } = await import("glob"),
|
|
105
|
-
w.clear(),
|
|
106
|
-
for (const s of
|
|
107
|
-
let
|
|
138
|
+
patterns: o = ["src/**/*.jogak.ts", "src/**/*.jogak.tsx"],
|
|
139
|
+
codeTheme: f = "vsDark"
|
|
140
|
+
} = t, l = t.cwd, m = t.tsConfigFilePath, c = t.disableCacheValidation === !0, p = t.resolveAlias;
|
|
141
|
+
let r, i, k;
|
|
142
|
+
const w = /* @__PURE__ */ new Map(), _ = /* @__PURE__ */ new Map(), T = /* @__PURE__ */ new Map();
|
|
143
|
+
async function M() {
|
|
144
|
+
const { glob: e } = await import("glob"), d = k ?? process.cwd(), a = await e(o, { cwd: d, absolute: !0 }), u = [];
|
|
145
|
+
w.clear(), _.clear();
|
|
146
|
+
for (const s of a) {
|
|
147
|
+
let y = "";
|
|
108
148
|
try {
|
|
109
|
-
|
|
149
|
+
y = await N(s, "utf8");
|
|
110
150
|
} catch {
|
|
111
151
|
continue;
|
|
112
152
|
}
|
|
113
|
-
let v = {},
|
|
153
|
+
let v = {}, n = null;
|
|
114
154
|
if (i !== void 0) {
|
|
115
155
|
try {
|
|
116
156
|
v = await i.extract(s);
|
|
@@ -118,79 +158,100 @@ function Z(t = {}) {
|
|
|
118
158
|
v = {};
|
|
119
159
|
}
|
|
120
160
|
try {
|
|
121
|
-
|
|
161
|
+
n = await i.extractMeta(s);
|
|
122
162
|
} catch {
|
|
123
|
-
|
|
163
|
+
n = null;
|
|
124
164
|
}
|
|
125
165
|
}
|
|
126
|
-
if (
|
|
127
|
-
const
|
|
128
|
-
w.set(
|
|
129
|
-
const
|
|
130
|
-
id:
|
|
131
|
-
title:
|
|
132
|
-
jogakNames:
|
|
166
|
+
if (n === null) continue;
|
|
167
|
+
const g = n.title;
|
|
168
|
+
w.set(g, s), _.set(s, g);
|
|
169
|
+
const j = {
|
|
170
|
+
id: g,
|
|
171
|
+
title: n.title,
|
|
172
|
+
jogakNames: n.jogakNames,
|
|
133
173
|
autoArgTypes: v,
|
|
134
|
-
userArgTypes:
|
|
135
|
-
source:
|
|
174
|
+
userArgTypes: n.userArgTypes,
|
|
175
|
+
source: y,
|
|
136
176
|
filePath: s,
|
|
137
|
-
metaExtras:
|
|
177
|
+
metaExtras: n.metaExtras
|
|
138
178
|
};
|
|
139
|
-
|
|
179
|
+
T.set(s, O(j)), u.push({ id: g, filePath: s, meta: j });
|
|
140
180
|
}
|
|
141
|
-
return
|
|
181
|
+
return u;
|
|
142
182
|
}
|
|
143
183
|
return {
|
|
144
184
|
name: "vite-plugin-jogak",
|
|
185
|
+
/**
|
|
186
|
+
* 사용자 path alias 주입.
|
|
187
|
+
*
|
|
188
|
+
* `runHost`는 vite root를 `@jogak/ui` 패키지로 두고 사용자 `vite.config.ts`를
|
|
189
|
+
* 무시하므로(`configFile: false`), 사용자가 컴포넌트 안에서 쓰는 `@/lib/utils`
|
|
190
|
+
* 같은 alias가 그냥은 적용되지 않는다. 본 hook이 사용자 tsconfig의
|
|
191
|
+
* `compilerOptions.paths`를 vite `resolve.alias`로 자동 변환해 주입한다.
|
|
192
|
+
*
|
|
193
|
+
* 우선순위: `options.resolveAlias` (명시) > tsconfig 자동 추출.
|
|
194
|
+
*/
|
|
195
|
+
config() {
|
|
196
|
+
const e = l ?? process.cwd(), d = m ?? h(e, "tsconfig.json"), a = z(d, e), u = {};
|
|
197
|
+
if (p !== void 0)
|
|
198
|
+
for (const [y, v] of Object.entries(p))
|
|
199
|
+
u[y] = h(e, v);
|
|
200
|
+
const s = { ...a, ...u };
|
|
201
|
+
if (Object.keys(s).length !== 0)
|
|
202
|
+
return {
|
|
203
|
+
resolve: { alias: s }
|
|
204
|
+
};
|
|
205
|
+
},
|
|
145
206
|
async configResolved(e) {
|
|
146
|
-
|
|
207
|
+
k = l ?? e.root, e.command === "serve" && !c && await X({
|
|
147
208
|
root: e.root,
|
|
148
209
|
logger: {
|
|
149
|
-
info: (
|
|
150
|
-
warn: (
|
|
210
|
+
info: (a) => e.logger.info(a),
|
|
211
|
+
warn: (a) => e.logger.warn(a)
|
|
151
212
|
}
|
|
152
213
|
});
|
|
153
|
-
const
|
|
154
|
-
i =
|
|
214
|
+
const d = m ?? h(k, "tsconfig.json");
|
|
215
|
+
i = S(d) ? R({ tsConfigFilePath: d }) : R();
|
|
155
216
|
},
|
|
156
217
|
configureServer(e) {
|
|
157
|
-
|
|
218
|
+
r = e;
|
|
158
219
|
},
|
|
159
220
|
buildEnd() {
|
|
160
221
|
i == null || i.releaseCache();
|
|
161
222
|
},
|
|
162
223
|
resolveId(e) {
|
|
163
224
|
if (e === D)
|
|
164
|
-
return
|
|
225
|
+
return x;
|
|
165
226
|
if (e.startsWith(F))
|
|
166
227
|
return "\0" + e;
|
|
167
228
|
},
|
|
168
229
|
async load(e) {
|
|
169
|
-
if (e ===
|
|
170
|
-
const
|
|
230
|
+
if (e === x) {
|
|
231
|
+
const a = (await M()).map((u) => u.meta);
|
|
171
232
|
return `import { defaultRegistry } from '@jogak/core'
|
|
172
233
|
|
|
173
234
|
const _entryLoader = (slug) =>
|
|
174
235
|
import(/* @vite-ignore */ '/@id/__x00__virtual:jogak/entry/' + slug)
|
|
175
236
|
defaultRegistry.setEntryLoader((id) => {
|
|
176
|
-
const slug = ${
|
|
237
|
+
const slug = ${et()}
|
|
177
238
|
return _entryLoader(slug(id))
|
|
178
239
|
})
|
|
179
240
|
|
|
180
|
-
const _metas = ${JSON.stringify(
|
|
241
|
+
const _metas = ${JSON.stringify(a)}
|
|
181
242
|
|
|
182
243
|
for (const m of _metas) defaultRegistry.registerMeta(m)
|
|
183
244
|
|
|
184
|
-
export const _jogakCodeTheme = ${JSON.stringify(
|
|
245
|
+
export const _jogakCodeTheme = ${JSON.stringify(f)}
|
|
185
246
|
export const _jogakMetas = _metas
|
|
186
247
|
`;
|
|
187
248
|
}
|
|
188
|
-
if (e.startsWith(
|
|
189
|
-
const
|
|
190
|
-
let
|
|
191
|
-
return
|
|
249
|
+
if (e.startsWith(A)) {
|
|
250
|
+
const d = e.slice(A.length), a = Z(d);
|
|
251
|
+
let u = w.get(a);
|
|
252
|
+
return u === void 0 && (await M(), u = w.get(a)), u === void 0 ? `// [jogak] unknown entry id: ${JSON.stringify(a)}
|
|
192
253
|
export {}
|
|
193
|
-
` : `import * as _user from ${JSON.stringify(
|
|
254
|
+
` : `import * as _user from ${JSON.stringify(u)}
|
|
194
255
|
import { defaultRegistry } from '@jogak/core'
|
|
195
256
|
|
|
196
257
|
const _meta = _user.default
|
|
@@ -199,7 +260,7 @@ delete _named.default
|
|
|
199
260
|
const _jogaks = Object.values(_named).filter(
|
|
200
261
|
(v) => v !== null && typeof v === 'object' && typeof v.name === 'string'
|
|
201
262
|
)
|
|
202
|
-
defaultRegistry.hydrateEntry(${JSON.stringify(
|
|
263
|
+
defaultRegistry.hydrateEntry(${JSON.stringify(a)}, _jogaks, _meta?.component)
|
|
203
264
|
|
|
204
265
|
if (import.meta.hot) {
|
|
205
266
|
import.meta.hot.accept()
|
|
@@ -209,60 +270,60 @@ export {}
|
|
|
209
270
|
`;
|
|
210
271
|
}
|
|
211
272
|
},
|
|
212
|
-
async handleHotUpdate({ file: e, modules:
|
|
213
|
-
const
|
|
214
|
-
if (!
|
|
215
|
-
const s =
|
|
216
|
-
|
|
217
|
-
),
|
|
218
|
-
let
|
|
273
|
+
async handleHotUpdate({ file: e, modules: d }) {
|
|
274
|
+
const a = /\.jogak\.(tsx?|jsx?)$/.test(e), u = /\.(tsx?|jsx?)$/.test(e) && !a;
|
|
275
|
+
if (!a && !u || r === void 0 || !a) return;
|
|
276
|
+
const s = r.moduleGraph.getModuleById(
|
|
277
|
+
x
|
|
278
|
+
), y = _.get(e), v = y !== void 0 ? A + Q(y) : void 0, n = v !== void 0 ? r.moduleGraph.getModuleById(v) : void 0;
|
|
279
|
+
let g = null, j = {}, E = "";
|
|
219
280
|
if (i !== void 0) {
|
|
220
281
|
try {
|
|
221
|
-
|
|
282
|
+
g = await i.extractMeta(e);
|
|
222
283
|
} catch {
|
|
223
|
-
|
|
284
|
+
g = null;
|
|
224
285
|
}
|
|
225
286
|
try {
|
|
226
|
-
|
|
287
|
+
j = await i.extract(e);
|
|
227
288
|
} catch {
|
|
228
|
-
|
|
289
|
+
j = {};
|
|
229
290
|
}
|
|
230
291
|
try {
|
|
231
|
-
|
|
292
|
+
E = await N(e, "utf8");
|
|
232
293
|
} catch {
|
|
233
|
-
|
|
294
|
+
E = "";
|
|
234
295
|
}
|
|
235
296
|
}
|
|
236
|
-
if (
|
|
237
|
-
s !== void 0 &&
|
|
297
|
+
if (g === null) {
|
|
298
|
+
s !== void 0 && r.moduleGraph.invalidateModule(s), n !== void 0 && r.moduleGraph.invalidateModule(n), r.ws.send({ type: "full-reload" });
|
|
238
299
|
return;
|
|
239
300
|
}
|
|
240
|
-
const
|
|
241
|
-
if (
|
|
242
|
-
s !== void 0 &&
|
|
301
|
+
const I = O(g), L = T.get(e), U = tt(L, I);
|
|
302
|
+
if (T.set(e, I), !U || y === void 0) {
|
|
303
|
+
s !== void 0 && r.moduleGraph.invalidateModule(s), n !== void 0 && r.moduleGraph.invalidateModule(n), r.ws.send({ type: "full-reload" });
|
|
243
304
|
return;
|
|
244
305
|
}
|
|
245
306
|
const V = {
|
|
246
|
-
id:
|
|
247
|
-
title:
|
|
248
|
-
jogakNames:
|
|
249
|
-
autoArgTypes:
|
|
250
|
-
userArgTypes:
|
|
251
|
-
source:
|
|
307
|
+
id: y,
|
|
308
|
+
title: g.title,
|
|
309
|
+
jogakNames: g.jogakNames,
|
|
310
|
+
autoArgTypes: j,
|
|
311
|
+
userArgTypes: g.userArgTypes,
|
|
312
|
+
source: E,
|
|
252
313
|
filePath: e,
|
|
253
|
-
metaExtras:
|
|
314
|
+
metaExtras: g.metaExtras
|
|
254
315
|
};
|
|
255
|
-
|
|
316
|
+
n !== void 0 && r.moduleGraph.invalidateModule(n), r.ws.send({
|
|
256
317
|
type: "custom",
|
|
257
318
|
event: "jogak:meta-update",
|
|
258
|
-
data: { id:
|
|
319
|
+
data: { id: y, meta: V }
|
|
259
320
|
});
|
|
260
|
-
const
|
|
261
|
-
return
|
|
321
|
+
const b = [...d];
|
|
322
|
+
return n !== void 0 && !b.includes(n) && b.push(n), b;
|
|
262
323
|
}
|
|
263
324
|
};
|
|
264
325
|
}
|
|
265
|
-
function
|
|
326
|
+
function et() {
|
|
266
327
|
return `(rawId) => {
|
|
267
328
|
if (typeof Buffer !== 'undefined') return Buffer.from(rawId, 'utf8').toString('base64url')
|
|
268
329
|
// 브라우저 폴백: btoa는 binary string 기준이라 UTF-8을 한번 인코딩해야 한다.
|
|
@@ -273,5 +334,5 @@ function Y() {
|
|
|
273
334
|
}`;
|
|
274
335
|
}
|
|
275
336
|
export {
|
|
276
|
-
|
|
337
|
+
it as jogak
|
|
277
338
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 사용자 tsconfig의 `compilerOptions.paths`를 vite `resolve.alias`로 변환한다.
|
|
3
|
+
*
|
|
4
|
+
* 동기:
|
|
5
|
+
* - `runHost`는 vite root를 `@jogak/ui` 패키지로 두고 사용자 `vite.config.ts`를
|
|
6
|
+
* 무시하므로(`configFile: false`), 사용자가 정의한 alias가 적용되지 않는다.
|
|
7
|
+
* - shadcn/ui 같은 라이브러리는 `@/lib/utils` 같은 alias를 컴포넌트 안에서
|
|
8
|
+
* 사용하고, 사용자가 작성한 `*.jogak.tsx`도 같은 alias로 컴포넌트를 import.
|
|
9
|
+
* - 따라서 jogak이 사용자의 path alias를 자동으로 인식하지 못하면 dev/build에서
|
|
10
|
+
* "Failed to resolve import" 에러가 난다.
|
|
11
|
+
*
|
|
12
|
+
* 처리 범위:
|
|
13
|
+
* - 단순 prefix 매핑: `"@/*": ["./src/*"]` → `{ "@": "<baseDir>/src" }`
|
|
14
|
+
* - references로 분할된 tsconfig (Vite 기본 스캐폴드 = `tsconfig.json` +
|
|
15
|
+
* `tsconfig.app.json`): 후보 경로 두 개 모두 시도하고 먼저 발견된 매핑을 채택.
|
|
16
|
+
*
|
|
17
|
+
* 미처리 (의도적):
|
|
18
|
+
* - `extends` 체인: TypeScript Compiler API를 부모 V8에 로드하기 부담이 커서
|
|
19
|
+
* 단순 정규식 + JSON 파싱으로 처리. 대부분의 사용자 케이스(scaffold default,
|
|
20
|
+
* shadcn/ui)는 references 패턴이라 본 범위에서 충분.
|
|
21
|
+
* - 복합 glob 패턴: 두 개 이상의 와일드카드를 포함하는 매핑은 처리하지 않는다.
|
|
22
|
+
*
|
|
23
|
+
* 자동 추출이 실패하면 `JogakPluginOptions.resolveAlias`로 명시적 alias를
|
|
24
|
+
* 전달할 수 있다 (사용자 fallback).
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* 사용자 tsconfig 후보 경로들에서 paths를 추출해 alias 맵으로 합친다.
|
|
28
|
+
*
|
|
29
|
+
* @param primaryTsConfig 사용자가 명시했거나 자동 감지된 1차 tsconfig 절대 경로
|
|
30
|
+
* @param userRoot 사용자 프로젝트 루트 — references 분할 시 fallback 후보 위치 계산용
|
|
31
|
+
*/
|
|
32
|
+
export declare function readTsConfigAlias(primaryTsConfig: string, userRoot: string): Readonly<Record<string, string>>;
|