pi-lean-portal 0.1.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 (55) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +608 -0
  3. package/backends/chromium/index.ts +50 -0
  4. package/backends/chromium-py/bridge.py +67 -0
  5. package/backends/firefox/index.ts +60 -0
  6. package/backends/firefox-py/bridge.py +64 -0
  7. package/backends/playwright-base/playwright-plugin.ts +1294 -0
  8. package/backends/python-adapter.ts +1141 -0
  9. package/backends/python-base/pi_browser_bridge/__init__.py +71 -0
  10. package/backends/python-base/pi_browser_bridge/accessibility.py +408 -0
  11. package/backends/python-base/pi_browser_bridge/bot_detection.py +115 -0
  12. package/backends/python-base/pi_browser_bridge/bridge.py +598 -0
  13. package/backends/python-base/pi_browser_bridge/playwright_base.py +1222 -0
  14. package/backends/python-base/pi_browser_bridge/transport.py +167 -0
  15. package/backends/python-base/pyproject.toml +15 -0
  16. package/browser-cookies.ts +88 -0
  17. package/browser-profile.ts +260 -0
  18. package/browser-status.ts +84 -0
  19. package/browser-toggle.ts +527 -0
  20. package/core/fetch-backend.ts +466 -0
  21. package/core/guides.ts +467 -0
  22. package/core/plugin-api.ts +302 -0
  23. package/core/plugin-config.ts +388 -0
  24. package/core/plugin-registry.ts +263 -0
  25. package/core/router.ts +1186 -0
  26. package/core/shared/accessibility-tree.ts +408 -0
  27. package/core/shared/bot-detection.ts +187 -0
  28. package/core/shared/browser-events.ts +111 -0
  29. package/core/shared/dom-extractor.ts +550 -0
  30. package/core/shared/nav-settle.ts +187 -0
  31. package/core/shared/paths.ts +56 -0
  32. package/core/shared/session-manager.ts +258 -0
  33. package/core/shared/settings-reader.ts +63 -0
  34. package/core/shared/snapshot-cache.ts +231 -0
  35. package/core/shared/storage-state.ts +560 -0
  36. package/core/shared/task-id.ts +77 -0
  37. package/core/shared/url-safety.ts +164 -0
  38. package/index.ts +253 -0
  39. package/package.json +63 -0
  40. package/ship-manifest.test.ts +12 -0
  41. package/tools/browser-back.ts +50 -0
  42. package/tools/browser-click.ts +74 -0
  43. package/tools/browser-console.ts +160 -0
  44. package/tools/browser-inspect.ts +136 -0
  45. package/tools/browser-navigate.ts +254 -0
  46. package/tools/browser-press.ts +80 -0
  47. package/tools/browser-scroll.ts +56 -0
  48. package/tools/browser-snapshot.ts +90 -0
  49. package/tools/browser-type.ts +60 -0
  50. package/tools/index.ts +19 -0
  51. package/tools/utils.ts +157 -0
  52. package/tools/web-fetch.ts +147 -0
  53. package/tools/web-guide.ts +55 -0
  54. package/tools/web-learn.ts +128 -0
  55. package/verify-ship-manifest.ts +126 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Ship-manifest verification helper.
