@revyse/next 0.0.0-stage → 0.1.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 +18 -2
- package/dist/client.cjs +11 -0
- package/dist/client.js +9 -0
- package/dist/index.cjs +189 -0
- package/dist/index.d.cts +57 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +143 -0
- package/dist/loader.cjs +15914 -0
- package/dist/loader.js +15879 -0
- package/package.json +54 -3
package/README.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @revyse/next
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Next.js integration for Revyse: in development builds only, tags elements with their source
|
|
4
|
+
location and injects the Revyse overlay served by the local agent (`npx revyse dev`). A
|
|
5
|
+
production build is untouched; a test proves it.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// next.config.ts
|
|
9
|
+
import { withRevyse } from "@revyse/next";
|
|
10
|
+
|
|
11
|
+
export default withRevyse({/* your config */});
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`npx revyse init` makes this edit for you as a diff you approve. Works with the App Router
|
|
15
|
+
and the Pages Router, webpack and Turbopack, Next 14 to 16.
|
|
16
|
+
|
|
17
|
+
## License
|
|
18
|
+
|
|
19
|
+
Proprietary (`UNLICENSED`). Use is governed by the Revyse terms: https://revyse.dev/terms
|
package/dist/client.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// src/client.ts
|
|
4
|
+
var url = decodeURIComponent(__resourceQuery.slice(1));
|
|
5
|
+
if (typeof document !== "undefined" && url && !document.querySelector(`script[src="${url}"]`)) {
|
|
6
|
+
const script = document.createElement("script");
|
|
7
|
+
script.type = "module";
|
|
8
|
+
script.async = true;
|
|
9
|
+
script.src = url;
|
|
10
|
+
document.head.append(script);
|
|
11
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var url = decodeURIComponent(__resourceQuery.slice(1));
|
|
3
|
+
if (typeof document !== "undefined" && url && !document.querySelector(`script[src="${url}"]`)) {
|
|
4
|
+
const script = document.createElement("script");
|
|
5
|
+
script.type = "module";
|
|
6
|
+
script.async = true;
|
|
7
|
+
script.src = url;
|
|
8
|
+
document.head.append(script);
|
|
9
|
+
}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
DEFAULT_AGENT_PORT: () => DEFAULT_AGENT_PORT,
|
|
34
|
+
DEFAULT_APP_URL: () => DEFAULT_APP_URL,
|
|
35
|
+
LOCATIONS_DIR: () => LOCATIONS_DIR,
|
|
36
|
+
liveLoaderScript: () => liveLoaderScript,
|
|
37
|
+
pagesRouterOf: () => pagesRouterOf,
|
|
38
|
+
withRevyse: () => withRevyse
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(src_exports);
|
|
41
|
+
|
|
42
|
+
// ../../node_modules/.pnpm/tsup@9.0.0_jiti@2.7.0_postcss@8.5.31_tsx@4.23.15_typescript@6.0.3/node_modules/tsup/assets/cjs_shims.js
|
|
43
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
44
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
45
|
+
|
|
46
|
+
// src/index.ts
|
|
47
|
+
var import_node_fs = require("fs");
|
|
48
|
+
var import_node_module = require("module");
|
|
49
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
50
|
+
var LOCATIONS_DIR = import_node_path.default.join("revyse", "locations");
|
|
51
|
+
var DEFAULT_AGENT_PORT = 4545;
|
|
52
|
+
var DEFAULT_APP_URL = "https://revyse.dev";
|
|
53
|
+
var PHASE_DEVELOPMENT_SERVER = "phase-development-server";
|
|
54
|
+
var PHASE_PRODUCTION_BUILD = "phase-production-build";
|
|
55
|
+
var require_ = (0, import_node_module.createRequire)(importMetaUrl);
|
|
56
|
+
function pagesRouterOf(root) {
|
|
57
|
+
for (const dir of ["pages", "src/pages"]) {
|
|
58
|
+
if (!(0, import_node_fs.existsSync)(import_node_path.default.join(root, dir))) continue;
|
|
59
|
+
const hasDocument = ["tsx", "jsx", "ts", "js"].some(
|
|
60
|
+
(ext) => (0, import_node_fs.existsSync)(import_node_path.default.join(root, dir, `_document.${ext}`))
|
|
61
|
+
);
|
|
62
|
+
return { dir, hasDocument };
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
var withImport = (entry, add) => {
|
|
67
|
+
const list = (v) => Array.isArray(v) ? v : [v];
|
|
68
|
+
if (typeof entry === "object" && !Array.isArray(entry))
|
|
69
|
+
return { ...entry, import: [...list(entry.import), add] };
|
|
70
|
+
return [...list(entry), add];
|
|
71
|
+
};
|
|
72
|
+
function liveLoaderScript(live) {
|
|
73
|
+
if (!/^pk_live_[0-9a-f]{32}$/.test(live.projectKey))
|
|
74
|
+
throw new Error(
|
|
75
|
+
"[revyse] live.projectKey must be the project's public key (pk_live_\u2026) from the Revyse project page"
|
|
76
|
+
);
|
|
77
|
+
const appUrl = live.appUrl ?? process.env.REVYSE_APP_URL ?? DEFAULT_APP_URL;
|
|
78
|
+
return { src: `${new URL(appUrl).origin}/live.js`, projectKey: live.projectKey };
|
|
79
|
+
}
|
|
80
|
+
function withRevyse(config = {}, options = {}) {
|
|
81
|
+
return async (phase, ctx) => {
|
|
82
|
+
const resolved = typeof config === "function" ? await config(phase, ctx) : config;
|
|
83
|
+
if (phase === PHASE_PRODUCTION_BUILD && options.live) {
|
|
84
|
+
return withLiveLoader(resolved, options.projectRoot ?? process.cwd(), options.live);
|
|
85
|
+
}
|
|
86
|
+
if (phase !== PHASE_DEVELOPMENT_SERVER || process.env.NODE_ENV === "production") {
|
|
87
|
+
return resolved;
|
|
88
|
+
}
|
|
89
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
90
|
+
const overlayScriptUrl = `http://127.0.0.1:${options.agentPort ?? DEFAULT_AGENT_PORT}/overlay.js`;
|
|
91
|
+
const loader = {
|
|
92
|
+
loader: require_.resolve("@revyse/next/loader"),
|
|
93
|
+
options: { projectRoot, overlayScriptUrl }
|
|
94
|
+
};
|
|
95
|
+
const pages = pagesRouterOf(projectRoot);
|
|
96
|
+
if (pages && !pages.hasDocument && process.env.TURBOPACK) {
|
|
97
|
+
console.warn(
|
|
98
|
+
`[revyse] ${pages.dir}/ has no custom _document, so with Turbopack Revyse can't load its overlay on Pages Router pages. Add ${pages.dir}/_document.tsx (Next's default document is fine), or run next dev with --webpack.`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const rule = {
|
|
102
|
+
loaders: [loader],
|
|
103
|
+
// Development only, and never third-party code.
|
|
104
|
+
condition: { all: ["development", { not: "foreign" }] }
|
|
105
|
+
};
|
|
106
|
+
const userWebpack = resolved.webpack;
|
|
107
|
+
return {
|
|
108
|
+
...resolved,
|
|
109
|
+
turbopack: {
|
|
110
|
+
...resolved.turbopack,
|
|
111
|
+
rules: { ...resolved.turbopack?.rules, "*.tsx": rule, "*.jsx": rule }
|
|
112
|
+
},
|
|
113
|
+
webpack(webpackConfig, context) {
|
|
114
|
+
const out = userWebpack ? userWebpack(webpackConfig, context) : webpackConfig;
|
|
115
|
+
if (context.dev) {
|
|
116
|
+
out.module.rules.unshift({
|
|
117
|
+
test: /\.(t|j)sx$/,
|
|
118
|
+
exclude: /node_modules/,
|
|
119
|
+
enforce: "pre",
|
|
120
|
+
use: [loader]
|
|
121
|
+
});
|
|
122
|
+
if (pages && !context.isServer) {
|
|
123
|
+
const client = `${require_.resolve("@revyse/next/client")}?${encodeURIComponent(overlayScriptUrl)}`;
|
|
124
|
+
const original = out.entry;
|
|
125
|
+
out.entry = async () => {
|
|
126
|
+
const entries = await (typeof original === "function" ? original() : original);
|
|
127
|
+
if (entries.main) entries.main = withImport(entries.main, client);
|
|
128
|
+
return entries;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function withLiveLoader(resolved, projectRoot, live) {
|
|
138
|
+
const token = process.env.REVYSE_BUILD_TOKEN;
|
|
139
|
+
if (live.locations && !token?.startsWith("rvb_"))
|
|
140
|
+
console.warn(
|
|
141
|
+
"[revyse] live.locations is on but REVYSE_BUILD_TOKEN isn't set, so this build has no exact locations. Create a build token on the project's Live site tab and set it where the site builds."
|
|
142
|
+
);
|
|
143
|
+
const locations = live.locations && token?.startsWith("rvb_") ? {
|
|
144
|
+
token,
|
|
145
|
+
manifestDir: import_node_path.default.join(projectRoot, resolved.distDir ?? ".next", LOCATIONS_DIR)
|
|
146
|
+
} : void 0;
|
|
147
|
+
const loader = {
|
|
148
|
+
loader: require_.resolve("@revyse/next/loader"),
|
|
149
|
+
options: {
|
|
150
|
+
projectRoot,
|
|
151
|
+
liveScript: liveLoaderScript(live),
|
|
152
|
+
...locations ? { locations } : {}
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const pages = pagesRouterOf(projectRoot);
|
|
156
|
+
if (pages && !pages.hasDocument) {
|
|
157
|
+
console.warn(
|
|
158
|
+
`[revyse] ${pages.dir}/ has no custom _document, so the live overlay's loader can't be added to Pages Router pages. Add ${pages.dir}/_document.tsx (Next's default document is fine).`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
const rule = { loaders: [loader], condition: { not: "foreign" } };
|
|
162
|
+
const userWebpack = resolved.webpack;
|
|
163
|
+
return {
|
|
164
|
+
...resolved,
|
|
165
|
+
turbopack: {
|
|
166
|
+
...resolved.turbopack,
|
|
167
|
+
rules: { ...resolved.turbopack?.rules, "*.tsx": rule, "*.jsx": rule }
|
|
168
|
+
},
|
|
169
|
+
webpack(webpackConfig, context) {
|
|
170
|
+
const out = userWebpack ? userWebpack(webpackConfig, context) : webpackConfig;
|
|
171
|
+
out.module.rules.unshift({
|
|
172
|
+
test: /\.(t|j)sx$/,
|
|
173
|
+
exclude: /node_modules/,
|
|
174
|
+
enforce: "pre",
|
|
175
|
+
use: [loader]
|
|
176
|
+
});
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
182
|
+
0 && (module.exports = {
|
|
183
|
+
DEFAULT_AGENT_PORT,
|
|
184
|
+
DEFAULT_APP_URL,
|
|
185
|
+
LOCATIONS_DIR,
|
|
186
|
+
liveLoaderScript,
|
|
187
|
+
pagesRouterOf,
|
|
188
|
+
withRevyse
|
|
189
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
|
|
3
|
+
interface RevyseNextOptions {
|
|
4
|
+
/** Port of the local Revyse agent started by `revyse dev`. */
|
|
5
|
+
agentPort?: number;
|
|
6
|
+
/** Project root; defaults to the directory Next runs in. */
|
|
7
|
+
projectRoot?: string;
|
|
8
|
+
/**
|
|
9
|
+
* The live overlay on the deployed site (ADR 0032): production builds get one `async`
|
|
10
|
+
* script tag for the Revyse loader, carrying the project's public key from the project page.
|
|
11
|
+
* The loader is inert for visitors; members activate it from Revyse. Without this option a
|
|
12
|
+
* production build contains no Revyse code at all.
|
|
13
|
+
*/
|
|
14
|
+
live?: {
|
|
15
|
+
/** The project's public key (`pk_live_…`), shown on the project page. */
|
|
16
|
+
projectKey: string;
|
|
17
|
+
/** The Revyse app serving the loader; defaults to `REVYSE_APP_URL` or https://revyse.dev. */
|
|
18
|
+
appUrl?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Exact locations (W8, ADR 0032 §6): elements get opaque `data-rv` ids keyed with the
|
|
21
|
+
* project's build token (`REVYSE_BUILD_TOKEN` in the build environment), and the build
|
|
22
|
+
* writes the manifest (id → file:line:col) under its output directory for
|
|
23
|
+
* `revyse live upload`. No path is in the pages. Without the token the build goes on
|
|
24
|
+
* without locations, and says so.
|
|
25
|
+
*/
|
|
26
|
+
locations?: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Where a build with exact locations writes its manifest, inside Next's output directory. */
|
|
30
|
+
declare const LOCATIONS_DIR: string;
|
|
31
|
+
declare const DEFAULT_AGENT_PORT = 4545;
|
|
32
|
+
declare const DEFAULT_APP_URL = "https://revyse.dev";
|
|
33
|
+
type ConfigInput = NextConfig | ((phase: string, ctx: {
|
|
34
|
+
defaultConfig: NextConfig;
|
|
35
|
+
}) => NextConfig | Promise<NextConfig>);
|
|
36
|
+
/** The Pages Router directory and whether it has a custom `_document`, if the app has one. */
|
|
37
|
+
declare function pagesRouterOf(root: string): {
|
|
38
|
+
dir: string;
|
|
39
|
+
hasDocument: boolean;
|
|
40
|
+
} | null;
|
|
41
|
+
/** The loader tag for a production build with the `live` option (ADR 0032 §1). */
|
|
42
|
+
declare function liveLoaderScript(live: NonNullable<RevyseNextOptions["live"]>): {
|
|
43
|
+
src: string;
|
|
44
|
+
projectKey: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Wraps a Next.js config. In `next dev` it adds a JSX loader (webpack and Turbopack) that tags
|
|
48
|
+
* host elements with their source location and loads the Revyse overlay. In every other phase
|
|
49
|
+
* — including `next build` — the config is returned untouched, so nothing ships to production,
|
|
50
|
+
* with one opt-in exception: `live` adds the live overlay's loader tag to production builds.
|
|
51
|
+
*/
|
|
52
|
+
declare function withRevyse(config?: ConfigInput, options?: RevyseNextOptions): (phase: string, ctx: {
|
|
53
|
+
defaultConfig: NextConfig;
|
|
54
|
+
}) => Promise<NextConfig>;
|
|
55
|
+
|
|
56
|
+
export { DEFAULT_AGENT_PORT, DEFAULT_APP_URL, LOCATIONS_DIR, liveLoaderScript, pagesRouterOf, withRevyse };
|
|
57
|
+
export type { RevyseNextOptions };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
|
|
3
|
+
interface RevyseNextOptions {
|
|
4
|
+
/** Port of the local Revyse agent started by `revyse dev`. */
|
|
5
|
+
agentPort?: number;
|
|
6
|
+
/** Project root; defaults to the directory Next runs in. */
|
|
7
|
+
projectRoot?: string;
|
|
8
|
+
/**
|
|
9
|
+
* The live overlay on the deployed site (ADR 0032): production builds get one `async`
|
|
10
|
+
* script tag for the Revyse loader, carrying the project's public key from the project page.
|
|
11
|
+
* The loader is inert for visitors; members activate it from Revyse. Without this option a
|
|
12
|
+
* production build contains no Revyse code at all.
|
|
13
|
+
*/
|
|
14
|
+
live?: {
|
|
15
|
+
/** The project's public key (`pk_live_…`), shown on the project page. */
|
|
16
|
+
projectKey: string;
|
|
17
|
+
/** The Revyse app serving the loader; defaults to `REVYSE_APP_URL` or https://revyse.dev. */
|
|
18
|
+
appUrl?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Exact locations (W8, ADR 0032 §6): elements get opaque `data-rv` ids keyed with the
|
|
21
|
+
* project's build token (`REVYSE_BUILD_TOKEN` in the build environment), and the build
|
|
22
|
+
* writes the manifest (id → file:line:col) under its output directory for
|
|
23
|
+
* `revyse live upload`. No path is in the pages. Without the token the build goes on
|
|
24
|
+
* without locations, and says so.
|
|
25
|
+
*/
|
|
26
|
+
locations?: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Where a build with exact locations writes its manifest, inside Next's output directory. */
|
|
30
|
+
declare const LOCATIONS_DIR: string;
|
|
31
|
+
declare const DEFAULT_AGENT_PORT = 4545;
|
|
32
|
+
declare const DEFAULT_APP_URL = "https://revyse.dev";
|
|
33
|
+
type ConfigInput = NextConfig | ((phase: string, ctx: {
|
|
34
|
+
defaultConfig: NextConfig;
|
|
35
|
+
}) => NextConfig | Promise<NextConfig>);
|
|
36
|
+
/** The Pages Router directory and whether it has a custom `_document`, if the app has one. */
|
|
37
|
+
declare function pagesRouterOf(root: string): {
|
|
38
|
+
dir: string;
|
|
39
|
+
hasDocument: boolean;
|
|
40
|
+
} | null;
|
|
41
|
+
/** The loader tag for a production build with the `live` option (ADR 0032 §1). */
|
|
42
|
+
declare function liveLoaderScript(live: NonNullable<RevyseNextOptions["live"]>): {
|
|
43
|
+
src: string;
|
|
44
|
+
projectKey: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Wraps a Next.js config. In `next dev` it adds a JSX loader (webpack and Turbopack) that tags
|
|
48
|
+
* host elements with their source location and loads the Revyse overlay. In every other phase
|
|
49
|
+
* — including `next build` — the config is returned untouched, so nothing ships to production,
|
|
50
|
+
* with one opt-in exception: `live` adds the live overlay's loader tag to production builds.
|
|
51
|
+
*/
|
|
52
|
+
declare function withRevyse(config?: ConfigInput, options?: RevyseNextOptions): (phase: string, ctx: {
|
|
53
|
+
defaultConfig: NextConfig;
|
|
54
|
+
}) => Promise<NextConfig>;
|
|
55
|
+
|
|
56
|
+
export { DEFAULT_AGENT_PORT, DEFAULT_APP_URL, LOCATIONS_DIR, liveLoaderScript, pagesRouterOf, withRevyse };
|
|
57
|
+
export type { RevyseNextOptions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { createRequire } from "module";
|
|
4
|
+
import path from "path";
|
|
5
|
+
var LOCATIONS_DIR = path.join("revyse", "locations");
|
|
6
|
+
var DEFAULT_AGENT_PORT = 4545;
|
|
7
|
+
var DEFAULT_APP_URL = "https://revyse.dev";
|
|
8
|
+
var PHASE_DEVELOPMENT_SERVER = "phase-development-server";
|
|
9
|
+
var PHASE_PRODUCTION_BUILD = "phase-production-build";
|
|
10
|
+
var require_ = createRequire(import.meta.url);
|
|
11
|
+
function pagesRouterOf(root) {
|
|
12
|
+
for (const dir of ["pages", "src/pages"]) {
|
|
13
|
+
if (!existsSync(path.join(root, dir))) continue;
|
|
14
|
+
const hasDocument = ["tsx", "jsx", "ts", "js"].some(
|
|
15
|
+
(ext) => existsSync(path.join(root, dir, `_document.${ext}`))
|
|
16
|
+
);
|
|
17
|
+
return { dir, hasDocument };
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
var withImport = (entry, add) => {
|
|
22
|
+
const list = (v) => Array.isArray(v) ? v : [v];
|
|
23
|
+
if (typeof entry === "object" && !Array.isArray(entry))
|
|
24
|
+
return { ...entry, import: [...list(entry.import), add] };
|
|
25
|
+
return [...list(entry), add];
|
|
26
|
+
};
|
|
27
|
+
function liveLoaderScript(live) {
|
|
28
|
+
if (!/^pk_live_[0-9a-f]{32}$/.test(live.projectKey))
|
|
29
|
+
throw new Error(
|
|
30
|
+
"[revyse] live.projectKey must be the project's public key (pk_live_\u2026) from the Revyse project page"
|
|
31
|
+
);
|
|
32
|
+
const appUrl = live.appUrl ?? process.env.REVYSE_APP_URL ?? DEFAULT_APP_URL;
|
|
33
|
+
return { src: `${new URL(appUrl).origin}/live.js`, projectKey: live.projectKey };
|
|
34
|
+
}
|
|
35
|
+
function withRevyse(config = {}, options = {}) {
|
|
36
|
+
return async (phase, ctx) => {
|
|
37
|
+
const resolved = typeof config === "function" ? await config(phase, ctx) : config;
|
|
38
|
+
if (phase === PHASE_PRODUCTION_BUILD && options.live) {
|
|
39
|
+
return withLiveLoader(resolved, options.projectRoot ?? process.cwd(), options.live);
|
|
40
|
+
}
|
|
41
|
+
if (phase !== PHASE_DEVELOPMENT_SERVER || process.env.NODE_ENV === "production") {
|
|
42
|
+
return resolved;
|
|
43
|
+
}
|
|
44
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
45
|
+
const overlayScriptUrl = `http://127.0.0.1:${options.agentPort ?? DEFAULT_AGENT_PORT}/overlay.js`;
|
|
46
|
+
const loader = {
|
|
47
|
+
loader: require_.resolve("@revyse/next/loader"),
|
|
48
|
+
options: { projectRoot, overlayScriptUrl }
|
|
49
|
+
};
|
|
50
|
+
const pages = pagesRouterOf(projectRoot);
|
|
51
|
+
if (pages && !pages.hasDocument && process.env.TURBOPACK) {
|
|
52
|
+
console.warn(
|
|
53
|
+
`[revyse] ${pages.dir}/ has no custom _document, so with Turbopack Revyse can't load its overlay on Pages Router pages. Add ${pages.dir}/_document.tsx (Next's default document is fine), or run next dev with --webpack.`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const rule = {
|
|
57
|
+
loaders: [loader],
|
|
58
|
+
// Development only, and never third-party code.
|
|
59
|
+
condition: { all: ["development", { not: "foreign" }] }
|
|
60
|
+
};
|
|
61
|
+
const userWebpack = resolved.webpack;
|
|
62
|
+
return {
|
|
63
|
+
...resolved,
|
|
64
|
+
turbopack: {
|
|
65
|
+
...resolved.turbopack,
|
|
66
|
+
rules: { ...resolved.turbopack?.rules, "*.tsx": rule, "*.jsx": rule }
|
|
67
|
+
},
|
|
68
|
+
webpack(webpackConfig, context) {
|
|
69
|
+
const out = userWebpack ? userWebpack(webpackConfig, context) : webpackConfig;
|
|
70
|
+
if (context.dev) {
|
|
71
|
+
out.module.rules.unshift({
|
|
72
|
+
test: /\.(t|j)sx$/,
|
|
73
|
+
exclude: /node_modules/,
|
|
74
|
+
enforce: "pre",
|
|
75
|
+
use: [loader]
|
|
76
|
+
});
|
|
77
|
+
if (pages && !context.isServer) {
|
|
78
|
+
const client = `${require_.resolve("@revyse/next/client")}?${encodeURIComponent(overlayScriptUrl)}`;
|
|
79
|
+
const original = out.entry;
|
|
80
|
+
out.entry = async () => {
|
|
81
|
+
const entries = await (typeof original === "function" ? original() : original);
|
|
82
|
+
if (entries.main) entries.main = withImport(entries.main, client);
|
|
83
|
+
return entries;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function withLiveLoader(resolved, projectRoot, live) {
|
|
93
|
+
const token = process.env.REVYSE_BUILD_TOKEN;
|
|
94
|
+
if (live.locations && !token?.startsWith("rvb_"))
|
|
95
|
+
console.warn(
|
|
96
|
+
"[revyse] live.locations is on but REVYSE_BUILD_TOKEN isn't set, so this build has no exact locations. Create a build token on the project's Live site tab and set it where the site builds."
|
|
97
|
+
);
|
|
98
|
+
const locations = live.locations && token?.startsWith("rvb_") ? {
|
|
99
|
+
token,
|
|
100
|
+
manifestDir: path.join(projectRoot, resolved.distDir ?? ".next", LOCATIONS_DIR)
|
|
101
|
+
} : void 0;
|
|
102
|
+
const loader = {
|
|
103
|
+
loader: require_.resolve("@revyse/next/loader"),
|
|
104
|
+
options: {
|
|
105
|
+
projectRoot,
|
|
106
|
+
liveScript: liveLoaderScript(live),
|
|
107
|
+
...locations ? { locations } : {}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const pages = pagesRouterOf(projectRoot);
|
|
111
|
+
if (pages && !pages.hasDocument) {
|
|
112
|
+
console.warn(
|
|
113
|
+
`[revyse] ${pages.dir}/ has no custom _document, so the live overlay's loader can't be added to Pages Router pages. Add ${pages.dir}/_document.tsx (Next's default document is fine).`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const rule = { loaders: [loader], condition: { not: "foreign" } };
|
|
117
|
+
const userWebpack = resolved.webpack;
|
|
118
|
+
return {
|
|
119
|
+
...resolved,
|
|
120
|
+
turbopack: {
|
|
121
|
+
...resolved.turbopack,
|
|
122
|
+
rules: { ...resolved.turbopack?.rules, "*.tsx": rule, "*.jsx": rule }
|
|
123
|
+
},
|
|
124
|
+
webpack(webpackConfig, context) {
|
|
125
|
+
const out = userWebpack ? userWebpack(webpackConfig, context) : webpackConfig;
|
|
126
|
+
out.module.rules.unshift({
|
|
127
|
+
test: /\.(t|j)sx$/,
|
|
128
|
+
exclude: /node_modules/,
|
|
129
|
+
enforce: "pre",
|
|
130
|
+
use: [loader]
|
|
131
|
+
});
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export {
|
|
137
|
+
DEFAULT_AGENT_PORT,
|
|
138
|
+
DEFAULT_APP_URL,
|
|
139
|
+
LOCATIONS_DIR,
|
|
140
|
+
liveLoaderScript,
|
|
141
|
+
pagesRouterOf,
|
|
142
|
+
withRevyse
|
|
143
|
+
};
|