crumbtrail 0.1.1 → 0.2.1
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/LICENSE +21 -0
- package/README.md +83 -0
- package/dist/bug-widget-LGIRLS76-WB3MQGAH.js +199 -0
- package/dist/chunk-MZDASWQ7.js +1570 -0
- package/dist/cli.cjs +214 -6044
- package/dist/cli.d.cts +2 -2
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +1 -1
- package/dist/{executor-BKiOvIvD.d.cts → executor-CW6Q5mhH.d.cts} +1 -1
- package/dist/{executor-BKiOvIvD.d.ts → executor-CW6Q5mhH.d.ts} +1 -1
- package/dist/index.cjs +120 -5950
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +8 -4
- package/dist/chunk-HAP4DPWC.js +0 -7423
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Crumbtrail
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# crumbtrail
|
|
2
|
+
|
|
3
|
+
The setup wizard for [Crumbtrail](https://crumbtrail.dev). It finds your app, wires
|
|
4
|
+
in the SDK, and confirms the first event actually arrives — so you don't have to
|
|
5
|
+
read an integration guide to get started.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx crumbtrail
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
That's the whole install. There's nothing to add to `package.json` first.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Running `npx crumbtrail` walks the full path in one pass:
|
|
16
|
+
|
|
17
|
+
1. **Detects** your stack — Next.js, Vite, React, Vue, Svelte, Express, Hono, Node,
|
|
18
|
+
and non-JS services like Django, Rails, Go and .NET.
|
|
19
|
+
2. **Logs you in** (opens a browser, or use `--no-browser` for a device code).
|
|
20
|
+
3. **Provisions** a project and service, and mints an ingest key.
|
|
21
|
+
4. **Installs** the right SDK package and **injects** the setup code into your entry
|
|
22
|
+
file. This is the only step that writes to your repo, and it always runs last.
|
|
23
|
+
5. **Verifies** the wiring end to end, then waits for your first real event.
|
|
24
|
+
|
|
25
|
+
In a monorepo, run it from the repo root: it scans every workspace and service,
|
|
26
|
+
shows you what it found, and wires the ones you pick.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
crumbtrail [options] Run the setup wizard (detect → login → wire → verify)
|
|
32
|
+
crumbtrail login Log in and cache a token, nothing else
|
|
33
|
+
crumbtrail logout Delete the cached token
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Option | Description |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `--yes`, `-y` | Skip confirmations (required with `--project` in CI) |
|
|
39
|
+
| `--project <id>` | Attach to an existing project instead of creating one |
|
|
40
|
+
| `--only <name>` | Monorepo: wire only this service (repeatable) |
|
|
41
|
+
| `--all` | Monorepo: wire every service it can, no prompts |
|
|
42
|
+
| `--workspace <dir>` | Wire just one package dir instead of the whole repo |
|
|
43
|
+
| `--no-browser` | Use the device-code login flow |
|
|
44
|
+
| `--skip-verify` | Don't wait for the first event |
|
|
45
|
+
| `--endpoint <url>` | Cloud endpoint (else `$CRUMBTRAIL_BASE_URL`, else the default) |
|
|
46
|
+
| `--version`, `-v` | Print the version |
|
|
47
|
+
|
|
48
|
+
### Non-interactive / CI
|
|
49
|
+
|
|
50
|
+
Outside a TTY the wizard refuses to guess. Pass `--yes` and an existing
|
|
51
|
+
`--project <id>`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx crumbtrail --yes --project prj_1234abcd --only web --skip-verify
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## What it writes
|
|
58
|
+
|
|
59
|
+
Only two kinds of change, both in the package it's wiring:
|
|
60
|
+
|
|
61
|
+
- the SDK import and `Crumbtrail.init(...)` call in your entry file
|
|
62
|
+
- `CRUMBTRAIL_KEY` appended to that package's `.env`
|
|
63
|
+
|
|
64
|
+
It won't touch a package that is already wired, and it never edits libraries or
|
|
65
|
+
config-only packages.
|
|
66
|
+
|
|
67
|
+
## Prefer to wire it by hand?
|
|
68
|
+
|
|
69
|
+
Nothing here is magic — see [`crumbtrail-core`](https://www.npmjs.com/package/crumbtrail-core)
|
|
70
|
+
for the three-line manual setup.
|
|
71
|
+
|
|
72
|
+
## Links
|
|
73
|
+
|
|
74
|
+
- **Website** — https://crumbtrail.dev
|
|
75
|
+
- **Docs** — https://crumbtrail.dev/docs
|
|
76
|
+
- **How it works** — https://crumbtrail.dev/how-it-works
|
|
77
|
+
- **Pricing** — https://crumbtrail.dev/pricing
|
|
78
|
+
- **Source** — https://github.com/crumbtrail-dev/crumbtrail-js
|
|
79
|
+
- **Issues** — https://github.com/crumbtrail-dev/crumbtrail-js/issues
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// ../core/dist/bug-widget-LGIRLS76.js
|
|
2
|
+
var WIDGET_CSS = `
|
|
3
|
+
:host {
|
|
4
|
+
all: initial;
|
|
5
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
6
|
+
font-size: 14px;
|
|
7
|
+
color: #e0e0e0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.bl-trigger {
|
|
11
|
+
position: fixed;
|
|
12
|
+
bottom: 20px;
|
|
13
|
+
right: 20px;
|
|
14
|
+
width: 48px;
|
|
15
|
+
height: 48px;
|
|
16
|
+
border-radius: 50%;
|
|
17
|
+
background: #dc2626;
|
|
18
|
+
border: none;
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
24
|
+
z-index: 2147483647;
|
|
25
|
+
transition: transform 0.15s ease, background 0.15s ease;
|
|
26
|
+
}
|
|
27
|
+
.bl-trigger:hover {
|
|
28
|
+
transform: scale(1.1);
|
|
29
|
+
background: #ef4444;
|
|
30
|
+
}
|
|
31
|
+
.bl-trigger svg {
|
|
32
|
+
width: 24px;
|
|
33
|
+
height: 24px;
|
|
34
|
+
fill: white;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.bl-popover {
|
|
38
|
+
position: fixed;
|
|
39
|
+
bottom: 80px;
|
|
40
|
+
right: 20px;
|
|
41
|
+
width: 320px;
|
|
42
|
+
background: #1e1e1e;
|
|
43
|
+
border: 1px solid #333;
|
|
44
|
+
border-radius: 12px;
|
|
45
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
|
46
|
+
z-index: 2147483647;
|
|
47
|
+
padding: 16px;
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
.bl-popover.open {
|
|
51
|
+
display: block;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.bl-popover h3 {
|
|
55
|
+
margin: 0 0 12px;
|
|
56
|
+
font-size: 15px;
|
|
57
|
+
font-weight: 600;
|
|
58
|
+
color: #f5f5f5;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.bl-note {
|
|
62
|
+
width: 100%;
|
|
63
|
+
min-height: 60px;
|
|
64
|
+
background: #2a2a2a;
|
|
65
|
+
border: 1px solid #444;
|
|
66
|
+
border-radius: 8px;
|
|
67
|
+
color: #e0e0e0;
|
|
68
|
+
padding: 8px 10px;
|
|
69
|
+
font-size: 13px;
|
|
70
|
+
font-family: inherit;
|
|
71
|
+
resize: vertical;
|
|
72
|
+
box-sizing: border-box;
|
|
73
|
+
}
|
|
74
|
+
.bl-note::placeholder {
|
|
75
|
+
color: #777;
|
|
76
|
+
}
|
|
77
|
+
.bl-note:focus {
|
|
78
|
+
outline: none;
|
|
79
|
+
border-color: #dc2626;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.bl-actions {
|
|
83
|
+
display: flex;
|
|
84
|
+
gap: 8px;
|
|
85
|
+
margin-top: 12px;
|
|
86
|
+
align-items: center;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.bl-btn {
|
|
90
|
+
padding: 8px 16px;
|
|
91
|
+
border-radius: 8px;
|
|
92
|
+
border: none;
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
font-size: 13px;
|
|
95
|
+
font-weight: 500;
|
|
96
|
+
transition: background 0.15s ease;
|
|
97
|
+
}
|
|
98
|
+
.bl-submit {
|
|
99
|
+
background: #dc2626;
|
|
100
|
+
color: white;
|
|
101
|
+
flex: 1;
|
|
102
|
+
}
|
|
103
|
+
.bl-submit:hover {
|
|
104
|
+
background: #ef4444;
|
|
105
|
+
}
|
|
106
|
+
.bl-submit:disabled {
|
|
107
|
+
opacity: 0.5;
|
|
108
|
+
cursor: not-allowed;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.bl-status {
|
|
112
|
+
font-size: 11px;
|
|
113
|
+
color: #777;
|
|
114
|
+
margin-top: 8px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.bl-hint {
|
|
118
|
+
font-size: 11px;
|
|
119
|
+
color: #555;
|
|
120
|
+
margin-top: 8px;
|
|
121
|
+
text-align: center;
|
|
122
|
+
}
|
|
123
|
+
`;
|
|
124
|
+
var BUG_SVG = `<svg viewBox="0 0 24 24"><path d="M20 8h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>`;
|
|
125
|
+
function mountWidget(logger) {
|
|
126
|
+
const host = document.createElement("div");
|
|
127
|
+
host.id = "crumbtrail-widget";
|
|
128
|
+
const shadow = host.attachShadow({ mode: "closed" });
|
|
129
|
+
const style = document.createElement("style");
|
|
130
|
+
style.textContent = WIDGET_CSS;
|
|
131
|
+
shadow.appendChild(style);
|
|
132
|
+
const trigger = document.createElement("button");
|
|
133
|
+
trigger.className = "bl-trigger";
|
|
134
|
+
trigger.innerHTML = BUG_SVG;
|
|
135
|
+
trigger.title = "Flag a bug (Ctrl+Shift+B)";
|
|
136
|
+
shadow.appendChild(trigger);
|
|
137
|
+
const popover = document.createElement("div");
|
|
138
|
+
popover.className = "bl-popover";
|
|
139
|
+
popover.innerHTML = `
|
|
140
|
+
<h3>Flag a Bug</h3>
|
|
141
|
+
<textarea class="bl-note" placeholder="What went wrong? (optional)"></textarea>
|
|
142
|
+
<div class="bl-actions">
|
|
143
|
+
<button class="bl-btn bl-submit">Send Bug Report</button>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="bl-status"></div>
|
|
146
|
+
<div class="bl-hint">Ctrl+Shift+B to toggle</div>
|
|
147
|
+
`;
|
|
148
|
+
shadow.appendChild(popover);
|
|
149
|
+
const noteInput = popover.querySelector(".bl-note");
|
|
150
|
+
const submitBtn = popover.querySelector(".bl-submit");
|
|
151
|
+
const statusEl = popover.querySelector(".bl-status");
|
|
152
|
+
let isOpen = false;
|
|
153
|
+
function toggle() {
|
|
154
|
+
isOpen = !isOpen;
|
|
155
|
+
popover.classList.toggle("open", isOpen);
|
|
156
|
+
if (isOpen) {
|
|
157
|
+
noteInput.focus();
|
|
158
|
+
} else {
|
|
159
|
+
reset();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function reset() {
|
|
163
|
+
noteInput.value = "";
|
|
164
|
+
statusEl.textContent = "";
|
|
165
|
+
}
|
|
166
|
+
trigger.addEventListener("click", toggle);
|
|
167
|
+
submitBtn.addEventListener("click", async () => {
|
|
168
|
+
submitBtn.disabled = true;
|
|
169
|
+
statusEl.textContent = "Sending...";
|
|
170
|
+
try {
|
|
171
|
+
const { bugId } = await logger.flagBug({
|
|
172
|
+
note: noteInput.value || void 0
|
|
173
|
+
});
|
|
174
|
+
statusEl.textContent = `Saved: ${bugId}`;
|
|
175
|
+
setTimeout(() => {
|
|
176
|
+
toggle();
|
|
177
|
+
submitBtn.disabled = false;
|
|
178
|
+
}, 1500);
|
|
179
|
+
} catch {
|
|
180
|
+
statusEl.textContent = "Failed to send";
|
|
181
|
+
submitBtn.disabled = false;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
function onKeyDown(e) {
|
|
185
|
+
if (e.ctrlKey && e.shiftKey && e.key === "B") {
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
toggle();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
document.addEventListener("keydown", onKeyDown);
|
|
191
|
+
document.body.appendChild(host);
|
|
192
|
+
return () => {
|
|
193
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
194
|
+
host.remove();
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
mountWidget
|
|
199
|
+
};
|