3
+ *
4
+ * Walks a package directory for production `.ts` files and compares them to
5
+ * the `files` array in `package.json`. Used by `ship-manifest.test.ts` files
6
+ * across the monorepo so every published package can prove its npm tarball
7
+ * actually contains the modules it imports at runtime.
8
+ *
9
+ * Ported from rpiv-mono's `@juicesharp/rpiv-test-utils` pattern.
10
+ */
11
+
12
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
13
+ import { dirname, relative, resolve } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const SKIP_DIRS = new Set(["node_modules", "docs", "__tests__"]);
17
+ const SKIP_FILES = new Set(["test-fixtures.ts"]);
18
+ /** Entries that won't exist on disk at rest but are valid (generated at pack time, e.g. by prepack). */
19
+ const SKIP_STALE = new Set(["LICENSE"]);
20
+
21
+ export interface ShipManifestResult {
22
+ /** Entries declared in `package.json` `files`. */
23
+ declared: readonly string[];
24
+ /** Production `.ts` files discovered on disk (relative to packageDir). */
25
+ onDisk: readonly string[];
26
+ /** On-disk files NOT covered by the `files` array — these would be missing from the published tarball. */
27
+ missing: readonly string[];
28
+ /** `files` entries with no corresponding path on disk — ghost entries that ship nothing. */
29
+ stale: readonly string[];
30
+ }
31
+
32
+ /**
33
+ * Verify a package's ship manifest against its on-disk production .ts tree.
34
+ *
35
+ * Accepts either a directory path or a `file:` URL string (so callers can
36
+ * pass `import.meta.url` directly — the helper resolves it to the test file's
37
+ * parent directory).
38
+ *
39
+ * Skips: dotfiles/dotdirs, `node_modules`, `docs`, `*.test.ts`, `test-fixtures.ts`.
40
+ * Does NOT check: asset directories (e.g. `locales/*.json`), `exports` map,
41
+ * `main`/`module` fields.
42
+ *
43
+ * The check is two-way: `missing` flags on-disk production files the tarball
44
+ * would omit; `stale` flags `files` entries that point at nothing on disk
45
+ * (asset entries like `README.md` count as present — staleness is plain
46
+ * existence, not the production-`.ts` walk).
47
+ */
48
+ export function verifyShipManifest(
49
+ packageDirOrUrl: string,
50
+ ): ShipManifestResult {
51
+ const packageDir = packageDirOrUrl.startsWith("file:")
52
+ ? dirname(fileURLToPath(packageDirOrUrl))
53
+ : packageDirOrUrl;
54
+ const pkgRaw = readFileSync(resolve(packageDir, "package.json"), "utf8");
55
+ const pkg = JSON.parse(pkgRaw) as { files?: string[] };
56
+ const declared = pkg.files ?? [];
57
+ const exactFiles = new Set<string>();
58
+ const dirPrefixes: string[] = [];
59
+ for (const entry of declared) {
60
+ // Negation patterns (`!foo/`) are npm `files`-array syntax for excluding
61
+ // sub-paths within an included directory. They have no on-disk counterpart;
62
+ // skip them for existence checks and staleness detection.
63
+ if (entry.startsWith("!")) continue;
64
+ // Treat trailing-slash entries AND bare directory names that exist on
65
+ // disk as recursive directory inclusion — matches npm's own `files`
66
+ // semantics so the test answers "would npm publish actually include this?"
67
+ // rather than enforcing a stylistic preference. Bare dir names are
68
+ // normalized to a trailing-slash prefix so a `"load"` entry covers
69
+ // `load/cache.ts` without spuriously matching a sibling `loader.ts`.
70
+ if (entry.endsWith("/")) dirPrefixes.push(entry);
71
+ else if (isDirOnDisk(packageDir, entry)) dirPrefixes.push(`${entry}/`);
72
+ else exactFiles.add(entry);
73
+ }
74
+
75
+ const onDisk = walkProductionTs(packageDir, packageDir);
76
+ const missing = onDisk.filter((f) => !isCovered(f, exactFiles, dirPrefixes));
77
+ // Staleness: check only non-negation entries. Negation patterns (`!foo/`)
78
+ // have no on-disk counterpart.
79
+ const stale = declared.filter(
80
+ (entry) =>
81
+ !entry.startsWith("!") &&
82
+ !SKIP_STALE.has(entry) &&
83
+ !existsSync(resolve(packageDir, entry)),
84
+ );
85
+
86
+ return { declared, onDisk, missing, stale };
87
+ }
88
+
89
+ function isDirOnDisk(packageDir: string, entry: string): boolean {
90
+ try {
91
+ return statSync(resolve(packageDir, entry)).isDirectory();
92
+ } catch {
93
+ // Entry not present on disk (e.g. an asset/extraneous `files` entry) —
94
+ // not a directory we can recurse into; the caller treats it as an exact file.
95
+ return false;
96
+ }
97
+ }
98
+
99
+ function isCovered(
100
+ file: string,
101
+ exactFiles: Set<string>,
102
+ dirPrefixes: readonly string[],
103
+ ): boolean {
104
+ if (exactFiles.has(file)) return true;
105
+ for (const prefix of dirPrefixes) {
106
+ if (file.startsWith(prefix)) return true;
107
+ }
108
+ return false;
109
+ }
110
+
111
+ function walkProductionTs(root: string, dir: string): string[] {
112
+ const out: string[] = [];
113
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
114
+ if (entry.name.startsWith(".")) continue;
115
+ if (entry.isDirectory() && SKIP_DIRS.has(entry.name)) continue;
116
+ const abs = resolve(dir, entry.name);
117
+ if (entry.isDirectory()) {
118
+ out.push(...walkProductionTs(root, abs));
119
+ continue;
120
+ }
121
+ if (!entry.isFile() || !entry.name.endsWith(".ts")) continue;
122
+ if (entry.name.endsWith(".test.ts") || SKIP_FILES.has(entry.name)) continue;
123
+ out.push(relative(root, abs));
124
+ }
125
+ return out;
126
+ }