@cavuno/board 4.15.0 → 4.18.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/CHANGELOG.md +27 -0
- package/dist/{_spec-DdWB8z1Z.d.mts → _spec-Dk0TIRUc.d.mts} +19 -7
- package/dist/{_spec-DdWB8z1Z.d.ts → _spec-Dk0TIRUc.d.ts} +19 -7
- package/dist/analytics.d.mts +58 -0
- package/dist/analytics.d.ts +58 -0
- package/dist/analytics.js +222 -0
- package/dist/analytics.mjs +199 -0
- package/dist/bin.mjs +99 -26
- package/dist/{blog-B7xorPBw.d.ts → blog-1THfucKR.d.ts} +1 -1
- package/dist/{blog-DopIQsKV.d.mts → blog-C04NWTh_.d.mts} +1 -1
- package/dist/{board-Bpnqn4Rg.d.ts → board-CqeoQAa1.d.ts} +2 -2
- package/dist/{board-CkgTW4cC.d.mts → board-DIO9aFXx.d.mts} +2 -2
- package/dist/{breadcrumbs-DelEqbSz.d.ts → breadcrumbs-CCT1oC2-.d.ts} +2 -2
- package/dist/{breadcrumbs-CAppxMoS.d.mts → breadcrumbs-mE9Zsxlq.d.mts} +2 -2
- package/dist/browser/cavuno-board.global.min.js +1 -1
- package/dist/{chunk-W73BOGOQ.mjs → chunk-2WBQVVOB.mjs} +1 -0
- package/dist/doctor.js +93 -21
- package/dist/doctor.mjs +93 -21
- package/dist/filters.d.mts +2 -2
- package/dist/filters.d.ts +2 -2
- package/dist/format.d.mts +4 -4
- package/dist/format.d.ts +4 -4
- package/dist/index.d.mts +12 -12
- package/dist/index.d.ts +12 -12
- package/dist/index.js +6 -2
- package/dist/index.mjs +6 -3
- package/dist/{jobs-Dq0TTcRf.d.mts → jobs-CVmAWGtJ.d.mts} +1 -1
- package/dist/{jobs-CExc4QdI.d.ts → jobs-Dvv0vX8p.d.ts} +1 -1
- package/dist/{search-D6hau3d4.d.mts → search-BJ5myYaf.d.mts} +1 -1
- package/dist/{search-CZOec95V.d.ts → search-CcstbHOe.d.ts} +1 -1
- package/dist/{seo-C1hFa0-v.d.ts → seo-CWO6N-iE.d.ts} +1 -1
- package/dist/{seo-CJSwd_ss.d.mts → seo-Ds6tLMqU.d.mts} +1 -1
- package/dist/seo-files.d.mts +2 -2
- package/dist/seo-files.d.ts +2 -2
- package/dist/seo.d.mts +6 -6
- package/dist/seo.d.ts +6 -6
- package/dist/server.d.mts +6 -6
- package/dist/server.d.ts +6 -6
- package/dist/server.mjs +1 -1
- package/dist/sitemap.d.mts +6 -6
- package/dist/sitemap.d.ts +6 -6
- package/dist/suggest.d.mts +2 -2
- package/dist/suggest.d.ts +2 -2
- package/package.json +11 -1
- package/skills/manifest.json +1 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// src/analytics/defaults.ts
|
|
2
|
+
var DEFAULT_COLLECT_URL = "https://cavuno.com/api/analytics/collect";
|
|
3
|
+
var DEFAULT_SCRIPT_URL = "https://cavuno.com/js/metrics.js";
|
|
4
|
+
var PENDING_TENANT_ID = "boards_pending";
|
|
5
|
+
var WELL_KNOWN_ANALYTICS_SCRIPT_PATH = "/.well-known/cavuno/analytics.js";
|
|
6
|
+
var WELL_KNOWN_SCRIPT_PATH = WELL_KNOWN_ANALYTICS_SCRIPT_PATH;
|
|
7
|
+
var WELL_KNOWN_COLLECT_PATH = "/.well-known/cavuno/collect";
|
|
8
|
+
|
|
9
|
+
// src/analytics/well-known.ts
|
|
10
|
+
var WELL_KNOWN_COLLECT_EVENTS_PATH = "/.well-known/cavuno/collect/v0/events";
|
|
11
|
+
var CORS_HEADERS = {
|
|
12
|
+
"Access-Control-Allow-Origin": "*",
|
|
13
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
14
|
+
"Access-Control-Allow-Headers": "Authorization, Content-Type, Accept",
|
|
15
|
+
"Access-Control-Max-Age": "86400",
|
|
16
|
+
"Cross-Origin-Resource-Policy": "cross-origin"
|
|
17
|
+
};
|
|
18
|
+
function stripTrailingSlash(pathname) {
|
|
19
|
+
return pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
20
|
+
}
|
|
21
|
+
function withCors(response) {
|
|
22
|
+
const headers = new Headers(response.headers);
|
|
23
|
+
for (const [key, value] of Object.entries(CORS_HEADERS)) {
|
|
24
|
+
headers.set(key, value);
|
|
25
|
+
}
|
|
26
|
+
return new Response(response.body, {
|
|
27
|
+
status: response.status,
|
|
28
|
+
statusText: response.statusText,
|
|
29
|
+
headers
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function corsPreflight() {
|
|
33
|
+
return withCors(new Response(null, { status: 204 }));
|
|
34
|
+
}
|
|
35
|
+
async function proxyCollect(request, targetUrl) {
|
|
36
|
+
if (request.method === "OPTIONS") {
|
|
37
|
+
return corsPreflight();
|
|
38
|
+
}
|
|
39
|
+
if (request.method !== "POST") {
|
|
40
|
+
return withCors(new Response(null, { status: 405 }));
|
|
41
|
+
}
|
|
42
|
+
const headers = new Headers();
|
|
43
|
+
const authorization = request.headers.get("Authorization");
|
|
44
|
+
const contentType = request.headers.get("Content-Type");
|
|
45
|
+
const accept = request.headers.get("Accept");
|
|
46
|
+
if (authorization) headers.set("Authorization", authorization);
|
|
47
|
+
if (contentType) headers.set("Content-Type", contentType);
|
|
48
|
+
if (accept) headers.set("Accept", accept);
|
|
49
|
+
const body = await request.arrayBuffer();
|
|
50
|
+
const upstream = await fetch(targetUrl, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers,
|
|
53
|
+
body
|
|
54
|
+
});
|
|
55
|
+
return withCors(
|
|
56
|
+
new Response(upstream.body, {
|
|
57
|
+
status: upstream.status,
|
|
58
|
+
headers: {
|
|
59
|
+
"Content-Type": upstream.headers.get("Content-Type") ?? "application/json"
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
async function matchAnalyticsWellKnown(request) {
|
|
65
|
+
const path = stripTrailingSlash(new URL(request.url).pathname);
|
|
66
|
+
if (path === WELL_KNOWN_ANALYTICS_SCRIPT_PATH) {
|
|
67
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
68
|
+
return new Response(null, { status: 405 });
|
|
69
|
+
}
|
|
70
|
+
return Response.redirect(DEFAULT_SCRIPT_URL, 302);
|
|
71
|
+
}
|
|
72
|
+
if (path === WELL_KNOWN_COLLECT_PATH) {
|
|
73
|
+
return proxyCollect(request, DEFAULT_COLLECT_URL);
|
|
74
|
+
}
|
|
75
|
+
if (path === WELL_KNOWN_COLLECT_EVENTS_PATH) {
|
|
76
|
+
return proxyCollect(request, `${DEFAULT_COLLECT_URL}/v0/events`);
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/analytics/index.ts
|
|
82
|
+
var GLOBAL_NAME = "CavunoAnalytics";
|
|
83
|
+
var installed = null;
|
|
84
|
+
function getRoot() {
|
|
85
|
+
return globalThis;
|
|
86
|
+
}
|
|
87
|
+
function normalizeCollectUrl(url) {
|
|
88
|
+
return url.replace(/\/+$/, "");
|
|
89
|
+
}
|
|
90
|
+
function resolveDefaultCollectUrl() {
|
|
91
|
+
return DEFAULT_COLLECT_URL;
|
|
92
|
+
}
|
|
93
|
+
function resolveDefaultScriptUrl() {
|
|
94
|
+
return DEFAULT_SCRIPT_URL;
|
|
95
|
+
}
|
|
96
|
+
function postCollectJson(state, action, payload) {
|
|
97
|
+
const body = JSON.stringify({
|
|
98
|
+
publishableKey: state.publishableKey,
|
|
99
|
+
action,
|
|
100
|
+
payload: payload ?? {}
|
|
101
|
+
});
|
|
102
|
+
void fetch(state.collectUrl, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: {
|
|
105
|
+
Authorization: `Bearer ${state.publishableKey}`,
|
|
106
|
+
"Content-Type": "application/json",
|
|
107
|
+
Accept: "application/json"
|
|
108
|
+
},
|
|
109
|
+
body,
|
|
110
|
+
keepalive: true
|
|
111
|
+
}).catch(() => {
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function exposeGlobal(state) {
|
|
115
|
+
const root = getRoot();
|
|
116
|
+
root[GLOBAL_NAME] = {
|
|
117
|
+
trackEvent(action, payload) {
|
|
118
|
+
postCollectJson(state, action, payload);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function injectScript(state, scriptUrl) {
|
|
123
|
+
const doc = getRoot().document;
|
|
124
|
+
if (!doc?.createElement) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (doc.querySelector?.(`script[data-cavuno-analytics="1"]`)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const el = doc.createElement("script");
|
|
131
|
+
el.defer = true;
|
|
132
|
+
el.src = scriptUrl;
|
|
133
|
+
el.setAttribute("data-cavuno-analytics", "1");
|
|
134
|
+
el.setAttribute("data-token", state.publishableKey);
|
|
135
|
+
el.setAttribute("data-host", state.collectUrl);
|
|
136
|
+
el.setAttribute("data-tenant-id", PENDING_TENANT_ID);
|
|
137
|
+
el.setAttribute("data-web-vitals", "true");
|
|
138
|
+
const head = doc.head;
|
|
139
|
+
if (head?.appendChild) {
|
|
140
|
+
head.appendChild(el);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const first = doc.getElementsByTagName("script")[0];
|
|
144
|
+
first?.parentNode?.insertBefore(el, first);
|
|
145
|
+
}
|
|
146
|
+
function install(options) {
|
|
147
|
+
const publishableKey = options.publishableKey.trim();
|
|
148
|
+
if (!publishableKey.startsWith("pk_")) {
|
|
149
|
+
throw new Error("analytics.install requires a publishable key (pk_\u2026)");
|
|
150
|
+
}
|
|
151
|
+
const collectUrl = normalizeCollectUrl(
|
|
152
|
+
(options.collectUrl ?? resolveDefaultCollectUrl()).trim() || resolveDefaultCollectUrl()
|
|
153
|
+
);
|
|
154
|
+
const scriptUrl = (options.scriptUrl ?? resolveDefaultScriptUrl()).trim() || resolveDefaultScriptUrl();
|
|
155
|
+
installed = { publishableKey, collectUrl };
|
|
156
|
+
exposeGlobal(installed);
|
|
157
|
+
injectScript(installed, scriptUrl);
|
|
158
|
+
}
|
|
159
|
+
function track(action, payload) {
|
|
160
|
+
const trimmed = action.trim();
|
|
161
|
+
if (!trimmed) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const root = getRoot();
|
|
165
|
+
const globalTrack = root[GLOBAL_NAME]?.trackEvent;
|
|
166
|
+
if (typeof globalTrack === "function" && installed) {
|
|
167
|
+
globalTrack(trimmed, payload);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (!installed) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
postCollectJson(installed, trimmed, payload);
|
|
174
|
+
}
|
|
175
|
+
var analytics = {
|
|
176
|
+
install,
|
|
177
|
+
track,
|
|
178
|
+
matchAnalyticsWellKnown,
|
|
179
|
+
DEFAULT_COLLECT_URL,
|
|
180
|
+
DEFAULT_SCRIPT_URL,
|
|
181
|
+
PENDING_TENANT_ID,
|
|
182
|
+
WELL_KNOWN_ANALYTICS_SCRIPT_PATH,
|
|
183
|
+
WELL_KNOWN_SCRIPT_PATH,
|
|
184
|
+
WELL_KNOWN_COLLECT_PATH,
|
|
185
|
+
WELL_KNOWN_COLLECT_EVENTS_PATH
|
|
186
|
+
};
|
|
187
|
+
export {
|
|
188
|
+
DEFAULT_COLLECT_URL,
|
|
189
|
+
DEFAULT_SCRIPT_URL,
|
|
190
|
+
PENDING_TENANT_ID,
|
|
191
|
+
WELL_KNOWN_ANALYTICS_SCRIPT_PATH,
|
|
192
|
+
WELL_KNOWN_COLLECT_EVENTS_PATH,
|
|
193
|
+
WELL_KNOWN_COLLECT_PATH,
|
|
194
|
+
WELL_KNOWN_SCRIPT_PATH,
|
|
195
|
+
analytics,
|
|
196
|
+
install,
|
|
197
|
+
matchAnalyticsWellKnown,
|
|
198
|
+
track
|
|
199
|
+
};
|
package/dist/bin.mjs
CHANGED
|
@@ -119,11 +119,83 @@ function summarize(results) {
|
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// src/doctor/
|
|
122
|
+
// src/doctor/analytics-surface.ts
|
|
123
123
|
import { existsSync, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync } from "fs";
|
|
124
124
|
import { join, relative } from "path";
|
|
125
|
+
var ANALYTICS = record("static.analytics-surface", 1);
|
|
126
|
+
var SOURCE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|astro|svelte|vue|mdx)$/;
|
|
127
|
+
var TEST_FILE = /\.(?:test|spec)\./;
|
|
128
|
+
var FORBIDDEN = [
|
|
129
|
+
{ id: "window.Tinybird", re: /\bwindow\.Tinybird\b/ },
|
|
130
|
+
{ id: "@tinybirdco/flock", re: /@tinybirdco\/flock/ },
|
|
131
|
+
{ id: "CAVUNO_TRACKER_TOKEN", re: /\bCAVUNO_TRACKER_TOKEN\b/ }
|
|
132
|
+
];
|
|
133
|
+
var SCAN_ROOTS = ["src", "app", "apps"];
|
|
134
|
+
var SKIP_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
135
|
+
"node_modules",
|
|
136
|
+
"dist",
|
|
137
|
+
".git",
|
|
138
|
+
".turbo",
|
|
139
|
+
"coverage",
|
|
140
|
+
"paraglide"
|
|
141
|
+
]);
|
|
142
|
+
function walkFiles(root, out) {
|
|
143
|
+
if (!existsSync(root)) return;
|
|
144
|
+
for (const entry of readdirSync2(root)) {
|
|
145
|
+
if (SKIP_DIR_NAMES.has(entry)) continue;
|
|
146
|
+
const full = join(root, entry);
|
|
147
|
+
const st = statSync(full);
|
|
148
|
+
if (st.isDirectory()) {
|
|
149
|
+
walkFiles(full, out);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (SOURCE_EXT.test(entry) && !TEST_FILE.test(entry)) {
|
|
153
|
+
out.push(full);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function checkAnalyticsSurface(projectRoot) {
|
|
158
|
+
const files = [];
|
|
159
|
+
for (const name of SCAN_ROOTS) {
|
|
160
|
+
walkFiles(join(projectRoot, name), files);
|
|
161
|
+
}
|
|
162
|
+
if (files.length === 0) {
|
|
163
|
+
return ANALYTICS(
|
|
164
|
+
"skip",
|
|
165
|
+
"no src/, app/, or apps/ tree to scan for analytics surface"
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const hits = [];
|
|
169
|
+
for (const file of files) {
|
|
170
|
+
let text;
|
|
171
|
+
try {
|
|
172
|
+
text = readFileSync2(file, "utf8");
|
|
173
|
+
} catch {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
for (const rule of FORBIDDEN) {
|
|
177
|
+
if (rule.re.test(text)) {
|
|
178
|
+
hits.push(`${relative(projectRoot, file)}:${rule.id}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (hits.length === 0) {
|
|
183
|
+
return ANALYTICS(
|
|
184
|
+
"pass",
|
|
185
|
+
"no Tinybird-branded analytics APIs in app source"
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return ANALYTICS(
|
|
189
|
+
"fail",
|
|
190
|
+
`use @cavuno/board/analytics + CAVUNO_BOARD only \u2014 found ${hits.slice(0, 8).join(", ")}${hits.length > 8 ? ` (+${hits.length - 8} more)` : ""}`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/doctor/cookie-conformance.ts
|
|
195
|
+
import { existsSync as existsSync2, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
196
|
+
import { join as join2, relative as relative2 } from "path";
|
|
125
197
|
var COOKIE = record("static.cookie-codec", 1);
|
|
126
|
-
var
|
|
198
|
+
var SOURCE_EXT2 = /\.(ts|tsx|js|jsx|mjs|cjs|astro|svelte|vue)$/;
|
|
127
199
|
var REMEDIATION = "set cookies only through the SDK server cookie codec (buildCookie/buildClearCookie from @cavuno/board/server)";
|
|
128
200
|
var SET_COOKIE_SINK = /set-cookie/i;
|
|
129
201
|
var DOCUMENT_COOKIE_ASSIGN = /document\.cookie\s*\+?=(?!=)/i;
|
|
@@ -226,23 +298,23 @@ function hasGeneratedBanner(text) {
|
|
|
226
298
|
function walkSourceFiles(dir, out) {
|
|
227
299
|
let entries;
|
|
228
300
|
try {
|
|
229
|
-
entries =
|
|
301
|
+
entries = readdirSync3(dir);
|
|
230
302
|
} catch {
|
|
231
303
|
return;
|
|
232
304
|
}
|
|
233
305
|
for (const name of entries) {
|
|
234
306
|
if (name === "node_modules" || name.startsWith(".")) continue;
|
|
235
307
|
if (GENERATED_DIRS.has(name) || GENERATED_FILE.test(name)) continue;
|
|
236
|
-
const full =
|
|
308
|
+
const full = join2(dir, name);
|
|
237
309
|
let st;
|
|
238
310
|
try {
|
|
239
|
-
st =
|
|
311
|
+
st = statSync2(full);
|
|
240
312
|
} catch {
|
|
241
313
|
continue;
|
|
242
314
|
}
|
|
243
315
|
if (st.isDirectory()) {
|
|
244
316
|
walkSourceFiles(full, out);
|
|
245
|
-
} else if (st.isFile() &&
|
|
317
|
+
} else if (st.isFile() && SOURCE_EXT2.test(name)) {
|
|
246
318
|
out.push(full);
|
|
247
319
|
}
|
|
248
320
|
}
|
|
@@ -252,8 +324,8 @@ function truncate(line, max = 120) {
|
|
|
252
324
|
return t.length > max ? `${t.slice(0, max)}\u2026` : t;
|
|
253
325
|
}
|
|
254
326
|
function checkCookieCodecConformance(projectRoot) {
|
|
255
|
-
const srcDir =
|
|
256
|
-
if (!
|
|
327
|
+
const srcDir = join2(projectRoot, "src");
|
|
328
|
+
if (!existsSync2(srcDir)) {
|
|
257
329
|
return [
|
|
258
330
|
COOKIE(
|
|
259
331
|
"skip",
|
|
@@ -265,10 +337,10 @@ function checkCookieCodecConformance(projectRoot) {
|
|
|
265
337
|
walkSourceFiles(srcDir, files);
|
|
266
338
|
const findings = [];
|
|
267
339
|
for (const file of files) {
|
|
268
|
-
const rel =
|
|
340
|
+
const rel = relative2(projectRoot, file).split("\\").join("/");
|
|
269
341
|
let text;
|
|
270
342
|
try {
|
|
271
|
-
text =
|
|
343
|
+
text = readFileSync3(file, "utf8");
|
|
272
344
|
} catch {
|
|
273
345
|
continue;
|
|
274
346
|
}
|
|
@@ -528,8 +600,8 @@ async function runReadProbes(fetchImpl, frontendUrl, seo) {
|
|
|
528
600
|
}
|
|
529
601
|
|
|
530
602
|
// src/doctor/run.ts
|
|
531
|
-
import { existsSync as
|
|
532
|
-
import { join as
|
|
603
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
604
|
+
import { join as join3 } from "path";
|
|
533
605
|
var STATIC_API = record("static.api", 1);
|
|
534
606
|
var STATIC_BOARD = record("static.board", 1);
|
|
535
607
|
var STATIC_SKILLS = record("static.skills", 1);
|
|
@@ -607,8 +679,8 @@ var SKILL_ROOTS = [
|
|
|
607
679
|
".cursor/skills"
|
|
608
680
|
];
|
|
609
681
|
function checkSkillsFreshness(projectRoot) {
|
|
610
|
-
const roots = SKILL_ROOTS.map((root) =>
|
|
611
|
-
(root) =>
|
|
682
|
+
const roots = SKILL_ROOTS.map((root) => join3(projectRoot, root)).filter(
|
|
683
|
+
(root) => existsSync3(root)
|
|
612
684
|
);
|
|
613
685
|
if (roots.length === 0) {
|
|
614
686
|
return STATIC_SKILLS(
|
|
@@ -621,10 +693,10 @@ function checkSkillsFreshness(projectRoot) {
|
|
|
621
693
|
const seen = /* @__PURE__ */ new Set();
|
|
622
694
|
for (const root of roots) {
|
|
623
695
|
for (const skill of corpus.skills) {
|
|
624
|
-
const copied =
|
|
625
|
-
if (!
|
|
696
|
+
const copied = join3(root, skill.name, "SKILL.md");
|
|
697
|
+
if (!existsSync3(copied)) continue;
|
|
626
698
|
seen.add(skill.name);
|
|
627
|
-
if (
|
|
699
|
+
if (readFileSync4(copied, "utf8") !== skill.content) {
|
|
628
700
|
stale.add(skill.name);
|
|
629
701
|
}
|
|
630
702
|
}
|
|
@@ -672,10 +744,10 @@ async function runDoctor(options) {
|
|
|
672
744
|
} else {
|
|
673
745
|
results.push(STATIC_BOARD("skip", "env checks failed \u2014 fix them first"));
|
|
674
746
|
}
|
|
675
|
-
|
|
676
|
-
results.push(
|
|
677
|
-
|
|
678
|
-
);
|
|
747
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
748
|
+
results.push(checkSkillsFreshness(projectRoot));
|
|
749
|
+
results.push(...checkCookieCodecConformance(projectRoot));
|
|
750
|
+
results.push(checkAnalyticsSurface(projectRoot));
|
|
679
751
|
results.push(
|
|
680
752
|
...options.frontendUrl ? await runReadProbes(fetchImpl, options.frontendUrl, seo) : skipReadProbes("no --frontend <url> given")
|
|
681
753
|
);
|
|
@@ -683,7 +755,7 @@ async function runDoctor(options) {
|
|
|
683
755
|
}
|
|
684
756
|
|
|
685
757
|
// src/setup/run.ts
|
|
686
|
-
import { cpSync, existsSync as
|
|
758
|
+
import { cpSync, existsSync as existsSync4, mkdirSync, readFileSync as readFileSync5, rmSync } from "fs";
|
|
687
759
|
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
688
760
|
var RETIRED_SKILL_NAMES = [
|
|
689
761
|
"cavuno-board-theme",
|
|
@@ -695,8 +767,8 @@ var RETIRED_SKILL_NAMES = [
|
|
|
695
767
|
];
|
|
696
768
|
function detectFramework(cwd) {
|
|
697
769
|
const pkgPath = resolve2(cwd, "package.json");
|
|
698
|
-
if (!
|
|
699
|
-
const pkg = JSON.parse(
|
|
770
|
+
if (!existsSync4(pkgPath)) return null;
|
|
771
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
700
772
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
701
773
|
if (deps["@tanstack/react-start"]) return "tanstack-start";
|
|
702
774
|
return null;
|
|
@@ -711,7 +783,7 @@ function runSetup(cwd = process.cwd()) {
|
|
|
711
783
|
resolve2(cwd, ".codex", "skills"),
|
|
712
784
|
resolve2(cwd, ".cursor", "skills")
|
|
713
785
|
];
|
|
714
|
-
const existing = roots.filter((root) =>
|
|
786
|
+
const existing = roots.filter((root) => existsSync4(root));
|
|
715
787
|
const targetDirs = existing.length > 0 ? existing : [roots[0]];
|
|
716
788
|
const copied = [];
|
|
717
789
|
for (const targetDir of targetDirs) {
|
|
@@ -744,7 +816,8 @@ async function doctor(argv) {
|
|
|
744
816
|
apiUrl: process.env.PUBLIC_CAVUNO_API_URL,
|
|
745
817
|
boardKey: process.env.PUBLIC_CAVUNO_BOARD
|
|
746
818
|
},
|
|
747
|
-
frontendUrl
|
|
819
|
+
frontendUrl,
|
|
820
|
+
projectRoot: process.cwd()
|
|
748
821
|
});
|
|
749
822
|
console.log("\n@cavuno/board doctor");
|
|
750
823
|
for (const result of results) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as Schemas } from './_spec-
|
|
2
|
-
import { L as ListEnvelope, m as RelatedSearch } from './jobs-
|
|
1
|
+
import { S as Schemas } from './_spec-Dk0TIRUc.js';
|
|
2
|
+
import { L as ListEnvelope, m as RelatedSearch } from './jobs-Dvv0vX8p.js';
|
|
3
3
|
|
|
4
4
|
type PublicCompany = Schemas['CompanyPublic'];
|
|
5
5
|
/** A market (sector) a company operates in — name + its source slug. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as Schemas } from './_spec-
|
|
2
|
-
import { L as ListEnvelope, m as RelatedSearch } from './jobs-
|
|
1
|
+
import { S as Schemas } from './_spec-Dk0TIRUc.mjs';
|
|
2
|
+
import { L as ListEnvelope, m as RelatedSearch } from './jobs-CVmAWGtJ.mjs';
|
|
3
3
|
|
|
4
4
|
type PublicCompany = Schemas['CompanyPublic'];
|
|
5
5
|
/** A market (sector) a company operates in — name + its source slug. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-
|
|
2
|
-
import { P as PublicJob } from './jobs-
|
|
1
|
+
import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-CqeoQAa1.js';
|
|
2
|
+
import { P as PublicJob } from './jobs-Dvv0vX8p.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Wire enum for `salaryTimeframe`. Defined here (not re-exported from any
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-
|
|
2
|
-
import { P as PublicJob } from './jobs-
|
|
1
|
+
import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-DIO9aFXx.mjs';
|
|
2
|
+
import { P as PublicJob } from './jobs-CVmAWGtJ.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Wire enum for `salaryTimeframe`. Defined here (not re-exported from any
|