visual-remote 0.2.0 → 0.3.0
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/README.md +25 -16
- package/apps/cli/dist/index.js +176 -9
- package/apps/cli/dist/next-client.js +11 -0
- package/apps/cli/dist/next.js +5057 -0
- package/apps/cli/next-client.d.ts +1 -0
- package/apps/cli/next.d.ts +22 -0
- package/package.json +18 -4
package/README.md
CHANGED
|
@@ -18,16 +18,20 @@ Node.js와 pnpm 버전은 각각 `.nvmrc`와 `package.json`에 고정되어 있
|
|
|
18
18
|
|
|
19
19
|
## 가장 빠른 사용
|
|
20
20
|
|
|
21
|
-
Vite 앱의 `package.json
|
|
21
|
+
Vite 또는 Next.js 앱의 `package.json`이 있는 폴더에서 한 번만 초기화합니다.
|
|
22
|
+
Next.js 자동 통합은 `instrumentation-client`를 지원하는 Next.js 15.3 이상이
|
|
23
|
+
필요합니다.
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
26
|
npx --yes visual-remote@latest init
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
`init`은 다음 작업을 수행합니다.
|
|
29
|
+
`init`은 프로젝트 종류를 감지하고 다음 작업을 수행합니다.
|
|
28
30
|
|
|
29
31
|
- 현재 프로젝트에 `visual-remote`를 개발 의존성으로 설치합니다.
|
|
30
|
-
- `vite.config
|
|
32
|
+
- Vite에서는 `vite.config`에 `visualRemote()` 플러그인을 추가합니다.
|
|
33
|
+
- Next.js에서는 `next.config`에 `withVisualRemote()`를 적용하고
|
|
34
|
+
`instrumentation-client`에 개발 전용 클라이언트 로더를 추가합니다.
|
|
31
35
|
- 현재 폴더에 `.visualdev/config.yaml`을 생성합니다.
|
|
32
36
|
|
|
33
37
|
이후에는 앱을 평소처럼 실행합니다.
|
|
@@ -42,14 +46,16 @@ npm run dev
|
|
|
42
46
|
|
|
43
47
|
```text
|
|
44
48
|
http://localhost:9011/api/* → 기존 앱이 그대로 처리
|
|
45
|
-
http://localhost:9011/@vite/* → 기존 Vite
|
|
49
|
+
http://localhost:9011/@vite/* → 기존 Vite HMR이 그대로 처리
|
|
50
|
+
http://localhost:9011/_next/* → 기존 Next.js 자산/HMR이 그대로 처리
|
|
46
51
|
http://localhost:9011/_visual/* → 내부 Visual Remote Bridge로만 전달
|
|
47
52
|
```
|
|
48
53
|
|
|
49
|
-
이미 실행 중이던 개발 서버가 있다면 `init` 후 한 번 재시작해야 변경된
|
|
54
|
+
이미 실행 중이던 개발 서버가 있다면 `init` 후 한 번 재시작해야 변경된 설정이
|
|
50
55
|
적용됩니다. Portr를 사용할 때도 내부 Bridge 포트가 아니라 기존 앱 포트만 노출합니다.
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
자동 통합은 Vite와 Next.js 프로젝트를 지원합니다. 다른 프레임워크나 설정 파일을
|
|
58
|
+
자동으로 수정하고 싶지 않은 프로젝트에서는 아래의 `attach` 방식을 사용할 수 있습니다.
|
|
53
59
|
|
|
54
60
|
## 저장소에서 개발
|
|
55
61
|
|
|
@@ -98,7 +104,7 @@ corepack pnpm test
|
|
|
98
104
|
## 설정
|
|
99
105
|
|
|
100
106
|
`init`은 명령을 실행한 현재 프로젝트 폴더에 설정을 생성합니다. 모노레포의 하위
|
|
101
|
-
Vite 앱에서 실행하면 Git 루트가 아니라 해당 앱 폴더에 생성됩니다. 기존 설정은
|
|
107
|
+
Vite 또는 Next.js 앱에서 실행하면 Git 루트가 아니라 해당 앱 폴더에 생성됩니다. 기존 설정은
|
|
102
108
|
덮어쓰지 않습니다.
|
|
103
109
|
|
|
104
110
|
```yaml
|
|
@@ -156,8 +162,8 @@ paths:
|
|
|
156
162
|
- dist/**
|
|
157
163
|
```
|
|
158
164
|
|
|
159
|
-
Vite
|
|
160
|
-
`verification`, `paths` 같은 상세 설정만 YAML에서 조정하면 됩니다.
|
|
165
|
+
Vite 플러그인 또는 Next.js 설정 래퍼가 개발 서버와 함께 내부 Bridge를 시작합니다.
|
|
166
|
+
`agent`, `verification`, `paths` 같은 상세 설정만 YAML에서 조정하면 됩니다.
|
|
161
167
|
|
|
162
168
|
## 기존 attach 방식
|
|
163
169
|
|
|
@@ -167,9 +173,9 @@ Vite 플러그인이 개발 서버와 함께 내부 Bridge를 시작하고 종
|
|
|
167
173
|
npx --yes visual-remote@latest http://localhost:9011
|
|
168
174
|
```
|
|
169
175
|
|
|
170
|
-
이 방식은 별도 Gateway 주소를 열어 앱 전체를
|
|
171
|
-
|
|
172
|
-
|
|
176
|
+
이 방식은 별도 Gateway 주소를 열어 앱 전체를 프록시합니다. 자동 통합을 사용할 수
|
|
177
|
+
있는 Vite와 Next.js 프로젝트에서는 `init`을 사용하고 원래 앱 주소로 접속합니다.
|
|
178
|
+
설정 파일을 변경하지 않거나 다른 프레임워크에 붙일 때는 `attach`를 사용합니다.
|
|
173
179
|
|
|
174
180
|
## 브라우저에서 변경 요청
|
|
175
181
|
|
|
@@ -210,7 +216,7 @@ visual status
|
|
|
210
216
|
visual doctor
|
|
211
217
|
```
|
|
212
218
|
|
|
213
|
-
- `init`: 현재 Vite 앱에 개발 전용 통합을 설치합니다.
|
|
219
|
+
- `init`: 현재 Vite 또는 Next.js 앱에 개발 전용 통합을 설치합니다.
|
|
214
220
|
- `attach`: 기본 명령의 명시적 이름이며 기존 사용법과 호환됩니다.
|
|
215
221
|
- `dev`: `init` 설정을 사용해 앱과 브리지를 함께 실행하는 선택 명령입니다.
|
|
216
222
|
- `status`: 현재 Git 작업 트리의 브리지 실행 상태를 확인합니다.
|
|
@@ -239,6 +245,8 @@ packages/overlay/dist/client.js
|
|
|
239
245
|
packages/overlay/dist/viewer.js
|
|
240
246
|
apps/cli/dist/index.js
|
|
241
247
|
apps/cli/dist/vite.js
|
|
248
|
+
apps/cli/dist/next.js
|
|
249
|
+
apps/cli/dist/next-client.js
|
|
242
250
|
```
|
|
243
251
|
|
|
244
252
|
## 저장소 구조
|
|
@@ -278,6 +286,7 @@ node --version
|
|
|
278
286
|
|
|
279
287
|
### 설정 파일 경고가 표시되는 경우
|
|
280
288
|
|
|
281
|
-
Vite 앱의 `package.json
|
|
282
|
-
`doctor`를 다시 실행합니다.
|
|
283
|
-
|
|
289
|
+
Vite 또는 Next.js 앱의 `package.json`이 있는 폴더에서 `visual init`을 실행한 뒤
|
|
290
|
+
`doctor`를 다시 실행합니다. Vite는 `vite.config`, Next.js는 `next.config`와
|
|
291
|
+
`instrumentation-client`가 구성되어야 합니다. 모노레포에서는 Git 루트가 아니라
|
|
292
|
+
실제 앱 폴더에서 실행합니다.
|
package/apps/cli/dist/index.js
CHANGED
|
@@ -5234,6 +5234,20 @@ var VITE_CONFIG_FILES = [
|
|
|
5234
5234
|
"vite.config.mjs"
|
|
5235
5235
|
];
|
|
5236
5236
|
var VITE_IMPORT = 'import { visualRemote } from "visual-remote/vite";';
|
|
5237
|
+
var NEXT_CONFIG_FILES = [
|
|
5238
|
+
"next.config.ts",
|
|
5239
|
+
"next.config.mjs",
|
|
5240
|
+
"next.config.js"
|
|
5241
|
+
];
|
|
5242
|
+
var NEXT_ESM_IMPORT = 'import { withVisualRemote } from "visual-remote/next";';
|
|
5243
|
+
var NEXT_CJS_IMPORT = 'const { withVisualRemote } = require("visual-remote/next");';
|
|
5244
|
+
var NEXT_CLIENT_MODULE = "visual-remote/next/client";
|
|
5245
|
+
var NEXT_CLIENT_BOOTSTRAP = [
|
|
5246
|
+
'if (process.env.NODE_ENV === "development") {',
|
|
5247
|
+
` void import("${NEXT_CLIENT_MODULE}");`,
|
|
5248
|
+
"}",
|
|
5249
|
+
""
|
|
5250
|
+
].join("\n");
|
|
5237
5251
|
function isMissingFile(error) {
|
|
5238
5252
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
5239
5253
|
}
|
|
@@ -5284,6 +5298,13 @@ function isViteProject(manifest, devScript) {
|
|
|
5284
5298
|
};
|
|
5285
5299
|
return "vite" in packages || /(^|[\s;&|])vite(?:\s|$)/.test(devScript);
|
|
5286
5300
|
}
|
|
5301
|
+
function isNextProject(manifest, devScript) {
|
|
5302
|
+
const packages = {
|
|
5303
|
+
...packageRecord(manifest.dependencies),
|
|
5304
|
+
...packageRecord(manifest.devDependencies)
|
|
5305
|
+
};
|
|
5306
|
+
return "next" in packages || /(^|[\s;&|])next(?:\s|$)/.test(devScript);
|
|
5307
|
+
}
|
|
5287
5308
|
function hasVisualRemote(manifest) {
|
|
5288
5309
|
return "visual-remote" in packageRecord(manifest.dependencies) || "visual-remote" in packageRecord(manifest.devDependencies);
|
|
5289
5310
|
}
|
|
@@ -5330,6 +5351,13 @@ async function findViteConfig(projectRoot) {
|
|
|
5330
5351
|
"visual init found Vite but could not find vite.config.ts, .mts, .js, or .mjs"
|
|
5331
5352
|
);
|
|
5332
5353
|
}
|
|
5354
|
+
async function findNextConfig(projectRoot) {
|
|
5355
|
+
for (const filename of NEXT_CONFIG_FILES) {
|
|
5356
|
+
const candidate = join5(projectRoot, filename);
|
|
5357
|
+
if (await fileExists2(candidate)) return candidate;
|
|
5358
|
+
}
|
|
5359
|
+
return join5(projectRoot, "next.config.mjs");
|
|
5360
|
+
}
|
|
5333
5361
|
function insertViteImport(source) {
|
|
5334
5362
|
const lines = source.split("\n");
|
|
5335
5363
|
let index = 0;
|
|
@@ -5367,6 +5395,130 @@ async function configureVite(configPath) {
|
|
|
5367
5395
|
await writeFile3(configPath, transformed, "utf8");
|
|
5368
5396
|
return true;
|
|
5369
5397
|
}
|
|
5398
|
+
function expressionEnd(source, expressionStart) {
|
|
5399
|
+
let roundDepth = 0;
|
|
5400
|
+
let squareDepth = 0;
|
|
5401
|
+
let curlyDepth = 0;
|
|
5402
|
+
let quote;
|
|
5403
|
+
let lineComment = false;
|
|
5404
|
+
let blockComment = false;
|
|
5405
|
+
for (let index = expressionStart; index < source.length; index += 1) {
|
|
5406
|
+
const character = source[index];
|
|
5407
|
+
const nextCharacter = source[index + 1];
|
|
5408
|
+
if (lineComment) {
|
|
5409
|
+
if (character === "\n") lineComment = false;
|
|
5410
|
+
continue;
|
|
5411
|
+
}
|
|
5412
|
+
if (blockComment) {
|
|
5413
|
+
if (character === "*" && nextCharacter === "/") {
|
|
5414
|
+
blockComment = false;
|
|
5415
|
+
index += 1;
|
|
5416
|
+
}
|
|
5417
|
+
continue;
|
|
5418
|
+
}
|
|
5419
|
+
if (quote !== void 0) {
|
|
5420
|
+
if (character === "\\") {
|
|
5421
|
+
index += 1;
|
|
5422
|
+
} else if (character === quote) {
|
|
5423
|
+
quote = void 0;
|
|
5424
|
+
}
|
|
5425
|
+
continue;
|
|
5426
|
+
}
|
|
5427
|
+
if (character === "/" && nextCharacter === "/") {
|
|
5428
|
+
lineComment = true;
|
|
5429
|
+
index += 1;
|
|
5430
|
+
continue;
|
|
5431
|
+
}
|
|
5432
|
+
if (character === "/" && nextCharacter === "*") {
|
|
5433
|
+
blockComment = true;
|
|
5434
|
+
index += 1;
|
|
5435
|
+
continue;
|
|
5436
|
+
}
|
|
5437
|
+
if (character === "'" || character === '"' || character === "`") {
|
|
5438
|
+
quote = character;
|
|
5439
|
+
continue;
|
|
5440
|
+
}
|
|
5441
|
+
if (character === "(") roundDepth += 1;
|
|
5442
|
+
if (character === ")") roundDepth -= 1;
|
|
5443
|
+
if (character === "[") squareDepth += 1;
|
|
5444
|
+
if (character === "]") squareDepth -= 1;
|
|
5445
|
+
if (character === "{") curlyDepth += 1;
|
|
5446
|
+
if (character === "}") curlyDepth -= 1;
|
|
5447
|
+
if (character === ";" && roundDepth === 0 && squareDepth === 0 && curlyDepth === 0) {
|
|
5448
|
+
return index;
|
|
5449
|
+
}
|
|
5450
|
+
}
|
|
5451
|
+
return source.length;
|
|
5452
|
+
}
|
|
5453
|
+
function wrapConfigExpression(source, assignmentPattern) {
|
|
5454
|
+
const assignment = assignmentPattern.exec(source);
|
|
5455
|
+
if (assignment?.index === void 0) {
|
|
5456
|
+
throw new Error("visual init could not find the default Next.js config export");
|
|
5457
|
+
}
|
|
5458
|
+
let start = assignment.index + assignment[0].length;
|
|
5459
|
+
while (/\s/.test(source[start] ?? "")) start += 1;
|
|
5460
|
+
const end = expressionEnd(source, start);
|
|
5461
|
+
const rawExpression = source.slice(start, end);
|
|
5462
|
+
const trailingWhitespace = rawExpression.match(/\s*$/)?.[0] ?? "";
|
|
5463
|
+
const expression = rawExpression.slice(0, rawExpression.length - trailingWhitespace.length);
|
|
5464
|
+
if (expression.length === 0) {
|
|
5465
|
+
throw new Error("visual init found an empty Next.js config export");
|
|
5466
|
+
}
|
|
5467
|
+
return `${source.slice(0, start)}withVisualRemote(${expression})${trailingWhitespace}${source.slice(end)}`;
|
|
5468
|
+
}
|
|
5469
|
+
function transformNextConfig(source) {
|
|
5470
|
+
if (source.includes("visual-remote/next") && /\bwithVisualRemote\s*\(/.test(source)) {
|
|
5471
|
+
return source;
|
|
5472
|
+
}
|
|
5473
|
+
if (/\bmodule\.exports\s*=/.test(source)) {
|
|
5474
|
+
const wrapped2 = wrapConfigExpression(source, /\bmodule\.exports\s*=/);
|
|
5475
|
+
return wrapped2.includes(NEXT_CJS_IMPORT) ? wrapped2 : `${NEXT_CJS_IMPORT}
|
|
5476
|
+
${wrapped2}`;
|
|
5477
|
+
}
|
|
5478
|
+
const wrapped = wrapConfigExpression(source, /\bexport\s+default\b/);
|
|
5479
|
+
return wrapped.includes(NEXT_ESM_IMPORT) ? wrapped : `${NEXT_ESM_IMPORT}
|
|
5480
|
+
${wrapped}`;
|
|
5481
|
+
}
|
|
5482
|
+
async function configureNext(configPath) {
|
|
5483
|
+
let source;
|
|
5484
|
+
try {
|
|
5485
|
+
source = await readFile5(configPath, "utf8");
|
|
5486
|
+
} catch (error) {
|
|
5487
|
+
if (!isMissingFile(error)) throw error;
|
|
5488
|
+
source = "export default {};\n";
|
|
5489
|
+
}
|
|
5490
|
+
const transformed = transformNextConfig(source);
|
|
5491
|
+
if (transformed === source) return false;
|
|
5492
|
+
await writeFile3(configPath, transformed, "utf8");
|
|
5493
|
+
return true;
|
|
5494
|
+
}
|
|
5495
|
+
async function findNextClientPath(projectRoot) {
|
|
5496
|
+
const candidates = [
|
|
5497
|
+
join5(projectRoot, "instrumentation-client.ts"),
|
|
5498
|
+
join5(projectRoot, "instrumentation-client.js"),
|
|
5499
|
+
join5(projectRoot, "src", "instrumentation-client.ts"),
|
|
5500
|
+
join5(projectRoot, "src", "instrumentation-client.js")
|
|
5501
|
+
];
|
|
5502
|
+
for (const candidate of candidates) {
|
|
5503
|
+
if (await fileExists2(candidate)) return candidate;
|
|
5504
|
+
}
|
|
5505
|
+
const sourceRoot = await fileExists2(join5(projectRoot, "src")) ? join5(projectRoot, "src") : projectRoot;
|
|
5506
|
+
const extension = await fileExists2(join5(projectRoot, "tsconfig.json")) ? "ts" : "js";
|
|
5507
|
+
return join5(sourceRoot, `instrumentation-client.${extension}`);
|
|
5508
|
+
}
|
|
5509
|
+
async function configureNextClient(clientPath) {
|
|
5510
|
+
let source = "";
|
|
5511
|
+
try {
|
|
5512
|
+
source = await readFile5(clientPath, "utf8");
|
|
5513
|
+
} catch (error) {
|
|
5514
|
+
if (!isMissingFile(error)) throw error;
|
|
5515
|
+
}
|
|
5516
|
+
if (source.includes(NEXT_CLIENT_MODULE)) return false;
|
|
5517
|
+
const separator = source.length === 0 || source.endsWith("\n") ? "" : "\n";
|
|
5518
|
+
await mkdir3(dirname4(clientPath), { recursive: true });
|
|
5519
|
+
await writeFile3(clientPath, `${source}${separator}${NEXT_CLIENT_BOOTSTRAP}`, "utf8");
|
|
5520
|
+
return true;
|
|
5521
|
+
}
|
|
5370
5522
|
function installCommand(request) {
|
|
5371
5523
|
if (request.packageManager === "pnpm") {
|
|
5372
5524
|
return {
|
|
@@ -5416,11 +5568,12 @@ async function initializeVisualDev(dependencies = {}) {
|
|
|
5416
5568
|
const repoRoot = await discoverGitWorktreeRoot(projectRoot);
|
|
5417
5569
|
const manifest = await readManifest(projectRoot);
|
|
5418
5570
|
const devScript = readDevScript(manifest);
|
|
5419
|
-
|
|
5420
|
-
|
|
5571
|
+
const framework = isViteProject(manifest, devScript) ? "vite" : isNextProject(manifest, devScript) ? "next" : void 0;
|
|
5572
|
+
if (framework === void 0) {
|
|
5573
|
+
throw new Error("visual init currently supports Vite and Next.js projects");
|
|
5421
5574
|
}
|
|
5422
5575
|
const packageManager = await detectPackageManager(projectRoot, repoRoot, manifest);
|
|
5423
|
-
const integrationPath = await findViteConfig(projectRoot);
|
|
5576
|
+
const integrationPath = framework === "vite" ? await findViteConfig(projectRoot) : await findNextConfig(projectRoot);
|
|
5424
5577
|
const packageInstalled = !hasVisualRemote(manifest);
|
|
5425
5578
|
if (packageInstalled) {
|
|
5426
5579
|
await (dependencies.installPackage ?? installPackage)({
|
|
@@ -5429,7 +5582,9 @@ async function initializeVisualDev(dependencies = {}) {
|
|
|
5429
5582
|
packageSpec: "visual-remote@latest"
|
|
5430
5583
|
});
|
|
5431
5584
|
}
|
|
5432
|
-
const integrationChanged = await configureVite(integrationPath);
|
|
5585
|
+
const integrationChanged = framework === "vite" ? await configureVite(integrationPath) : await configureNext(integrationPath);
|
|
5586
|
+
const clientPath = framework === "next" ? await findNextClientPath(projectRoot) : void 0;
|
|
5587
|
+
const clientChanged = clientPath === void 0 ? void 0 : await configureNextClient(clientPath);
|
|
5433
5588
|
const configPath = join5(projectRoot, CONFIG_PATH);
|
|
5434
5589
|
const created = !await fileExists2(configPath);
|
|
5435
5590
|
if (created) {
|
|
@@ -5461,24 +5616,35 @@ async function initializeVisualDev(dependencies = {}) {
|
|
|
5461
5616
|
}
|
|
5462
5617
|
}
|
|
5463
5618
|
return {
|
|
5619
|
+
framework,
|
|
5464
5620
|
created,
|
|
5465
5621
|
configPath,
|
|
5466
5622
|
devScript,
|
|
5467
5623
|
packageManager,
|
|
5468
5624
|
integrationPath,
|
|
5469
5625
|
integrationChanged,
|
|
5626
|
+
...clientPath === void 0 || clientChanged === void 0 ? {} : { clientPath, clientChanged },
|
|
5470
5627
|
packageInstalled
|
|
5471
5628
|
};
|
|
5472
5629
|
}
|
|
5473
5630
|
function formatInitResult(result) {
|
|
5474
5631
|
const configLabel = result.created ? "Created" : "Existing";
|
|
5475
5632
|
const integrationLabel = result.integrationChanged ? "Configured" : "Existing";
|
|
5476
|
-
|
|
5633
|
+
const rows = [
|
|
5634
|
+
`Framework: ${result.framework === "next" ? "Next.js" : "Vite"}`,
|
|
5477
5635
|
`${configLabel}: ${relative7(process.cwd(), result.configPath) || CONFIG_PATH}`,
|
|
5478
|
-
`${integrationLabel}: ${relative7(process.cwd(), result.integrationPath)}
|
|
5636
|
+
`${integrationLabel}: ${relative7(process.cwd(), result.integrationPath)}`
|
|
5637
|
+
];
|
|
5638
|
+
if (result.clientPath !== void 0) {
|
|
5639
|
+
rows.push(
|
|
5640
|
+
`${result.clientChanged ? "Configured" : "Existing"}: ${relative7(process.cwd(), result.clientPath)}`
|
|
5641
|
+
);
|
|
5642
|
+
}
|
|
5643
|
+
rows.push(
|
|
5479
5644
|
result.packageInstalled ? "Installed: visual-remote@latest" : "Installed: visual-remote",
|
|
5480
5645
|
"Next: Start the app normally and open its original URL."
|
|
5481
|
-
|
|
5646
|
+
);
|
|
5647
|
+
return rows.join("\n");
|
|
5482
5648
|
}
|
|
5483
5649
|
|
|
5484
5650
|
// src/status.ts
|
|
@@ -5531,8 +5697,8 @@ function setExitCode(dependencies, code) {
|
|
|
5531
5697
|
}
|
|
5532
5698
|
}
|
|
5533
5699
|
function createCli(dependencies = {}) {
|
|
5534
|
-
const program = new Command().name("visual").description("Visual Remote Dev Bridge").version("0.
|
|
5535
|
-
program.command("init").description("
|
|
5700
|
+
const program = new Command().name("visual").description("Visual Remote Dev Bridge").version("0.3.0");
|
|
5701
|
+
program.command("init").description("Configure Visual Remote for the current Vite or Next.js project").action(async () => {
|
|
5536
5702
|
const result = await initializeVisualDev(dependencies);
|
|
5537
5703
|
output(dependencies, formatInitResult(result));
|
|
5538
5704
|
});
|
|
@@ -5611,5 +5777,6 @@ export {
|
|
|
5611
5777
|
runDoctor,
|
|
5612
5778
|
startAttachBridge,
|
|
5613
5779
|
startManagedBridge,
|
|
5780
|
+
transformNextConfig,
|
|
5614
5781
|
transformViteConfig
|
|
5615
5782
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/next-client.ts
|
|
2
|
+
var clientPath = "/_visual/client.js";
|
|
3
|
+
if (document.querySelector(`script[src="${clientPath}"]`) === null && document.querySelector("script[data-visual-remote-client]") === null) {
|
|
4
|
+
const script = document.createElement("script");
|
|
5
|
+
script.type = "module";
|
|
6
|
+
script.src = clientPath;
|
|
7
|
+
script.dataset.visualRemoteClient = "";
|
|
8
|
+
const nonceSource = document.querySelector("script[nonce]");
|
|
9
|
+
if (nonceSource?.nonce) script.nonce = nonceSource.nonce;
|
|
10
|
+
document.head.append(script);
|
|
11
|
+
}
|