nfunc-mcp 0.3.0 → 0.4.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.
Files changed (42) hide show
  1. package/README.md +84 -376
  2. package/dist/index.js +4 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/mappers/labFieldComparator.d.ts +62 -0
  5. package/dist/mappers/labFieldComparator.js +134 -0
  6. package/dist/mappers/labFieldComparator.js.map +1 -0
  7. package/dist/mappers/psiAggregator.d.ts +130 -0
  8. package/dist/mappers/psiAggregator.js +293 -0
  9. package/dist/mappers/psiAggregator.js.map +1 -0
  10. package/dist/mappers/webVitalsMapper.d.ts +52 -0
  11. package/dist/mappers/webVitalsMapper.js +131 -0
  12. package/dist/mappers/webVitalsMapper.js.map +1 -0
  13. package/dist/tools/performanceAudit.d.ts +2 -0
  14. package/dist/tools/performanceAudit.js +446 -0
  15. package/dist/tools/performanceAudit.js.map +1 -0
  16. package/dist/tools/performanceAuditPlan.d.ts +2 -0
  17. package/dist/tools/performanceAuditPlan.js +438 -0
  18. package/dist/tools/performanceAuditPlan.js.map +1 -0
  19. package/dist/utils/csvReader.d.ts +20 -0
  20. package/dist/utils/csvReader.js +172 -0
  21. package/dist/utils/csvReader.js.map +1 -0
  22. package/dist/utils/httpClient.d.ts +84 -0
  23. package/dist/utils/httpClient.js +171 -0
  24. package/dist/utils/httpClient.js.map +1 -0
  25. package/dist/utils/psiAuth.d.ts +26 -0
  26. package/dist/utils/psiAuth.js +36 -0
  27. package/dist/utils/psiAuth.js.map +1 -0
  28. package/dist/utils/psiParser.d.ts +124 -0
  29. package/dist/utils/psiParser.js +200 -0
  30. package/dist/utils/psiParser.js.map +1 -0
  31. package/dist/utils/publicUrl.d.ts +17 -0
  32. package/dist/utils/publicUrl.js +115 -0
  33. package/dist/utils/publicUrl.js.map +1 -0
  34. package/dist/utils/sitemapReader.d.ts +27 -0
  35. package/dist/utils/sitemapReader.js +272 -0
  36. package/dist/utils/sitemapReader.js.map +1 -0
  37. package/dist/utils/urlClassifier.d.ts +45 -0
  38. package/dist/utils/urlClassifier.js +267 -0
  39. package/dist/utils/urlClassifier.js.map +1 -0
  40. package/docs/manual.md +558 -0
  41. package/docs/psi-report-spec.md +174 -0
  42. package/package.json +13 -3
