@jogak/core 0.1.0-alpha.1 → 0.1.0-alpha.10.2

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/dist/actions-BvvUNlgo.js +69 -0
  3. package/dist/actions-D9bnuJ1b.cjs +1 -0
  4. package/dist/adapter.d.ts +80 -0
  5. package/dist/adapters/next/index.cjs +73 -0
  6. package/dist/adapters/next/index.d.ts +5 -0
  7. package/dist/adapters/next/index.mjs +222 -0
  8. package/dist/adapters/next/scaffold.d.ts +23 -0
  9. package/dist/adapters/next/spawn-dev.d.ts +2 -0
  10. package/dist/adapters/standalone/index.cjs +1 -0
  11. package/dist/adapters/standalone/index.d.ts +3 -0
  12. package/dist/adapters/standalone/index.mjs +21 -0
  13. package/dist/adapters/vite/build.d.ts +2 -0
  14. package/dist/adapters/vite/index.cjs +22 -0
  15. package/dist/adapters/vite/index.d.ts +5 -0
  16. package/dist/adapters/vite/index.mjs +134 -0
  17. package/dist/adapters/vite/preview-frame-plugin.d.ts +6 -0
  18. package/dist/adapters/vite/spawn-dev.d.ts +2 -0
  19. package/dist/adapters/webpack/index.cjs +74 -0
  20. package/dist/adapters/webpack/index.d.ts +5 -0
  21. package/dist/adapters/webpack/index.mjs +214 -0
  22. package/dist/adapters/webpack/scaffold.d.ts +18 -0
  23. package/dist/adapters/webpack/spawn-dev.d.ts +2 -0
  24. package/dist/builder-detect.d.ts +9 -0
  25. package/dist/config.d.ts +71 -0
  26. package/dist/detect-global-css-CDcuUAYE.cjs +1 -0
  27. package/dist/detect-global-css-CIVMmgzy.js +33 -0
  28. package/dist/index.cjs +1 -0
  29. package/dist/index.d.ts +5 -1
  30. package/dist/index.mjs +13 -413
  31. package/dist/plugin-DhT-PH1R.js +354 -0
  32. package/dist/plugin-Wtlz0hae.cjs +50 -0
  33. package/dist/preview-entry/protocol.d.ts +29 -0
  34. package/dist/preview-entry/source.d.ts +30 -0
  35. package/dist/registry-CnBX6XxF.js +397 -0
  36. package/dist/registry-DRRMxvoz.cjs +1 -0
  37. package/dist/registry.d.ts +3 -0
  38. package/dist/renderers/next/client/Preview.d.ts +27 -0
  39. package/dist/renderers/next/client/index.d.ts +2 -0
  40. package/dist/renderers/next/index.cjs +1 -0
  41. package/dist/renderers/next/index.d.ts +4 -0
  42. package/dist/renderers/next/index.mjs +53 -0
  43. package/dist/renderers/next/server/JogakLayout.d.ts +28 -0
  44. package/dist/renderers/next/server/index.d.ts +2 -0
  45. package/dist/renderers/react/JogakProvider.d.ts +8 -0
  46. package/dist/renderers/react/adapter.d.ts +2 -0
  47. package/dist/renderers/react/index.cjs +1 -0
  48. package/dist/renderers/react/index.d.ts +7 -0
  49. package/dist/renderers/react/index.mjs +101 -0
  50. package/dist/renderers/react/useEntry.d.ts +40 -0
  51. package/dist/renderers/react/useRegistryMeta.d.ts +27 -0
  52. package/dist/renderers/web-components/define.d.ts +11 -0
  53. package/dist/renderers/web-components/index.cjs +1 -0
  54. package/dist/renderers/web-components/index.d.ts +1 -0
  55. package/dist/renderers/web-components/index.mjs +48 -0
  56. package/dist/server.cjs +1 -0
  57. package/dist/server.d.ts +12 -0
  58. package/dist/server.mjs +45 -0
  59. package/dist/source-9OiU8x_y.cjs +43 -0
  60. package/dist/source-D44KTQPu.js +50 -0
  61. package/dist/types.d.ts +161 -0
  62. package/dist/vite/index.cjs +1 -0
  63. package/dist/vite/index.mjs +2 -275
  64. package/dist/vite-plugin/detect-global-css.d.ts +33 -0
  65. package/dist/vite-plugin/index.cjs +1 -0
  66. package/dist/vite-plugin/index.d.ts +12 -0
  67. package/dist/vite-plugin/index.mjs +4 -0
  68. package/dist/vite-plugin/resolve-paths.d.ts +32 -0
  69. package/dist/{vite → vite-plugin}/virtual-ids.d.ts +17 -0
  70. package/package.json +101 -10
  71. package/dist/index.js +0 -1
  72. package/dist/vite/index.js +0 -41
  73. /package/dist/build/{index.js → index.cjs} +0 -0
  74. /package/dist/meta/{extractor-child.js → extractor-child.cjs} +0 -0
  75. /package/dist/{vite → vite-plugin}/cache-validate.d.ts +0 -0
  76. /package/dist/{vite → vite-plugin}/plugin.d.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,118 @@ 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.10.2] — 2026-05-09
