canopy-engine 0.0.0-stage → 0.1.3
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/FEEDBACK.md +46 -0
- package/LICENSE +24 -0
- package/README.md +172 -2
- package/dist/canopy.js +98 -0
- package/dist/queries/arrowFunctions.scm +5 -0
- package/dist/queries/callExpressions.scm +2 -0
- package/dist/queries/classMethods.scm +6 -0
- package/dist/queries/exports.scm +9 -0
- package/dist/queries/fetchApiCalls.scm +15 -0
- package/dist/queries/functionDeclarations.scm +4 -0
- package/dist/queries/htmlScriptRoot.scm +5 -0
- package/dist/queries/imports.scm +3 -0
- package/dist/queries/jsxElements.scm +5 -0
- package/dist/queries/matchExtensionListeners.scm +62 -0
- package/dist/queries/matchFastifyRoutes.scm +28 -0
- package/dist/queries/methodCalls.scm +4 -0
- package/dist/queries/rawSocketSend.scm +26 -0
- package/dist/queries/rawSocketTypeCheck.scm +20 -0
- package/dist/queries/returns.scm +2 -0
- package/dist/queries/socketEmit.scm +8 -0
- package/dist/queries/socketOn.scm +19 -0
- package/dist/queries/typescript/arrowFunctions.scm +15 -0
- package/dist/queries/typescript/classMethods.scm +65 -0
- package/dist/queries/typescript/defaultExports.scm +6 -0
- package/dist/queries/typescript/exports.scm +16 -0
- package/dist/queries/typescript/imports.scm +8 -0
- package/package.json +94 -4
- package/ui-react/dist/bundle.css +2 -0
- package/ui-react/dist/bundle.js +110 -0
- package/ui-react/dist/fonts/Inter-latin-var.woff2 +0 -0
- package/ui-react/dist/fonts/JetBrainsMono-latin-var.woff2 +0 -0
- package/ui-react/dist/fonts/OFL-Inter.txt +92 -0
- package/ui-react/dist/fonts/OFL-JetBrainsMono.txt +93 -0
- package/ui-react/index.html +17 -0
- package/vendor/tree-sitter-html/package.json +6 -0
- package/vendor/tree-sitter-html/tree-sitter-html.wasm +0 -0
- package/vendor/tree-sitter-javascript/package.json +6 -0
- package/vendor/tree-sitter-javascript/tree-sitter-javascript.wasm +0 -0
- package/vendor/tree-sitter-typescript/package.json +6 -0
- package/vendor/tree-sitter-typescript/tree-sitter-tsx.wasm +0 -0
- package/vendor/tree-sitter-typescript/tree-sitter-typescript.wasm +0 -0
package/FEEDBACK.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Canopy feedback sheet
|
|
2
|
+
|
|
3
|
+
Thank you for trying Canopy. Please fill this in as you go; short answers are fine. Total time: about 20 minutes.
|
|
4
|
+
|
|
5
|
+
## 1. Setup
|
|
6
|
+
|
|
7
|
+
- Operating system and version:
|
|
8
|
+
- Node version (`node --version`):
|
|
9
|
+
- What the repository is (stack, rough number of files, a git repository?):
|
|
10
|
+
- Paste the output of `canopy doctor`:
|
|
11
|
+
- Did `canopy sync .` finish? (yes / no) How long did it take?
|
|
12
|
+
- Any error text (copy it exactly):
|
|
13
|
+
|
|
14
|
+
## 2. The 5-minute test
|
|
15
|
+
|
|
16
|
+
Start a timer when the map first opens. Do not read the code. After 5 minutes, write 3 sentences about what this system does and where its execution starts (its entry points):
|
|
17
|
+
|
|
18
|
+
1.
|
|
19
|
+
2.
|
|
20
|
+
3.
|
|
21
|
+
|
|
22
|
+
How accurate do you think your 3 sentences are, 1 (not at all) to 5 (fully)?
|
|
23
|
+
|
|
24
|
+
## 3. Follow one real feature end to end
|
|
25
|
+
|
|
26
|
+
Pick a feature you know (for example "a user logs in" or "a file is uploaded"). Find where it starts on the map and follow it as far as it goes.
|
|
27
|
+
|
|
28
|
+
- Which feature did you pick?
|
|
29
|
+
- Did the map show the whole path, start to finish? (yes / mostly / no)
|
|
30
|
+
- Where did you get lost, or where did the path stop?
|
|
31
|
+
- What did you have to go and read in the code anyway?
|
|
32
|
+
|
|
33
|
+
## 4. Five questions
|
|
34
|
+
|
|
35
|
+
1. What confused you?
|
|
36
|
+
2. What was missing?
|
|
37
|
+
3. What would you use this for?
|
|
38
|
+
4. Would you use it again? Why or why not?
|
|
39
|
+
5. Who else should try it?
|
|
40
|
+
|
|
41
|
+
## 5. Bugs
|
|
42
|
+
|
|
43
|
+
For each problem: what you did, what you expected, what happened (screenshot or copied text helps).
|
|
44
|
+
|
|
45
|
+
-
|
|
46
|
+
-
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Canopy Beta License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Spill It Labs Private Limited. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Permission is granted, free of charge, to use this software
|
|
6
|
+
("Canopy") for personal, educational, evaluation and
|
|
7
|
+
non-commercial purposes, on your own computer, subject to these
|
|
8
|
+
terms:
|
|
9
|
+
|
|
10
|
+
1. No redistribution. You may not copy, publish, sublicense, sell
|
|
11
|
+
or otherwise distribute Canopy or any part of it.
|
|
12
|
+
2. No reverse engineering. You may not decompile, disassemble or
|
|
13
|
+
attempt to extract the source code of Canopy, except where
|
|
14
|
+
applicable law forbids this restriction.
|
|
15
|
+
3. Commercial use. Use inside a company or for paid work needs a
|
|
16
|
+
separate written agreement. Contact: canopy.spillitlabs@gmail.com.
|
|
17
|
+
4. Your code stays yours. Canopy runs locally and does not send
|
|
18
|
+
your source code anywhere. The only network feature is the
|
|
19
|
+
optional update check (canopy update).
|
|
20
|
+
5. No warranty. Canopy is provided "as is", without warranty of
|
|
21
|
+
any kind. The author is not liable for any damages arising from
|
|
22
|
+
its use.
|
|
23
|
+
6. Ending. This license ends automatically if you break these
|
|
24
|
+
terms. The author may change the license for future versions.
|
package/README.md
CHANGED
|
@@ -1,3 +1,173 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Canopy
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Beta. JS/TS only.** Canopy is an early release for testers. It reads JavaScript and TypeScript projects; other languages are not read.
|
|
4
|
+
|
|
5
|
+
Canopy reads a **JavaScript or TypeScript** codebase and draws a map of what it does: where execution starts (routes, event listeners, socket handlers, the app's main file), what each of those calls, in order, and how the parts of a project (services) fit together. The map is built from the code itself.
|
|
6
|
+
|
|
7
|
+
**JavaScript and TypeScript only** (`.js .jsx .mjs .cjs .ts .tsx .mts .cts`). Other languages (for example Python) and Vue / Svelte files are not read.
|
|
8
|
+
|
|
9
|
+
## Install (needs Node 18 or newer)
|
|
10
|
+
|
|
11
|
+
**1. Try it, always the latest, nothing to install.** Run this inside your project folder:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npx -y canopy-engine@latest # needs the network
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**2. Install for regular use.** Once, then use the short name:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install -g canopy-engine # needs the network
|
|
21
|
+
canopy
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
(The two lines marked "needs the network" download from the npm registry. If you were given a file instead, `canopy-engine-0.1.3.tgz`, install that: `npm install -g ./canopy-engine-0.1.3.tgz`.)
|
|
25
|
+
|
|
26
|
+
**If the `canopy` command clashes with another tool** on your computer, use `canopy-engine` instead. It is the same program under a second name: `canopy-engine --version`, `canopy-engine doctor`, and so on.
|
|
27
|
+
|
|
28
|
+
## What `canopy` does
|
|
29
|
+
|
|
30
|
+
`canopy` does these steps in order and prints a plain line for each; if one fails it stops with one line saying what happened and what to do:
|
|
31
|
+
|
|
32
|
+
1. **Checks this computer** - Node 18+, a folder you can write to, free disk space (300 MB), git, a free port (the same checks as `canopy doctor`).
|
|
33
|
+
2. **Looks at your project** - counts the JavaScript / TypeScript files. A folder with none (for example a Python-only project) stops here: "Canopy currently supports JavaScript and TypeScript".
|
|
34
|
+
3. **Prepares `.canopy/`** - the only folder Canopy writes inside your project; it adds `.canopy/` to `.gitignore` (creating the file if needed, never removing a line).
|
|
35
|
+
4. **Asks about the commit hook** - "Update the map on every commit? [Y/n]" (default yes; `-y` skips the question; with no terminal it answers yes). See "Hook on and off" below.
|
|
36
|
+
5. **Builds the map** - the first time takes seconds to minutes depending on size; later runs only re-read what changed. It ends with a short summary: services, workflows, files inside a service, files with parse errors.
|
|
37
|
+
6. **Opens the map** - starts a viewer on a free local port (127.0.0.1 only) and opens your browser. Ctrl+C stops it.
|
|
38
|
+
|
|
39
|
+
Then it prints "Next time just run `canopy`." and the feedback link. Options: `-y` (no questions), `--no-open` (build the map, do not start the viewer; for scripts), `--port=N`, `--for=SECONDS` (stop the viewer by itself), and a folder to look at instead of the current one: `canopy path/to/project`.
|
|
40
|
+
|
|
41
|
+
**Supported languages: JavaScript and TypeScript only** (`.js .jsx .mjs .cjs .ts .tsx .mts .cts`). Other languages (for example Python) and Vue / Svelte files are not read.
|
|
42
|
+
|
|
43
|
+
## Updating
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
canopy update --check # needs the network
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `canopy update --check` says whether a newer version is on npm and changes nothing: "up to date (x.y.z)" or "x.y.z available (you have a.b.c). Run: canopy update".
|
|
50
|
+
- `canopy update` installs the newest version with `npm install -g canopy-engine@latest`, shows npm's output, then runs the new `canopy --version` to confirm it. If anything goes wrong it prints the exact command to run yourself. If you run Canopy with `npx -y canopy-engine@latest`, you always get the newest version and there is nothing to update.
|
|
51
|
+
- **No silent updates, ever.** Canopy never downloads, installs or changes itself on its own. The engine makes no network calls at all, except these two explicit commands (`canopy update --check` and `canopy update`), which ask registry.npmjs.org for the newest version number and nothing else.
|
|
52
|
+
- When the map opens in your browser, the page makes **one** request to registry.npmjs.org (the same version number, nothing about you or your project) and, if a newer version exists, shows a small notice at the bottom left: "Canopy x.y.z is available. In your terminal run: canopy update". You can close it; it stays closed for that version. To turn the request off completely, start Canopy with the environment variable `CANOPY_NO_UPDATE_CHECK=1` (the page then gets no address to ask and makes no request).
|
|
53
|
+
|
|
54
|
+
## Commands
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
canopy --version
|
|
58
|
+
canopy --help
|
|
59
|
+
canopy doctor
|
|
60
|
+
canopy sync .
|
|
61
|
+
canopy history
|
|
62
|
+
canopy diff
|
|
63
|
+
canopy open --for=3
|
|
64
|
+
canopy hook install
|
|
65
|
+
canopy hook uninstall
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- `canopy update [--check]` - see "Updating" above.
|
|
69
|
+
- `canopy [path]` - the one-command journey above.
|
|
70
|
+
- `canopy sync [path]` - analyze, and store a new version only if the code changed.
|
|
71
|
+
- `canopy open [path]` - serve the viewer on the latest output. `--port=N` picks the port; `--for=SECONDS` stops by itself after that time (for scripts).
|
|
72
|
+
- `canopy doctor [path]` - OK / FAIL per check (Node version, grammars, queries, write access, git, viewer, hook), each with the fix.
|
|
73
|
+
- `canopy history`, `canopy diff [from] [to] [--json]` - the stored versions and what changed between two of them.
|
|
74
|
+
- `canopy hook install` / `canopy hook uninstall` - see below.
|
|
75
|
+
|
|
76
|
+
## Links between services
|
|
77
|
+
|
|
78
|
+
When a project has more than one service (a frontend and a backend, a server and a realtime server), Canopy links the calls that cross between them:
|
|
79
|
+
|
|
80
|
+
- **HTTP**: a `fetch`, `axios` (also `axios.create({ baseURL })` instances), `ky`, `got` or `XMLHttpRequest` call with a method and a path is matched to a route of another service. Paths with parameters (`/users/${id}` and `/users/:id`), a base URL in a variable (`${API_URL}/users`) and wrapper functions (`request("POST", "/friends/request")`, where the link starts at the function that calls the wrapper) are followed.
|
|
81
|
+
- **WebSocket**: `new WebSocket(url)` / `io(url)` is linked to the service that runs a WebSocket server (a socket.io client only to a socket.io server), a `socket.send(...)` whose message is built at run time to that server's `message` listener, and, the other way round, what the server sends over the socket to the message handler of the client that connects to it (always "inferred": the message itself is not read).
|
|
82
|
+
|
|
83
|
+
Every link says how sure Canopy is: **exact** means the client URL is written out in full (no variable base URL, no parameters), the route is written out in full, and the method and path are equal on both sides; **resolved** means the base URL was followed to the service that owns it, using the project's own configuration files (an environment variable read from `.env`, a `docker-compose` service name or port, a dev-server proxy, or a server that listens on that port), and a route there matches; the link says which variable and which file; **inferred** is everything else (a base URL it had to guess, parameters matched loosely, a leading `/api` ignored, only the path matched).
|
|
84
|
+
|
|
85
|
+
Canopy reads .env and deploy-config files locally to resolve service URLs; it never stores or transmits secret values. The files are `.env` (and `.env.local`, `.env.development`, `.env.production`, `.env.example`), `docker-compose*.yml`, `render.yaml`, `fly.toml`, `railway.json` / `railway.toml`, `vercel.json` (rewrites and redirects), `netlify.toml` (redirects), `app.json` (Heroku), `Dockerfile` (`EXPOSE` and `ENV`), the dev-server proxy of `vite.config` / `next.config`, and the `proxy` field of `package.json`. They are read as plain text and never run. Only URL-like and port-like values are looked at (anything else is dropped as it is read), and only the variable name, the file name and the address without user name, password or query string can appear in the output. The links are in `.canopy/output/systemGraph.js` (`crossServiceEdges`, with `confidence`, `method`, `url`, `reason`, and for resolved links `resolvedFrom`), the service-to-service counts in `serviceLinks` (`exact` / `resolved` / `inferred`), and the steps that cross carry `crossesInto` in the viewer.
|
|
86
|
+
|
|
87
|
+
In the viewer, a step that calls into another service is joined by an edge to a small box in that service (what is called, which function receives it). The edge is solid for exact and resolved links and dashed for inferred ones; hover it for the tag and the reason (for a resolved link, the variable and the file). "View in {service}" on the box opens the receiving workflow, and the start of that workflow shows "Called from {service}: {file}" (click to go back to the caller). Back returns to the step you left.
|
|
88
|
+
|
|
89
|
+
A `package.json` `bin` or `main` that points at build output (`dist/cli.js`) now starts the map at the source file it was built from, when the repository itself says which one (a sourcemap, `tsconfig` `outDir`/`rootDir`, a `dist` -> `src` layout, or a build script that names the source such as `esbuild src/cli.js`).
|
|
90
|
+
|
|
91
|
+
## Hook on and off
|
|
92
|
+
|
|
93
|
+
The hook starts `canopy sync` in the background after every commit and merge so the map stays current. It never blocks or fails a commit and prints nothing when it works. When it runs it looks for Canopy in this order: `canopy` on your PATH; else `npx --yes canopy-engine@<the version you installed>`; else it prints one line, `canopy not found; skipping map update`, and carries on.
|
|
94
|
+
|
|
95
|
+
- Turn it on: answer Y in `canopy` (or use `-y`), or run `canopy hook install` (safe to repeat; your own hook content is kept).
|
|
96
|
+
- Turn it off: `canopy hook uninstall` (removes only Canopy's block). If you answered n once, `canopy` will not ask again.
|
|
97
|
+
|
|
98
|
+
## When it doesn't work
|
|
99
|
+
|
|
100
|
+
Run `canopy doctor` and send its output with your feedback. Healthy output (the hook line is not critical):
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
canopy 0.1.3 doctor (C:\work\my-project)
|
|
104
|
+
|
|
105
|
+
OK Node version >= 18 - v22.12.0
|
|
106
|
+
OK tree-sitter grammars (wasm) - 5 files
|
|
107
|
+
OK query files (.scm) - 17 files
|
|
108
|
+
OK write access to <path>/.canopy - C:\work\my-project\.canopy
|
|
109
|
+
OK git available - git version 2.45.1.windows.1
|
|
110
|
+
OK map viewer present
|
|
111
|
+
FAIL post-commit hook installed
|
|
112
|
+
fix: canopy hook install "C:\work\my-project" (not critical)
|
|
113
|
+
|
|
114
|
+
all critical checks passed
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
A critical problem looks like this, and `canopy doctor` then exits with 1:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
FAIL write access to <path>/.canopy - EEXIST: file already exists, mkdir 'C:\work\my-project\.canopy'
|
|
121
|
+
fix: make C:\work\my-project writable for your user, or run canopy on a folder you own
|
|
122
|
+
|
|
123
|
+
1 critical problem(s) - fix them and run canopy doctor again
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Exit codes of `canopy`: 0 ok, 1 a problem (the message says what to do), 3 no JavaScript / TypeScript files.
|
|
127
|
+
|
|
128
|
+
## What is in `.canopy/`
|
|
129
|
+
|
|
130
|
+
| file | what it is |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `output/workflows.js` | every traced workflow with its steps, calls and source - what the viewer reads (`workflows.json` is the same data as plain JSON when it fits under 25 MB) |
|
|
133
|
+
| `output/systemGraph.js` | links between workflows and between services |
|
|
134
|
+
| `output/services.js` | the services found (frontend, backend, ...) with counts |
|
|
135
|
+
| `output/meta.js`, `meta.json` | repo root and the coverage report (files analyzed, skipped, with parse errors) |
|
|
136
|
+
| `output/history.js` | the version list and recent diffs shown in the viewer's Changes panel |
|
|
137
|
+
| `history/*.json.gz` | one compressed snapshot per version (total size capped at 200 MB, `CANOPY_SNAPSHOT_MAX_MB`) |
|
|
138
|
+
| `sync.log` | log of background syncs started by the hook |
|
|
139
|
+
|
|
140
|
+
## The viewer in five bullets
|
|
141
|
+
|
|
142
|
+
- First screen: the **services** of the project and the links between them; click one to list its **workflows**.
|
|
143
|
+
- A workflow opens as a chain of cards: the entry point (a route, a listener, the main file) and the functions it calls, in source order, with branches (`if`, `switch`, `try`) shown side by side.
|
|
144
|
+
- Click a call to open it as its own card; **Trace from root** opens everything beneath the entry point (it pauses at 3,000 rows and offers Continue).
|
|
145
|
+
- The `</>` button on any card shows the exact source lines.
|
|
146
|
+
- The **Changes** panel marks what is NEW or MODIFIED between two stored versions.
|
|
147
|
+
|
|
148
|
+
## Known limits
|
|
149
|
+
|
|
150
|
+
Each line is backed by a measurement (the numbers are quoted in the lines below).
|
|
151
|
+
|
|
152
|
+
- JavaScript and TypeScript only; other languages are silently skipped (a Python-only folder gives an empty map).
|
|
153
|
+
- Links between services are found for HTTP calls with a readable method and path and for WebSocket connections; links are "resolved" only when the project's own files say which service a base URL belongs to, otherwise "inferred" (the base URL is a variable). Calls whose URL is built at run time are not linked; a message a server sends to a browser is linked to the client's message handler only when that handler calls into the project, and the link is always "inferred".
|
|
154
|
+
- Method calls on objects mostly stay unresolved (`obj.method()`: 1.3% resolved in express); plain function calls and imports resolve better.
|
|
155
|
+
- Flow type annotations are not supported (parse-server: 47 of 370 files have syntax errors).
|
|
156
|
+
- Anonymous exports have no node, so calls into them are not followed.
|
|
157
|
+
- Repositories with 5,000+ files take minutes (strapi, 5,451 files: 219 s the first time).
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
- `canopy doctor` first. It exits non-zero only when a critical check fails (Node, grammars, queries, write access).
|
|
162
|
+
- "no map yet": run `canopy sync <path>` (or just `canopy`) before `canopy open <path>`.
|
|
163
|
+
- A commit prints `canopy not found; skipping map update`: neither `canopy` nor `npx` is on the PATH git uses; install Canopy globally (`npm i -g canopy-engine`) or run `canopy hook uninstall`.
|
|
164
|
+
- Parse errors in a few files are normal; the coverage block printed by `canopy sync` lists them and the rest of each file is still analyzed.
|
|
165
|
+
- The viewer answers "forbidden" (403): it only accepts a `127.0.0.1` or `localhost` address. A forwarded port opened under another host name (Codespaces, dev containers, `ssh -L` with a custom name) is refused on purpose; open `http://127.0.0.1:<port>/` instead.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
Canopy is free for personal, educational and evaluation use on your own computer; commercial use (inside a company or for paid work) needs a separate written agreement. The full terms are in the `LICENSE` file in this package.
|
|
170
|
+
|
|
171
|
+
## Feedback
|
|
172
|
+
|
|
173
|
+
Please use [FEEDBACK.md](FEEDBACK.md) (about 20 minutes) and send it back, with the output of `canopy doctor`, to whoever gave you this package. `canopy` prints the feedback link from `canopyFeedbackUrl` in package.json (a placeholder until the owner sets it).
|