@webjsdev/server 0.8.62 → 0.8.64

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 (48) hide show
  1. package/index.d.ts +32 -3
  2. package/package.json +2 -2
  3. package/src/browser-entries.js +64 -0
  4. package/src/check/helpers.js +365 -0
  5. package/src/check/rules-actions.js +174 -0
  6. package/src/check/rules-components.js +275 -0
  7. package/src/check/rules-imports.js +166 -0
  8. package/src/check/rules-registry.js +128 -0
  9. package/src/check/rules-routing.js +224 -0
  10. package/src/check/rules-typescript.js +177 -0
  11. package/src/check/rules.js +127 -0
  12. package/src/check/runner-support.js +405 -0
  13. package/src/check/runner.js +113 -0
  14. package/src/check.js +4 -1774
  15. package/src/component-elision.js +1 -1
  16. package/src/dev/config.js +338 -0
  17. package/src/dev/handler.js +1372 -0
  18. package/src/dev/helpers.js +542 -0
  19. package/src/dev/serve.js +840 -0
  20. package/src/dev/server.js +322 -0
  21. package/src/dev-classify.js +174 -0
  22. package/src/dev-reload-worker.js +133 -7
  23. package/src/dev-styles.js +97 -0
  24. package/src/dev.js +22 -3077
  25. package/src/form-dispatch.js +12 -3
  26. package/src/importmap.js +6 -3
  27. package/src/listener-core.js +16 -2
  28. package/src/module-graph.js +112 -7
  29. package/src/rate-limit.js +50 -5
  30. package/src/router.js +11 -1
  31. package/src/ssr/client-router-flag.js +42 -0
  32. package/src/ssr/document.js +361 -0
  33. package/src/ssr/env-shim.js +51 -0
  34. package/src/ssr/escape.js +29 -0
  35. package/src/ssr/head.js +857 -0
  36. package/src/ssr/preloads.js +195 -0
  37. package/src/ssr/render.js +1481 -0
  38. package/src/ssr/responses.js +201 -0
  39. package/src/ssr.js +28 -2445
  40. package/src/vendor/audit.js +400 -0
  41. package/src/vendor/integrity.js +245 -0
  42. package/src/vendor/jspm.js +348 -0
  43. package/src/vendor/manifest.js +96 -0
  44. package/src/vendor/pins.js +892 -0
  45. package/src/vendor/providers.js +35 -0
  46. package/src/vendor/resolver.js +225 -0
  47. package/src/vendor/scanner.js +132 -0
  48. package/src/vendor.js +29 -2371
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Stylesheet re-request for the in-place dev refresh (#1398), the BROWSER half.
3
+ * Kept as a standalone browser-safe module (no node imports) so the served
4
+ * reload client inlines the EXACT source a browser test drives, with no drift,
5
+ * the same pattern as `dev-overlay.js` (#264) and `dev-reload-worker.js` (#887).
6
+ *
7
+ * Why it has to exist at all. A swap never re-requests the page's stylesheets
8
+ * on its own: `mergeHead` preserves every stylesheet unconditionally (#936),
9
+ * `addNewHeadElements` is add-only, and the dev href carries no content hash
10
+ * (`asset()` is prod-only), so the link node is kept by identity and the browser
11
+ * never asks the server for it again. A full page reload used to do that
12
+ * asking, which is how `webjs.dev.regenerate` (#967) ever ran, since it rebuilds
13
+ * a stale build output like `public/tailwind.css` ON REQUEST. Without this, an
14
+ * edit that adds a utility class morphs in and the class has no backing rule
15
+ * until a manual reload. Every in-repo app is configured that way, and the plain
16
+ * `tailwindcss --watch` shape has the same problem.
17
+ */
18
+
19
+ /**
20
+ * Re-request every same-origin stylesheet under `root`, cache-busted.
21
+ *
22
+ * The replacement is inserted BESIDE the old link, and which of the two
23
+ * survives depends on how the request went. That asymmetry is the whole point
24
+ * and must not be collapsed into one shared handler:
25
+ *
26
+ * - On `load` the OLD link is dropped, so the page is never briefly unstyled.
27
+ * - On `error` the NEW link is dropped and the old one kept. A re-request can
28
+ * fail (the server is mid-restart, the file was renamed or deleted), and
29
+ * removing the last working sheet there would leave the page permanently
30
+ * unstyled, which is exactly the failure #936 and #1400 exist to prevent.
31
+ *
32
+ * Duplicates are collapsed to one link per IDENTITY, where the identity is
33
+ * every attribute except the href's query. The duplicate being collapsed is the
34
+ * one the head merge re-appends (the incoming bare-href link beside the busted
35
+ * one), so the head would otherwise gain a link on every refresh. Keying on the
36
+ * path alone would be wrong in the other direction: it would delete an author's
37
+ * second, legitimately distinct link to the same file, such as a `media="print"`
38
+ * sheet.
39
+ *
40
+ * @param {ParentNode} [root] where to scan, defaulting to the whole document.
41
+ * Injectable so a browser test can scope itself to its own container.
42
+ * @param {() => number} [now] cache-buster source, injectable for tests.
43
+ * @returns {Element[]} the replacement links, so a caller (a test) can await them.
44
+ */
45
+ export function refreshStyles(root, now) {
46
+ const scope = root || (typeof document !== 'undefined' ? document : null);
47
+ if (!scope) return [];
48
+ const stamp = now || Date.now;
49
+ /** @type {Record<string, { el: Element, url: URL }>} */
50
+ const kept = Object.create(null);
51
+ const links = [].slice.call(scope.querySelectorAll('link[rel~="stylesheet"][href]'));
52
+ for (const el of links) {
53
+ let url;
54
+ try { url = new URL(el.getAttribute('href'), location.href); } catch (_) { continue; }
55
+ if (url.origin !== location.origin) continue;
56
+ const key = identityKey(el, url);
57
+ if (kept[key]) { if (el.parentNode) el.parentNode.removeChild(el); continue; }
58
+ kept[key] = { el, url };
59
+ }
60
+ const added = [];
61
+ for (const key of Object.keys(kept)) {
62
+ const old = kept[key].el;
63
+ const url = kept[key].url;
64
+ if (!old.parentNode) continue;
65
+ url.searchParams.set('__webjs_dev', String(stamp()));
66
+ const next = /** @type {Element} */ (old.cloneNode(false));
67
+ next.setAttribute('href', url.pathname + url.search);
68
+ next.addEventListener('load', function () {
69
+ if (old.parentNode) old.parentNode.removeChild(old);
70
+ });
71
+ next.addEventListener('error', function () {
72
+ // Keep the sheet that still works rather than the one that just failed.
73
+ if (next.parentNode) next.parentNode.removeChild(next);
74
+ });
75
+ old.parentNode.insertBefore(next, old.nextSibling);
76
+ added.push(next);
77
+ }
78
+ return added;
79
+ }
80
+
81
+ /**
82
+ * A link's identity for de-duping: its path plus every attribute except `href`.
83
+ * JSON-encoded over a sorted list so no separator can collide with an attribute
84
+ * value.
85
+ * @param {Element} el
86
+ * @param {URL} url
87
+ */
88
+ function identityKey(el, url) {
89
+ const parts = [];
90
+ const attrs = el.attributes;
91
+ for (let a = 0; a < attrs.length; a++) {
92
+ if (attrs[a].name === 'href') continue;
93
+ parts.push([attrs[a].name, attrs[a].value]);
94
+ }
95
+ parts.sort((x, y) => (x[0] < y[0] ? -1 : x[0] > y[0] ? 1 : 0));
96
+ return JSON.stringify([url.pathname, parts]);
97
+ }