9
+
10
+ ### Fixed
11
+
12
+ - **vitest.workspace.ts**: 알파.10에서 7개 패키지 디렉토리를 삭제했지만 `vitest.workspace.ts`가 여전히 `packages/react`, `packages/next`, `packages/web-components`를 참조해 `pnpm test` 시 startup error. core/ui/cli 3개로 정리.
13
+
14
+ 기타 패키지: source 변경 없음, synchronized release 유지를 위해 버전만 bump.
15
+
16
+ ## [0.1.0-alpha.10.1] — 2026-05-09
17
+
18
+ ### Fixed
19
+
20
+ - **CI typecheck**: 알파.10에서 root `tsconfig.json` references에 `packages/cli`를 추가했으나, `tsc -b`가 cli typecheck 시점에 ui의 `dist/host/index.d.ts` (실제 파일은 없음 — ui는 `noEmit: true`)를 찾으려 해 `Cannot find module '@jogak/ui/host'` 에러 발생. 알파.9 이전처럼 cli는 root references에서 제외 — cli는 자기 `pnpm build` 단계의 `tsc -p tsconfig.json`에서 typecheck됨 (그 시점엔 ui dist가 이미 빌드돼 있음).
21
+
22
+ 기타 패키지: source 변경 없음, synchronized release 유지를 위해 버전만 bump.
23
+
24
+ ## [0.1.0-alpha.10] — 2026-05-09
25
+
26
+ ### Architectural unification — 10 packages → 3 packages
27
+
28
+ 알파.9.x에서 분리됐던 4개 빌더 어댑터(`@jogak/vite-adapter`, `@jogak/next-adapter`, `@jogak/webpack-adapter`, `@jogak/standalone-adapter`)와 3개 프레임워크 렌더러(`@jogak/react`, `@jogak/next`, `@jogak/web-components`)를 모두 `@jogak/core`로 통합. 이들의 본질은 build-tool / runtime 통합 코드이며 별도 패키지로 격리할 만한 런타임 substance가 없다는 판단.
29
+
30
+ 이제 publish되는 패키지는 `@jogak/core`, `@jogak/ui`, `@jogak/cli` 3개로 축소. 기능은 모두 유지되며 사용자 install도 단순화 (vite/next/webpack peer deps는 모두 `peerDependenciesMeta.optional` 처리 — 사용자가 실제로 쓰는 빌더만 install).
31
+
32
+ ### Added
33
+
34
+ - **`@jogak/core/adapters/{vite,next,webpack,standalone}`**: 4개 builder adapter subpath. `@jogak/${name}-adapter` 패키지를 흡수.
35
+ - **`@jogak/core/renderers/{react,next,web-components}`**: 3개 framework renderer subpath. 동명 별도 패키지를 흡수.
36
+ - **`@jogak/core/vite-plugin`**: 알파.9.x의 `@jogak/core/vite`를 정식 명명. 기존 `@jogak/core/vite`는 backward-compat alias로 유지.
37
+ - **CLI `loadAdapter`**: 사용자 cwd의 `@jogak/core` exports를 직접 lookup해서 adapter dynamic import. 별도 어댑터 패키지 install 불필요.
38
+
39
+ ### Changed
40
+
41
+ - **import 경로 마이그레이션** (사용자 영향):
42
+ - `import ... from '@jogak/react'` → `import ... from '@jogak/core/renderers/react'`
43
+ - `import ... from '@jogak/next'` → `import ... from '@jogak/core/renderers/next'`
44
+ - `import ... from '@jogak/web-components'` → `import ... from '@jogak/core/renderers/web-components'`
45
+ - `import { jogak } from '@jogak/core/vite'` → `import { jogak } from '@jogak/core/vite-plugin'` (구 경로도 동작하지만 deprecated)
46
+ - **`@jogak/core` peer deps 확장**: react/react-dom/next/webpack/webpack-dev-server/webpack-merge/html-webpack-plugin 추가 (모두 optional). 사용자가 쓰는 빌더만 설치.
47
+ - **iframe scaffold 코드** (next-adapter, webpack-adapter): 생성되는 page.tsx/preview-entry.tsx가 `@jogak/core/renderers/react`를 import (이전 `@jogak/react`).
48
+
49
+ ### Removed
50
+
51
+ - 7개 패키지 디렉토리 + npm registry deprecate notice:
52
+ - `@jogak/react`, `@jogak/next`, `@jogak/web-components`
53
+ - `@jogak/vite-adapter`, `@jogak/next-adapter`, `@jogak/webpack-adapter`, `@jogak/standalone-adapter`
54
+ - 알파.9.x 사용자는 `npm view @jogak/<pkg> deprecated` 메시지로 마이그레이션 안내 받음.
55
+
56
+ ### CI
57
+
58
+ - `release.yml`: pack/publish 목록을 `core/ui/cli` 3개로 축소. Trusted Publisher 신규 등록 zero (3개 모두 알파.9 시점 등록 완료).
59
+
60
+ ## [0.1.0-alpha.9.2] — 2026-05-09
61
+
62
+ ### Fixed
63
+
64
+ - **CI**: `release.yml`의 publish 단계가 `jogak-next-*.tgz` 글로브 패턴을 사용해 `next` 패키지 publish 시 `next-adapter` tarball까지 매치되어 npm publish가 EUSAGE(다중 tarball)으로 실패. 이로 인해 알파.9.1에서 `core/react/ui/web-components`만 publish되고 `next/cli` 및 4개 어댑터는 publish 안 됨. 정확한 파일명(`jogak-${pkg}-${VERSION}.tgz`)으로 변경.
65
+
66
+ 기타 패키지: source 변경 없음, synchronized release 유지를 위해 버전만 bump.
67
+
68
+ ## [0.1.0-alpha.9.1] — 2026-05-09
69
+
70
+ ### Fixed
71
+
72
+ - **CI**: `release.yml`의 pack 단계가 `core/react/ui/web-components/next/cli`만 포함했고 알파.9에서 신규 추가된 4개 어댑터(`vite-adapter` / `next-adapter` / `webpack-adapter` / `standalone-adapter`)를 누락. v0.1.0-alpha.9 태그로 부분 publish됐으나 어댑터들이 npm에 올라가지 않아 사용자가 import 불가. 4개 어댑터를 pack 목록에 추가 후 alpha.9.1로 재발행.
73
+
74
+ 기타 패키지: source 변경 없음, synchronized release 유지를 위해 버전만 bump.
75
+
76
+ ## [0.1.0-alpha.9] — 2026-05-09
77
+
78
+ ### Added
79
+
80
+ - **`@jogak/vite-adapter`**, **`@jogak/next-adapter`**, **`@jogak/webpack-adapter`**, **`@jogak/standalone-adapter`**: 새 builder-agnostic adapter 패키지군. CLI가 사용자 cwd의 빌더(`next.config`, `vite.config`, `webpack.config`)를 감지하여 해당 adapter를 dynamic import한다. 사용자 컴포넌트는 사용자의 정상 빌더 client에서 평가되므로 utility class compiler(Tailwind v4 등)이 자연스럽게 동작한다.
81
+ - **`@jogak/core`**: `BuilderAdapter` ABI(`adapter.ts`), 빌더 자동 감지(`detectBuilder`, `@jogak/core/server`), preview entry 공통 source(`renderPreviewEntrySource`), postMessage 프로토콜(`@jogak/core/preview-entry/protocol`).
82
+ - **`JogakPluginOptions.userPreviewUrl` / `previewEntryPath`**: adapter dispatch 결과를 host UI iframe src로 주입하는 통로. (`userViteUrl`은 alpha.8 호환을 위해 alias로 유지)
83
+ - **`@jogak/next-adapter`**: Next 14+ App Router에 `<userRoot>/app/jogak-preview/page.tsx` scaffold(`.gitignore` 자동, shutdown cleanup). `next dev` child process spawn + HTTP poll ready 감지. CLI가 사전 생성한 `.jogak/registry.ts`의 entries를 import하여 모듈 평가 시점에 등록.
84
+ - **`@jogak/webpack-adapter`**: `<userRoot>/.jogak/webpack-preview/preview-entry.tsx` scaffold + `webpack-dev-server` programmatic API + `webpack-merge`로 사용자 webpack.config 통합.
85
+
86
+ ### Changed
87
+
88
+ - **`@jogak/core`**: `fs`/`path`를 사용하는 server-only utility(`detectBuilder`, `resolveGlobalCssPaths`, `detectUserGlobalCss`)를 `@jogak/core/server` subpath로 분리. client bundle에 Node 모듈이 leak되는 문제를 차단.
89
+ - **`@jogak/core`**, **`@jogak/ui`**, all adapters: CJS 산출물 확장자를 `.js` → `.cjs`로 변경. `"type": "module"` 환경에서 `.js`가 ESM으로 해석되어 발생하던 `exports is not defined in ES module scope` 오류를 해소.
90
+ - **`previewIsolation`** default: `'shadow'` → `'iframe'`. shadow DOM 모드는 일부 portal 라이브러리(Radix 등)와 호환성 이슈가 있어 iframe 격리를 표준으로.
91
+ - **`@jogak/ui`** preview-frame: 기존 `__jogak_setProps__` 직접 호출 프로토콜 → postMessage(`jogak:setProps` / `jogak:rendered` / `jogak:error`)로 통일. 모든 어댑터의 iframe entry가 동일 프로토콜을 따른다.
92
+ - **`@jogak/cli`**: `jogak dev`가 registry 생성 완료를 대기한 뒤 어댑터를 spawn (이전: fire-and-forget). non-vite 어댑터의 scaffold가 비어있는 registry를 import하던 race condition 해소.
93
+
94
+ ### Fixed
95
+
96
+ - **`@jogak/cli`**: 어댑터 dynamic import 시 `import.meta.resolve`/`createRequire`가 cli/dist 기준으로 해석돼 사용자 cwd의 어댑터 패키지를 찾지 못하던 문제. `<cwd>/node_modules/@jogak/${name}-adapter/package.json`을 직접 읽어 `exports['.'].import` 경로로 해석하도록 변경.
97
+ - **`@jogak/next-adapter`**: 이전 시도의 `__jogak_preview__` 경로는 Next App Router의 private folder convention(`_`로 시작하는 폴더는 라우팅 제외)과 충돌해 404. `jogak-preview`로 변경.
98
+
99
+ ## [0.1.0-alpha.3] — 2026-05-07
100
+
101
+ ### Added
102
+
103
+ - **`@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.
104
+ - **`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.
105
+
106
+ ### Fixed
107
+
108
+ - 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.
109
+
110
+ Other packages: no source changes; version bumped to keep the workspace synchronized.
111
+
112
+ ## [0.1.0-alpha.2] — 2026-05-07
113
+
114
+ ### Fixed
115
+
116
+ - **`@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).
117
+
118
+ Other packages: no source changes; version bumped to keep the workspace synchronized.
119
+
8
120
  ## [0.1.0-alpha.1] — 2026-05-07
9
121
 
10
122
  ### Changed
@@ -0,0 +1,69 @@
1
+ var m = (n) => {
2
+ throw TypeError(n);
3
+ };
4
+ var l = (n, t, i) => t.has(n) || m("Cannot " + i);
5
+ var e = (n, t, i) => (l(n, t, "read from private field"), i ? i.call(n) : t.get(n)), r = (n, t, i) => t.has(n) ? m("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(n) : t.set(n, i), u = (n, t, i, o) => (l(n, t, "write to private field"), o ? o.call(n, i) : t.set(n, i), i), g = (n, t, i) => (l(n, t, "access private method"), i);
6
+ var p = (n, t, i, o) => ({
7
+ set _(c) {
8
+ u(n, t, c, i);
9
+ },
10
+ get _() {
11
+ return e(n, t, o);
12
+ }
13
+ });
14
+ var s, f, d, h, y;
15
+ class k {
16
+ constructor() {
17
+ r(this, h);
18
+ r(this, s, []);
19
+ r(this, f, /* @__PURE__ */ new Set());
20
+ r(this, d, 1);
21
+ }
22
+ emit(t, i) {
23
+ const o = {
24
+ id: p(this, d)._++,
25
+ name: t,
26
+ args: i,
27
+ timestamp: Date.now()
28
+ };
29
+ u(this, s, [...e(this, s), o]), g(this, h, y).call(this);
30
+ }
31
+ subscribe(t) {
32
+ return e(this, f).add(t), t(e(this, s)), () => {
33
+ e(this, f).delete(t);
34
+ };
35
+ }
36
+ clear() {
37
+ e(this, s).length !== 0 && (u(this, s, []), g(this, h, y).call(this));
38
+ }
39
+ getLogs() {
40
+ return e(this, s);
41
+ }
42
+ }
43
+ s = new WeakMap(), f = new WeakMap(), d = new WeakMap(), h = new WeakSet(), y = function() {
44
+ for (const t of e(this, f)) t(e(this, s));
45
+ };
46
+ const A = new k();
47
+ function v(n, t = A) {
48
+ return (...i) => {
49
+ t.emit(n, i);
50
+ };
51
+ }
52
+ function C(n, t, i = A) {
53
+ const o = { ...n };
54
+ for (const c of Object.keys(t)) {
55
+ const a = t[c];
56
+ if (a === void 0) continue;
57
+ const b = a.action !== void 0 && a.action !== !1, w = a.type === "function";
58
+ if (!b && !w || typeof o[c] == "function") continue;
59
+ const j = typeof a.action == "string" ? a.action : c;
60
+ o[c] = v(j, i);
61
+ }
62
+ return o;
63
+ }
64
+ export {
65
+ k as A,
66
+ v as a,
67
+ A as d,
68
+ C as i
69
+ };
@@ -0,0 +1 @@
1
+ "use strict";var m=n=>{throw TypeError(n)};var d=(n,t,i)=>t.has(n)||m("Cannot "+i);var o=(n,t,i)=>(d(n,t,"read from private field"),i?i.call(n):t.get(n)),h=(n,t,i)=>t.has(n)?m("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(n):t.set(n,i),u=(n,t,i,e)=>(d(n,t,"write to private field"),e?e.call(n,i):t.set(n,i),i),g=(n,t,i)=>(d(n,t,"access private method"),i);var p=(n,t,i,e)=>({set _(c){u(n,t,c,i)},get _(){return o(n,t,e)}});var s,f,l,r,y;class C{constructor(){h(this,r);h(this,s,[]);h(this,f,new Set);h(this,l,1)}emit(t,i){const e={id:p(this,l)._++,name:t,args:i,timestamp:Date.now()};u(this,s,[...o(this,s),e]),g(this,r,y).call(this)}subscribe(t){return o(this,f).add(t),t(o(this,s)),()=>{o(this,f).delete(t)}}clear(){o(this,s).length!==0&&(u(this,s,[]),g(this,r,y).call(this))}getLogs(){return o(this,s)}}s=new WeakMap,f=new WeakMap,l=new WeakMap,r=new WeakSet,y=function(){for(const t of o(this,f))t(o(this,s))};const A=new C;function b(n,t=A){return(...i)=>{t.emit(n,i)}}function v(n,t,i=A){const e={...n};for(const c of Object.keys(t)){const a=t[c];if(a===void 0)continue;const j=a.action!==void 0&&a.action!==!1,w=a.type==="function";if(!j&&!w||typeof e[c]=="function")continue;const k=typeof a.action=="string"?a.action:c;e[c]=b(k,i)}return e}exports.ActionChannel=C;exports.action=b;exports.defaultActionChannel=A;exports.injectActions=v;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * 알파.9: 빌더-agnostic 어댑터 ABI.
3
+ *
4
+ * jogak이 사용자 빌더(Vite / Next.js / Webpack / Vanilla)에 무관하게 사용자 컴포넌트를
5
+ * 사용자 빌더의 정상 client에서 평가하도록 하는 공통 인터페이스. core는 어떤 빌더도
6
+ * 직접 import하지 않고 어댑터 dispatch만 책임진다.
7
+ *
8
+ * 어댑터 구현체는 별도 패키지로 분리:
9
+ * - `@jogak/vite-adapter`
10
+ * - `@jogak/next-adapter`
11
+ * - `@jogak/webpack-adapter`
12
+ * - `@jogak/standalone-adapter`
13
+ *
14
+ * `@jogak/cli`가 사용자 cwd 시그널로 builder를 자동 감지하고 해당 adapter를 dynamic import.
15
+ */
16
+ export type BuilderName = 'vite' | 'next' | 'webpack' | 'standalone' | 'custom';
17
+ export type GlobalCssSpec = boolean | string | readonly string[];
18
+ /**
19
+ * 모든 빌더 어댑터가 구현해야 하는 공통 ABI.
20
+ */
21
+ export interface BuilderAdapter {
22
+ readonly name: BuilderName;
23
+ /** dev server를 spawn. 사용자 빌더의 정상 client + jogak preview entry 주입. */
24
+ spawnDev(opts: SpawnDevOptions): Promise<DevHandle>;
25
+ /** 정적 산출물 빌드. iframe entry를 사용자 빌더로 빌드 + jogak SPA outDir에 통합. */
26
+ build(opts: BuildOptions): Promise<BuildResult>;
27
+ /** preview entry 통신/주입에 필요한 metadata. */
28
+ readonly previewEntryMeta: PreviewEntryMeta;
29
+ }
30
+ export interface SpawnDevOptions {
31
+ readonly cwd: string;
32
+ readonly globalCss?: GlobalCssSpec;
33
+ readonly port?: number;
34
+ readonly host?: string | boolean;
35
+ /** 로그 출력 — 미지정 시 console 사용. */
36
+ readonly logger?: HostLogger;
37
+ /** adapter별 추가 옵션 (vite: configFile, next: appDir 등). */
38
+ readonly extra?: Readonly<Record<string, unknown>>;
39
+ }
40
+ export interface DevHandle {
41
+ /** dev server URL (jogak SPA가 iframe src base로 사용). */
42
+ readonly url: string;
43
+ readonly port: number;
44
+ /** SIGINT/SIGTERM 시 jogak CLI가 호출. 멱등 보장. */
45
+ close(): Promise<void>;
46
+ }
47
+ export interface BuildOptions {
48
+ readonly cwd: string;
49
+ readonly globalCss?: GlobalCssSpec;
50
+ /** 사용자 빌더 산출물의 출력 디렉토리. jogak이 outDir/preview/로 복사. */
51
+ readonly previewOutDir: string;
52
+ readonly logger?: HostLogger;
53
+ readonly extra?: Readonly<Record<string, unknown>>;
54
+ }
55
+ export interface BuildResult {
56
+ /** 사용자 빌더가 생성한 산출물 절대 경로 디렉토리 (= previewOutDir). */
57
+ readonly outDir: string;
58
+ /** 사용자 빌더가 emit한 entry HTML의 path-relative URL (예: 'index.html'). */
59
+ readonly entryHtml: string;
60
+ readonly assetCount: number;
61
+ readonly totalBytes: number;
62
+ readonly elapsedMs: number;
63
+ }
64
+ export interface PreviewEntryMeta {
65
+ /** dev URL의 entry path (예: '/__jogak_preview__/index.html'). adapter별 routing. */
66
+ readonly devEntryPath: string;
67
+ /** build 산출물의 entry HTML basename (예: 'index.html'). */
68
+ readonly buildEntryName: string;
69
+ /** preview entry 가상 모듈 ID (모든 adapter 공통: 'virtual:jogak/preview-entry'). */
70
+ readonly previewEntryVirtualId: string;
71
+ }
72
+ /**
73
+ * 어댑터에 전달하는 logger 인터페이스. core가 ui/host에 의존하지 않도록 별도 정의.
74
+ * 미지정 시 console fallback.
75
+ */
76
+ export interface HostLogger {
77
+ info(message: string): void;
78
+ warn(message: string): void;
79
+ error(message: string): void;
80
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const y=require("node:child_process"),c=require("node:fs"),u=require("node:path"),w=require("../../detect-global-css-CDcuUAYE.cjs"),p="jogak-preview",m=`/${p}`;function g(e){const o=v(e.cwd);if(o===void 0)throw new Error(`[jogak/next-adapter] App Router 디렉토리를 찾지 못했습니다 (${e.cwd}/app 또는 ${e.cwd}/src/app).
2
+ Pages Router는 알파.10에서 지원 예정. 임시 우회: \`app/\` 디렉토리 생성 후 재시도.`);const r=u.resolve(o,p);c.mkdirSync(r,{recursive:!0});const n=w.resolveGlobalCssPaths(e.globalCss,e.cwd).map(a=>`import ${JSON.stringify(a)}`).join(`
3
+ `),i=u.resolve(e.cwd,".jogak/registry"),t=k(u.relative(r,i)),s=t.startsWith(".")?t:`./${t}`;return c.writeFileSync(u.resolve(r,"page.tsx"),j(n,s),"utf8"),c.writeFileSync(u.resolve(r,"layout.tsx"),E(),"utf8"),h(e.cwd,`${p}/`),{route:m,cleanup:()=>{try{c.rmSync(r,{recursive:!0,force:!0})}catch{}}}}function v(e){const o=u.resolve(e,"src/app");if(c.existsSync(o))return o;const r=u.resolve(e,"app");if(c.existsSync(r))return r}function h(e,o){const r=u.resolve(e,".gitignore");let n="";if(c.existsSync(r))try{n=c.readFileSync(r,"utf-8")}catch{return}const i=`**/${o}`;if(n.split(`
4
+ `).some(l=>l.trim()===i))return;const s="# jogak (auto-generated, do not commit preview scaffolding)",a=n.endsWith(`
5
+ `)||n===""?`${n}${s}
6
+ ${i}
7
+ `:`${n}
8
+ ${s}
9
+ ${i}
10
+ `;try{c.writeFileSync(r,a,"utf-8")}catch{}}function E(){return`import type { ReactNode } from 'react'
11
+
12
+ // jogak preview layout — RootLayout이 사용자 globalCss를 import하므로 여기서 추가 import 불필요.
13
+ export default function JogakPreviewLayout({ children }: { children: ReactNode }) {
14
+ return children
15
+ }
16
+ `}function k(e){return e.split(/[\\/]/u).join("/")}function j(e,o){return`'use client'
17
+ import { useEffect, useRef } from 'react'
18
+ import { reactAdapter } from '@jogak/core/renderers/react'
19
+ import { defaultRegistry } from '@jogak/core'
20
+ import { entries as _jogakEntries } from ${JSON.stringify(o)}
21
+ ${e}
22
+
23
+ // 모듈 평가 시점 1회 등록 — HMR 재평가 대비 멱등 처리.
24
+ for (const entry of _jogakEntries) {
25
+ if (defaultRegistry.get(entry.id) === undefined) {
26
+ defaultRegistry.register(entry)
27
+ }
28
+ }
29
+
30
+ export default function JogakPreviewPage() {
31
+ const ref = useRef<HTMLDivElement>(null)
32
+
33
+ useEffect(() => {
34
+ let currentContainer: HTMLDivElement | null = null
35
+
36
+ const renderEntry = async (entryId: string, args: Record<string, unknown>) => {
37
+ const entry = await defaultRegistry.requestEntry(entryId)
38
+ if (currentContainer === null) {
39
+ currentContainer = document.createElement('div')
40
+ ref.current?.replaceChildren(currentContainer)
41
+ }
42
+ reactAdapter.render(entry, args, currentContainer)
43
+ }
44
+
45
+ const unmount = () => {
46
+ if (currentContainer !== null) {
47
+ reactAdapter.unmount(currentContainer)
48
+ currentContainer = null
49
+ }
50
+ }
51
+
52
+ const handler = (event: MessageEvent) => {
53
+ const data = event.data
54
+ if (data == null || typeof data !== 'object') return
55
+ if (data.type === 'jogak:setProps') {
56
+ void renderEntry(data.entryId, data.args ?? {}).then(() => {
57
+ window.parent.postMessage({ type: 'jogak:rendered', entryId: data.entryId }, '*')
58
+ }).catch((err) => {
59
+ window.parent.postMessage({ type: 'jogak:error', message: String(err?.message ?? err) }, '*')
60
+ })
61
+ } else if (data.type === 'jogak:unmount') {
62
+ unmount()
63
+ }
64
+ }
65
+
66
+ window.addEventListener('message', handler)
67
+ window.parent.postMessage({ type: 'jogak:ready' }, '*')
68
+ return () => { window.removeEventListener('message', handler) }
69
+ }, [])
70
+
71
+ return <div id="jogak-preview-root" ref={ref} />
72
+ }
73
+ `}async function S(e){var a,l;const o=e.extra??{},r=g({cwd:e.cwd,...e.globalCss!==void 0?{globalCss:e.globalCss}:{}}),n=e.port??5174,i=o.cmd??"next",t=y.spawn(i,["dev","-p",String(n),"-H",String(e.host??"localhost")],{cwd:e.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,JOGAK_PREVIEW:"1"}});(a=t.stdout)==null||a.on("data",d=>{process.stdout.write(`[next] ${d.toString()}`)}),(l=t.stderr)==null||l.on("data",d=>{process.stderr.write(`[next] ${d.toString()}`)});const s=`http://localhost:${String(n)}`;try{await R(`${s}${r.route}`,6e4)}catch(d){if(t.pid!==void 0)try{process.kill(t.pid,"SIGTERM")}catch{}throw r.cleanup(),d}return{url:s,port:n,close:async()=>{if(t.pid!==void 0)try{process.kill(t.pid,"SIGTERM"),await new Promise(d=>{const f=setTimeout(()=>{try{t.pid!==void 0&&process.kill(t.pid,"SIGKILL")}catch{}d()},5e3);t.on("exit",()=>{clearTimeout(f),d()})})}catch{}r.cleanup()}}}async function R(e,o){const r=Date.now();let n;for(;Date.now()-r<o;){try{const t=new AbortController,s=setTimeout(()=>{t.abort()},2e3),a=await fetch(e,{signal:t.signal});if(clearTimeout(s),(a.ok||a.status===404)&&a.ok)return}catch(t){n=t}await new Promise(t=>setTimeout(t,500))}const i=n instanceof Error?n.message:String(n??"timeout");throw new Error(`[jogak/next-adapter] next dev ready timeout (${o}ms): ${i}`)}const x={devEntryPath:"/jogak-preview",buildEntryName:"jogak-preview/index.html",previewEntryVirtualId:"virtual:jogak/preview-entry"},P={name:"next",spawnDev:S,async build(e){throw new Error("[jogak/next-adapter] build is not implemented yet (alpha.9 v1). Use `jogak dev` for now.")},previewEntryMeta:x};exports.default=P;exports.scaffoldPreviewPage=g;
@@ -0,0 +1,5 @@
1
+ import { BuilderAdapter } from '../../index.js';
2
+ declare const nextAdapter: BuilderAdapter;
3
+ export default nextAdapter;
4
+ export { scaffoldPreviewPage } from './scaffold.js';
5
+ export type { ScaffoldOptions, ScaffoldHandle } from './scaffold.js';
@@ -0,0 +1,222 @@
1
+ import { spawn as y } from "node:child_process";
2
+ import { mkdirSync as m, writeFileSync as l, rmSync as w, existsSync as p, readFileSync as v } from "node:fs";
3
+ import { resolve as d, relative as h } from "node:path";
4
+ import { r as E } from "../../detect-global-css-CIVMmgzy.js";
5
+ const g = "jogak-preview", k = `/${g}`;
6
+ function j(e) {
7
+ const o = R(e.cwd);
8
+ if (o === void 0)
9
+ throw new Error(
10
+ `[jogak/next-adapter] App Router 디렉토리를 찾지 못했습니다 (${e.cwd}/app 또는 ${e.cwd}/src/app).
11
+ Pages Router는 알파.10에서 지원 예정. 임시 우회: \`app/\` 디렉토리 생성 후 재시도.`
12
+ );
13
+ const r = d(o, g);
14
+ m(r, { recursive: !0 });
15
+ const n = E(e.globalCss, e.cwd).map((a) => `import ${JSON.stringify(a)}`).join(`
16
+ `), i = d(e.cwd, ".jogak/registry"), t = P(h(r, i)), s = t.startsWith(".") ? t : `./${t}`;
17
+ return l(
18
+ d(r, "page.tsx"),
19
+ S(n, s),
20
+ "utf8"
21
+ ), l(d(r, "layout.tsx"), x(), "utf8"), $(e.cwd, `${g}/`), {
22
+ route: k,
23
+ cleanup: () => {
24
+ try {
25
+ w(r, { recursive: !0, force: !0 });
26
+ } catch {
27
+ }
28
+ }
29
+ };
30
+ }
31
+ function R(e) {
32
+ const o = d(e, "src/app");
33
+ if (p(o)) return o;
34
+ const r = d(e, "app");
35
+ if (p(r)) return r;
36
+ }
37
+ function $(e, o) {
38
+ const r = d(e, ".gitignore");
39
+ let n = "";
40
+ if (p(r))
41
+ try {
42
+ n = v(r, "utf-8");
43
+ } catch {
44
+ return;
45
+ }
46
+ const i = `**/${o}`;
47
+ if (n.split(`
48
+ `).some((u) => u.trim() === i)) return;
49
+ const s = "# jogak (auto-generated, do not commit preview scaffolding)", a = n.endsWith(`
50
+ `) || n === "" ? `${n}${s}
51
+ ${i}
52
+ ` : `${n}
53
+ ${s}
54
+ ${i}
55
+ `;
56
+ try {
57
+ l(r, a, "utf-8");
58
+ } catch {
59
+ }
60
+ }
61
+ function x() {
62
+ return `import type { ReactNode } from 'react'
63
+
64
+ // jogak preview layout — RootLayout이 사용자 globalCss를 import하므로 여기서 추가 import 불필요.
65
+ export default function JogakPreviewLayout({ children }: { children: ReactNode }) {
66
+ return children
67
+ }
68
+ `;
69
+ }
70
+ function P(e) {
71
+ return e.split(/[\\/]/u).join("/");
72
+ }
73
+ function S(e, o) {
74
+ return `'use client'
75
+ import { useEffect, useRef } from 'react'
76
+ import { reactAdapter } from '@jogak/core/renderers/react'
77
+ import { defaultRegistry } from '@jogak/core'
78
+ import { entries as _jogakEntries } from ${JSON.stringify(o)}
79
+ ${e}
80
+
81
+ // 모듈 평가 시점 1회 등록 — HMR 재평가 대비 멱등 처리.
82
+ for (const entry of _jogakEntries) {
83
+ if (defaultRegistry.get(entry.id) === undefined) {
84
+ defaultRegistry.register(entry)
85
+ }
86
+ }
87
+
88
+ export default function JogakPreviewPage() {
89
+ const ref = useRef<HTMLDivElement>(null)
90
+
91
+ useEffect(() => {
92
+ let currentContainer: HTMLDivElement | null = null
93
+
94
+ const renderEntry = async (entryId: string, args: Record<string, unknown>) => {
95
+ const entry = await defaultRegistry.requestEntry(entryId)
96
+ if (currentContainer === null) {
97
+ currentContainer = document.createElement('div')
98
+ ref.current?.replaceChildren(currentContainer)
99
+ }
100
+ reactAdapter.render(entry, args, currentContainer)
101
+ }
102
+
103
+ const unmount = () => {
104
+ if (currentContainer !== null) {
105
+ reactAdapter.unmount(currentContainer)
106
+ currentContainer = null
107
+ }
108
+ }
109
+
110
+ const handler = (event: MessageEvent) => {
111
+ const data = event.data
112
+ if (data == null || typeof data !== 'object') return
113
+ if (data.type === 'jogak:setProps') {
114
+ void renderEntry(data.entryId, data.args ?? {}).then(() => {
115
+ window.parent.postMessage({ type: 'jogak:rendered', entryId: data.entryId }, '*')
116
+ }).catch((err) => {
117
+ window.parent.postMessage({ type: 'jogak:error', message: String(err?.message ?? err) }, '*')
118
+ })
119
+ } else if (data.type === 'jogak:unmount') {
120
+ unmount()
121
+ }
122
+ }
123
+
124
+ window.addEventListener('message', handler)
125
+ window.parent.postMessage({ type: 'jogak:ready' }, '*')
126
+ return () => { window.removeEventListener('message', handler) }
127
+ }, [])
128
+
129
+ return <div id="jogak-preview-root" ref={ref} />
130
+ }
131
+ `;
132
+ }
133
+ async function C(e) {
134
+ var a, u;
135
+ const o = e.extra ?? {}, r = j({
136
+ cwd: e.cwd,
137
+ ...e.globalCss !== void 0 ? { globalCss: e.globalCss } : {}
138
+ }), n = e.port ?? 5174, i = o.cmd ?? "next", t = y(
139
+ i,
140
+ ["dev", "-p", String(n), "-H", String(e.host ?? "localhost")],
141
+ {
142
+ cwd: e.cwd,
143
+ stdio: ["ignore", "pipe", "pipe"],
144
+ env: { ...process.env, JOGAK_PREVIEW: "1" }
145
+ }
146
+ );
147
+ (a = t.stdout) == null || a.on("data", (c) => {
148
+ process.stdout.write(`[next] ${c.toString()}`);
149
+ }), (u = t.stderr) == null || u.on("data", (c) => {
150
+ process.stderr.write(`[next] ${c.toString()}`);
151
+ });
152
+ const s = `http://localhost:${String(n)}`;
153
+ try {
154
+ await I(`${s}${r.route}`, 6e4);
155
+ } catch (c) {
156
+ if (t.pid !== void 0)
157
+ try {
158
+ process.kill(t.pid, "SIGTERM");
159
+ } catch {
160
+ }
161
+ throw r.cleanup(), c;
162
+ }
163
+ return {
164
+ url: s,
165
+ port: n,
166
+ close: async () => {
167
+ if (t.pid !== void 0)
168
+ try {
169
+ process.kill(t.pid, "SIGTERM"), await new Promise((c) => {
170
+ const f = setTimeout(() => {
171
+ try {
172
+ t.pid !== void 0 && process.kill(t.pid, "SIGKILL");
173
+ } catch {
174
+ }
175
+ c();
176
+ }, 5e3);
177
+ t.on("exit", () => {
178
+ clearTimeout(f), c();
179
+ });
180
+ });
181
+ } catch {
182
+ }
183
+ r.cleanup();
184
+ }
185
+ };
186
+ }
187
+ async function I(e, o) {
188
+ const r = Date.now();
189
+ let n;
190
+ for (; Date.now() - r < o; ) {
191
+ try {
192
+ const t = new AbortController(), s = setTimeout(() => {
193
+ t.abort();
194
+ }, 2e3), a = await fetch(e, { signal: t.signal });
195
+ if (clearTimeout(s), (a.ok || a.status === 404) && a.ok)
196
+ return;
197
+ } catch (t) {
198
+ n = t;
199
+ }
200
+ await new Promise((t) => setTimeout(t, 500));
201
+ }
202
+ const i = n instanceof Error ? n.message : String(n ?? "timeout");
203
+ throw new Error(`[jogak/next-adapter] next dev ready timeout (${o}ms): ${i}`);
204
+ }
205
+ const b = {
206
+ devEntryPath: "/jogak-preview",
207
+ buildEntryName: "jogak-preview/index.html",
208
+ previewEntryVirtualId: "virtual:jogak/preview-entry"
209
+ }, L = {
210
+ name: "next",
211
+ spawnDev: C,
212
+ async build(e) {
213
+ throw new Error(
214
+ "[jogak/next-adapter] build is not implemented yet (alpha.9 v1). Use `jogak dev` for now."
215
+ );
216
+ },
217
+ previewEntryMeta: b
218
+ };
219
+ export {
220
+ L as default,
221
+ j as scaffoldPreviewPage
222
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 알파.9: next-adapter — `<userRoot>/app/jogak-preview/page.tsx` scaffold.
3
+ *
4
+ * Next.js webpack은 vite처럼 가상 모듈을 지원하지 않으므로 사용자 cwd의 app 디렉토리에
5
+ * 직접 page.tsx를 generate한다. `.gitignore`에 자동 추가하고 shutdown 시 cleanup.
6
+ *
7
+ * App Router 우선:
8
+ * - `<cwd>/src/app/` 우선 (사용자가 src/ 사용 시)
9
+ * - 없으면 `<cwd>/app/`
10
+ *
11
+ * Pages Router는 알파.10 검토.
12
+ */
13
+ export interface ScaffoldOptions {
14
+ readonly cwd: string;
15
+ readonly globalCss?: boolean | string | readonly string[];
16
+ }
17
+ export interface ScaffoldHandle {
18
+ /** Cleanup — shutdown 시 호출. scaffolded 디렉토리 제거. */
19
+ cleanup(): void;
20
+ /** scaffolded preview path (route, e.g. `/jogak-preview`). */
21
+ readonly route: string;
22
+ }
23
+ export declare function scaffoldPreviewPage(opts: ScaffoldOptions): ScaffoldHandle;
@@ -0,0 +1,2 @@
1
+ import { DevHandle, SpawnDevOptions } from '../../index.js';
2
+ export declare function spawnNextDev(opts: SpawnDevOptions): Promise<DevHandle>;
@@ -0,0 +1 @@
1
+ "use strict";const a={devEntryPath:"/preview-frame.html",buildEntryName:"preview-frame.html",previewEntryVirtualId:"virtual:jogak/preview-entry"},r={name:"standalone",async spawnDev(e){throw new Error("[jogak/standalone-adapter] no separate dev server. CLI dispatch should detect this adapter and skip user vite spawn — use fallback (jogak SPA scope) for preview iframe.")},async build(e){throw new Error("[jogak/standalone-adapter] build is not supported in alpha.9 v1.")},previewEntryMeta:a};module.exports=r;
@@ -0,0 +1,3 @@
1
+ import { BuilderAdapter } from '../../index.js';
2
+ declare const standaloneAdapter: BuilderAdapter;
3
+ export default standaloneAdapter;
@@ -0,0 +1,21 @@
1
+ const a = {
2
+ devEntryPath: "/preview-frame.html",
3
+ buildEntryName: "preview-frame.html",
4
+ previewEntryVirtualId: "virtual:jogak/preview-entry"
5
+ }, r = {
6
+ name: "standalone",
7
+ async spawnDev(e) {
8
+ throw new Error(
9
+ "[jogak/standalone-adapter] no separate dev server. CLI dispatch should detect this adapter and skip user vite spawn — use fallback (jogak SPA scope) for preview iframe."
10
+ );
11
+ },
12
+ async build(e) {
13
+ throw new Error(
14
+ "[jogak/standalone-adapter] build is not supported in alpha.9 v1."
15
+ );
16
+ },
17
+ previewEntryMeta: a
18
+ };
19
+ export {
20
+ r as default
21
+ };
@@ -0,0 +1,2 @@
1
+ import { BuildOptions, BuildResult } from '../../index.js';
2
+ export declare function buildVite(opts: BuildOptions): Promise<BuildResult>;