@reticlehq/init 2.14.0 → 3.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/dist/{detect.d.ts → detect/detect.d.ts} +1 -1
- package/dist/{detect.js → detect/detect.js} +6 -2
- package/dist/{dev-server-ports.js → detect/dev-server-ports.js} +8 -0
- package/dist/{existing-config.d.ts → detect/existing-config.d.ts} +2 -4
- package/dist/{existing-config.js → detect/existing-config.js} +2 -4
- package/dist/{lockfiles.d.ts → detect/lockfiles.d.ts} +1 -1
- package/dist/{lockfiles.js → detect/lockfiles.js} +1 -2
- package/dist/{workspace-apps.d.ts → detect/workspace-apps.d.ts} +3 -5
- package/dist/{workspace-apps.js → detect/workspace-apps.js} +2 -4
- package/dist/{workspace-redirect.d.ts → detect/workspace-redirect.d.ts} +3 -5
- package/dist/{workspace-redirect.js → detect/workspace-redirect.js} +8 -12
- package/dist/{closing-hint.d.ts → diagnose/closing-hint.d.ts} +3 -4
- package/dist/{closing-hint.js → diagnose/closing-hint.js} +14 -19
- package/dist/diagnose/containerised-dev-server.d.ts +32 -0
- package/dist/diagnose/containerised-dev-server.js +56 -0
- package/dist/{csp-check.d.ts → diagnose/csp-check.d.ts} +2 -2
- package/dist/{csp-check.js → diagnose/csp-check.js} +2 -2
- package/dist/{desktop-doctor.js → diagnose/desktop-doctor.js} +12 -6
- package/dist/{init-failure.d.ts → diagnose/init-failure.d.ts} +1 -2
- package/dist/{init-failure.js → diagnose/init-failure.js} +1 -2
- package/dist/diagnose/install-hint.d.ts +8 -0
- package/dist/{install-hint.js → diagnose/install-hint.js} +3 -4
- package/dist/{install-retries.d.ts → diagnose/install-retries.d.ts} +3 -4
- package/dist/{install-retries.js → diagnose/install-retries.js} +6 -8
- package/dist/host.d.ts +14 -1
- package/dist/host.js +3 -0
- package/dist/index.d.ts +32 -12
- package/dist/index.js +36 -12
- package/dist/node-io.d.ts +12 -1
- package/dist/node-io.js +53 -25
- package/dist/{astro-patch.d.ts → patch/astro-patch.d.ts} +1 -1
- package/dist/{astro-patch.js → patch/astro-patch.js} +1 -1
- package/dist/{cra.js → patch/cra.js} +1 -1
- package/dist/{electron-patch.js → patch/electron-patch.js} +1 -1
- package/dist/{next-patch.d.ts → patch/next-patch.d.ts} +2 -2
- package/dist/{next-patch.js → patch/next-patch.js} +2 -2
- package/dist/{nuxt-patch.js → patch/nuxt-patch.js} +1 -1
- package/dist/{snippets.d.ts → patch/snippets.d.ts} +11 -21
- package/dist/{snippets.js → patch/snippets.js} +20 -29
- package/dist/{tanstack-start.d.ts → patch/tanstack-start.d.ts} +2 -3
- package/dist/{tanstack-start.js → patch/tanstack-start.js} +3 -4
- package/dist/{vite-config.js → patch/vite-config.js} +15 -13
- package/dist/{connect-steps.d.ts → plan/connect-steps.d.ts} +3 -3
- package/dist/{connect-steps.js → plan/connect-steps.js} +4 -4
- package/dist/{framework-adapter.d.ts → plan/framework-adapter.d.ts} +11 -2
- package/dist/{framework-adapter.js → plan/framework-adapter.js} +12 -1
- package/dist/plan/notices.d.ts +23 -0
- package/dist/plan/notices.js +94 -0
- package/dist/{plan-electron-vite.d.ts → plan/plan-electron-vite.d.ts} +3 -4
- package/dist/{plan-electron-vite.js → plan/plan-electron-vite.js} +7 -8
- package/dist/{plan-framework.d.ts → plan/plan-framework.d.ts} +4 -13
- package/dist/{plan-framework.js → plan/plan-framework.js} +14 -34
- package/dist/{plan.d.ts → plan/plan-types.d.ts} +14 -17
- package/dist/plan/plan-types.js +24 -0
- package/dist/plan/plan.d.ts +20 -0
- package/dist/{plan.js → plan/plan.js} +27 -88
- package/dist/{agent-rules.d.ts → project/agent-rules.d.ts} +2 -2
- package/dist/{agent-rules.js → project/agent-rules.js} +17 -21
- package/dist/project/install-source-config.d.ts +14 -0
- package/dist/{install-source-config.js → project/install-source-config.js} +3 -7
- package/dist/project/remember-project.js +74 -0
- package/dist/register/detect-clients.d.ts +23 -0
- package/dist/register/detect-clients.js +28 -0
- package/dist/{mcp-clients.js → register/mcp-clients.js} +4 -8
- package/dist/{mcp-registered.d.ts → register/mcp-registered.d.ts} +1 -4
- package/dist/{mcp-registered.js → register/mcp-registered.js} +1 -4
- package/dist/{mcp.d.ts → register/mcp.d.ts} +5 -8
- package/dist/{mcp.js → register/mcp.js} +6 -9
- package/dist/register/slash-command.d.ts +27 -0
- package/dist/{slash-command.js → register/slash-command.js} +10 -10
- package/dist/register/windows-quote.d.ts +17 -0
- package/dist/register/windows-quote.js +49 -0
- package/dist/run-types.d.ts +131 -0
- package/dist/run-types.js +8 -0
- package/dist/run.d.ts +3 -120
- package/dist/run.js +111 -56
- package/package.json +5 -5
- package/dist/install-hint.d.ts +0 -9
- package/dist/install-source-config.d.ts +0 -18
- package/dist/remember-project.js +0 -40
- package/dist/slash-command.d.ts +0 -27
- package/dist/windows-quote.d.ts +0 -38
- package/dist/windows-quote.js +0 -70
- /package/dist/{capabilities.d.ts → detect/capabilities.d.ts} +0 -0
- /package/dist/{capabilities.js → detect/capabilities.js} +0 -0
- /package/dist/{app-choice.d.ts → detect/declared/app-choice.d.ts} +0 -0
- /package/dist/{app-choice.js → detect/declared/app-choice.js} +0 -0
- /package/dist/{init-opt-out.d.ts → detect/declared/init-opt-out.d.ts} +0 -0
- /package/dist/{init-opt-out.js → detect/declared/init-opt-out.js} +0 -0
- /package/dist/{dev-script.d.ts → detect/dev-script.d.ts} +0 -0
- /package/dist/{dev-script.js → detect/dev-script.js} +0 -0
- /package/dist/{dev-server-ports.d.ts → detect/dev-server-ports.d.ts} +0 -0
- /package/dist/{non-js-project.d.ts → detect/non-js-project.d.ts} +0 -0
- /package/dist/{non-js-project.js → detect/non-js-project.js} +0 -0
- /package/dist/{platform.d.ts → detect/platform.d.ts} +0 -0
- /package/dist/{platform.js → detect/platform.js} +0 -0
- /package/dist/{csp-doctor.d.ts → diagnose/csp-doctor.d.ts} +0 -0
- /package/dist/{csp-doctor.js → diagnose/csp-doctor.js} +0 -0
- /package/dist/{desktop-doctor.d.ts → diagnose/desktop-doctor.d.ts} +0 -0
- /package/dist/{astro-host.d.ts → patch/astro-host.d.ts} +0 -0
- /package/dist/{astro-host.js → patch/astro-host.js} +0 -0
- /package/dist/{brace-scan.d.ts → patch/brace-scan.d.ts} +0 -0
- /package/dist/{brace-scan.js → patch/brace-scan.js} +0 -0
- /package/dist/{cra.d.ts → patch/cra.d.ts} +0 -0
- /package/dist/{electron-patch.d.ts → patch/electron-patch.d.ts} +0 -0
- /package/dist/{electron-vite-patch.d.ts → patch/electron-vite-patch.d.ts} +0 -0
- /package/dist/{electron-vite-patch.js → patch/electron-vite-patch.js} +0 -0
- /package/dist/{format-generated.d.ts → patch/format-generated.d.ts} +0 -0
- /package/dist/{format-generated.js → patch/format-generated.js} +0 -0
- /package/dist/{nuxt-patch.d.ts → patch/nuxt-patch.d.ts} +0 -0
- /package/dist/{patch-kind.d.ts → patch/patch-kind.d.ts} +0 -0
- /package/dist/{patch-kind.js → patch/patch-kind.js} +0 -0
- /package/dist/{vite-config.d.ts → patch/vite-config.d.ts} +0 -0
- /package/dist/{vite-owning-config.d.ts → patch/vite-owning-config.d.ts} +0 -0
- /package/dist/{vite-owning-config.js → patch/vite-owning-config.js} +0 -0
- /package/dist/{preflight.d.ts → plan/preflight.d.ts} +0 -0
- /package/dist/{preflight.js → plan/preflight.js} +0 -0
- /package/dist/{project-id.d.ts → project/project-id.d.ts} +0 -0
- /package/dist/{project-id.js → project/project-id.js} +0 -0
- /package/dist/{refresh-rules.d.ts → project/refresh-rules.d.ts} +0 -0
- /package/dist/{refresh-rules.js → project/refresh-rules.js} +0 -0
- /package/dist/{remember-project.d.ts → project/remember-project.d.ts} +0 -0
- /package/dist/{codex-toml.d.ts → register/codex-toml.d.ts} +0 -0
- /package/dist/{codex-toml.js → register/codex-toml.js} +0 -0
- /package/dist/{mcp-clients.d.ts → register/mcp-clients.d.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -9,17 +9,41 @@
|
|
|
9
9
|
* ends up unable to move a file.
|
|
10
10
|
*/
|
|
11
11
|
export { runInit, resolveLockfiles, } from './run.js';
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Exported for the ONE other place in this repo that spawns a package manager: `reticle update`.
|
|
14
|
+
*
|
|
15
|
+
* It is a pure string rule with its own tests, and it was private while a second caller needed it
|
|
16
|
+
* -- which is exactly the shape that let `reticle setup mcp` reimplement the spawn as a bare
|
|
17
|
+
* `execFileSync` and break on Windows. Two copies of a quoting rule is the version of this bug that
|
|
18
|
+
* is hardest to see, so there is one.
|
|
19
|
+
*/
|
|
20
|
+
export { windowsShellArg } from './register/windows-quote.js';
|
|
21
|
+
export { buildNodeIo, probeCli } from './node-io.js';
|
|
13
22
|
export { SILENT_HOST } from './host.js';
|
|
14
23
|
export { RETICLE_VERSION, RETICLE_NPM_PACKAGE } from './version.js';
|
|
15
|
-
export { InitFailure } from './init-failure.js';
|
|
16
|
-
export { NodePlatform } from './platform.js';
|
|
17
|
-
export { DEV_SERVER_PORTS, isLikelyDevServerPort, devServerPortWarning, } from './dev-server-ports.js';
|
|
18
|
-
export { configWithInstallSource } from './install-source-config.js';
|
|
19
|
-
export { projectIdOf, rememberProjectOnDisk } from './remember-project.js';
|
|
20
|
-
export { detectPackageManager, installCommandParts, parseMajor, PackageManager } from './detect.js';
|
|
21
|
-
export { findWorkspaceApps } from './workspace-apps.js';
|
|
22
|
-
export { refreshAgentRules } from './refresh-rules.js';
|
|
23
|
-
export { diagnoseDesktop, isDesktopProject } from './desktop-doctor.js';
|
|
24
|
-
export { diagnoseWebCsp } from './csp-doctor.js';
|
|
25
|
-
export { reticleConfigContent } from './snippets.js';
|
|
24
|
+
export { InitFailure } from './diagnose/init-failure.js';
|
|
25
|
+
export { NodePlatform } from './detect/platform.js';
|
|
26
|
+
export { DEV_SERVER_PORTS, isLikelyDevServerPort, devServerPortWarning, } from './detect/dev-server-ports.js';
|
|
27
|
+
export { configWithInstallSource } from './project/install-source-config.js';
|
|
28
|
+
export { projectIdOf, rememberProjectOnDisk } from './project/remember-project.js';
|
|
29
|
+
export { detectPackageManager, installCommandParts, parseMajor, PackageManager, } from './detect/detect.js';
|
|
30
|
+
export { findWorkspaceApps } from './detect/workspace-apps.js';
|
|
31
|
+
export { refreshAgentRules } from './project/refresh-rules.js';
|
|
32
|
+
export { diagnoseDesktop, isDesktopProject } from './diagnose/desktop-doctor.js';
|
|
33
|
+
export { diagnoseWebCsp } from './diagnose/csp-doctor.js';
|
|
34
|
+
export { reticleConfigContent } from './patch/snippets.js';
|
|
35
|
+
/**
|
|
36
|
+
* MCP registration, for a caller that has no project.
|
|
37
|
+
*
|
|
38
|
+
* `reticle setup mcp` registers the server for the USER across every agent on the machine, which is
|
|
39
|
+
* what the one-line installer runs before any project exists. It needs the same client table and
|
|
40
|
+
* the same detection `init` uses — a second copy would be a second answer to "which agents are
|
|
41
|
+
* here", and the two would disagree the first time a client was added to one of them.
|
|
42
|
+
*/
|
|
43
|
+
export { McpClient, ConfigScope, MCP_CLIENTS, ClientMergeStatus, clientSpec, mergeClientConfig, } from './register/mcp-clients.js';
|
|
44
|
+
export { claudeAddCommand,
|
|
45
|
+
// The two probes `run.ts` uses to decide about Claude Code. Exported because `reticle setup mcp`
|
|
46
|
+
// asks the same question and had no way to ask it: Claude Code keeps no config file, so the
|
|
47
|
+
// file-reading detector cannot see it, and the installer silently skipped the commonest client.
|
|
48
|
+
claudeAvailableProbe, claudeExistsProbe, } from './register/mcp.js';
|
|
49
|
+
export { detectMcpClients } from './register/detect-clients.js';
|
package/dist/node-io.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { InitHost } from './host.js';
|
|
|
10
10
|
*
|
|
11
11
|
* The set is closed and tiny — the four package managers, `npx`, and the Claude CLI — because those
|
|
12
12
|
* are the only things the plan can ask for. It is a named constant for the same reason every other
|
|
13
|
-
* wire string here is one, and it is CHECKED because of
|
|
13
|
+
* wire string here is one, and it is CHECKED because of the shell: on Windows these spawn through
|
|
14
14
|
* a shell, and a shell turns the command name into something the shell parses rather than a file it
|
|
15
15
|
* executes. Arguments are quoted by `shellSafe`; the command name was the half nothing covered.
|
|
16
16
|
*
|
|
@@ -19,4 +19,15 @@ import type { InitHost } from './host.js';
|
|
|
19
19
|
* as "the command ran and failed" and hide the bug in a retry.
|
|
20
20
|
*/
|
|
21
21
|
export declare const RUNNABLE_COMMANDS: readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* Run one allowed CLI quietly and say whether it succeeded — the `probe` above, without an `InitIo`.
|
|
24
|
+
*
|
|
25
|
+
* Exported because `reticle setup mcp` needs exactly this and had reimplemented it as a bare
|
|
26
|
+
* `execFileSync(command, args)`. That works everywhere except Windows, where `claude` is a `.cmd`
|
|
27
|
+
* shim that cannot be spawned without a shell: the probe threw ENOENT, the installer concluded the
|
|
28
|
+
* machine had no Claude Code on it, and said so. The three rules that make this correct —
|
|
29
|
+
* `runnable`, `shellSafe` and the shell decision — already lived here and were private, which is the whole
|
|
30
|
+
* reason a second, broken copy existed.
|
|
31
|
+
*/
|
|
32
|
+
export declare function probeCli(command: string, args: readonly string[]): boolean;
|
|
22
33
|
export declare function buildNodeIo(cwd: string, host: InitHost): InitIo;
|
package/dist/node-io.js
CHANGED
|
@@ -4,25 +4,14 @@
|
|
|
4
4
|
* command, not the MCP stdio transport.
|
|
5
5
|
*/
|
|
6
6
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, accessSync, constants, } from 'node:fs';
|
|
7
|
-
import { NodePlatform } from './platform.js';
|
|
7
|
+
import { NodePlatform } from './detect/platform.js';
|
|
8
8
|
import { join, dirname, isAbsolute } from 'node:path';
|
|
9
9
|
import { homedir } from 'node:os';
|
|
10
10
|
import { spawnSync } from 'node:child_process';
|
|
11
|
-
import { windowsShellArg } from './windows-quote.js';
|
|
12
|
-
/**
|
|
13
|
-
* `shell: true` ONLY where it earns its keep.
|
|
14
|
-
*
|
|
15
|
-
* It exists so package-manager shims (`pnpm.cmd`, `npx.cmd`) resolve on Windows. On POSIX it buys
|
|
16
|
-
* nothing and costs correctness: under a shell, arguments are re-parsed, so a path containing a
|
|
17
|
-
* space — `/Users/ada/My Projects/app` — silently becomes two arguments and registration fails with
|
|
18
|
-
* no error anyone can read.
|
|
19
|
-
*/
|
|
20
|
-
function shellOpt() {
|
|
21
|
-
return NodePlatform.WINDOWS === process.platform ? { shell: true } : {};
|
|
22
|
-
}
|
|
11
|
+
import { windowsShellArg } from './register/windows-quote.js';
|
|
23
12
|
/**
|
|
24
13
|
* Under a shell, quote what the shell would otherwise split or interpret. Windows only, where
|
|
25
|
-
* `shell: true` is required (see
|
|
14
|
+
* `shell: true` is required (see spawnAllowed). The rule itself lives in windows-quote.ts as a pure
|
|
26
15
|
* function so it can be tested on every platform — keeping it inside this branch is why it was
|
|
27
16
|
* wrong for as long as it was.
|
|
28
17
|
*/
|
|
@@ -36,7 +25,7 @@ function shellSafe(args) {
|
|
|
36
25
|
*
|
|
37
26
|
* The set is closed and tiny — the four package managers, `npx`, and the Claude CLI — because those
|
|
38
27
|
* are the only things the plan can ask for. It is a named constant for the same reason every other
|
|
39
|
-
* wire string here is one, and it is CHECKED because of
|
|
28
|
+
* wire string here is one, and it is CHECKED because of the shell: on Windows these spawn through
|
|
40
29
|
* a shell, and a shell turns the command name into something the shell parses rather than a file it
|
|
41
30
|
* executes. Arguments are quoted by `shellSafe`; the command name was the half nothing covered.
|
|
42
31
|
*
|
|
@@ -53,6 +42,53 @@ function runnable(command) {
|
|
|
53
42
|
}
|
|
54
43
|
return found;
|
|
55
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Every spawn `init` makes, in the one shape Node does not deprecate.
|
|
47
|
+
*
|
|
48
|
+
* Passing an args ARRAY together with `shell: true` is DEP0190, and on Windows — the only platform
|
|
49
|
+
* where this turns the shell on — every single `init` and `curl | sh` install printed this
|
|
50
|
+
* into the middle of its output:
|
|
51
|
+
*
|
|
52
|
+
* [DEP0190] DeprecationWarning: Passing args to a child process with shell option true can lead
|
|
53
|
+
* to security vulnerabilities, as the arguments are not escaped, only concatenated.
|
|
54
|
+
*
|
|
55
|
+
* A security warning in the middle of an install is a bad first thing to show somebody, and on the
|
|
56
|
+
* platform with the most users it was every install. The deprecation is also RIGHT about the
|
|
57
|
+
* reason: Node does not escape, it concatenates. We already escape — `windowsShellArg` implements
|
|
58
|
+
* the `CommandLineToArgvW` rule and is tested on every platform — so the fix is to own the
|
|
59
|
+
* concatenation rather than hand Node an array it will join unsafely. Same command line, same
|
|
60
|
+
* quoting, no warning.
|
|
61
|
+
*
|
|
62
|
+
* POSIX keeps the array and no shell, where argv is passed through untouched and a path with a
|
|
63
|
+
* space cannot be re-split.
|
|
64
|
+
*/
|
|
65
|
+
function spawnAllowed(command, args, options) {
|
|
66
|
+
const name = runnable(command);
|
|
67
|
+
if (NodePlatform.WINDOWS !== process.platform) {
|
|
68
|
+
return spawnSync(name, [...args], options);
|
|
69
|
+
}
|
|
70
|
+
// The name is one of RUNNABLE_COMMANDS, so it never needs quoting itself.
|
|
71
|
+
return spawnSync([name, ...shellSafe(args)].join(' '), [], { ...options, shell: true });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Run one allowed CLI quietly and say whether it succeeded — the `probe` above, without an `InitIo`.
|
|
75
|
+
*
|
|
76
|
+
* Exported because `reticle setup mcp` needs exactly this and had reimplemented it as a bare
|
|
77
|
+
* `execFileSync(command, args)`. That works everywhere except Windows, where `claude` is a `.cmd`
|
|
78
|
+
* shim that cannot be spawned without a shell: the probe threw ENOENT, the installer concluded the
|
|
79
|
+
* machine had no Claude Code on it, and said so. The three rules that make this correct —
|
|
80
|
+
* `runnable`, `shellSafe` and the shell decision — already lived here and were private, which is the whole
|
|
81
|
+
* reason a second, broken copy existed.
|
|
82
|
+
*/
|
|
83
|
+
export function probeCli(command, args) {
|
|
84
|
+
try {
|
|
85
|
+
const result = spawnAllowed(command, args, { stdio: 'ignore' });
|
|
86
|
+
return 0 === result.status;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
56
92
|
export function buildNodeIo(cwd, host) {
|
|
57
93
|
// Project-relative by default; absolute paths (e.g. ~/.cursor/mcp.json) pass through unchanged.
|
|
58
94
|
const abs = (rel) => (isAbsolute(rel) ? rel : join(cwd, rel));
|
|
@@ -116,11 +152,7 @@ export function buildNodeIo(cwd, host) {
|
|
|
116
152
|
},
|
|
117
153
|
exec(command, args) {
|
|
118
154
|
// Inherit stdio so the install's own progress is visible to the user.
|
|
119
|
-
const result =
|
|
120
|
-
cwd,
|
|
121
|
-
stdio: 'inherit',
|
|
122
|
-
...shellOpt(),
|
|
123
|
-
});
|
|
155
|
+
const result = spawnAllowed(command, args, { cwd, stdio: 'inherit' });
|
|
124
156
|
return 0 === result.status;
|
|
125
157
|
},
|
|
126
158
|
/** One access check, rather than discovering it as an EACCES stack four phases later. */
|
|
@@ -135,11 +167,7 @@ export function buildNodeIo(cwd, host) {
|
|
|
135
167
|
},
|
|
136
168
|
probe(command, args) {
|
|
137
169
|
// Quiet yes/no check (CLI availability, existing registration). Never throws.
|
|
138
|
-
const result =
|
|
139
|
-
cwd,
|
|
140
|
-
stdio: 'ignore',
|
|
141
|
-
...shellOpt(),
|
|
142
|
-
});
|
|
170
|
+
const result = spawnAllowed(command, args, { cwd, stdio: 'ignore' });
|
|
143
171
|
return 0 === result.status;
|
|
144
172
|
},
|
|
145
173
|
print(line) {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Half-editing a build config is worse than a documented manual step.
|
|
13
13
|
*/
|
|
14
14
|
import { type SourcePatch } from './patch-kind.js';
|
|
15
|
-
import { UiLibrary } from '
|
|
15
|
+
import { UiLibrary } from '../detect/detect.js';
|
|
16
16
|
export declare function patchAstroConfig(source: string): SourcePatch;
|
|
17
17
|
export declare function patchAstroLayout(source: string, port: number | undefined, projectId: string | undefined, uiLibrary?: UiLibrary, testids?: readonly string[]): SourcePatch;
|
|
18
18
|
/** Where Astro keeps ambient types — `create-astro` ships this file. */
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { RETICLE_DEFAULT_PORT, bridgeWsUrl } from '@reticlehq/core';
|
|
15
15
|
import { PatchKind } from './patch-kind.js';
|
|
16
|
-
import { UiLibrary } from '
|
|
16
|
+
import { UiLibrary } from '../detect/detect.js';
|
|
17
17
|
import { registerCapabilitiesCall, sdkImport } from './snippets.js';
|
|
18
18
|
import { patchViteOwningConfig } from './vite-owning-config.js';
|
|
19
19
|
/** Present in a patched layout and in the printed recipe's script. */
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* mechanism and is gitignored by CRA's own template.
|
|
14
14
|
*/
|
|
15
15
|
import { bridgeWsUrl } from '@reticlehq/core';
|
|
16
|
-
import { CLI } from '
|
|
16
|
+
import { CLI } from '../project/agent-rules.js';
|
|
17
17
|
import { registerCapabilitiesCall } from './snippets.js';
|
|
18
18
|
/** The line added to `src/index.tsx` / `src/index.js`. Side-effect import: the module guards itself on NODE_ENV. */
|
|
19
19
|
export const CRA_DEV_MODULE_IMPORT = "import './reticle-dev';";
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* (zero, several, a factory) is MANUAL carrying the doctor's existing fix text, not a guess.
|
|
8
8
|
*/
|
|
9
9
|
import { matchingParenEnd } from './brace-scan.js';
|
|
10
|
-
import { CAPTURE_REQUIRE, ELECTRON_CAPTURE_FIX, PRELOAD_REQUIRE } from '
|
|
10
|
+
import { CAPTURE_REQUIRE, ELECTRON_CAPTURE_FIX, PRELOAD_REQUIRE, } from '../diagnose/desktop-doctor.js';
|
|
11
11
|
import { PatchKind } from './patch-kind.js';
|
|
12
12
|
const ESM_PRELOAD_EXT = /\.(?:ts|mts|mjs)$/i;
|
|
13
13
|
const WINDOW_DECL = /const\s+(\w+)\s*=\s*new\s+BrowserWindow\s*\(/g;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Pure, conservative patchers for the two files a Next app needed edited BY HAND: `next.config.*`
|
|
3
3
|
* (wrap the export in `withReticle`) and `app/layout.tsx` (mount `<ReticleDev />`). Same contract as
|
|
4
4
|
* the Vite patcher — recognise the obvious shape, bail to `manual` on anything ambiguous, never
|
|
5
|
-
* half-edit.
|
|
6
|
-
*
|
|
5
|
+
* half-edit. These must not be left manual: both edits fail silently when skipped, and one of them
|
|
6
|
+
* is JSX.
|
|
7
7
|
*/
|
|
8
8
|
import { type SourcePatch } from './patch-kind.js';
|
|
9
9
|
/** Where the generated connect component goes, and how the mount file should import it. */
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Pure, conservative patchers for the two files a Next app needed edited BY HAND: `next.config.*`
|
|
3
3
|
* (wrap the export in `withReticle`) and `app/layout.tsx` (mount `<ReticleDev />`). Same contract as
|
|
4
4
|
* the Vite patcher — recognise the obvious shape, bail to `manual` on anything ambiguous, never
|
|
5
|
-
* half-edit.
|
|
6
|
-
*
|
|
5
|
+
* half-edit. These must not be left manual: both edits fail silently when skipped, and one of them
|
|
6
|
+
* is JSX.
|
|
7
7
|
*/
|
|
8
8
|
import { PatchKind } from './patch-kind.js';
|
|
9
9
|
const RETICLE_NEXT_PACKAGE = '@reticlehq/next';
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { patchViteOwningConfig } from './vite-owning-config.js';
|
|
16
16
|
import { sdkImport } from './snippets.js';
|
|
17
|
-
import { UiLibrary } from '
|
|
17
|
+
import { UiLibrary } from '../detect/detect.js';
|
|
18
18
|
/** The config filenames Nuxt itself accepts, in the order `init` should prefer them. */
|
|
19
19
|
export const NUXT_CONFIG_CANDIDATES = ['nuxt.config.ts', 'nuxt.config.js', 'nuxt.config.mjs'];
|
|
20
20
|
/**
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Generated file contents and copy-paste snippets for `reticle init`. Kept as named constants/builders
|
|
3
3
|
* so the runner never inlines free strings.
|
|
4
4
|
*/
|
|
5
|
-
import { UiLibrary } from '
|
|
6
|
-
import type { FoundStore } from '
|
|
5
|
+
import { UiLibrary } from '../detect/detect.js';
|
|
6
|
+
import type { FoundStore } from '../detect/capabilities.js';
|
|
7
7
|
/**
|
|
8
8
|
* The connect argument literal: a non-default port adds a `url`, and a projectId is always passed
|
|
9
9
|
* (so the app is identifiable across port changes). Empty string only when neither applies.
|
|
@@ -140,15 +140,11 @@ export declare function djangoMiddlewareSnippet(connectArgLiteral: string): stri
|
|
|
140
140
|
export declare function htmlManual(port: number | undefined, projectId?: string, pairingToken?: string): string;
|
|
141
141
|
export declare const NEXT_RETICLE_DEV_PATH = "app/reticle-dev.tsx";
|
|
142
142
|
export declare const SVELTEKIT_HOOKS_PATH = "src/hooks.client.ts";
|
|
143
|
-
/**
|
|
144
|
-
* Said to the user's face rather than discovered later. React, Next, Remix and Astro each have an
|
|
145
|
-
* app and a CI gate; SvelteKit has neither, so "it generated some wiring" is not evidence it works.
|
|
146
|
-
*/
|
|
147
143
|
/**
|
|
148
144
|
* Said out loud when the app does not render through React. The SDK is framework-agnostic — DOM,
|
|
149
145
|
* network, console and routing all still work — but `@reticlehq/react` is a React adapter, so
|
|
150
|
-
* component names and source mapping do not, and no CI gate covers this stack.
|
|
151
|
-
*
|
|
146
|
+
* component names and source mapping do not, and no CI gate covers this stack. Saying so beats
|
|
147
|
+
* reporting all-green.
|
|
152
148
|
*/
|
|
153
149
|
export declare function unverifiedUiLibraryNote(library: string): string;
|
|
154
150
|
export declare const UNVERIFIED_FRAMEWORK_NOTE = "Reticle has no SvelteKit app and no CI gate for one, so this wiring is untested \u2014 it may work, but nothing proves it and nothing will tell us if it breaks. Supported and gated today: Vite + React, Next.js, Remix and Astro. If the hook does not register a session, please open an issue.";
|
|
@@ -244,20 +240,14 @@ export declare function nuxtPluginFile(port: number | undefined, projectId?: str
|
|
|
244
240
|
*/
|
|
245
241
|
export declare const NUXT_PLUGIN_NOTICE: string;
|
|
246
242
|
/**
|
|
247
|
-
* The Nuxt recipe, written out in full because
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
* codebase — the reporter only continued after auditing our dist to confirm there are no React
|
|
252
|
-
* imports at runtime, which most people will not do. It then handed over a snippet guarded on
|
|
253
|
-
* `window.location.hostname === 'localhost'`, which fails twice over in Nuxt: `window` does not
|
|
254
|
-
* exist during SSR, and the dev host here was a hosts-file alias (required for the backend's
|
|
255
|
-
* white-label origin detection), so the guard was false and the connect never ran — no error, no log
|
|
256
|
-
* line, nothing to debug. And nothing said a running dev server does not pick up a new plugin.
|
|
243
|
+
* The Nuxt recipe, written out in full because each trap in it is one a Nuxt 4 app actually hit:
|
|
244
|
+
* a Vue codebase classified as `html` and handed `@reticlehq/react`, a connect guarded on
|
|
245
|
+
* `window.location.hostname === 'localhost'` (false on any hosts-file alias, and `window` does not
|
|
246
|
+
* exist during SSR), and a running dev server that never picked up the new plugin.
|
|
257
247
|
*
|
|
258
|
-
* So: `import.meta.dev`
|
|
259
|
-
*
|
|
260
|
-
*
|
|
248
|
+
* So: `import.meta.dev` instead of a hostname check, `.client.ts` instead of an SSR guard, the
|
|
249
|
+
* framework-neutral sensor instead of the React kit, the non-localhost flag named up front, and the
|
|
250
|
+
* restart said out loud.
|
|
261
251
|
*/
|
|
262
252
|
export declare function nuxtManual(port: number | undefined, projectId?: string): string;
|
|
263
253
|
/**
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* so the runner never inlines free strings.
|
|
4
4
|
*/
|
|
5
5
|
import { RETICLE_DEFAULT_PORT, ReticleDir, bridgeWsUrl, RETICLE_CLIENT_HOST, RETICLE_WS_PATH, } from '@reticlehq/core';
|
|
6
|
-
import { UiLibrary } from '
|
|
7
|
-
import { RETICLE_VERSION } from '
|
|
6
|
+
import { UiLibrary } from '../detect/detect.js';
|
|
7
|
+
import { RETICLE_VERSION } from '../version.js';
|
|
8
8
|
/**
|
|
9
9
|
* The SDK as one import a plain page can actually resolve.
|
|
10
10
|
*
|
|
@@ -113,11 +113,13 @@ pointers, not the app.`;
|
|
|
113
113
|
import { reticle } from '@reticlehq/vite-plugin';
|
|
114
114
|
|
|
115
115
|
export default defineConfig({
|
|
116
|
-
plugins: [${
|
|
116
|
+
plugins: [${call}, ${frameworkPluginExample(uiLibrary)}],
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
The position in the array does not matter: the plugin declares \`enforce: 'pre'\`, so Vite runs it
|
|
120
|
+
before every normal plugin wherever you put it. Shown first only because that is where \`init\`
|
|
121
|
+
writes it when it patches the config for you. It applies during \`vite\` (dev) only — it is dropped
|
|
122
|
+
from \`vite build\`.${note}`;
|
|
121
123
|
}
|
|
122
124
|
/**
|
|
123
125
|
* The electron-vite recipe: the plugin belongs in `renderer`, never in `main` or `preload`.
|
|
@@ -573,15 +575,11 @@ ${staticPageSnippet(withToken)}
|
|
|
573
575
|
}
|
|
574
576
|
export const NEXT_RETICLE_DEV_PATH = 'app/reticle-dev.tsx';
|
|
575
577
|
export const SVELTEKIT_HOOKS_PATH = 'src/hooks.client.ts';
|
|
576
|
-
/**
|
|
577
|
-
* Said to the user's face rather than discovered later. React, Next, Remix and Astro each have an
|
|
578
|
-
* app and a CI gate; SvelteKit has neither, so "it generated some wiring" is not evidence it works.
|
|
579
|
-
*/
|
|
580
578
|
/**
|
|
581
579
|
* Said out loud when the app does not render through React. The SDK is framework-agnostic — DOM,
|
|
582
580
|
* network, console and routing all still work — but `@reticlehq/react` is a React adapter, so
|
|
583
|
-
* component names and source mapping do not, and no CI gate covers this stack.
|
|
584
|
-
*
|
|
581
|
+
* component names and source mapping do not, and no CI gate covers this stack. Saying so beats
|
|
582
|
+
* reporting all-green.
|
|
585
583
|
*/
|
|
586
584
|
export function unverifiedUiLibraryNote(library) {
|
|
587
585
|
// Preact is not in the same position as Vue or Svelte and must not be told it is. The React
|
|
@@ -812,20 +810,14 @@ export const NUXT_PLUGIN_NOTICE = 'Restart the dev server: one that is already r
|
|
|
812
810
|
'needs TWO additions, not one: allowNonLocalhost: true AND the token from ~/.reticle/pairing-token. ' +
|
|
813
811
|
'The flag alone is NOT sufficient off localhost.';
|
|
814
812
|
/**
|
|
815
|
-
* The Nuxt recipe, written out in full because
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
* codebase — the reporter only continued after auditing our dist to confirm there are no React
|
|
820
|
-
* imports at runtime, which most people will not do. It then handed over a snippet guarded on
|
|
821
|
-
* `window.location.hostname === 'localhost'`, which fails twice over in Nuxt: `window` does not
|
|
822
|
-
* exist during SSR, and the dev host here was a hosts-file alias (required for the backend's
|
|
823
|
-
* white-label origin detection), so the guard was false and the connect never ran — no error, no log
|
|
824
|
-
* line, nothing to debug. And nothing said a running dev server does not pick up a new plugin.
|
|
813
|
+
* The Nuxt recipe, written out in full because each trap in it is one a Nuxt 4 app actually hit:
|
|
814
|
+
* a Vue codebase classified as `html` and handed `@reticlehq/react`, a connect guarded on
|
|
815
|
+
* `window.location.hostname === 'localhost'` (false on any hosts-file alias, and `window` does not
|
|
816
|
+
* exist during SSR), and a running dev server that never picked up the new plugin.
|
|
825
817
|
*
|
|
826
|
-
* So: `import.meta.dev`
|
|
827
|
-
*
|
|
828
|
-
*
|
|
818
|
+
* So: `import.meta.dev` instead of a hostname check, `.client.ts` instead of an SSR guard, the
|
|
819
|
+
* framework-neutral sensor instead of the React kit, the non-localhost flag named up front, and the
|
|
820
|
+
* restart said out loud.
|
|
829
821
|
*/
|
|
830
822
|
export function nuxtManual(port, projectId) {
|
|
831
823
|
const base = connectArg(port, projectId);
|
|
@@ -884,11 +876,10 @@ export function reticleConfigContent(framework, port, projectId, installSource)
|
|
|
884
876
|
fields['projectId'] = projectId;
|
|
885
877
|
if (port !== undefined && port !== RETICLE_DEFAULT_PORT)
|
|
886
878
|
fields['port'] = port;
|
|
887
|
-
// How this install arrived, recorded HERE because
|
|
888
|
-
//
|
|
889
|
-
//
|
|
890
|
-
//
|
|
891
|
-
// converts" could not be asked at all. Written once, read for the life of the project.
|
|
879
|
+
// How this install arrived, recorded HERE because this is the only moment anything knows it. It
|
|
880
|
+
// arrives as an environment variable set by whichever channel ran the install, and an environment
|
|
881
|
+
// variable is gone by the next command, so every later event reported `unknown`. Written once,
|
|
882
|
+
// read for the life of the project.
|
|
892
883
|
//
|
|
893
884
|
// A closed vocabulary, narrowed before it gets here, so this can never carry a path or a URL.
|
|
894
885
|
if (installSource !== undefined && installSource.length > 0) {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The TanStack Start connect recipe.
|
|
3
3
|
*
|
|
4
|
-
* Its own module
|
|
5
|
-
*
|
|
6
|
-
* recipe and the reasoning behind that refusal are a unit.
|
|
4
|
+
* Its own module because Start is the one framework whose document module `init` deliberately
|
|
5
|
+
* refuses to write, so the recipe and the reasoning behind that refusal are a unit.
|
|
7
6
|
*/
|
|
8
7
|
/** TanStack Start's document module — the file that SSRs `<html>`. */
|
|
9
8
|
export declare const TANSTACK_START_ROOT_PATH = "src/routes/__root.tsx";
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The TanStack Start connect recipe.
|
|
3
3
|
*
|
|
4
|
-
* Its own module
|
|
5
|
-
*
|
|
6
|
-
* recipe and the reasoning behind that refusal are a unit.
|
|
4
|
+
* Its own module because Start is the one framework whose document module `init` deliberately
|
|
5
|
+
* refuses to write, so the recipe and the reasoning behind that refusal are a unit.
|
|
7
6
|
*/
|
|
8
|
-
import { UiLibrary } from '
|
|
7
|
+
import { UiLibrary } from '../detect/detect.js';
|
|
9
8
|
import { connectArg, sdkImport, UNVERIFIED_TANSTACK_START_NOTE } from './snippets.js';
|
|
10
9
|
/** TanStack Start's document module — the file that SSRs `<html>`. */
|
|
11
10
|
export const TANSTACK_START_ROOT_PATH = 'src/routes/__root.tsx';
|
|
@@ -10,19 +10,18 @@ const RETICLE_MARKER = '@reticlehq/vite-plugin';
|
|
|
10
10
|
/**
|
|
11
11
|
* The `reticle(...)` call — the bridge port so the injected connect targets it.
|
|
12
12
|
*
|
|
13
|
-
* **`captureNetworkBodies` is OPT-IN.**
|
|
14
|
-
* a good one: without a body, a write that answers 2xx grades `unknown / outcome_unread`, because a
|
|
15
|
-
* 200 describes the transport and not the result. Measured on a real payments UI — a refund posted
|
|
16
|
-
* rupees into a paise field, the server answered 200 having refunded a hundredth of it, the page
|
|
17
|
-
* rendered the amount the user had typed, and every DOM-level check passed.
|
|
13
|
+
* **`captureNetworkBodies` is OPT-IN.**
|
|
18
14
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
15
|
+
* The case FOR capturing bodies is real: without one, a write that answers 2xx grades
|
|
16
|
+
* `unknown / outcome_unread`, because a 200 describes the transport and not the result. A request
|
|
17
|
+
* that posts a wrong amount can answer 200, render the amount the user typed, and pass every
|
|
18
|
+
* DOM-level check.
|
|
19
|
+
*
|
|
20
|
+
* That justifies the CAPABILITY, not the default. Any app proxying authenticated API traffic through
|
|
21
|
+
* Vite puts request bodies in the daemon's buffer on the first drive, and the credential classes are
|
|
22
|
+
* redacted while an address or an email is not. Writing the line into someone's config IS deciding
|
|
23
|
+
* that for them — and `init` is run unattended by an agent, so the person who knows whether the data
|
|
24
|
+
* is sensitive is not in the room.
|
|
26
25
|
*
|
|
27
26
|
* So the default is off and the ways in are all deliberate:
|
|
28
27
|
* - `reticle init --capture-bodies` writes the line, for someone who has decided
|
|
@@ -77,7 +76,10 @@ function insertImport(source) {
|
|
|
77
76
|
* single-line array needs the space, or the result reads `[reticle(),react()]`.
|
|
78
77
|
*/
|
|
79
78
|
function insertPlugin(source, call) {
|
|
80
|
-
|
|
79
|
+
// `(match, offset, source)` — PLUGINS_ARRAY has no capture group. Reading the second argument as
|
|
80
|
+
// one put the whole source string in `offset`, so the index below was `undefined` and the
|
|
81
|
+
// separator was empty every single time.
|
|
82
|
+
return source.replace(PLUGINS_ARRAY, (match, offset) => {
|
|
81
83
|
const next = source[offset + match.length] ?? '';
|
|
82
84
|
const separator = '' === next || /\s/.test(next) ? '' : ' ';
|
|
83
85
|
return `${match}${call},${separator}`;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The step titles `init` emits, and which of them decide whether the app can dial the daemon.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* A cohesive unit on its own terms: one question, asked of a step title, with one consequence — a
|
|
5
|
+
* manual step in this set makes `init` exit non-zero instead of reporting a success over an app that
|
|
6
|
+
* can never connect.
|
|
7
7
|
*
|
|
8
8
|
* The membership used to be matched against free strings written out a second time here, so
|
|
9
9
|
* renaming a step in `plan-framework.ts` silently dropped it out of the set and nothing went red.
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The step titles `init` emits, and which of them decide whether the app can dial the daemon.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* A cohesive unit on its own terms: one question, asked of a step title, with one consequence — a
|
|
5
|
+
* manual step in this set makes `init` exit non-zero instead of reporting a success over an app that
|
|
6
|
+
* can never connect.
|
|
7
7
|
*
|
|
8
8
|
* The membership used to be matched against free strings written out a second time here, so
|
|
9
9
|
* renaming a step in `plan-framework.ts` silently dropped it out of the set and nothing went red.
|
|
10
10
|
* `StepTitle` is now the one place a title is spelled: both files import it, so a rename is a
|
|
11
11
|
* compile error and `plan-framework.test.ts` pins that no builder has drifted back to a literal.
|
|
12
12
|
*/
|
|
13
|
-
import { CSP_STEP_TITLE } from '
|
|
13
|
+
import { CSP_STEP_TITLE } from '../diagnose/csp-check.js';
|
|
14
14
|
/** Every fixed title a plan step can carry. The one spelling; nothing writes a title inline. */
|
|
15
15
|
export const StepTitle = {
|
|
16
16
|
VITE_PLUGIN: 'Vite plugin',
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
*
|
|
19
19
|
* `framework-adapter.test.ts` asserts the seam between the two halves.
|
|
20
20
|
*/
|
|
21
|
-
import { Framework } from '
|
|
21
|
+
import { Framework } from '../detect/detect.js';
|
|
22
22
|
import { StepTitle } from './connect-steps.js';
|
|
23
|
-
import type { PlanInput, Step } from './plan.js';
|
|
23
|
+
import type { PlanInput, Step } from './plan-types.js';
|
|
24
24
|
export declare const RETICLE_REACT_KIT = "@reticlehq/react";
|
|
25
25
|
/** The framework-neutral sensor, for stacks the React adapter has nothing to attach to. */
|
|
26
26
|
export declare const RETICLE_BROWSER_SDK = "@reticlehq/browser";
|
|
@@ -58,3 +58,12 @@ export interface FrameworkAdapter {
|
|
|
58
58
|
readonly carriesOwnUnverifiedNote: boolean;
|
|
59
59
|
}
|
|
60
60
|
export declare const FRAMEWORK_ADAPTERS: Record<Framework, FrameworkAdapter>;
|
|
61
|
+
/**
|
|
62
|
+
* The per-framework half of the plan, looked up rather than switched.
|
|
63
|
+
*
|
|
64
|
+
* `FRAMEWORK_ADAPTERS` is a `Record<Framework, FrameworkAdapter>`, so a member added to `Framework`
|
|
65
|
+
* is a compile error in that one table instead of a framework the plan quietly does not serve. The
|
|
66
|
+
* exhaustive switch this replaced gave the same guarantee for the steps alone; the record gives it
|
|
67
|
+
* for the packages, the connect-step titles and the unverified-note flag in the same edit.
|
|
68
|
+
*/
|
|
69
|
+
export declare function frameworkSteps(input: PlanInput): Step[];
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
* `framework-adapter.test.ts` asserts the seam between the two halves.
|
|
20
20
|
*/
|
|
21
|
-
import { Framework } from '
|
|
21
|
+
import { Framework } from '../detect/detect.js';
|
|
22
22
|
import { StepTitle } from './connect-steps.js';
|
|
23
23
|
import { VITE_PLUGIN_DETAIL, astroSteps, craSteps, htmlSteps, nextSteps, nuxtSteps, reactRouterSteps, svelteKitSteps, tanstackStartSteps, viteSteps, } from './plan-framework.js';
|
|
24
24
|
import { electronViteSteps } from './plan-electron-vite.js';
|
|
@@ -136,3 +136,14 @@ export const FRAMEWORK_ADAPTERS = {
|
|
|
136
136
|
carriesOwnUnverifiedNote: false,
|
|
137
137
|
},
|
|
138
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* The per-framework half of the plan, looked up rather than switched.
|
|
141
|
+
*
|
|
142
|
+
* `FRAMEWORK_ADAPTERS` is a `Record<Framework, FrameworkAdapter>`, so a member added to `Framework`
|
|
143
|
+
* is a compile error in that one table instead of a framework the plan quietly does not serve. The
|
|
144
|
+
* exhaustive switch this replaced gave the same guarantee for the steps alone; the record gives it
|
|
145
|
+
* for the packages, the connect-step titles and the unverified-note flag in the same edit.
|
|
146
|
+
*/
|
|
147
|
+
export function frameworkSteps(input) {
|
|
148
|
+
return FRAMEWORK_ADAPTERS[input.detection.framework].steps(input);
|
|
149
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PlanInput, Step } from './plan-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The two things a containerised dev server does differently, said before they go wrong.
|
|
4
|
+
*
|
|
5
|
+
* Null for every project with no container marker near it, which is almost all of them — so this
|
|
6
|
+
* adds nothing to the ordinary plan and does not move the install baseline.
|
|
7
|
+
*/
|
|
8
|
+
export declare function containerisedStep(input: PlanInput): Step | null;
|
|
9
|
+
/** Windows only. The reported install never reached mcpManual because `claude mcp add` succeeded. */
|
|
10
|
+
export declare function windowsMcpNoteStep(input: PlanInput): Step | null;
|
|
11
|
+
/**
|
|
12
|
+
* A step that says out loud when the app isn't React. SvelteKit already carries its own unverified
|
|
13
|
+
* note, so it isn't doubled up here.
|
|
14
|
+
*/
|
|
15
|
+
export declare function uiLibraryStep(input: PlanInput): Step[];
|
|
16
|
+
/**
|
|
17
|
+
* A WebGL subtree is pixels, and Reticle reads the DOM.
|
|
18
|
+
*
|
|
19
|
+
* react-three-fiber and its relatives render into a canvas, so the tools that find and drive
|
|
20
|
+
* elements have nothing to find. Disclosed rather than blocked: the rest of the app is still
|
|
21
|
+
* verifiable and a NOTICE says which part is not.
|
|
22
|
+
*/
|
|
23
|
+
export declare function webGlCanvasStep(input: PlanInput): Step[];
|