@picked/cli 0.0.101-next.2 → 0.0.101
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/README.md +29 -11
- package/dist/.tsbuildinfo +1 -1
- package/dist/cjs/cli.js +4 -2
- package/dist/cjs/index.js +1 -1
- package/dist/esm/cli.js +69 -67
- package/dist/esm/index.js +2 -2
- package/dist/types/commands/docs.d.ts +65 -0
- package/dist/types/commands/docs.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/docs.d.ts +94 -0
- package/dist/types/lib/docs.d.ts.map +1 -0
- package/dist/{workspace-use-CnR5FkxR.js → workspace-use-CXcLlf_z.js} +423 -254
- package/dist/workspace-use-Df1AcQnn.cjs +53 -0
- package/package.json +5 -5
- package/dist/workspace-use-Cjn8sjJj.cjs +0 -51
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
let e=require("node:fs"),t=require("node:fs/promises"),n=require("node:path"),r=require("@picked/typegen"),i=require("@picked/config"),a=require("node:http"),o=require("node:child_process"),s=require("node:crypto"),c=require("node:os"),l=require("@picked/admin-api-client"),u=require("node:readline");var d=`https://docs.picked.app`;function f(e){let t=e.trim().replace(/^https?:\/\/[^/]+/,``),n=t.search(/[#?]/);return`/${((n===-1?t:t.slice(0,n)).split(`node_modules/picked/docs/`).pop()??``).replace(/\.mdx?$/,``).replace(/(?:^|\/)index$/,``).split(`/`).filter(e=>e!==``&&e!==`.`).join(`/`)}`}function p(e){let t=/^---\n(?<yaml>[\s\S]*?)\n---\n+/.exec(e);if(!t)return{body:e};let n=t.groups?.yaml&&/^type:\s*(?<value>\S+)/m.exec(t.groups.yaml);return{type:n?n.groups?.value:void 0,body:e.slice(t[0].length)}}function ee(e){let t=e.split(/\n{2,}/).map(e=>e.trim()),n=t.findIndex(e=>e.startsWith(`# `));return{title:n===-1?void 0:t[n]?.slice(2).trim(),description:t.slice(n+1).find(e=>e!==``&&!/^(?:#|:::|```|<|import |export |\||-|\d+\.)/.test(e))?.split(`
|
|
2
|
+
`).map(e=>e.trim()).join(` `)}}async function m(e){return(await(0,t.readdir)(e,{recursive:!0,withFileTypes:!0})).filter(e=>e.isFile()&&/\.mdx?$/.test(e.name)).map(e=>(0,n.join)(e.parentPath,e.name))}function te(e){let r=async t=>(await m(e)).find(r=>f((0,n.relative)(e,r).split(n.sep).join(`/`))===t);return{location:e,list:async()=>{let r=await m(e);return(await Promise.all(r.map(async r=>{let{type:i,body:a}=p(await(0,t.readFile)(r,`utf8`)),{title:o,description:s}=ee(a),c=f((0,n.relative)(e,r).split(n.sep).join(`/`));return{path:c,title:o??c,...i&&{type:i},...s&&{description:s},file:r}}))).toSorted((e,t)=>e.path.localeCompare(t.path))},read:async e=>{let n=await r(f(e));return n?p(await(0,t.readFile)(n,`utf8`)).body:void 0}}}function h(e){return typeof e!=`object`||!e||!(`pages`in e)||!Array.isArray(e.pages)?[]:e.pages.filter(e=>typeof e==`object`&&!!e&&`path`in e&&typeof e.path==`string`&&`title`in e&&typeof e.title==`string`&&`body`in e&&typeof e.body==`string`)}function ne(e=fetch){let t=`${d}/docs-index.json`,n,r=()=>(n??=e(t).then(async e=>{if(!e.ok)throw Error(`Could not fetch ${t}: ${String(e.status)}`);return h(await e.json())}),n);return{location:t,list:async()=>(await r()).map(({path:e,title:t,type:n,description:r})=>({path:e,title:t,...n&&{type:n},...r&&{description:r}})),read:async e=>{let t=f(e);return(await r()).find(e=>e.path===t)?.body}}}function re(t){for(let r=t;;r=(0,n.dirname)(r)){let t=(0,n.join)(r,`package.json`);if((0,e.existsSync)(t)){let n=JSON.parse((0,e.readFileSync)(t,`utf8`)),i=typeof n==`object`&&n&&`name`in n&&typeof n.name==`string`?n.name:void 0;return{dir:r,name:i}}if((0,n.dirname)(r)===r)return}}function ie(t){return[t.env.PICKED_DOCS_DIR,(()=>{if(!t.bin||!(0,e.existsSync)(t.bin))return;let r=re((0,n.dirname)((0,e.realpathSync)(t.bin)));return r?.name===`picked`?(0,n.join)(r.dir,`docs`):void 0})(),(()=>{for(let r=t.cwd;;r=(0,n.dirname)(r)){if((0,e.existsSync)((0,n.join)(r,`node_modules`,`picked`,`package.json`)))return(0,n.join)(r,`node_modules`,`picked`,`docs`);if((0,n.dirname)(r)===r)return}})()].find(t=>typeof t==`string`&&(0,e.existsSync)(t))}function g(e){let t=ie({cwd:e?.cwd??process.cwd(),bin:process.argv[1],env:process.env});return t?te(t):ne()}function ae(e,t){let n=t.toLowerCase().split(/[\s/-]+/).filter(Boolean);return e.filter(e=>{let t=`${e.path} ${e.title} ${e.description??``}`.toLowerCase();return n.every(e=>t.includes(e))})}var oe="Read a page with `picked docs read <path>`.";async function _(e){let t=e.source??g(),n=await t.list(),r=e.type?n.filter(t=>t.type===e.type):n,i=e.query?ae(r,e.query):r;if(i.length===0)return console.error(`No documentation page matches. Run \`picked docs list\` to see all ${String(n.length)}.`),1;if(e.json)return console.log(JSON.stringify(i,null,2)),0;for(let e of i)console.log(`${e.path}\t${e.title}`);return console.error(`\n${String(i.length)} ${i.length===1?`page`:`pages`} from ${t.location}. ${oe}`),0}function se(e,t){let n=t.toLowerCase().split(/[\s/-]+/).filter(Boolean),r=e.map(e=>{let t=`${e.path} ${e.title}`.toLowerCase();return{page:e,score:n.filter(e=>t.includes(e)).length}}),i=Math.max(0,...r.map(({score:e})=>e));return r.filter(({score:e})=>e>0&&e===i).slice(0,5).map(({page:e})=>e)}async function v(e){if(!e.page)return console.error("Usage: picked docs read <path>, for example `picked docs read /how-to/install-the-sdk`."),1;let t=e.source??g(),n=f(e.page),r=await t.read(n);if(r===void 0){let e=se(await t.list(),n).map(e=>` ${e.path}\t${e.title}`);return console.error([`No documentation page at ${n}.`,...e.length>0?[`Closest pages:`,...e]:[],"Run `picked docs list [words]` to find a page."].join(`
|
|
3
|
+
`)),1}return console.log(`<!-- ${d}${n===`/`?``:n} -->\n\n${r}`),0}function y(e){return e===void 0||e===`list`||e===`ls`}function ce(e){return y(e)?`docs list`:`docs read`}async function le(e){let[t,...n]=e.args;return y(t)?_({query:n.join(` `)||void 0,type:e.type,json:e.json,source:e.source}):v({page:t===`read`?n[0]:t,source:e.source})}async function b(e){let t=e?.cwd??process.cwd(),n=await(0,i.loadResolvedPickedConfig)(t);if(!n)return console.error(`No picked.config.{ts,js,json} found in the current directory.`),1;try{let t=await(0,r.generate)({config:n,check:e?.check??!1,onWarn:e=>{console.warn(e)}});return e?.check?t.changed?(console.error(`Types are out of date: ${t.typesOutput}`),1):(console.log(`Types are up to date (${t.typesOutput}).`),0):(console.log(`Generated types at ${t.typesOutput}`),0)}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}function ue(e){return process.platform===`darwin`?{command:`open`,args:[e]}:process.platform===`win32`?{command:`cmd`,args:[`/c`,`start`,`""`,e]}:{command:`xdg-open`,args:[e]}}function de(e){let{command:t,args:n}=ue(e);try{let e=(0,o.spawn)(t,n,{detached:!0,stdio:`ignore`});e.on(`error`,()=>void 0),e.unref()}catch{}return Promise.resolve()}var fe=8;function pe(){return(0,n.join)((0,c.homedir)(),`.picked`)}function me(e){let t=(0,i.normalizeApiUrl)(e),{hostname:n,port:r}=new URL(t);return`${(r?`${n}-${r}`:n).replace(/[^a-z0-9.-]/gi,`_`)}-${(0,s.createHash)(`sha256`).update(t).digest(`hex`).slice(0,fe)}`}function x(e){return(0,n.join)(pe(),`auth`,`${me(e)}.json`)}var S=384;function he(e){return typeof e==`object`&&!!e&&`clientId`in e&&typeof e.clientId==`string`&&`redirectUri`in e&&typeof e.redirectUri==`string`}function ge(e){return!(typeof e!=`object`||!e||!(`accessToken`in e)||typeof e.accessToken!=`string`||!(`refreshToken`in e)||typeof e.refreshToken!=`string`||!(`expiresAt`in e)||typeof e.expiresAt!=`number`||`user`in e&&e.user!==void 0&&(typeof e.user!=`object`||e.user===null))}function _e(e){return!(typeof e!=`object`||!e||!(`apiUrl`in e)||typeof e.apiUrl!=`string`||`client`in e&&e.client!==void 0&&!he(e.client)||`session`in e&&e.session!==void 0&&!ge(e.session))}async function C(n){let r=x(n);if(!(0,e.existsSync)(r))return null;try{let e=JSON.parse(await(0,t.readFile)(r,`utf8`));return _e(e)?e:null}catch{return null}}async function ve(e){let r=x(e.apiUrl);await(0,t.mkdir)((0,n.dirname)(r),{recursive:!0});let i=`${r}.${process.pid.toString()}.tmp`;await(0,t.writeFile)(i,`${JSON.stringify(e,null,2)}\n`,{encoding:`utf8`,mode:S}),await(0,t.chmod)(i,S),await(0,t.rename)(i,r)}async function w(e,t){let n=await C(e);await ve({apiUrl:(0,i.normalizeApiUrl)(e),client:n?.client,session:n?.session,...t})}async function ye(e,t){await w(e,{client:t})}async function T(e,t){await w(e,{session:t})}async function be(e){await(0,t.rm)(x(e),{force:!0})}var xe=32,Se=16;function E(e){return e.toString(`base64`).replaceAll(`+`,`-`).replaceAll(`/`,`_`).replaceAll(`=`,``)}function D(){return E((0,s.randomBytes)(xe))}function O(e){return E((0,s.createHash)(`sha256`).update(e).digest())}function k(){return E((0,s.randomBytes)(Se))}var A=[8976,8977,8988],j=18e4,Ce=`openid profile email`;async function M(e){let t;try{t=await fetch(`${e}/.well-known/oauth-authorization-server`)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Failed to reach the Picked OAuth discovery endpoint: ${t}`)}if(!t.ok)throw Error(`OAuth discovery request failed (${t.status.toString()}).`);let n=await t.json();if(typeof n!=`object`||!n)throw Error(`Malformed OAuth discovery document.`);if(!(`authorization_endpoint`in n)||typeof n.authorization_endpoint!=`string`)throw Error(`OAuth discovery document is missing authorization_endpoint.`);if(!(`token_endpoint`in n)||typeof n.token_endpoint!=`string`)throw Error(`OAuth discovery document is missing token_endpoint.`);let r=`registration_endpoint`in n&&typeof n.registration_endpoint==`string`?n.registration_endpoint:void 0,i=`code_challenge_methods_supported`in n&&Array.isArray(n.code_challenge_methods_supported)?n.code_challenge_methods_supported.filter(e=>typeof e==`string`):void 0;return{authorizationEndpoint:n.authorization_endpoint,tokenEndpoint:n.token_endpoint,registrationEndpoint:r,codeChallengeMethods:i}}async function we(e,t,n){if(!t.registrationEndpoint)throw Error(`OAuth client registration is not available for this Picked API.`);let r=await fetch(t.registrationEndpoint,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({client_name:`Picked CLI`,redirect_uris:[n],grant_types:[`authorization_code`,`refresh_token`],response_types:[`code`],token_endpoint_auth_method:`none`})});if(!r.ok)throw Error(`OAuth client registration failed (${r.status.toString()}).`);let i=await r.json();if(typeof i!=`object`||!i||!(`client_id`in i)||typeof i.client_id!=`string`)throw Error(`OAuth client registration returned an unexpected response.`);return await ye(e,{clientId:i.client_id,redirectUri:n}),i.client_id}async function Te(e,t,n){let r=(await C(e))?.client;return r?.redirectUri===n?r.clientId:we(e,t,n)}function Ee(e,t){return new Promise(n=>{let r=()=>{e.removeListener(`error`,r),n(!1)};e.once(`error`,r),e.listen(t,`127.0.0.1`,()=>{e.removeListener(`error`,r),n(!0)})})}async function De(e){for(let t of A)if(await Ee(e,t))return t;throw Error(`No loopback port available for the OAuth callback (tried ${A.join(`, `)}).`)}function Oe(e,t,n){return new Promise((r,i)=>{let a=()=>{clearTimeout(o),process.removeListener(`SIGINT`,s),e.close()},o=setTimeout(()=>{a(),i(Error(`Timed out waiting for the browser sign-in to complete.`))},n),s=()=>{a(),i(Error(`Sign-in cancelled.`))};process.once(`SIGINT`,s),e.on(`request`,(e,n)=>{let o=new URL(e.url??`/`,`http://127.0.0.1`);if(o.pathname!==`/callback`){n.writeHead(404),n.end();return}let s=o.searchParams.get(`error`);if(s){n.writeHead(200,{"content-type":`text/html`}),n.end(`<html><body>Sign-in failed. You can close this tab.</body></html>`),a(),i(Error(`Authorization failed: ${s}`));return}let c=o.searchParams.get(`code`),l=o.searchParams.get(`state`);if(!c||l!==t){n.writeHead(400,{"content-type":`text/html`}),n.end(`<html><body>Invalid sign-in response. Close this tab and try again.</body></html>`),a(),i(Error(`Invalid OAuth callback: missing code or state mismatch.`));return}n.writeHead(200,{"content-type":`text/html`}),n.end(`<html><body>Signed in. You can close this tab and return to the terminal.</body></html>`),a(),r({code:c})})})}async function N(e){let t;try{t=await e.json()}catch{return null}if(typeof t!=`object`||!t||!(`access_token`in t)||typeof t.access_token!=`string`||!(`expires_in`in t)||typeof t.expires_in!=`number`)return null;let n=`refresh_token`in t&&typeof t.refresh_token==`string`?t.refresh_token:void 0;return{accessToken:t.access_token,refreshToken:n,expiresIn:t.expires_in}}function ke(e){let t=e.split(`.`),n=t[1];if(t.length!==3||!n)return{};try{let e=JSON.parse(Buffer.from(n,`base64url`).toString(`utf8`));return typeof e!=`object`||!e?{}:{id:`sub`in e&&typeof e.sub==`string`?e.sub:void 0,email:`email`in e&&typeof e.email==`string`?e.email:void 0}}catch{return{}}}async function Ae(e){let t=await M(e),n=(0,a.createServer)(),r=`http://127.0.0.1:${(await De(n)).toString()}/callback`,i=await Te(e,t,r),o=D(),s=O(o),c=k(),l=new URL(t.authorizationEndpoint);l.searchParams.set(`response_type`,`code`),l.searchParams.set(`client_id`,i),l.searchParams.set(`redirect_uri`,r),l.searchParams.set(`code_challenge`,s),l.searchParams.set(`code_challenge_method`,`S256`),l.searchParams.set(`state`,c),l.searchParams.set(`scope`,Ce),console.log(`Opening your browser to sign in...\n${l.toString()}`),await de(l.toString());let{code:u}=await Oe(n,c,j),d=new URLSearchParams({grant_type:`authorization_code`,code:u,redirect_uri:r,client_id:i,code_verifier:o}),f=await fetch(t.tokenEndpoint,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:d.toString()});if(!f.ok)throw Error(`Token exchange failed (${f.status.toString()}).`);let p=await N(f);if(!p?.refreshToken)throw Error(`Token exchange did not return a refresh token.`);return{accessToken:p.accessToken,refreshToken:p.refreshToken,expiresAt:Date.now()+p.expiresIn*1e3,user:ke(p.accessToken)}}async function je(e){if(!e.client||!e.session)throw Error("Session expired. Run `picked login`.");let t=await M(e.apiUrl),n=new URLSearchParams({grant_type:`refresh_token`,refresh_token:e.session.refreshToken,client_id:e.client.clientId}),r;try{r=await fetch(t.tokenEndpoint,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:n.toString()})}catch{throw Error("Session expired. Run `picked login`.")}if(!r.ok)throw Error("Session expired. Run `picked login`.");let i=await N(r);if(!i)throw Error("Session expired. Run `picked login`.");return{accessToken:i.accessToken,refreshToken:i.refreshToken??e.session.refreshToken,expiresAt:Date.now()+i.expiresIn*1e3,user:e.session.user}}var Me=6e4;async function P(e){let t=await C(e);if(!t?.session)throw Error(`Not logged in to ${e}. Run \`picked login\`.`);if(t.session.expiresAt-Date.now()>Me)return t.session.accessToken;let n=await je(t);return await T(e,n),n.accessToken}function F(){let e=process.env.PICKED_API_KEY?.trim();return e===``?void 0:e}async function I(e){let t=F();return t?(0,l.createAdminApiClient)({apiUrl:e,apiKey:t}):(await P(e),(0,l.createAdminApiClient)({apiUrl:e,token:()=>P(e)}))}var Ne=`https://api.picked.app`;async function L(e=process.cwd()){let t=process.env.PICKED_API_URL;if(t)return(0,i.normalizeApiUrl)(t);let n=await(0,i.loadPickedConfig)(e);return(0,i.normalizeApiUrl)(n?.apiUrl??Ne)}async function Pe(e){let t=await L(e?.cwd);if(F())return console.error(`\`picked login\` does not apply while PICKED_API_KEY is set: every command authenticates to ${t} with that API key. Unset PICKED_API_KEY to sign in as a user.`),1;try{let e=await Ae(t);await T(t,e);let n=e.user?.email??e.user?.id??`unknown user`;return console.log(`Logged in as ${n} (${t})`),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}async function Fe(e){let t=await L(e?.cwd);return await be(t),console.log(`Logged out of ${t}.`),0}async function Ie(e){let t=e?.cwd??process.cwd(),n=await(0,i.loadPickedConfig)(t);if(!n)return console.error(`No picked.config.{ts,js,json} found in the current directory.`),1;let r=await L(t);console.log(`API: ${r}`),console.log(`Config default: project ${n.projectId} (source: ${n.source??`published`})`);let a=await(0,i.readActiveSelection)(t,r);if(!a)return console.log(`Active selection: none (using the config default).`),0;if(!a.workspace)return console.log(`Active selection: live (published) in project ${a.projectId}`),0;let{name:o,status:s,source:c}=a.workspace;return console.log(`Active selection: ${o} [${s}] in project ${a.projectId} (source: ${c})`),0}async function Le(e){let t=await L(e?.cwd);if(F())return console.error(`\`picked whoami\` does not apply while PICKED_API_KEY is set: an API key authenticates to ${t} as a project or organization, not as a user.`),1;let n=await C(t);if(!n?.session)return console.error(`Not logged in to ${t}. Run \`picked login\`.`),1;let{user:r}=n.session,i=r?.email??r?.id??`unknown user`;return console.log(`${i} (${t})`),0}var R=`bundle.json`,z=`assets`,Re=/^[0-9a-f]{64}$/;function B(e,t,r){let i=(0,n.resolve)(e),a=(0,n.resolve)(i,t);if(!a.startsWith(i.endsWith(n.sep)?i:i+n.sep))throw Error(`${r} ${t} must name a directory inside ${i}.`);return a}function V(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function ze(e){return(0,s.createHash)(`sha256`).update(e).digest(`hex`)}function H(e,t){return(0,n.join)(e,z,t)}function Be(e,t){let n=`bundle assets[${String(t)}]`;if(!V(e))throw Error(`${n} is not an object.`);let{versionId:r,fileName:i,mimeType:a,sizeBytes:o,sha256:s,downloadUrl:c}=e;if(typeof r!=`string`||typeof i!=`string`||typeof a!=`string`||typeof c!=`string`||typeof o!=`number`||!Number.isInteger(o)||o<0)throw Error(`${n} needs a string versionId, fileName, mimeType and downloadUrl, and an integer sizeBytes.`);if(s===null)return{versionId:r,fileName:i,mimeType:a,sizeBytes:o,sha256:s,downloadUrl:c};let l=typeof s==`string`?s.toLowerCase():``;if(!Re.test(l))throw Error(`${n} (${i}) has a sha256 that is not a hex SHA-256 digest.`);return{versionId:r,fileName:i,mimeType:a,sizeBytes:o,sha256:l,downloadUrl:c}}function U(e){let{assets:t}=e;if(!Array.isArray(t))throw Error(`The bundle has no assets array.`);return t.map((e,t)=>Be(e,t))}function W(e,t,n){if(t.byteLength!==e.sizeBytes)throw Error(`${e.fileName} (${n}) has size ${String(t.byteLength)} bytes; the manifest says ${String(e.sizeBytes)}.`);let r=ze(t);if(e.sha256!==null&&r!==e.sha256)throw Error(`${e.fileName} (${n}) has SHA-256 ${r}; the manifest says ${e.sha256}.`);return r}function Ve(e,t){let n=Array.isArray(e.assets)?e.assets:[];return{...e,assets:n.map((e,n)=>V(e)?{...e,sha256:t[n]}:e)}}var He=12e4,Ue=3e5,G=class extends Error{name=`PayloadUserErrorsError`};function K(e,t){if(t.length!==0)throw new G(`${e} failed:\n${t.map(e=>{let t=e.field?.length?` (${e.field.join(`.`)})`:``;return` ${e.code}: ${e.message}${t}`}).join(`
|
|
4
|
+
`)}`)}async function We(e,t){let{project:n}=await e.request(l.ProjectLiveVersionDocument,{input:{id:t}});if(!n)throw Error(`Project ${t} was not found.`);let r=n.liveWorkspaceVersion;if(!r)throw Error(`Project ${t} has no published version.`);if(!r.snapshotWorkspaceId)throw Error(`The live version ${r.id} of project ${t} has no snapshot workspace to export. Publish the project again.`);return r.snapshotWorkspaceId}async function Ge(e,t){let{workspaceExport:n}=await e.request(l.WorkspaceExportDocument,{input:{workspaceId:t}});if(K(`Export of workspace ${t}`,n.userErrors),!V(n.bundle))throw Error(`Export of workspace ${t} returned no bundle.`);return n.bundle}async function Ke(e,t){let{projectId:n,fileName:r,mimeType:i,sha256:a,bytes:o}=t,{assetUploadInit:s}=await e.request(l.AssetUploadInitDocument,{input:{projectId:n,fileName:r,contentType:i,sha256:a}});if(s.deduplicated)return{assetId:s.assetId,versionId:s.versionId,deduplicated:!0};if(!s.uploadUrl)throw Error(`The API returned no upload URL for ${r}.`);let c=await fetch(s.uploadUrl,{method:`PUT`,headers:{"Content-Type":i},body:o,signal:AbortSignal.timeout(He)});if(!c.ok)throw Error(`Upload of ${r} failed with status ${String(c.status)}: ${await c.text()}`);let{assetCommit:u}=await e.request(l.AssetCommitDocument,{input:{projectId:n,assetId:s.assetId,versionId:s.versionId,fileName:r,storagePath:s.storagePath,sha256:a}});return K(`Commit of ${r}`,u.userErrors),{assetId:s.assetId,versionId:s.versionId,deduplicated:!1}}async function qe(e,t){await e.request(l.AssetDeleteDocument,{input:{id:t}})}async function Je(e,t){let{workspaceImport:n}=await e.request(l.WorkspaceImportDocument,{input:t},{timeoutMs:Ue});if(K(`Import into project ${t.projectId}`,n.userErrors),!n.workspace)throw Error(`Import into project ${t.projectId} returned no workspace.`);return n.workspace}async function Ye(e,t){let{workspacePublish:n}=await e.request(l.WorkspacePublishDocument,{input:{workspaceId:t}});K(`Publish of workspace ${t}`,n.userErrors)}var Xe=12e4;function Ze(e,t){if(!e.project)throw Error(`Missing --project <id>.`);if(e.workspace&&e.live)throw Error(`Pass --workspace <id> or --live, not both.`);if(!e.workspace&&!e.live)throw Error(`Pass --workspace <id> or --live.`);if(!e.out)throw Error(`Missing --out <dir>.`);return{projectId:e.project,workspaceId:e.workspace??null,outDir:B(t,e.out,`--out`)}}async function Qe(e){if((await(0,t.readdir)(e).catch(e=>{if(V(e)&&e.code===`ENOENT`)return[];throw e})).length>0)throw Error(`${e} is not empty. Export into a new or empty directory.`)}async function $e(e){let t=await fetch(e.downloadUrl,{signal:AbortSignal.timeout(Xe)});if(!t.ok)throw Error(`Download of ${e.fileName} from ${e.downloadUrl} failed with status ${String(t.status)}.`);let n=new Uint8Array(await t.arrayBuffer());return{bytes:n,sha256:W(e,n,e.downloadUrl)}}async function et(e,r,i){await(0,t.mkdir)((0,n.join)(e,z));let a=[];for(let n of i){let{bytes:r,sha256:i}=await $e(n);await(0,t.writeFile)(H(e,i),r),a.push(i)}let o=Ve(r,a);await(0,t.writeFile)((0,n.join)(e,R),`${JSON.stringify(o,null,2)}\n`)}async function tt(e,r,i){await(0,t.mkdir)((0,n.dirname)(e),{recursive:!0});let a=await(0,t.mkdtemp)((0,n.join)((0,n.dirname)(e),`.${(0,n.basename)(e)}.partial-`));try{await et(a,r,i),await(0,t.rmdir)(e).catch(e=>{if(!(V(e)&&e.code===`ENOENT`))throw e}),await(0,t.rename)(a,e)}catch(e){throw await(0,t.rm)(a,{recursive:!0,force:!0}),e}}async function nt(e,t){let n=t.workspaceId??await We(e,t.projectId),r=await Ge(e,n),i=V(r.source)?r.source.projectId:void 0;if(i!==t.projectId)throw Error(`Workspace ${n} belongs to project ${String(i)}, not ${t.projectId}.`);return r}async function rt(e){try{let t=Ze(e,e.cwd??process.cwd());await Qe(t.outDir);let n=await nt(await I(await L(e.cwd)),t),r=U(n);await tt(t.outDir,n,r);let i=V(n.workspace)?String(n.workspace.name):``;return console.log(`Exported workspace "${i}" with ${String(r.length)} assets to ${t.outDir}`),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}async function it(e){let r=(0,n.join)(e,R),i=await(0,t.readFile)(r,`utf8`).catch(e=>{throw Error(`Cannot read ${r}. Pass the directory \`picked workspace export\` wrote.`,{cause:e})}),a=JSON.parse(i);if(!V(a))throw Error(`${r} is not a JSON object.`);return a}async function at(e,n){let r=[];for(let i of n){if(i.sha256===null)throw Error(`The manifest item for ${i.fileName} has no SHA-256. Export the bundle with \`picked workspace export\`.`);let n=H(e,i.sha256),a=new Uint8Array(await(0,t.readFile)(n));r.push({asset:i,sha256:W(i,a,n),bytes:a})}return r}async function ot(e,t,n,r){let i=[];for(let{asset:a,sha256:o,bytes:s}of n){let n=await Ke(e,{projectId:t,fileName:a.fileName,mimeType:a.mimeType,sha256:o,bytes:s});n.deduplicated||r.push(n.assetId),i.push({sourceVersionId:a.versionId,assetId:n.assetId,versionId:n.versionId})}return i}async function q(e,t){let n=[],r=[];for(let i of t)try{await qe(e,i),n.push(i)}catch(e){let t=e instanceof Error?e.message:String(e);r.push(`Could not delete asset ${i} (${t}); delete it from the project by hand.`)}return[...n.length>0?[`Deleted the ${String(n.length)} asset${n.length===1?``:`s`} this run uploaded: ${n.join(`, `)}.`]:[],...r].join(`
|
|
5
|
+
`)}function J(e,t){let n=e instanceof Error?e.message:String(e);return Error(t?`${n}\n${t}`:n,{cause:e})}function st(e){let t=[`The outcome of the import is unknown: the API may have created the workspace. Check the project for it before you import again.`];return e.length>0&&t.push(`Kept the ${String(e.length)} asset${e.length===1?``:`s`} this run uploaded: ${e.join(`, `)}. If the project has no new workspace, delete them from the project.`),t.join(`
|
|
6
|
+
`)}var ct=new Set([`FORBIDDEN`,`UNAUTHENTICATED`,`BAD_USER_INPUT`,`GRAPHQL_VALIDATION_FAILED`]);function lt(e){return e instanceof G||e instanceof l.AdminApiResponseError&&e.codes.length>0&&e.codes.every(e=>e!==void 0&&ct.has(e))}async function ut(e,t){let n=[],r=await ot(e,t.projectId,t.assets,n).catch(async t=>{throw J(t,await q(e,n))});return{workspace:await Je(e,{projectId:t.projectId,name:t.name,bundle:t.bundle,assetMap:r}).catch(async t=>{throw J(t,lt(t)?await q(e,n):st(n))}),uploaded:n.length}}async function dt(e){try{if(!e.project)throw Error(`Missing --project <id>.`);if(!e.in)throw Error(`Missing --in <dir>.`);let t=e.project,n=B(e.cwd??process.cwd(),e.in,`--in`),r=await it(n),i=await at(n,U(r)),a=await I(await L(e.cwd)),{workspace:o,uploaded:s}=await ut(a,{projectId:t,name:e.name,bundle:r,assets:i});return console.log(`Imported workspace "${o.name}" as ${o.id} into project ${t} (assets: ${String(s)} uploaded, ${String(i.length-s)} already in the project).`),e.publish&&(await Ye(a,o.id).catch(e=>{let t=e instanceof Error?e.message:String(e);throw Error(`Workspace ${o.id} was imported, but not published. ${t}`,{cause:e})}),console.log(`Published workspace ${o.id}.`)),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}var ft=(0,l.graphql)(`
|
|
7
|
+
query PickedWorkspaces {
|
|
8
|
+
user {
|
|
9
|
+
organizations(first: 50) {
|
|
10
|
+
edges {
|
|
11
|
+
node {
|
|
12
|
+
id
|
|
13
|
+
name
|
|
14
|
+
slug
|
|
15
|
+
projects(first: 100) {
|
|
16
|
+
edges {
|
|
17
|
+
node {
|
|
18
|
+
id
|
|
19
|
+
name
|
|
20
|
+
liveWorkspace {
|
|
21
|
+
id
|
|
22
|
+
}
|
|
23
|
+
liveWorkspaceVersion {
|
|
24
|
+
id
|
|
25
|
+
}
|
|
26
|
+
workspaces(first: 100) {
|
|
27
|
+
edges {
|
|
28
|
+
node {
|
|
29
|
+
id
|
|
30
|
+
name
|
|
31
|
+
status
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`),pt=(0,l.graphql)(`
|
|
44
|
+
query PickedPreviewToken($id: ID!, $projectId: ID!) {
|
|
45
|
+
workspace(id: $id, projectId: $projectId) {
|
|
46
|
+
id
|
|
47
|
+
name
|
|
48
|
+
status
|
|
49
|
+
previewToken
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
`);async function Y(e){let t=await e.request(ft,{});if(!t.user)throw Error(`Not signed in as a user, or no organizations are visible to this account. An API key has no organization list.`);return t.user.organizations.edges.map(e=>{let t=e.node;return{id:t.id,name:t.name,slug:t.slug??``,projects:t.projects.edges.map(e=>{let t=e.node;return{id:t.id,name:t.name,liveWorkspaceId:t.liveWorkspace?.id??null,liveVersionId:t.liveWorkspaceVersion?.id??null,workspaces:t.workspaces.edges.map(e=>({id:e.node.id,name:e.node.name,status:e.node.status}))}})}})}async function X(e,t,n){let r=(await e.request(pt,{id:n,projectId:t})).workspace;if(!r)throw Error(`Workspace "${n}" was not found in project "${t}".`);return{status:r.status,name:r.name,previewToken:r.previewToken}}function mt(e){for(let t of e){console.log(`${t.name} (${t.slug})`);for(let e of t.projects){console.log(` ${e.name} [${e.id}]`);for(let t of e.workspaces){let n=t.status===`LIVE`||t.id===e.liveWorkspaceId?` (live)`:``;console.log(` ${t.name} [${t.status}]${n}`)}}}}async function Z(e){try{let t=await Y(await I(await L(e?.cwd)));return e?.json?(console.log(JSON.stringify(t,null,2)),0):(mt(t),0)}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}function ht(e,t){return new Promise(n=>{e.question(t,n)})}async function Q(e,t){if(t.length===0)throw Error(`No choices available to select from.`);let n=(0,u.createInterface)({input:process.stdin,output:process.stderr});process.stderr.write(`${e}\n`),t.forEach((e,t)=>{process.stderr.write(` ${(t+1).toString()}. ${e.label}\n`)});try{for(;;){let e=await ht(n,`Enter a number (1-${t.length.toString()}): `),r=Number.parseInt(e,10),i=Number.isInteger(r)?t[r-1]:void 0;if(i)return i.value;process.stderr.write(`Invalid choice, try again.
|
|
53
|
+
`)}}finally{n.close()}}function $(e,t,n){return{projectId:e,workspace:{id:t,name:n.name,status:n.status,source:`preview`,previewToken:n.previewToken}}}async function gt(e,t,n){return n?$(t,n,await X(e,t,n)):{projectId:t}}async function _t(e){let t=await Q(`Select a project`,(await Y(e)).flatMap(e=>e.projects.map(t=>({label:`${e.name} / ${t.name}`,value:t})))),n=t.workspaces.map(e=>({label:`${e.name} [${e.status}]`,value:e}));t.liveVersionId&&n.unshift({label:`Published (live version)`,value:null});let r=await Q(`Select a workspace`,n);if(!r)return{projectId:t.id};r.status===`ARCHIVED`&&console.error(`Warning: archived workspaces may fail to load via the delivery API.`);let i=await X(e,t.id,r.id);return $(t.id,r.id,i)}function vt(e){if(!e.workspace){console.log(`Active workspace: live (published) in project ${e.projectId}`);return}let{name:t,status:n,source:r}=e.workspace;console.log(`Active workspace: ${t} [${n}] in project ${e.projectId} (source: ${r})`)}async function yt(e){let t=e?.cwd??process.cwd();try{let n=await L(t),r=await I(n),a=e?.project?await gt(r,e.project,e.workspace):await _t(r);return await(0,i.writeActiveSelection)(t,n,a),vt(a),e?.generate!==!1&&await b({cwd:t}),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return Le}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return Pe}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return le}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return rt}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Z}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return Ie}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return dt}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return Fe}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return yt}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return ce}});
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@picked/cli",
|
|
3
3
|
"description": "Picked command-line interface for local development workflows",
|
|
4
|
-
"version": "0.0.101
|
|
4
|
+
"version": "0.0.101",
|
|
5
5
|
"bin": {
|
|
6
6
|
"picked": "dist/esm/cli.js"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@picked/admin-api-client": "0.0.101
|
|
10
|
-
"@picked/config": "0.0.101
|
|
11
|
-
"@picked/telemetry": "0.0.101
|
|
12
|
-
"@picked/typegen": "0.0.101
|
|
9
|
+
"@picked/admin-api-client": "0.0.101",
|
|
10
|
+
"@picked/config": "0.0.101",
|
|
11
|
+
"@picked/telemetry": "0.0.101",
|
|
12
|
+
"@picked/typegen": "0.0.101"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@repo/eslint-config": "workspace:*",
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
let e=require("@picked/typegen"),t=require("@picked/config"),n=require("node:http"),r=require("node:child_process"),i=require("node:fs"),a=require("node:fs/promises"),o=require("node:path"),s=require("node:crypto"),c=require("node:os"),l=require("@picked/admin-api-client"),u=require("node:readline");async function d(n){let r=n?.cwd??process.cwd(),i=await(0,t.loadResolvedPickedConfig)(r);if(!i)return console.error(`No picked.config.{ts,js,json} found in the current directory.`),1;try{let t=await(0,e.generate)({config:i,check:n?.check??!1,onWarn:e=>{console.warn(e)}});return n?.check?t.changed?(console.error(`Types are out of date: ${t.typesOutput}`),1):(console.log(`Types are up to date (${t.typesOutput}).`),0):(console.log(`Generated types at ${t.typesOutput}`),0)}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}function f(e){return process.platform===`darwin`?{command:`open`,args:[e]}:process.platform===`win32`?{command:`cmd`,args:[`/c`,`start`,`""`,e]}:{command:`xdg-open`,args:[e]}}function p(e){let{command:t,args:n}=f(e);try{let e=(0,r.spawn)(t,n,{detached:!0,stdio:`ignore`});e.on(`error`,()=>void 0),e.unref()}catch{}return Promise.resolve()}var m=8;function h(){return(0,o.join)((0,c.homedir)(),`.picked`)}function ee(e){let n=(0,t.normalizeApiUrl)(e),{hostname:r,port:i}=new URL(n);return`${(i?`${r}-${i}`:r).replace(/[^a-z0-9.-]/gi,`_`)}-${(0,s.createHash)(`sha256`).update(n).digest(`hex`).slice(0,m)}`}function g(e){return(0,o.join)(h(),`auth`,`${ee(e)}.json`)}var _=384;function te(e){return typeof e==`object`&&!!e&&`clientId`in e&&typeof e.clientId==`string`&&`redirectUri`in e&&typeof e.redirectUri==`string`}function ne(e){return!(typeof e!=`object`||!e||!(`accessToken`in e)||typeof e.accessToken!=`string`||!(`refreshToken`in e)||typeof e.refreshToken!=`string`||!(`expiresAt`in e)||typeof e.expiresAt!=`number`||`user`in e&&e.user!==void 0&&(typeof e.user!=`object`||e.user===null))}function re(e){return!(typeof e!=`object`||!e||!(`apiUrl`in e)||typeof e.apiUrl!=`string`||`client`in e&&e.client!==void 0&&!te(e.client)||`session`in e&&e.session!==void 0&&!ne(e.session))}async function v(e){let t=g(e);if(!(0,i.existsSync)(t))return null;try{let e=JSON.parse(await(0,a.readFile)(t,`utf8`));return re(e)?e:null}catch{return null}}async function y(e){let t=g(e.apiUrl);await(0,a.mkdir)((0,o.dirname)(t),{recursive:!0});let n=`${t}.${process.pid.toString()}.tmp`;await(0,a.writeFile)(n,`${JSON.stringify(e,null,2)}\n`,{encoding:`utf8`,mode:_}),await(0,a.chmod)(n,_),await(0,a.rename)(n,t)}async function b(e,n){let r=await v(e);await y({apiUrl:(0,t.normalizeApiUrl)(e),client:r?.client,session:r?.session,...n})}async function x(e,t){await b(e,{client:t})}async function S(e,t){await b(e,{session:t})}async function ie(e){await(0,a.rm)(g(e),{force:!0})}var ae=32,oe=16;function C(e){return e.toString(`base64`).replaceAll(`+`,`-`).replaceAll(`/`,`_`).replaceAll(`=`,``)}function se(){return C((0,s.randomBytes)(ae))}function ce(e){return C((0,s.createHash)(`sha256`).update(e).digest())}function le(){return C((0,s.randomBytes)(oe))}var w=[8976,8977,8988],ue=18e4,de=`openid profile email`;async function T(e){let t;try{t=await fetch(`${e}/.well-known/oauth-authorization-server`)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`Failed to reach the Picked OAuth discovery endpoint: ${t}`)}if(!t.ok)throw Error(`OAuth discovery request failed (${t.status.toString()}).`);let n=await t.json();if(typeof n!=`object`||!n)throw Error(`Malformed OAuth discovery document.`);if(!(`authorization_endpoint`in n)||typeof n.authorization_endpoint!=`string`)throw Error(`OAuth discovery document is missing authorization_endpoint.`);if(!(`token_endpoint`in n)||typeof n.token_endpoint!=`string`)throw Error(`OAuth discovery document is missing token_endpoint.`);let r=`registration_endpoint`in n&&typeof n.registration_endpoint==`string`?n.registration_endpoint:void 0,i=`code_challenge_methods_supported`in n&&Array.isArray(n.code_challenge_methods_supported)?n.code_challenge_methods_supported.filter(e=>typeof e==`string`):void 0;return{authorizationEndpoint:n.authorization_endpoint,tokenEndpoint:n.token_endpoint,registrationEndpoint:r,codeChallengeMethods:i}}async function fe(e,t,n){if(!t.registrationEndpoint)throw Error(`OAuth client registration is not available for this Picked API.`);let r=await fetch(t.registrationEndpoint,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({client_name:`Picked CLI`,redirect_uris:[n],grant_types:[`authorization_code`,`refresh_token`],response_types:[`code`],token_endpoint_auth_method:`none`})});if(!r.ok)throw Error(`OAuth client registration failed (${r.status.toString()}).`);let i=await r.json();if(typeof i!=`object`||!i||!(`client_id`in i)||typeof i.client_id!=`string`)throw Error(`OAuth client registration returned an unexpected response.`);return await x(e,{clientId:i.client_id,redirectUri:n}),i.client_id}async function pe(e,t,n){let r=(await v(e))?.client;return r?.redirectUri===n?r.clientId:fe(e,t,n)}function me(e,t){return new Promise(n=>{let r=()=>{e.removeListener(`error`,r),n(!1)};e.once(`error`,r),e.listen(t,`127.0.0.1`,()=>{e.removeListener(`error`,r),n(!0)})})}async function he(e){for(let t of w)if(await me(e,t))return t;throw Error(`No loopback port available for the OAuth callback (tried ${w.join(`, `)}).`)}function ge(e,t,n){return new Promise((r,i)=>{let a=()=>{clearTimeout(o),process.removeListener(`SIGINT`,s),e.close()},o=setTimeout(()=>{a(),i(Error(`Timed out waiting for the browser sign-in to complete.`))},n),s=()=>{a(),i(Error(`Sign-in cancelled.`))};process.once(`SIGINT`,s),e.on(`request`,(e,n)=>{let o=new URL(e.url??`/`,`http://127.0.0.1`);if(o.pathname!==`/callback`){n.writeHead(404),n.end();return}let s=o.searchParams.get(`error`);if(s){n.writeHead(200,{"content-type":`text/html`}),n.end(`<html><body>Sign-in failed. You can close this tab.</body></html>`),a(),i(Error(`Authorization failed: ${s}`));return}let c=o.searchParams.get(`code`),l=o.searchParams.get(`state`);if(!c||l!==t){n.writeHead(400,{"content-type":`text/html`}),n.end(`<html><body>Invalid sign-in response. Close this tab and try again.</body></html>`),a(),i(Error(`Invalid OAuth callback: missing code or state mismatch.`));return}n.writeHead(200,{"content-type":`text/html`}),n.end(`<html><body>Signed in. You can close this tab and return to the terminal.</body></html>`),a(),r({code:c})})})}async function E(e){let t;try{t=await e.json()}catch{return null}if(typeof t!=`object`||!t||!(`access_token`in t)||typeof t.access_token!=`string`||!(`expires_in`in t)||typeof t.expires_in!=`number`)return null;let n=`refresh_token`in t&&typeof t.refresh_token==`string`?t.refresh_token:void 0;return{accessToken:t.access_token,refreshToken:n,expiresIn:t.expires_in}}function D(e){let t=e.split(`.`),n=t[1];if(t.length!==3||!n)return{};try{let e=JSON.parse(Buffer.from(n,`base64url`).toString(`utf8`));return typeof e!=`object`||!e?{}:{id:`sub`in e&&typeof e.sub==`string`?e.sub:void 0,email:`email`in e&&typeof e.email==`string`?e.email:void 0}}catch{return{}}}async function O(e){let t=await T(e),r=(0,n.createServer)(),i=`http://127.0.0.1:${(await he(r)).toString()}/callback`,a=await pe(e,t,i),o=se(),s=ce(o),c=le(),l=new URL(t.authorizationEndpoint);l.searchParams.set(`response_type`,`code`),l.searchParams.set(`client_id`,a),l.searchParams.set(`redirect_uri`,i),l.searchParams.set(`code_challenge`,s),l.searchParams.set(`code_challenge_method`,`S256`),l.searchParams.set(`state`,c),l.searchParams.set(`scope`,de),console.log(`Opening your browser to sign in...\n${l.toString()}`),await p(l.toString());let{code:u}=await ge(r,c,ue),d=new URLSearchParams({grant_type:`authorization_code`,code:u,redirect_uri:i,client_id:a,code_verifier:o}),f=await fetch(t.tokenEndpoint,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:d.toString()});if(!f.ok)throw Error(`Token exchange failed (${f.status.toString()}).`);let m=await E(f);if(!m?.refreshToken)throw Error(`Token exchange did not return a refresh token.`);return{accessToken:m.accessToken,refreshToken:m.refreshToken,expiresAt:Date.now()+m.expiresIn*1e3,user:D(m.accessToken)}}async function k(e){if(!e.client||!e.session)throw Error("Session expired. Run `picked login`.");let t=await T(e.apiUrl),n=new URLSearchParams({grant_type:`refresh_token`,refresh_token:e.session.refreshToken,client_id:e.client.clientId}),r;try{r=await fetch(t.tokenEndpoint,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:n.toString()})}catch{throw Error("Session expired. Run `picked login`.")}if(!r.ok)throw Error("Session expired. Run `picked login`.");let i=await E(r);if(!i)throw Error("Session expired. Run `picked login`.");return{accessToken:i.accessToken,refreshToken:i.refreshToken??e.session.refreshToken,expiresAt:Date.now()+i.expiresIn*1e3,user:e.session.user}}var A=6e4;async function j(e){let t=await v(e);if(!t?.session)throw Error(`Not logged in to ${e}. Run \`picked login\`.`);if(t.session.expiresAt-Date.now()>A)return t.session.accessToken;let n=await k(t);return await S(e,n),n.accessToken}function M(){let e=process.env.PICKED_API_KEY?.trim();return e===``?void 0:e}async function N(e){let t=M();return t?(0,l.createAdminApiClient)({apiUrl:e,apiKey:t}):(await j(e),(0,l.createAdminApiClient)({apiUrl:e,token:()=>j(e)}))}var P=`https://api.picked.app`;async function F(e=process.cwd()){let n=process.env.PICKED_API_URL;if(n)return(0,t.normalizeApiUrl)(n);let r=await(0,t.loadPickedConfig)(e);return(0,t.normalizeApiUrl)(r?.apiUrl??P)}async function I(e){let t=await F(e?.cwd);if(M())return console.error(`\`picked login\` does not apply while PICKED_API_KEY is set: every command authenticates to ${t} with that API key. Unset PICKED_API_KEY to sign in as a user.`),1;try{let e=await O(t);await S(t,e);let n=e.user?.email??e.user?.id??`unknown user`;return console.log(`Logged in as ${n} (${t})`),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}async function L(e){let t=await F(e?.cwd);return await ie(t),console.log(`Logged out of ${t}.`),0}async function _e(e){let n=e?.cwd??process.cwd(),r=await(0,t.loadPickedConfig)(n);if(!r)return console.error(`No picked.config.{ts,js,json} found in the current directory.`),1;let i=await F(n);console.log(`API: ${i}`),console.log(`Config default: project ${r.projectId} (source: ${r.source??`published`})`);let a=await(0,t.readActiveSelection)(n,i);if(!a)return console.log(`Active selection: none (using the config default).`),0;if(!a.workspace)return console.log(`Active selection: live (published) in project ${a.projectId}`),0;let{name:o,status:s,source:c}=a.workspace;return console.log(`Active selection: ${o} [${s}] in project ${a.projectId} (source: ${c})`),0}async function ve(e){let t=await F(e?.cwd);if(M())return console.error(`\`picked whoami\` does not apply while PICKED_API_KEY is set: an API key authenticates to ${t} as a project or organization, not as a user.`),1;let n=await v(t);if(!n?.session)return console.error(`Not logged in to ${t}. Run \`picked login\`.`),1;let{user:r}=n.session,i=r?.email??r?.id??`unknown user`;return console.log(`${i} (${t})`),0}var R=`bundle.json`,z=`assets`,ye=/^[0-9a-f]{64}$/;function B(e,t,n){let r=(0,o.resolve)(e),i=(0,o.resolve)(r,t);if(!i.startsWith(r.endsWith(o.sep)?r:r+o.sep))throw Error(`${n} ${t} must name a directory inside ${r}.`);return i}function V(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function be(e){return(0,s.createHash)(`sha256`).update(e).digest(`hex`)}function H(e,t){return(0,o.join)(e,z,t)}function xe(e,t){let n=`bundle assets[${String(t)}]`;if(!V(e))throw Error(`${n} is not an object.`);let{versionId:r,fileName:i,mimeType:a,sizeBytes:o,sha256:s,downloadUrl:c}=e;if(typeof r!=`string`||typeof i!=`string`||typeof a!=`string`||typeof c!=`string`||typeof o!=`number`||!Number.isInteger(o)||o<0)throw Error(`${n} needs a string versionId, fileName, mimeType and downloadUrl, and an integer sizeBytes.`);if(s===null)return{versionId:r,fileName:i,mimeType:a,sizeBytes:o,sha256:s,downloadUrl:c};let l=typeof s==`string`?s.toLowerCase():``;if(!ye.test(l))throw Error(`${n} (${i}) has a sha256 that is not a hex SHA-256 digest.`);return{versionId:r,fileName:i,mimeType:a,sizeBytes:o,sha256:l,downloadUrl:c}}function U(e){let{assets:t}=e;if(!Array.isArray(t))throw Error(`The bundle has no assets array.`);return t.map((e,t)=>xe(e,t))}function W(e,t,n){if(t.byteLength!==e.sizeBytes)throw Error(`${e.fileName} (${n}) has size ${String(t.byteLength)} bytes; the manifest says ${String(e.sizeBytes)}.`);let r=be(t);if(e.sha256!==null&&r!==e.sha256)throw Error(`${e.fileName} (${n}) has SHA-256 ${r}; the manifest says ${e.sha256}.`);return r}function Se(e,t){let n=Array.isArray(e.assets)?e.assets:[];return{...e,assets:n.map((e,n)=>V(e)?{...e,sha256:t[n]}:e)}}var Ce=12e4,we=3e5,G=class extends Error{name=`PayloadUserErrorsError`};function K(e,t){if(t.length!==0)throw new G(`${e} failed:\n${t.map(e=>{let t=e.field?.length?` (${e.field.join(`.`)})`:``;return` ${e.code}: ${e.message}${t}`}).join(`
|
|
2
|
-
`)}`)}async function Te(e,t){let{project:n}=await e.request(l.ProjectLiveVersionDocument,{input:{id:t}});if(!n)throw Error(`Project ${t} was not found.`);let r=n.liveWorkspaceVersion;if(!r)throw Error(`Project ${t} has no published version.`);if(!r.snapshotWorkspaceId)throw Error(`The live version ${r.id} of project ${t} has no snapshot workspace to export. Publish the project again.`);return r.snapshotWorkspaceId}async function Ee(e,t){let{workspaceExport:n}=await e.request(l.WorkspaceExportDocument,{input:{workspaceId:t}});if(K(`Export of workspace ${t}`,n.userErrors),!V(n.bundle))throw Error(`Export of workspace ${t} returned no bundle.`);return n.bundle}async function De(e,t){let{projectId:n,fileName:r,mimeType:i,sha256:a,bytes:o}=t,{assetUploadInit:s}=await e.request(l.AssetUploadInitDocument,{input:{projectId:n,fileName:r,contentType:i,sha256:a}});if(s.deduplicated)return{assetId:s.assetId,versionId:s.versionId,deduplicated:!0};if(!s.uploadUrl)throw Error(`The API returned no upload URL for ${r}.`);let c=await fetch(s.uploadUrl,{method:`PUT`,headers:{"Content-Type":i},body:o,signal:AbortSignal.timeout(Ce)});if(!c.ok)throw Error(`Upload of ${r} failed with status ${String(c.status)}: ${await c.text()}`);let{assetCommit:u}=await e.request(l.AssetCommitDocument,{input:{projectId:n,assetId:s.assetId,versionId:s.versionId,fileName:r,storagePath:s.storagePath,sha256:a}});return K(`Commit of ${r}`,u.userErrors),{assetId:s.assetId,versionId:s.versionId,deduplicated:!1}}async function Oe(e,t){await e.request(l.AssetDeleteDocument,{input:{id:t}})}async function ke(e,t){let{workspaceImport:n}=await e.request(l.WorkspaceImportDocument,{input:t},{timeoutMs:we});if(K(`Import into project ${t.projectId}`,n.userErrors),!n.workspace)throw Error(`Import into project ${t.projectId} returned no workspace.`);return n.workspace}async function Ae(e,t){let{workspacePublish:n}=await e.request(l.WorkspacePublishDocument,{input:{workspaceId:t}});K(`Publish of workspace ${t}`,n.userErrors)}var je=12e4;function Me(e,t){if(!e.project)throw Error(`Missing --project <id>.`);if(e.workspace&&e.live)throw Error(`Pass --workspace <id> or --live, not both.`);if(!e.workspace&&!e.live)throw Error(`Pass --workspace <id> or --live.`);if(!e.out)throw Error(`Missing --out <dir>.`);return{projectId:e.project,workspaceId:e.workspace??null,outDir:B(t,e.out,`--out`)}}async function Ne(e){if((await(0,a.readdir)(e).catch(e=>{if(V(e)&&e.code===`ENOENT`)return[];throw e})).length>0)throw Error(`${e} is not empty. Export into a new or empty directory.`)}async function Pe(e){let t=await fetch(e.downloadUrl,{signal:AbortSignal.timeout(je)});if(!t.ok)throw Error(`Download of ${e.fileName} from ${e.downloadUrl} failed with status ${String(t.status)}.`);let n=new Uint8Array(await t.arrayBuffer());return{bytes:n,sha256:W(e,n,e.downloadUrl)}}async function Fe(e,t,n){await(0,a.mkdir)((0,o.join)(e,z));let r=[];for(let t of n){let{bytes:n,sha256:i}=await Pe(t);await(0,a.writeFile)(H(e,i),n),r.push(i)}let i=Se(t,r);await(0,a.writeFile)((0,o.join)(e,R),`${JSON.stringify(i,null,2)}\n`)}async function Ie(e,t,n){await(0,a.mkdir)((0,o.dirname)(e),{recursive:!0});let r=await(0,a.mkdtemp)((0,o.join)((0,o.dirname)(e),`.${(0,o.basename)(e)}.partial-`));try{await Fe(r,t,n),await(0,a.rmdir)(e).catch(e=>{if(!(V(e)&&e.code===`ENOENT`))throw e}),await(0,a.rename)(r,e)}catch(e){throw await(0,a.rm)(r,{recursive:!0,force:!0}),e}}async function Le(e,t){let n=t.workspaceId??await Te(e,t.projectId),r=await Ee(e,n),i=V(r.source)?r.source.projectId:void 0;if(i!==t.projectId)throw Error(`Workspace ${n} belongs to project ${String(i)}, not ${t.projectId}.`);return r}async function Re(e){try{let t=Me(e,e.cwd??process.cwd());await Ne(t.outDir);let n=await Le(await N(await F(e.cwd)),t),r=U(n);await Ie(t.outDir,n,r);let i=V(n.workspace)?String(n.workspace.name):``;return console.log(`Exported workspace "${i}" with ${String(r.length)} assets to ${t.outDir}`),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}async function ze(e){let t=(0,o.join)(e,R),n=await(0,a.readFile)(t,`utf8`).catch(e=>{throw Error(`Cannot read ${t}. Pass the directory \`picked workspace export\` wrote.`,{cause:e})}),r=JSON.parse(n);if(!V(r))throw Error(`${t} is not a JSON object.`);return r}async function Be(e,t){let n=[];for(let r of t){if(r.sha256===null)throw Error(`The manifest item for ${r.fileName} has no SHA-256. Export the bundle with \`picked workspace export\`.`);let t=H(e,r.sha256),i=new Uint8Array(await(0,a.readFile)(t));n.push({asset:r,sha256:W(r,i,t),bytes:i})}return n}async function Ve(e,t,n,r){let i=[];for(let{asset:a,sha256:o,bytes:s}of n){let n=await De(e,{projectId:t,fileName:a.fileName,mimeType:a.mimeType,sha256:o,bytes:s});n.deduplicated||r.push(n.assetId),i.push({sourceVersionId:a.versionId,assetId:n.assetId,versionId:n.versionId})}return i}async function q(e,t){let n=[],r=[];for(let i of t)try{await Oe(e,i),n.push(i)}catch(e){let t=e instanceof Error?e.message:String(e);r.push(`Could not delete asset ${i} (${t}); delete it from the project by hand.`)}return[...n.length>0?[`Deleted the ${String(n.length)} asset${n.length===1?``:`s`} this run uploaded: ${n.join(`, `)}.`]:[],...r].join(`
|
|
3
|
-
`)}function J(e,t){let n=e instanceof Error?e.message:String(e);return Error(t?`${n}\n${t}`:n,{cause:e})}function He(e){let t=[`The outcome of the import is unknown: the API may have created the workspace. Check the project for it before you import again.`];return e.length>0&&t.push(`Kept the ${String(e.length)} asset${e.length===1?``:`s`} this run uploaded: ${e.join(`, `)}. If the project has no new workspace, delete them from the project.`),t.join(`
|
|
4
|
-
`)}var Ue=new Set([`FORBIDDEN`,`UNAUTHENTICATED`,`BAD_USER_INPUT`,`GRAPHQL_VALIDATION_FAILED`]);function We(e){return e instanceof G||e instanceof l.AdminApiResponseError&&e.codes.length>0&&e.codes.every(e=>e!==void 0&&Ue.has(e))}async function Ge(e,t){let n=[],r=await Ve(e,t.projectId,t.assets,n).catch(async t=>{throw J(t,await q(e,n))});return{workspace:await ke(e,{projectId:t.projectId,name:t.name,bundle:t.bundle,assetMap:r}).catch(async t=>{throw J(t,We(t)?await q(e,n):He(n))}),uploaded:n.length}}async function Y(e){try{if(!e.project)throw Error(`Missing --project <id>.`);if(!e.in)throw Error(`Missing --in <dir>.`);let t=e.project,n=B(e.cwd??process.cwd(),e.in,`--in`),r=await ze(n),i=await Be(n,U(r)),a=await N(await F(e.cwd)),{workspace:o,uploaded:s}=await Ge(a,{projectId:t,name:e.name,bundle:r,assets:i});return console.log(`Imported workspace "${o.name}" as ${o.id} into project ${t} (assets: ${String(s)} uploaded, ${String(i.length-s)} already in the project).`),e.publish&&(await Ae(a,o.id).catch(e=>{let t=e instanceof Error?e.message:String(e);throw Error(`Workspace ${o.id} was imported, but not published. ${t}`,{cause:e})}),console.log(`Published workspace ${o.id}.`)),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}var Ke=(0,l.graphql)(`
|
|
5
|
-
query PickedWorkspaces {
|
|
6
|
-
user {
|
|
7
|
-
organizations(first: 50) {
|
|
8
|
-
edges {
|
|
9
|
-
node {
|
|
10
|
-
id
|
|
11
|
-
name
|
|
12
|
-
slug
|
|
13
|
-
projects(first: 100) {
|
|
14
|
-
edges {
|
|
15
|
-
node {
|
|
16
|
-
id
|
|
17
|
-
name
|
|
18
|
-
liveWorkspace {
|
|
19
|
-
id
|
|
20
|
-
}
|
|
21
|
-
liveWorkspaceVersion {
|
|
22
|
-
id
|
|
23
|
-
}
|
|
24
|
-
workspaces(first: 100) {
|
|
25
|
-
edges {
|
|
26
|
-
node {
|
|
27
|
-
id
|
|
28
|
-
name
|
|
29
|
-
status
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
`),qe=(0,l.graphql)(`
|
|
42
|
-
query PickedPreviewToken($id: ID!, $projectId: ID!) {
|
|
43
|
-
workspace(id: $id, projectId: $projectId) {
|
|
44
|
-
id
|
|
45
|
-
name
|
|
46
|
-
status
|
|
47
|
-
previewToken
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
`);async function X(e){let t=await e.request(Ke,{});if(!t.user)throw Error(`Not signed in as a user, or no organizations are visible to this account. An API key has no organization list.`);return t.user.organizations.edges.map(e=>{let t=e.node;return{id:t.id,name:t.name,slug:t.slug??``,projects:t.projects.edges.map(e=>{let t=e.node;return{id:t.id,name:t.name,liveWorkspaceId:t.liveWorkspace?.id??null,liveVersionId:t.liveWorkspaceVersion?.id??null,workspaces:t.workspaces.edges.map(e=>({id:e.node.id,name:e.node.name,status:e.node.status}))}})}})}async function Z(e,t,n){let r=(await e.request(qe,{id:n,projectId:t})).workspace;if(!r)throw Error(`Workspace "${n}" was not found in project "${t}".`);return{status:r.status,name:r.name,previewToken:r.previewToken}}function Je(e){for(let t of e){console.log(`${t.name} (${t.slug})`);for(let e of t.projects){console.log(` ${e.name} [${e.id}]`);for(let t of e.workspaces){let n=t.status===`LIVE`||t.id===e.liveWorkspaceId?` (live)`:``;console.log(` ${t.name} [${t.status}]${n}`)}}}}async function Ye(e){try{let t=await X(await N(await F(e?.cwd)));return e?.json?(console.log(JSON.stringify(t,null,2)),0):(Je(t),0)}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}function Xe(e,t){return new Promise(n=>{e.question(t,n)})}async function Q(e,t){if(t.length===0)throw Error(`No choices available to select from.`);let n=(0,u.createInterface)({input:process.stdin,output:process.stderr});process.stderr.write(`${e}\n`),t.forEach((e,t)=>{process.stderr.write(` ${(t+1).toString()}. ${e.label}\n`)});try{for(;;){let e=await Xe(n,`Enter a number (1-${t.length.toString()}): `),r=Number.parseInt(e,10),i=Number.isInteger(r)?t[r-1]:void 0;if(i)return i.value;process.stderr.write(`Invalid choice, try again.
|
|
51
|
-
`)}}finally{n.close()}}function $(e,t,n){return{projectId:e,workspace:{id:t,name:n.name,status:n.status,source:`preview`,previewToken:n.previewToken}}}async function Ze(e,t,n){return n?$(t,n,await Z(e,t,n)):{projectId:t}}async function Qe(e){let t=await Q(`Select a project`,(await X(e)).flatMap(e=>e.projects.map(t=>({label:`${e.name} / ${t.name}`,value:t})))),n=t.workspaces.map(e=>({label:`${e.name} [${e.status}]`,value:e}));t.liveVersionId&&n.unshift({label:`Published (live version)`,value:null});let r=await Q(`Select a workspace`,n);if(!r)return{projectId:t.id};r.status===`ARCHIVED`&&console.error(`Warning: archived workspaces may fail to load via the delivery API.`);let i=await Z(e,t.id,r.id);return $(t.id,r.id,i)}function $e(e){if(!e.workspace){console.log(`Active workspace: live (published) in project ${e.projectId}`);return}let{name:t,status:n,source:r}=e.workspace;console.log(`Active workspace: ${t} [${n}] in project ${e.projectId} (source: ${r})`)}async function et(e){let n=e?.cwd??process.cwd();try{let r=await F(n),i=await N(r),a=e?.project?await Ze(i,e.project,e.workspace):await Qe(i);return await(0,t.writeActiveSelection)(n,r,a),$e(a),e?.generate!==!1&&await d({cwd:n}),0}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(t),1}}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return Re}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Ye}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return _e}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return et}});
|