@detiq/crawler 0.2.0 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/crawler.ts +31 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@detiq/crawler",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
6
6
  "type": "module",
package/src/crawler.ts CHANGED
@@ -853,24 +853,6 @@ export async function crawlProject(opts: {
853
853
  } catch { /* older engines without these entry types — leave stashed values at defaults */ }
854
854
  });
855
855
 
856
- // ── HTTP Basic Auth: inject Authorization header for same-origin requests ───
857
- // CDP-connected contexts cannot use browser.newContext({ httpCredentials }),
858
- // so we intercept via page.route() instead.
859
- if (opts.httpBasicUsername && opts.httpBasicPassword) {
860
- const encoded = Buffer.from(`${opts.httpBasicUsername}:${opts.httpBasicPassword}`).toString('base64');
861
- const appOrigin = new URL(opts.appUrl).origin;
862
- await page.route('**/*', (route: any) => {
863
- const reqUrl = route.request().url();
864
- if (reqUrl.startsWith(appOrigin)) {
865
- route.continue({
866
- headers: { ...route.request().headers(), 'Authorization': `Basic ${encoded}` },
867
- });
868
- } else {
869
- route.continue();
870
- }
871
- });
872
- }
873
-
874
856
  // ── API/Bearer token injection ────────────────────────────────────────────
875
857
  // If an authToken is provided, inject it as an HTTP header on every request
876
858
  // and store it in localStorage so client-side code can pick it up.
@@ -885,20 +867,6 @@ export async function crawlProject(opts: {
885
867
  }, opts.authToken);
886
868
  }
887
869
 
888
- // ── Crawler login bypass: inject internal secret header on login requests ────
889
- // Prevents the per-email rate limiter from blocking re-auth attempts made by
890
- // the crawler during long crawl sessions. The API verifies the secret before
891
- // skipping the limiter.
892
- const crawlerSecret = process.env.CRAWLER_INTERNAL_SECRET;
893
- if (crawlerSecret) {
894
- const loginPattern = `${new URL(opts.appUrl).origin}**/auth/login*`;
895
- await page.route(loginPattern, (route: any) => {
896
- route.continue({
897
- headers: { ...route.request().headers(), 'x-zeta-crawler': crawlerSecret },
898
- });
899
- });
900
- }
901
-
902
870
  // ── Web Vitals capture: CLS via buffered PerformanceObserver ─────────────────
903
871
  // CLS entries are only delivered to a PerformanceObserver; this init script
904
872
  // re-runs on every new document. LCP is captured per-page in the crawl loop.
@@ -1012,6 +980,37 @@ export async function crawlProject(opts: {
1012
980
  // Final fallback: if rawPage is still null, use the Stagehand page (events may not work)
1013
981
  if (!rawPage) rawPage = page;
1014
982
 
983
+ // ── HTTP Basic Auth: inject Authorization header for same-origin requests ───
984
+ // Must use rawPage (real Playwright page) — Stagehand V3Page proxy does not implement route().
985
+ if (opts.httpBasicUsername && opts.httpBasicPassword) {
986
+ const encoded = Buffer.from(`${opts.httpBasicUsername}:${opts.httpBasicPassword}`).toString('base64');
987
+ const appOrigin = new URL(opts.appUrl).origin;
988
+ await rawPage.route('**/*', (route: any) => {
989
+ const reqUrl = route.request().url();
990
+ if (reqUrl.startsWith(appOrigin)) {
991
+ route.continue({
992
+ headers: { ...route.request().headers(), 'Authorization': `Basic ${encoded}` },
993
+ });
994
+ } else {
995
+ route.continue();
996
+ }
997
+ });
998
+ }
999
+
1000
+ // ── Crawler login bypass: inject internal secret header on login requests ────
1001
+ // Prevents the per-email rate limiter from blocking re-auth attempts made by
1002
+ // the crawler during long crawl sessions. The API verifies the secret before
1003
+ // skipping the limiter.
1004
+ const crawlerSecret = process.env.CRAWLER_INTERNAL_SECRET;
1005
+ if (crawlerSecret) {
1006
+ const loginPattern = `${new URL(opts.appUrl).origin}**/auth/login*`;
1007
+ await rawPage.route(loginPattern, (route: any) => {
1008
+ route.continue({
1009
+ headers: { ...route.request().headers(), 'x-zeta-crawler': crawlerSecret },
1010
+ });
1011
+ });
1012
+ }
1013
+
1015
1014
  try {
1016
1015
  // Step 1: Navigate and authenticate
1017
1016
  await onProgress?.(8, 'Loading app');