document360-capture 0.2.7 → 0.2.8
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.js +1 -1
- package/dist/config/projectConfig.d.ts +5 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as Ue}from"commander";import{createRequire as Ne}from"node:module";import{input as Xt,confirm as Yt}from"@inquirer/prompts";import{existsSync as K,readFileSync as Kt}from"node:fs";import{basename as Vt,join as Qt}from"node:path";import{readFileSync as J,writeFileSync as Lt,existsSync as W,mkdirSync as Mt}from"node:fs";import{basename as Bt,dirname as _t,join as U}from"node:path";var Ft=U(".d360-writer","capture.json"),j={captureDir:"user-docs/_capture",outputDir:"user-docs/_screenshots",viewport:{width:1440,height:900},loginTimeoutMs:0,annotation:{enabled:!0}},b=class extends Error{};function d(t=process.cwd()){return U(t,Ft)}function m(t){if(!W(t))throw new Error(`No project config at ${t}. Run \`d360-capture init\` to create one.`);let e=JSON.parse(J(t,"utf8").replace(/^/,""));return Jt(e,t)}function O(t,e){Mt(_t(t),{recursive:!0}),Lt(t,JSON.stringify(e,null,2)+`
|
|
2
|
+
import{Command as Ue}from"commander";import{createRequire as Ne}from"node:module";import{input as Xt,confirm as Yt}from"@inquirer/prompts";import{existsSync as K,readFileSync as Kt}from"node:fs";import{basename as Vt,join as Qt}from"node:path";import{readFileSync as J,writeFileSync as Lt,existsSync as W,mkdirSync as Mt}from"node:fs";import{basename as Bt,dirname as _t,join as U}from"node:path";var Ft=U(".d360-writer","capture.json"),j={captureDir:".d360-writer/user-docs/_capture",outputDir:".d360-writer/user-docs/_screenshots",viewport:{width:1440,height:900},loginTimeoutMs:0,annotation:{enabled:!0}},b=class extends Error{};function d(t=process.cwd()){return U(t,Ft)}function m(t){if(!W(t))throw new Error(`No project config at ${t}. Run \`d360-capture init\` to create one.`);let e=JSON.parse(J(t,"utf8").replace(/^/,""));return Jt(e,t)}function O(t,e){Mt(_t(t),{recursive:!0}),Lt(t,JSON.stringify(e,null,2)+`
|
|
3
3
|
`,"utf8")}function Ht(t){try{return"^"+new URL(t).origin.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}catch{return"."}}function Jt(t,e,o=process.cwd()){Wt(t,e);let r=Object.keys(t.profiles),n=t.defaultProfile??(r.length===1?r[0]:r.includes("staging")?"staging":r[0]);return{projectId:t.projectId||qt(o)||Bt(o),captureDir:t.captureDir??j.captureDir,outputDir:t.outputDir??j.outputDir,viewport:t.viewport??{...j.viewport},loginTimeoutMs:t.loginTimeoutMs??j.loginTimeoutMs,annotation:t.annotation??{...j.annotation},profiles:t.profiles,defaultProfile:n}}function $(t,e){let o=e??t.defaultProfile,r=t.profiles[o];if(!r){let i=Object.keys(t.profiles).join(", ");throw new b(`Unknown profile "${o}". Available: ${i}`)}let n=r.connection.authBoundaryUrlPattern;return{name:o,connection:{startUrl:r.connection.startUrl,authBoundaryUrlPattern:n||Ht(r.connection.startUrl)},captureDir:r.captureDir??t.captureDir,outputDir:r.outputDir??t.outputDir,viewport:r.viewport??t.viewport,production:r.production===!0,scope:r.scope??{},authBoundaryDefaulted:!n}}function Wt(t,e){if(t.environments&&!t.profiles)throw new b(`Config at ${e} uses the old "environments" shape, which is no longer supported. It is now "profiles" (each with a "connection" { startUrl }) + "defaultProfile". Re-run \`d360-capture init\`, then \`d360-capture auth --profile <name>\`.`);if(!t.profiles||Object.keys(t.profiles).length===0)throw new b(`Invalid config at ${e}: needs at least one profile under "profiles".`);for(let[o,r]of Object.entries(t.profiles))if(!r?.connection?.startUrl)throw new b(`Invalid config at ${e}: profile "${o}" is missing connection.startUrl.`);if(t.defaultProfile&&!t.profiles[t.defaultProfile])throw new b(`Invalid config at ${e}: defaultProfile "${t.defaultProfile}" is not in profiles.`)}function qt(t){let e=U(t,"package.json");if(!W(e))return null;try{return JSON.parse(J(e,"utf8")).name??null}catch{return null}}import{existsSync as q,readFileSync as Gt}from"node:fs";import{join as G}from"node:path";var zt=G(".d360-writer","config.json");function z(t=process.cwd()){return G(t,zt)}function X(t=process.cwd()){return q(z(t))}function Y(t=process.cwd()){let e=z(t);if(!q(e))return{};try{let o=JSON.parse(Gt(e,"utf8").replace(/^/,"")),r=o.docsDir?.replace(/\/+$/,"");return{projectId:o.projectId,captureDir:o.captureDir??(r?`${r}/_capture`:void 0),outputDir:o.outputDir??(r?`${r}/_screenshots`:void 0)}}catch{return{}}}async function V(t={}){let e=process.cwd(),o=d(e),r=t.yes===!0;if(K(o)&&!r&&!await Yt({message:`${o} already exists. Overwrite?`,default:!1})){console.log("Init cancelled.");return}let n=Y(e),i=n.projectId||Zt(e)||Vt(e),s=[n.projectId&&"project name",n.captureDir&&"directories"].filter(Boolean);s.length>0?(console.log(""),console.log(`Found .d360-writer/config.json \u2014 inheriting ${s.join(" + ")}.`)):X(e)&&(console.log(""),console.log("Found .d360-writer/config.json (could not read defaults from it \u2014 using built-in defaults)."));let a=r?"https://example.com/":await Xt({message:"Live app URL (where captures start):",default:"https://example.com/",validate:p=>p.startsWith("http")?!0:"Must be a full URL"}),l={projectId:i,...n.captureDir?{captureDir:n.captureDir}:{},...n.outputDir?{outputDir:n.outputDir}:{},profiles:{staging:{connection:{startUrl:a}}},defaultProfile:"staging"};O(o,l),console.log(""),console.log(`\u2713 Wrote ${o}`),r&&a==="https://example.com/"&&console.log(" \u26A0 Set the staging profile's connection.startUrl to your real app URL."),console.log(""),console.log("Next steps:"),console.log(" 1. d360-capture auth # log in once, no timeout"),console.log(" 2. d360-capture capture # run all specs in the capture dir"),console.log(""),console.log("Add a prod profile or tune the auth boundary later by editing .d360-writer/capture.json."),console.log("")}function Zt(t){let e=Qt(t,"package.json");if(!K(e))return null;try{return JSON.parse(Kt(e,"utf8")).name??null}catch{return null}}import{chromium as re}from"playwright";import{existsSync as Q,mkdirSync as te,statSync as ee}from"node:fs";import{homedir as oe}from"node:os";import{join as N,dirname as Ze}from"node:path";function Z(){return N(oe(),".document360-capture","auth-states")}function R(t,e){return N(Z(),t,`${e}.json`)}function tt(t){let e=N(Z(),t);Q(e)||te(e,{recursive:!0})}function x(t,e){let o=R(t,e);if(!Q(o))return{path:o,exists:!1};let r=ee(o);return{path:o,exists:!0,ageMs:Date.now()-r.mtimeMs}}async function et(t){let e=m(d()),o=$(e,t.profile);tt(e.projectId);let r=R(e.projectId,o.name);console.log(""),o.production&&console.log(`\u26A0 Profile "${o.name}" is PRODUCTION.`),console.log(`Opening Chromium against ${o.connection.startUrl}`),console.log(`Auth-state will save to: ${r}`),console.log("");let n=await re.launch({headless:!1,args:["--start-maximized"]}),i=await n.newContext({viewport:null}),s=await i.newPage();await s.goto(o.connection.startUrl,{waitUntil:"domcontentloaded"}),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Log in fully (MFA included) at your own pace."),console.log(" When you reach the post-login app, come back to this"),console.log(" terminal and press ENTER to save the session."),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log("");let a=new RegExp(o.connection.authBoundaryUrlPattern),l=setInterval(()=>{a.test(s.url())&&i.storageState({path:r}).catch(()=>{})},3e4);try{for(;;){await ne();let p=s.url();if(a.test(p))break;console.log(""),console.log("\u2717 Login doesn't look complete yet \u2014 the browser is still at:"),console.log(` ${p}`),console.log(" Finish logging in until you can see the app, then press ENTER again."),console.log(" (Ctrl+C aborts without saving.)")}await i.storageState({path:r}),console.log(""),console.log(`\u2713 Session saved to ${r}`),console.log(" This file contains session cookies \u2014 never commit it to git.")}finally{clearInterval(l),await n.close().catch(()=>{})}}function ne(){return new Promise(t=>{let e=()=>{process.stdin.off("data",e),process.stdin.pause(),t()};process.stdin.resume(),process.stdin.once("data",e)})}import{existsSync as be,readdirSync as De}from"node:fs";import{isAbsolute as $t,resolve as xt}from"node:path";import{writeFileSync as ot,mkdirSync as ie,existsSync as rt}from"node:fs";import{createRequire as se}from"node:module";import{join as k,isAbsolute as nt,resolve as it}from"node:path";var T=se(import.meta.url);function st(t){let{cwd:e,profileName:o,captureDir:r,viewport:n,storageStatePath:i}=t,s=k(e,".d360-writer","cache");rt(s)||ie(s,{recursive:!0});let a=k(s,`playwright.${o}.config.cjs`),l=nt(r)?r:it(e,r),p=nt(i)?i:it(e,i),f=T.resolve("@playwright/test"),c=`// Generated by document360-capture \u2014 do not edit by hand.
|
|
4
4
|
const { defineConfig } = require(${JSON.stringify(f)});
|
|
5
5
|
module.exports = defineConfig({
|
|
@@ -82,10 +82,12 @@ export type ResolvedProfile = {
|
|
|
82
82
|
authBoundaryDefaulted: boolean;
|
|
83
83
|
};
|
|
84
84
|
export declare const PROJECT_CONFIG_FILENAME: string;
|
|
85
|
-
/** Filled in for any field a minimal config omits.
|
|
85
|
+
/** Filled in for any field a minimal config omits. Default location lives under .d360-writer/ to
|
|
86
|
+
match the writer's single-footprint layout (the capture dirs derive from the writer's docsDir
|
|
87
|
+
when present; these are the bare fallback). */
|
|
86
88
|
export declare const DEFAULTS: {
|
|
87
|
-
readonly captureDir: "user-docs/_capture";
|
|
88
|
-
readonly outputDir: "user-docs/_screenshots";
|
|
89
|
+
readonly captureDir: ".d360-writer/user-docs/_capture";
|
|
90
|
+
readonly outputDir: ".d360-writer/user-docs/_screenshots";
|
|
89
91
|
readonly viewport: {
|
|
90
92
|
readonly width: 1440;
|
|
91
93
|
readonly height: 900;
|
package/package.json
CHANGED