@@ -0,0 +1,267 @@
1
+ import { isSessionGated } from "./publicUrl.js";
2
+ /**
3
+ * Query parameters that identify the visitor or the campaign rather than the
4
+ * page. Left in, they would split one template into dozens of "shapes" that
5
+ * all render identically.
6
+ */
7
+ const TRACKING_PARAMS = /^(utm_|gclid|fbclid|msclkid|mc_cid|mc_eid|_ga|igshid|srsltid|ref|referrer|source|cmpid|campaign)/i;
8
+ /**
9
+ * A segment position needs at least this many distinct values to be wildcarded.
10
+ * Two siblings are as likely to be two distinct pages as one template with two
11
+ * instances, so the floor is three.
12
+ */
13
+ const WILDCARD_DISTINCT = 3;
14
+ /**
15
+ * The signal that separates an identifier from a section name: **fan-out**.
16
+ *
17
+ * Cardinality alone does not work, and getting this wrong is visible on real
18
+ * sites. On nodejs.org, "/en/{blog,download,learn,about}" has only a handful of
19
+ * distinct values, so a pure count threshold wildcarded it and merged 1,054
20
+ * blog posts, download pages and API docs into one meaningless "/en/*\/*\/*"
21
+ * template.
22
+ *
23
+ * A section name is shared by many URLs (blog → 900 pages); an identifier
24
+ * belongs to one (v04.3 → 1 page). So a segment is a wildcard when its values
25
+ * each account for very few URLs, and stays literal when each value heads a
26
+ * substantial subtree — regardless of how many there are.
27
+ */
28
+ const MAX_MEAN_FANOUT = 2.5;
29
+ /**
30
+ * The first path segment is the site's own taxonomy — "categories", "products",
31
+ * "info" — and collapsing it produces the useless pattern "/*". It only gets
32
+ * wildcarded on a clear id explosion.
33
+ */
34
+ const WILDCARD_DISTINCT_ROOT = 20;
35
+ const ID_LIKE = /^(\d+|[0-9a-f]{8,}|[0-9a-f-]{16,}|p\d+|sku[-_]?\w+)$/i;
36
+ /**
37
+ * Route vocabulary — segments that name a *kind* of page, never an instance.
38
+ *
39
+ * Fan-out alone misreads these on a small URL list. Given eight URLs under
40
+ * /ecommerce/, the segments {page, product, cart, checkout, my-account} average
41
+ * 1.6 URLs each, which looks exactly like a set of identifiers — so the
42
+ * classifier collapsed paginated listings and product detail pages into one
43
+ * "/ecommerce/*\/*" template and proposed sampling them as if they were the
44
+ * same page type. On the full inventory the fan-out for "product" would be
45
+ * large and the heuristic would work, but a plan should not be wrong just
46
+ * because the input list is short.
47
+ */
48
+ const ROUTE_WORDS = new Set([
49
+ "page", "pages", "product", "products", "category", "categories", "collection",
50
+ "collections", "cart", "basket", "checkout", "account", "my-account", "login",
51
+ "signin", "register", "search", "tag", "tags", "author", "feed", "blog", "news",
52
+ "article", "articles", "post", "posts", "info", "about", "help", "support",
53
+ "shop", "store", "browse", "dept", "department", "item", "items", "sku",
54
+ ]);
55
+ /**
56
+ * A content slug: hyphenated and long enough to be a title rather than a route.
57
+ * "adrienne-trek-jacket" is an instance; "my-account" is a route.
58
+ */
59
+ function looksLikeSlug(value) {
60
+ if (!value.includes("-"))
61
+ return false;
62
+ const words = value.split("-").length;
63
+ return value.length >= 14 || words >= 3;
64
+ }
65
+ function parseUrl(raw) {
66
+ let url;
67
+ try {
68
+ url = new URL(raw);
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ const segments = url.pathname.split("/").filter(Boolean);
74
+ const keys = [...url.searchParams.keys()]
75
+ .filter((k) => !TRACKING_PARAMS.test(k))
76
+ .map((k) => k.toLowerCase())
77
+ .sort();
78
+ return { raw, segments, querySig: [...new Set(keys)].join("&") };
79
+ }
80
+ /**
81
+ * Wildcard a segment when its values are identifiers rather than taxonomy.
82
+ * Cardinality alone is the main signal; an id-shaped majority is enough on its
83
+ * own, since "/p/12345" and "/p/12346" are the same page template even when
84
+ * only two exist.
85
+ */
86
+ function shouldWildcard(depth, values) {
87
+ const distinct = new Set(values);
88
+ if (distinct.size < 2)
89
+ return false;
90
+ // Numeric, hash-shaped and long-slug values are identifiers whatever their
91
+ // fan-out; route vocabulary never is.
92
+ const values_ = [...distinct].map((v) => v.toLowerCase());
93
+ const idLike = values_.filter((v) => ID_LIKE.test(v) || looksLikeSlug(v)).length;
94
+ if (idLike / distinct.size > 0.6)
95
+ return true;
96
+ if (values_.every((v) => ROUTE_WORDS.has(v)))
97
+ return false;
98
+ if (depth === 0 && distinct.size < WILDCARD_DISTINCT_ROOT)
99
+ return false;
100
+ if (distinct.size < WILDCARD_DISTINCT)
101
+ return false;
102
+ return values.length / distinct.size <= MAX_MEAN_FANOUT;
103
+ }
104
+ /**
105
+ * Recursive descent over path segments.
106
+ *
107
+ * At each depth, URLs that end here form their own pattern, and the rest are
108
+ * grouped by their next segment — wildcarded together when that segment looks
109
+ * like an identifier, kept apart when it looks like a section name. Recursion
110
+ * (rather than one global pass per depth) is what keeps "/categories/*" and
111
+ * "/products/*" separate instead of collapsing both into "/*\/*".
112
+ */
113
+ function descend(urls, depth, prefix, out) {
114
+ const terminal = urls.filter((u) => u.segments.length === depth);
115
+ const deeper = urls.filter((u) => u.segments.length > depth);
116
+ if (terminal.length > 0) {
117
+ const key = "/" + prefix.join("/");
118
+ for (const u of terminal) {
119
+ const full = u.querySig ? `${key}?${u.querySig}` : key;
120
+ const bucket = out.get(full);
121
+ if (bucket)
122
+ bucket.push(u);
123
+ else
124
+ out.set(full, [u]);
125
+ }
126
+ }
127
+ if (deeper.length === 0)
128
+ return;
129
+ if (shouldWildcard(depth, deeper.map((u) => u.segments[depth]))) {
130
+ descend(deeper, depth + 1, [...prefix, "*"], out);
131
+ return;
132
+ }
133
+ const groups = new Map();
134
+ for (const u of deeper) {
135
+ const token = u.segments[depth];
136
+ const bucket = groups.get(token);
137
+ if (bucket)
138
+ bucket.push(u);
139
+ else
140
+ groups.set(token, [u]);
141
+ }
142
+ for (const [token, group] of groups) {
143
+ descend(group, depth + 1, [...prefix, token], out);
144
+ }
145
+ }
146
+ /**
147
+ * Human labels for common commerce and content shapes.
148
+ *
149
+ * Deliberately conservative: an unrecognised pattern is labelled by its path
150
+ * rather than guessed at, because a wrong label in an executive report is
151
+ * worse than a literal one.
152
+ */
153
+ function labelFor(pattern) {
154
+ const [path, query] = pattern.split("?");
155
+ const p = path.toLowerCase();
156
+ const depth = path.split("/").filter(Boolean).length;
157
+ const wildcards = (path.match(/\*/g) ?? []).length;
158
+ const paginated = query ? ` (${query.includes("p") || query.includes("page") ? "paginated" : "filtered"})` : "";
159
+ if (path === "/")
160
+ return "Homepage";
161
+ if (/(^|\/)(cart|basket|bag)(\/|$)/.test(p))
162
+ return "Cart";
163
+ if (/(^|\/)(checkout|payment)(\/|$)/.test(p))
164
+ return "Checkout";
165
+ if (/(^|\/)(search|s|find)(\/|$)/.test(p))
166
+ return "Search results";
167
+ if (/(^|\/)(store-locator|stores|locations|find-a-store)(\/|$)/.test(p))
168
+ return "Store locator";
169
+ if (/(^|\/)(account|my-account|profile|orders|wishlist)(\/|$)/.test(p))
170
+ return "Account";
171
+ if (/(^|\/)(login|signin|sign-in|register|signup)(\/|$)/.test(p))
172
+ return "Login / register";
173
+ if (/(^|\/)(product|products|p|item|items|sku|dp)(\/|$)/.test(p))
174
+ return `PDP (product)${paginated}`;
175
+ if (/(^|\/)(blog|news|articles|stories|posts)(\/|$)/.test(p))
176
+ return `Content / article${paginated}`;
177
+ if (/(^|\/)(info|about|help|faq|support|legal|privacy|terms|policies|customer-service)(\/|$)/.test(p))
178
+ return `Info / static${paginated}`;
179
+ if (/(^|\/)(categories|category|c|collections|shop|browse|dept|department)(\/|$)/.test(p)) {
180
+ const kind = wildcards >= 2 ? "subcategory" : "category";
181
+ return `PLP (${kind})${paginated}`;
182
+ }
183
+ if (wildcards > 0 && depth <= 2)
184
+ return `Listing${paginated}`;
185
+ return `${path}${paginated}`;
186
+ }
187
+ /**
188
+ * Sample size by population.
189
+ *
190
+ * Three is the ceiling because PSI is slow and quota is finite, and because
191
+ * variance between pages of one template is usually smaller than variance
192
+ * between templates — a fourth PDP tells you much less than a first Cart.
193
+ */
194
+ function suggestSample(population) {
195
+ if (population <= 1)
196
+ return 1;
197
+ if (population <= 5)
198
+ return 2;
199
+ return 3;
200
+ }
201
+ /**
202
+ * Representatives, chosen for spread rather than at random.
203
+ *
204
+ * Shortest first: it is usually the canonical, most-linked instance of the
205
+ * template. Then the longest and a middle one, because URL length correlates
206
+ * with depth and with how much content the page carries, and a template's
207
+ * worst page is more often its longest.
208
+ */
209
+ function pickCandidates(urls, count) {
210
+ const sorted = [...urls].sort((a, b) => a.length - b.length || a.localeCompare(b));
211
+ if (sorted.length <= count)
212
+ return sorted;
213
+ const picks = [sorted[0]];
214
+ if (count >= 2)
215
+ picks.push(sorted[sorted.length - 1]);
216
+ if (count >= 3)
217
+ picks.push(sorted[Math.floor(sorted.length / 2)]);
218
+ for (let i = 1; picks.length < count && i < sorted.length; i++) {
219
+ if (!picks.includes(sorted[i]))
220
+ picks.push(sorted[i]);
221
+ }
222
+ return picks.slice(0, count);
223
+ }
224
+ function slugify(pattern) {
225
+ return (pattern
226
+ .replace(/[?&=]/g, "-")
227
+ .replace(/\*/g, "wild")
228
+ .replace(/[^a-z0-9]+/gi, "-")
229
+ .replace(/^-+|-+$/g, "")
230
+ .toLowerCase() || "root");
231
+ }
232
+ export function classifyUrls(rawUrls, options = {}) {
233
+ const { minTemplateSize = 1 } = options;
234
+ const parsed = [];
235
+ let skipped = 0;
236
+ for (const raw of rawUrls) {
237
+ const p = parseUrl(raw);
238
+ if (p)
239
+ parsed.push(p);
240
+ else
241
+ skipped++;
242
+ }
243
+ const buckets = new Map();
244
+ descend(parsed, 0, [], buckets);
245
+ const templates = [];
246
+ for (const [pattern, group] of buckets) {
247
+ if (group.length < minTemplateSize)
248
+ continue;
249
+ const urls = group.map((g) => g.raw);
250
+ const suggested = suggestSample(urls.length);
251
+ templates.push({
252
+ id: slugify(pattern),
253
+ label: labelFor(pattern),
254
+ pattern,
255
+ urlCount: urls.length,
256
+ suggestedSample: suggested,
257
+ candidates: pickCandidates(urls, suggested),
258
+ auditable: true,
259
+ anySessionGated: urls.some(isSessionGated),
260
+ });
261
+ }
262
+ // Biggest templates first: a reader scanning the plan should see the shapes
263
+ // that dominate the site before the long tail of one-off pages.
264
+ templates.sort((a, b) => b.urlCount - a.urlCount || a.pattern.localeCompare(b.pattern));
265
+ return { templates, skipped };
266
+ }
267
+ //# sourceMappingURL=urlClassifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlClassifier.js","sourceRoot":"","sources":["../../src/utils/urlClassifier.ts"],"names":[],"mappings":"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"}