@qulib/core 0.5.0 → 0.5.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.
- package/dist/cli/auth-login-resolve.js +1 -1
- package/dist/cli/auth-login-run.d.ts.map +1 -1
- package/dist/cli/auth-login-run.js +3 -1
- package/dist/tools/auth/detect.d.ts.map +1 -1
- package/dist/tools/auth/detect.js +3 -2
- package/dist/tools/auth/explore.d.ts.map +1 -1
- package/dist/tools/auth/explore.js +52 -0
- package/package.json +1 -1
|
@@ -29,7 +29,7 @@ export function parseCredentialsJsonString(json) {
|
|
|
29
29
|
return out;
|
|
30
30
|
}
|
|
31
31
|
export function resolveFormLoginPath(baseUrl, authOptions, authPathId) {
|
|
32
|
-
const formPaths = (authOptions ?? []).filter((o) => o.type === 'form-login' && o.requirements.method === 'credentials');
|
|
32
|
+
const formPaths = (authOptions ?? []).filter((o) => (o.type === 'form-login' || o.type === 'form-multi') && o.requirements.method === 'credentials');
|
|
33
33
|
if (formPaths.length === 0) {
|
|
34
34
|
throw new Error(`No automatable form-login path detected on ${baseUrl}. Use \`qulib auth init\` for manual login.`);
|
|
35
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-login-run.d.ts","sourceRoot":"","sources":["../../src/cli/auth-login-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAsB5D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"auth-login-run.d.ts","sourceRoot":"","sources":["../../src/cli/auth-login-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAsB5D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAMhE;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoIhB"}
|
|
@@ -16,7 +16,9 @@ function sleep(ms) {
|
|
|
16
16
|
return new Promise((r) => setTimeout(r, ms));
|
|
17
17
|
}
|
|
18
18
|
export function authPathNeedsClickReveal(path) {
|
|
19
|
-
return path.type === 'form-login'
|
|
19
|
+
return ((path.type === 'form-login' || path.type === 'form-multi') &&
|
|
20
|
+
(path.source === 'heuristic' || path.source === 'user-local') &&
|
|
21
|
+
!builtInOAuthIds.has(path.id));
|
|
20
22
|
}
|
|
21
23
|
export async function runAutomatedAuthLogin(params) {
|
|
22
24
|
const { chromium } = await import('@playwright/test');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAY,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAIzE,MAAM,MAAM,yBAAyB,GACjC,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,cAAc,GACd,yBAAyB,GACzB,iBAAiB,GACjB,SAAS,CAAC;AAEd,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAY,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAIzE,MAAM,MAAM,yBAAyB,GACjC,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,cAAc,GACd,yBAAyB,GACzB,iBAAiB,GACjB,SAAS,CAAC;AAEd,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB;AAwQD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,4BAA4B,CA6B/B;AAOD,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CAgD9C;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,EACf,SAAS,SAAQ,GAChB,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAelD;AAED,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,SAAS,SAAQ,GAChB,OAAO,CAAC,4BAA4B,CAAC,CAyDvC;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,SAAQ,EACjB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,OAAO,CAAC,YAAY,CAAC,CAqJvB"}
|
|
@@ -151,7 +151,7 @@ function authPathsFromOauthButtons(oauthButtons, loginUrl) {
|
|
|
151
151
|
}
|
|
152
152
|
async function probeClickToRevealForms(page, loginUrl, alreadyMatchedTexts, timeoutMs, progress) {
|
|
153
153
|
const out = [];
|
|
154
|
-
const buttons = page.locator('button');
|
|
154
|
+
const buttons = page.locator('button, [role="button"]');
|
|
155
155
|
const n = await buttons.count();
|
|
156
156
|
const seenLabels = new Set();
|
|
157
157
|
const SUBMIT_RE = /^(sign in|log in|submit|continue|next|cancel|close)$/i;
|
|
@@ -207,8 +207,9 @@ async function probeClickToRevealForms(page, loginUrl, alreadyMatchedTexts, time
|
|
|
207
207
|
await waitNetworkIdleBestEffort(page);
|
|
208
208
|
continue;
|
|
209
209
|
}
|
|
210
|
+
await waitNetworkIdleBestEffort(page);
|
|
210
211
|
try {
|
|
211
|
-
await page.locator('input[type="password"]:visible').first().waitFor({ state: 'visible', timeout:
|
|
212
|
+
await page.locator('input[type="password"]:visible').first().waitFor({ state: 'visible', timeout: 5000 });
|
|
212
213
|
}
|
|
213
214
|
catch {
|
|
214
215
|
await page.goto(loginUrl, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/explore.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/explore.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AA2PzE,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,SAAS,SAAQ,EACjB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAiM1B"}
|
|
@@ -185,6 +185,43 @@ async function buildFormPaths(page) {
|
|
|
185
185
|
},
|
|
186
186
|
];
|
|
187
187
|
}
|
|
188
|
+
async function probeUserLocalProviderClick(page, providerLabel, loginUrl, timeoutMs) {
|
|
189
|
+
const originBefore = new URL(page.url()).origin;
|
|
190
|
+
let clicked = false;
|
|
191
|
+
try {
|
|
192
|
+
await page.getByRole('button', { name: providerLabel, exact: true }).first().click({ timeout: 3000 });
|
|
193
|
+
clicked = true;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
try {
|
|
197
|
+
const escaped = providerLabel.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
198
|
+
await page
|
|
199
|
+
.locator('button, [role="button"]')
|
|
200
|
+
.filter({ hasText: new RegExp(`^\\s*${escaped}\\s*$`, 'i') })
|
|
201
|
+
.first()
|
|
202
|
+
.click({ timeout: 3000 });
|
|
203
|
+
clicked = true;
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
/* skip */
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (!clicked)
|
|
210
|
+
return [];
|
|
211
|
+
try {
|
|
212
|
+
await page.waitForLoadState('domcontentloaded', { timeout: 5000 });
|
|
213
|
+
}
|
|
214
|
+
catch { /* best-effort */ }
|
|
215
|
+
await waitNetworkIdleBestEffort(page);
|
|
216
|
+
if (new URL(page.url()).origin !== originBefore) {
|
|
217
|
+
await page.goto(loginUrl, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
const formPaths = await buildFormPaths(page);
|
|
221
|
+
await page.goto(loginUrl, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
|
|
222
|
+
await waitNetworkIdleBestEffort(page);
|
|
223
|
+
return formPaths;
|
|
224
|
+
}
|
|
188
225
|
export async function exploreAuth(url, timeoutMs = 20000, progress) {
|
|
189
226
|
const browser = await launchBrowser();
|
|
190
227
|
try {
|
|
@@ -246,6 +283,21 @@ export async function exploreAuth(url, timeoutMs = 20000, progress) {
|
|
|
246
283
|
continue;
|
|
247
284
|
}
|
|
248
285
|
consumed.add(id);
|
|
286
|
+
if (p.source === 'user-local') {
|
|
287
|
+
const probed = await probeUserLocalProviderClick(page, p.label, finalUrl, timeoutMs);
|
|
288
|
+
if (probed.length > 0) {
|
|
289
|
+
for (const fp of probed) {
|
|
290
|
+
authPaths.push({
|
|
291
|
+
...fp,
|
|
292
|
+
id: p.id,
|
|
293
|
+
label: p.label,
|
|
294
|
+
source: 'user-local',
|
|
295
|
+
});
|
|
296
|
+
progress?.info(`explore_auth path id=${p.id} type=${fp.type} automatable=${fp.automatable} (user-local probe)`);
|
|
297
|
+
}
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
249
301
|
authPaths.push({
|
|
250
302
|
id,
|
|
251
303
|
label: p.label,
|