@revyse/next 0.1.0 → 0.2.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # @revyse/next
2
2
 
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.
3
+ Next.js integration for Revyse: in `next dev` only, starts the local agent, tags elements with
4
+ their source location and injects the Revyse overlay, so there is no separate `revyse dev` to
5
+ run. A production build is untouched; a test proves it.
6
6
 
7
7
  ```ts
8
8
  // next.config.ts
package/dist/index.cjs CHANGED
@@ -33,6 +33,8 @@ __export(src_exports, {
33
33
  DEFAULT_AGENT_PORT: () => DEFAULT_AGENT_PORT,
34
34
  DEFAULT_APP_URL: () => DEFAULT_APP_URL,
35
35
  LOCATIONS_DIR: () => LOCATIONS_DIR,
36
+ configuredAgentPort: () => configuredAgentPort,
37
+ ensureLocalAgent: () => ensureLocalAgent,
36
38
  liveLoaderScript: () => liveLoaderScript,
37
39
  pagesRouterOf: () => pagesRouterOf,
38
40
  withRevyse: () => withRevyse
@@ -53,6 +55,44 @@ var DEFAULT_APP_URL = "https://revyse.dev";
53
55
  var PHASE_DEVELOPMENT_SERVER = "phase-development-server";
54
56
  var PHASE_PRODUCTION_BUILD = "phase-production-build";
55
57
  var require_ = (0, import_node_module.createRequire)(importMetaUrl);
58
+ function configuredAgentPort(root) {
59
+ try {
60
+ const config = JSON.parse((0, import_node_fs.readFileSync)(import_node_path.default.join(root, "revyse.config.json"), "utf8"));
61
+ return typeof config.agentPort === "number" ? config.agentPort : void 0;
62
+ } catch {
63
+ return void 0;
64
+ }
65
+ }
66
+ var say = (msg) => console.log(`[revyse] ${msg}`);
67
+ var warn = (msg) => console.warn(`[revyse] ${msg}`);
68
+ var agentStart;
69
+ function ensureLocalAgent(root, load = () => import("revyse/agent")) {
70
+ if (process.env.REVYSE_AGENT === "off") return Promise.resolve();
71
+ agentStart ??= startAgent(root, load).catch(
72
+ (err) => warn(
73
+ `Couldn't start Revyse (${err.message}). Check that \`revyse\` is installed as a dev dependency, or run \`npx revyse dev\`.`
74
+ )
75
+ );
76
+ return agentStart;
77
+ }
78
+ async function startAgent(root, load) {
79
+ if (!(0, import_node_fs.existsSync)(import_node_path.default.join(root, "revyse.config.json"))) {
80
+ warn("This app isn't set up for Revyse yet: run `npx revyse init`.");
81
+ return;
82
+ }
83
+ const { startLocalAgent } = await load();
84
+ const started = await startLocalAgent({ root, log: say });
85
+ if (started.status === "running") return;
86
+ if (started.status === "taken") {
87
+ warn(
88
+ started.root ? `Port ${started.port} is used by Revyse for ${started.root}, so the overlay here would talk to that project. Set "agentPort" in revyse.config.json to another port, such as ${started.port + 1}.` : `Port ${started.port} is in use by another program. Set "agentPort" in revyse.config.json to a free port.`
89
+ );
90
+ return;
91
+ }
92
+ say(
93
+ started.agent.connected ? "Ready: open your app and click the Revyse button." : "Ready, but this project isn't connected to Revyse yet: run `npx revyse init` to connect it."
94
+ );
95
+ }
56
96
  function pagesRouterOf(root) {
57
97
  for (const dir of ["pages", "src/pages"]) {
58
98
  if (!(0, import_node_fs.existsSync)(import_node_path.default.join(root, dir))) continue;
@@ -87,7 +127,9 @@ function withRevyse(config = {}, options = {}) {
87
127
  return resolved;
88
128
  }
89
129
  const projectRoot = options.projectRoot ?? process.cwd();
90
- const overlayScriptUrl = `http://127.0.0.1:${options.agentPort ?? DEFAULT_AGENT_PORT}/overlay.js`;
130
+ const agentPort = options.agentPort ?? configuredAgentPort(projectRoot) ?? DEFAULT_AGENT_PORT;
131
+ const overlayScriptUrl = `http://127.0.0.1:${agentPort}/overlay.js`;
132
+ void ensureLocalAgent(projectRoot);
91
133
  const loader = {
92
134
  loader: require_.resolve("@revyse/next/loader"),
93
135
  options: { projectRoot, overlayScriptUrl }
@@ -183,6 +225,8 @@ function withLiveLoader(resolved, projectRoot, live) {
183
225
  DEFAULT_AGENT_PORT,
184
226
  DEFAULT_APP_URL,
185
227
  LOCATIONS_DIR,
228
+ configuredAgentPort,
229
+ ensureLocalAgent,
186
230
  liveLoaderScript,
187
231
  pagesRouterOf,
188
232
  withRevyse
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { NextConfig } from 'next';
2
2
 
3
3
  interface RevyseNextOptions {
4
- /** Port of the local Revyse agent started by `revyse dev`. */
4
+ /** Port of the local Revyse agent; defaults to `agentPort` in `revyse.config.json`, then 4545. */
5
5
  agentPort?: number;
6
6
  /** Project root; defaults to the directory Next runs in. */
7
7
  projectRoot?: string;
@@ -33,6 +33,35 @@ declare const DEFAULT_APP_URL = "https://revyse.dev";
33
33
  type ConfigInput = NextConfig | ((phase: string, ctx: {
34
34
  defaultConfig: NextConfig;
35
35
  }) => NextConfig | Promise<NextConfig>);
36
+ /** `agentPort` from the project's `revyse.config.json`, if it has one. */
37
+ declare function configuredAgentPort(root: string): number | undefined;
38
+ /** What `withRevyse()` uses from `revyse/agent` (the CLI package's local agent). */
39
+ interface AgentModule {
40
+ startLocalAgent(opts: {
41
+ root: string;
42
+ log: (msg: string) => void;
43
+ }): Promise<{
44
+ status: "started";
45
+ agent: {
46
+ url: string;
47
+ connected: boolean;
48
+ };
49
+ } | {
50
+ status: "running";
51
+ port: number;
52
+ } | {
53
+ status: "taken";
54
+ port: number;
55
+ root: string | null;
56
+ }>;
57
+ }
58
+ /**
59
+ * Starts the local agent inside `next dev` (L14, ADR 0041), so the overlay works without
60
+ * `revyse dev`. Next 15 runs the config in its CLI process and its server process: whichever
61
+ * comes second finds this project's agent on the port and leaves it be. `REVYSE_AGENT=off`
62
+ * turns it off; `load` is for tests.
63
+ */
64
+ declare function ensureLocalAgent(root: string, load?: () => Promise<AgentModule>): Promise<void>;
36
65
  /** The Pages Router directory and whether it has a custom `_document`, if the app has one. */
37
66
  declare function pagesRouterOf(root: string): {
38
67
  dir: string;
@@ -44,8 +73,9 @@ declare function liveLoaderScript(live: NonNullable<RevyseNextOptions["live"]>):
44
73
  projectKey: string;
45
74
  };
46
75
  /**
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
76
+ * Wraps a Next.js config. In `next dev` it starts the local agent (L14) and adds a JSX loader
77
+ * (webpack and Turbopack) that tags host elements with their source location and loads the
78
+ * Revyse overlay. In every other phase
49
79
  * — including `next build` — the config is returned untouched, so nothing ships to production,
50
80
  * with one opt-in exception: `live` adds the live overlay's loader tag to production builds.
51
81
  */
@@ -53,5 +83,5 @@ declare function withRevyse(config?: ConfigInput, options?: RevyseNextOptions):
53
83
  defaultConfig: NextConfig;
54
84
  }) => Promise<NextConfig>;
55
85
 
56
- export { DEFAULT_AGENT_PORT, DEFAULT_APP_URL, LOCATIONS_DIR, liveLoaderScript, pagesRouterOf, withRevyse };
57
- export type { RevyseNextOptions };
86
+ export { DEFAULT_AGENT_PORT, DEFAULT_APP_URL, LOCATIONS_DIR, configuredAgentPort, ensureLocalAgent, liveLoaderScript, pagesRouterOf, withRevyse };
87
+ export type { AgentModule, RevyseNextOptions };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { NextConfig } from 'next';
2
2
 
3
3
  interface RevyseNextOptions {
4
- /** Port of the local Revyse agent started by `revyse dev`. */
4
+ /** Port of the local Revyse agent; defaults to `agentPort` in `revyse.config.json`, then 4545. */
5
5
  agentPort?: number;
6
6
  /** Project root; defaults to the directory Next runs in. */
7
7
  projectRoot?: string;
@@ -33,6 +33,35 @@ declare const DEFAULT_APP_URL = "https://revyse.dev";
33
33
  type ConfigInput = NextConfig | ((phase: string, ctx: {
34
34
  defaultConfig: NextConfig;
35
35
  }) => NextConfig | Promise<NextConfig>);
36
+ /** `agentPort` from the project's `revyse.config.json`, if it has one. */
37
+ declare function configuredAgentPort(root: string): number | undefined;
38
+ /** What `withRevyse()` uses from `revyse/agent` (the CLI package's local agent). */
39
+ interface AgentModule {
40
+ startLocalAgent(opts: {
41
+ root: string;
42
+ log: (msg: string) => void;
43
+ }): Promise<{
44
+ status: "started";
45
+ agent: {
46
+ url: string;
47
+ connected: boolean;
48
+ };
49
+ } | {
50
+ status: "running";
51
+ port: number;
52
+ } | {
53
+ status: "taken";
54
+ port: number;
55
+ root: string | null;
56
+ }>;
57
+ }
58
+ /**
59
+ * Starts the local agent inside `next dev` (L14, ADR 0041), so the overlay works without
60
+ * `revyse dev`. Next 15 runs the config in its CLI process and its server process: whichever
61
+ * comes second finds this project's agent on the port and leaves it be. `REVYSE_AGENT=off`
62
+ * turns it off; `load` is for tests.
63
+ */
64
+ declare function ensureLocalAgent(root: string, load?: () => Promise<AgentModule>): Promise<void>;
36
65
  /** The Pages Router directory and whether it has a custom `_document`, if the app has one. */
37
66
  declare function pagesRouterOf(root: string): {
38
67
  dir: string;
@@ -44,8 +73,9 @@ declare function liveLoaderScript(live: NonNullable<RevyseNextOptions["live"]>):
44
73
  projectKey: string;
45
74
  };
46
75
  /**
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
76
+ * Wraps a Next.js config. In `next dev` it starts the local agent (L14) and adds a JSX loader
77
+ * (webpack and Turbopack) that tags host elements with their source location and loads the
78
+ * Revyse overlay. In every other phase
49
79
  * — including `next build` — the config is returned untouched, so nothing ships to production,
50
80
  * with one opt-in exception: `live` adds the live overlay's loader tag to production builds.
51
81
  */
@@ -53,5 +83,5 @@ declare function withRevyse(config?: ConfigInput, options?: RevyseNextOptions):
53
83
  defaultConfig: NextConfig;
54
84
  }) => Promise<NextConfig>;
55
85
 
56
- export { DEFAULT_AGENT_PORT, DEFAULT_APP_URL, LOCATIONS_DIR, liveLoaderScript, pagesRouterOf, withRevyse };
57
- export type { RevyseNextOptions };
86
+ export { DEFAULT_AGENT_PORT, DEFAULT_APP_URL, LOCATIONS_DIR, configuredAgentPort, ensureLocalAgent, liveLoaderScript, pagesRouterOf, withRevyse };
87
+ export type { AgentModule, RevyseNextOptions };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { existsSync } from "fs";
2
+ import { existsSync, readFileSync } from "fs";
3
3
  import { createRequire } from "module";
4
4
  import path from "path";
5
5
  var LOCATIONS_DIR = path.join("revyse", "locations");
@@ -8,6 +8,44 @@ var DEFAULT_APP_URL = "https://revyse.dev";
8
8
  var PHASE_DEVELOPMENT_SERVER = "phase-development-server";
9
9
  var PHASE_PRODUCTION_BUILD = "phase-production-build";
10
10
  var require_ = createRequire(import.meta.url);
11
+ function configuredAgentPort(root) {
12
+ try {
13
+ const config = JSON.parse(readFileSync(path.join(root, "revyse.config.json"), "utf8"));
14
+ return typeof config.agentPort === "number" ? config.agentPort : void 0;
15
+ } catch {
16
+ return void 0;
17
+ }
18
+ }
19
+ var say = (msg) => console.log(`[revyse] ${msg}`);
20
+ var warn = (msg) => console.warn(`[revyse] ${msg}`);
21
+ var agentStart;
22
+ function ensureLocalAgent(root, load = () => import("revyse/agent")) {
23
+ if (process.env.REVYSE_AGENT === "off") return Promise.resolve();
24
+ agentStart ??= startAgent(root, load).catch(
25
+ (err) => warn(
26
+ `Couldn't start Revyse (${err.message}). Check that \`revyse\` is installed as a dev dependency, or run \`npx revyse dev\`.`
27
+ )
28
+ );
29
+ return agentStart;
30
+ }
31
+ async function startAgent(root, load) {
32
+ if (!existsSync(path.join(root, "revyse.config.json"))) {
33
+ warn("This app isn't set up for Revyse yet: run `npx revyse init`.");
34
+ return;
35
+ }
36
+ const { startLocalAgent } = await load();
37
+ const started = await startLocalAgent({ root, log: say });
38
+ if (started.status === "running") return;
39
+ if (started.status === "taken") {
40
+ warn(
41
+ started.root ? `Port ${started.port} is used by Revyse for ${started.root}, so the overlay here would talk to that project. Set "agentPort" in revyse.config.json to another port, such as ${started.port + 1}.` : `Port ${started.port} is in use by another program. Set "agentPort" in revyse.config.json to a free port.`
42
+ );
43
+ return;
44
+ }
45
+ say(
46
+ started.agent.connected ? "Ready: open your app and click the Revyse button." : "Ready, but this project isn't connected to Revyse yet: run `npx revyse init` to connect it."
47
+ );
48
+ }
11
49
  function pagesRouterOf(root) {
12
50
  for (const dir of ["pages", "src/pages"]) {
13
51
  if (!existsSync(path.join(root, dir))) continue;
@@ -42,7 +80,9 @@ function withRevyse(config = {}, options = {}) {
42
80
  return resolved;
43
81
  }
44
82
  const projectRoot = options.projectRoot ?? process.cwd();
45
- const overlayScriptUrl = `http://127.0.0.1:${options.agentPort ?? DEFAULT_AGENT_PORT}/overlay.js`;
83
+ const agentPort = options.agentPort ?? configuredAgentPort(projectRoot) ?? DEFAULT_AGENT_PORT;
84
+ const overlayScriptUrl = `http://127.0.0.1:${agentPort}/overlay.js`;
85
+ void ensureLocalAgent(projectRoot);
46
86
  const loader = {
47
87
  loader: require_.resolve("@revyse/next/loader"),
48
88
  options: { projectRoot, overlayScriptUrl }
@@ -137,6 +177,8 @@ export {
137
177
  DEFAULT_AGENT_PORT,
138
178
  DEFAULT_APP_URL,
139
179
  LOCATIONS_DIR,
180
+ configuredAgentPort,
181
+ ensureLocalAgent,
140
182
  liveLoaderScript,
141
183
  pagesRouterOf,
142
184
  withRevyse
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revyse/next",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Next.js integration for Revyse: dev-only source locations and overlay injection.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -38,7 +38,8 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/parser": "8.0.7",
41
- "magic-string": "1.4.3"
41
+ "magic-string": "1.4.3",
42
+ "revyse": "0.2.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@playwright/test": "~1.56.1",