dockito 0.0.1-beta.8 → 0.0.1-beta.9

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/dockito.js +19 -4
  2. package/package.json +1 -1
package/dockito.js CHANGED
@@ -150,12 +150,27 @@ The file (or - for stdin) is a list of changes, or {"base": N, "ops": [...],
150
150
  {"update": {"sheet": "Tasks", "where": "ID = T-104", "set": {"Status": "Done"}}}
151
151
  {"append": {"sheet": "Tasks", "rows": [{"ID": "T-214", "Status": "Open"}]}}
152
152
  {"insertRows": {"sheet": "Tasks", "after": 40, "count": 2}}, deleteRows
153
- {"rows": "41:42"}, moveRows {"rows": "5:6", "after": 10}; insertCols,
154
- deleteCols, moveCols the same with letters
153
+ {"rows": "41:42"} or a list, "9, 16, 41:42"; moveRows {"rows": "5:6",
154
+ "after": 10}; insertCols, deleteCols, moveCols the same with letters
155
155
  {"format": {"range": "Tasks!1:1", "bold": true, "fill": "#fff2cc"}}
156
+ cells, rows "1:1" or columns "F:F"; null clears a field:
157
+ bold italic underline strike wrap true or false
158
+ size points, 1 to 409
159
+ font a font's name, as "Inter"
160
+ color fill "#rrggbb"
161
+ hAlign left, center, right or justify
162
+ vAlign top, middle or bottom
163
+ indent 0 to 250
164
+ borderTop borderRight borderBottom borderLeft
165
+ "thin #d0d5dd", or {"line": "thin",
166
+ "color": "#d0d5dd"}; lines are thin,
167
+ medium, thick, dashed, dotted or double
168
+ numFmt Excel's, as "$#,##0.00", "d mmm yyyy"
156
169
  {"resize": {"range": "Tasks!B:C", "size": 120}}, merge, unmerge
157
170
  addSheet, renameSheet, moveSheet, deleteSheet, sheetProps (frozenRows,
158
- hidden, tabColor), setName, deleteName, addTable, setTable, deleteTable
171
+ frozenCols, hidden, tabColor), setName, deleteName, setTable, deleteTable
172
+ {"addTable": {"range": "Tasks!A1:D40", "name": "Tasks"}}: a header row
173
+ and banded rows in one change; a cell's own fill shows over them
159
174
  Values: a number, true, false, null (empty), a string ("=\u2026" is a formula),
160
175
  {"text": "=as typed"} or {"date": "2026-10-19"}.
161
176
 
@@ -180,7 +195,7 @@ Ends at the current version, to apply changes at.
180
195
  mcp), saved points with their notes, and the git commit.`},restore:{use:"restore <doc> <entry>",about:"Make a History entry current again",page:"Makes an older entry the current one, as a new entry. Nothing is lost."},save:{use:"save <doc> [entry] -m <note>",about:"Keep an entry as a saved point",page:`Keeps an entry (default: the current one) as a saved point, so History
181
196
  never drops it, with an optional note.`},login:{use:"login [--update]",about:"Sign in through the browser",page:`Opens the browser, where you check a code and choose this login's access
182
197
  in each workspace: View, Publish or Everything. --update changes that access.
183
- --no-browser prints the link instead.`},logout:{use:"logout",about:"Sign out this machine",page:"Signs this machine out and removes its token."},whoami:{use:"whoami",about:"Who you are and what this login can reach",page:"Your name, the login's expiry, and its access in each workspace."},agent:{use:"agent",about:"What an AI agent needs to know",page:"Prints what Dockito is and how an AI agent should use this CLI."}};var qe="0.0.1-beta.8",E=lt(),ce=dt(E),Je=`dockito-cli/${qe} (${process.platform})`;function T(){let e=ye(ce);return e||p("Not logged in. Run `dockito login`."),fe({url:E,token:e,source:"cli",userAgent:Je})}function Ot(e){let[t,n]=process.platform==="darwin"?["open",[e]]:process.platform==="win32"?["cmd",["/c","start","",e]]:["xdg-open",[e]];try{let o=rn(t,n,{stdio:"ignore",detached:!0});return o.on("error",()=>{}),o.unref(),!0}catch{return!1}}var hn=()=>!process.env.SSH_CONNECTION&&!process.env.CI&&(process.platform!=="linux"||!!process.env.DISPLAY||!!process.env.WAYLAND_DISPLAY),gn=e=>new Promise(t=>setTimeout(t,e)),fn=()=>ln().replace(/\.local$/,"").slice(0,60)||"Unknown device";function M(e){return it(e)??p(`"${e}" isn't a doc link or code. \`dockito ls\` lists docs with their codes.`)}function $t(e){let t=dn(Tt(e)),n=kt("git",["rev-parse","HEAD"],{cwd:t,encoding:"utf8"});if(n.error||n.status!==0)return null;let o=kt("git",["status","--porcelain","--",Be(e)],{cwd:t,encoding:"utf8"});return o.status!==0||o.stdout.trim()?null:n.stdout.trim()}var St=e=>an("sha256").update(e).digest("hex");async function mn(e){let t=ye(ce);e.update&&!t&&p("Not logged in. Run `dockito login` first."),process.env.DOCKITO_TOKEN&&$(R("DOCKITO_TOKEN is set, so commands will keep using it instead of this login."));let n=fe({url:E,token:e.update?t:null,userAgent:Je}),o=await n.startLogin("Dockito CLI",fn()),s=!e["no-browser"]&&hn()&&Ot(o.verification_uri_complete);h(s?`Opening ${o.verification_uri_complete}`:`Open ${S(o.verification_uri)}`),h(`Code: ${S(o.user_code)}`),$(g("Waiting for approval\u2026"));let i=o.interval*1e3,a=Date.now()+o.expires_in*1e3;for(;Date.now()<a;){await gn(i);try{let c=await n.pollLogin(o.device_code);if(!c)continue;let u=pt(ce,c.token);h(`${b("\u2713")} Logged in as ${c.user.name}${c.user.username?g(` (${c.user.username})`):""}`);for(let l of c.workspaces)h(` ${l.name} ${g(`${l.slug} \xB7 ${G[l.level]}`)}`);u==="file"&&$(R("No keychain found, so the token is in a file only you can read, in ~/.config/dockito."));return}catch(c){if(c instanceof x&&c.code==="access_denied"&&p("Denied in the browser."),c instanceof x&&c.code==="expired_token"&&p("The code expired. Run `dockito login` again."),c instanceof x&&c.code==="offline"){i=Math.min(i*2,3e4);continue}throw c}}p("The code expired. Run `dockito login` again.")}async function wn(){let e=ye(ce);if(!e)return h("Not logged in.");process.env.DOCKITO_TOKEN&&p("DOCKITO_TOKEN is set; unset it or revoke that token in Account \u2192 Tokens.");try{await fe({url:E,token:e,userAgent:Je}).logout()}catch(t){if(!(t instanceof x)||t.code!=="invalid_token"&&t.code!=="not_found")throw t}ht(ce),h(`${b("\u2713")} Logged out`)}async function yn(e){let t=await T().whoami();if(e.json)return h(JSON.stringify(t,null,2));h(`${t.user.name} ${g(`${t.user.username} \xB7 ${t.user.email}`)}`),t.token&&h(g(`${t.token.name} \xB7 ${t.token.source==="cli"?"ends after 90 days without use":`expires ${new Date(t.token.expiresAt).toLocaleDateString()}`}`)),h(),ne(t.workspaces.map(n=>[n.slug,n.name,g(n.level?G[n.level]:n.role)])),E!=="https://dockito-app.dockito.workers.dev"&&$(g(`
198
+ --no-browser prints the link instead.`},logout:{use:"logout",about:"Sign out this machine",page:"Signs this machine out and removes its token."},whoami:{use:"whoami",about:"Who you are and what this login can reach",page:"Your name, the login's expiry, and its access in each workspace."},agent:{use:"agent",about:"What an AI agent needs to know",page:"Prints what Dockito is and how an AI agent should use this CLI."}};var qe="0.0.1-beta.9",E=lt(),ce=dt(E),Je=`dockito-cli/${qe} (${process.platform})`;function T(){let e=ye(ce);return e||p("Not logged in. Run `dockito login`."),fe({url:E,token:e,source:"cli",userAgent:Je})}function Ot(e){let[t,n]=process.platform==="darwin"?["open",[e]]:process.platform==="win32"?["cmd",["/c","start","",e]]:["xdg-open",[e]];try{let o=rn(t,n,{stdio:"ignore",detached:!0});return o.on("error",()=>{}),o.unref(),!0}catch{return!1}}var hn=()=>!process.env.SSH_CONNECTION&&!process.env.CI&&(process.platform!=="linux"||!!process.env.DISPLAY||!!process.env.WAYLAND_DISPLAY),gn=e=>new Promise(t=>setTimeout(t,e)),fn=()=>ln().replace(/\.local$/,"").slice(0,60)||"Unknown device";function M(e){return it(e)??p(`"${e}" isn't a doc link or code. \`dockito ls\` lists docs with their codes.`)}function $t(e){let t=dn(Tt(e)),n=kt("git",["rev-parse","HEAD"],{cwd:t,encoding:"utf8"});if(n.error||n.status!==0)return null;let o=kt("git",["status","--porcelain","--",Be(e)],{cwd:t,encoding:"utf8"});return o.status!==0||o.stdout.trim()?null:n.stdout.trim()}var St=e=>an("sha256").update(e).digest("hex");async function mn(e){let t=ye(ce);e.update&&!t&&p("Not logged in. Run `dockito login` first."),process.env.DOCKITO_TOKEN&&$(R("DOCKITO_TOKEN is set, so commands will keep using it instead of this login."));let n=fe({url:E,token:e.update?t:null,userAgent:Je}),o=await n.startLogin("Dockito CLI",fn()),s=!e["no-browser"]&&hn()&&Ot(o.verification_uri_complete);h(s?`Opening ${o.verification_uri_complete}`:`Open ${S(o.verification_uri)}`),h(`Code: ${S(o.user_code)}`),$(g("Waiting for approval\u2026"));let i=o.interval*1e3,a=Date.now()+o.expires_in*1e3;for(;Date.now()<a;){await gn(i);try{let c=await n.pollLogin(o.device_code);if(!c)continue;let u=pt(ce,c.token);h(`${b("\u2713")} Logged in as ${c.user.name}${c.user.username?g(` (${c.user.username})`):""}`);for(let l of c.workspaces)h(` ${l.name} ${g(`${l.slug} \xB7 ${G[l.level]}`)}`);u==="file"&&$(R("No keychain found, so the token is in a file only you can read, in ~/.config/dockito."));return}catch(c){if(c instanceof x&&c.code==="access_denied"&&p("Denied in the browser."),c instanceof x&&c.code==="expired_token"&&p("The code expired. Run `dockito login` again."),c instanceof x&&c.code==="offline"){i=Math.min(i*2,3e4);continue}throw c}}p("The code expired. Run `dockito login` again.")}async function wn(){let e=ye(ce);if(!e)return h("Not logged in.");process.env.DOCKITO_TOKEN&&p("DOCKITO_TOKEN is set; unset it or revoke that token in Account \u2192 Tokens.");try{await fe({url:E,token:e,userAgent:Je}).logout()}catch(t){if(!(t instanceof x)||t.code!=="invalid_token"&&t.code!=="not_found")throw t}ht(ce),h(`${b("\u2713")} Logged out`)}async function yn(e){let t=await T().whoami();if(e.json)return h(JSON.stringify(t,null,2));h(`${t.user.name} ${g(`${t.user.username} \xB7 ${t.user.email}`)}`),t.token&&h(g(`${t.token.name} \xB7 ${t.token.source==="cli"?"ends after 90 days without use":`expires ${new Date(t.token.expiresAt).toLocaleDateString()}`}`)),h(),ne(t.workspaces.map(n=>[n.slug,n.name,g(n.level?G[n.level]:n.role)])),E!=="https://dockito-app.dockito.workers.dev"&&$(g(`
184
199
  ${E}`))}async function kn(e,t){e.length||p("Name a file: `dockito publish notes.md --to <project/folder>`"),t.doc&&e.length>1&&p("--doc takes one file."),t.title!==void 0&&e.length>1&&p("--title takes one file."),t.title!==void 0&&!t.title.trim()&&p("--title needs a title."),t.public&&t.doc&&p("--public is only for a new doc; an existing one can be made public from Share in the app.");for(let l of e)(!xt(l)||!cn(l).isFile())&&p(`${l} isn't a file${un(l)?"":` (looked for ${Tt(l)})`}.`);let n=e.filter(Ke);n.length&&t.doc&&p("A .csv makes a new sheet; it can't replace a doc. Leave out --doc, or change a sheet with `dockito apply`."),n.length&&t.message&&p("Sheets don't keep saved points yet: publish the .csv without -m.");let o=T(),s=[];if(t.doc){let l=await o.doc(M(t.doc)),m=new Uint8Array(xe(e[0])),f=await o.update(l.doc.id,Be(e[0]),m,{note:t.message,commit:$t(e[0])});return t.json?h(JSON.stringify([{file:e[0],...f,link:o.linkOf(f.slug)}],null,2)):h(f.unchanged?`${g("=")} ${e[0]} ${g("unchanged")} ${o.linkOf(f.slug)}`:`${b("\u2713")} ${e[0]} \u2192 ${o.linkOf(f.slug)}`)}let i=await o.tree(),a=ke(i,t.workspace);I(a)||p(`This login has View access in ${a.slug}. Run \`dockito login --update\`.`);let c=Fe(a,t.to),u=await o.files(a.id,c.project);for(let l of e){let m=new Uint8Array(xe(l)),f=Be(l),w=t.new?[]:te(u,c.folder,f),O=w.filter(D=>D.kind==="sheet");O.length&&p(`${f} in ${c.label} is ${O.length>1?`${O.length} live sheets`:"a live sheet"} (${O.map(D=>o.linkOf(D.slug)).join(", ")}): change ${O.length>1?"one":"it"} with \`dockito apply\`. --new makes a new sheet from the file instead.`),w.length>1&&p(`${w.length} docs in ${c.label} are named ${f}: ${w.map(D=>o.linkOf(D.slug)).join(", ")}. Pick one with --doc, or publish a new one with --new.`);let k=w[0];if(k&&t.public&&!(await o.doc(k.slug)).doc.public&&p(`${f} is already a private doc in ${c.label} (${o.linkOf(k.slug)}). Only Share in the app can make it public; \`--new --public\` publishes a new public doc.`),k&&k.sha256===St(m)&&!t.message){s.push({file:l,id:k.id,slug:k.slug,version:k.version,unchanged:!0,link:o.linkOf(k.slug)}),t.json||h(`${g("=")} ${l} ${g("unchanged")} ${o.linkOf(k.slug)}`);continue}let v=k?await o.update(k.id,f,m,{note:t.message,commit:$t(l)}):await o.create(a.id,f,m,{project:c.project,folder:c.folder,public:t.public,title:t.title});!k&&t.message&&await o.save(v.id,v.version,t.message);let U="public"in v&&v.public===!0;s.push({file:l,...v,...Ke(l)?{type:"sheet"}:{},link:o.linkOf(v.slug),new:!k}),t.json||h(`${b("\u2713")} ${l} \u2192 ${o.linkOf(v.slug)} ${g(k?v.unchanged?"unchanged":"updated":`new ${Ke(l)?"sheet ":""}in ${c.label}`)}${U?` ${b("\xB7 public")}`:""}${t.message?g(` \xB7 saved: ${t.message}`):""}`)}t.json?h(JSON.stringify(s,null,2)):!t.to&&s.some(l=>l.new)&&$(g("In the workspace's Docs. To put docs in a project: --to <project/folder>; `dockito tree` lists them."))}async function bn(e){let t=await T().tree();if(e.json)return h(JSON.stringify(t,null,2));let n=o=>g(`${o} doc${o===1?"":"s"}`);for(let o of t.workspaces){h(`${S(o.slug)} ${o.name} ${g(`\xB7 ${o.level?G[o.level]:o.role}`)}`);let s=[[g("Docs"),"",n(o.docs)]];for(let i of o.projects){s.push([i.slug,i.name,n(i.docs)]);let a=(c,u)=>{for(let l of i.folders.filter(m=>m.parentId===c))s.push([`${u}/${l.name}`,"",n(l.docs)]),a(l.id,`${u}/${l.name}`)};a(null,i.slug)}ne(s.map(i=>[" ",...i])),h()}$(g("Publish into a place: dockito publish <file> -w <workspace> --to <project/folder>"))}async function $n(e,t){e&&t.to&&e!==t.to&&p(`Two places: ${e} and --to ${t.to}. Give one.`);let n=e??t.to,o=T(),s=await o.tree(),i=ke(s,t.workspace),a=Fe(i,n),c=await o.docs(i.id,{project:a.project,folder:a.folder}),u=a.project?i.projects.find(w=>w.id===a.project):null,l=n?[]:i.projects,m=u?u.folders.filter(w=>w.parentId===a.folder):[];if(t.json)return h(JSON.stringify({workspace:i.slug,place:n??null,projects:l,folders:m,docs:c},null,2));let f=[];for(let w of l)f.push([S(`${w.slug}/`),w.name,g(`${w.docs} doc${w.docs===1?"":"s"}`),""]);for(let w of m)f.push([S(`${w.name}/`),"",g(`${w.docs} doc${w.docs===1?"":"s"}`),""]);for(let w of c)f.push([w.slug,w.title+g(w.kind==="html"?" .html":w.kind==="sheet"?" sheet":" .md"),g(me(w.updatedAt)),g(w.updatedByName??"")]);if(!f.length)return $(g(`Nothing in ${a.label} yet.`));ne(f)}async function vn(e,t){let[n,...o]=(e??"").split("/").filter(Boolean);n||p("`dockito mkdir <project>[/folder[/subfolder]]`"),o.length>2&&p("Folders go at most 2 deep inside a project.");let s=T(),i=ke(await s.tree(),t.workspace),a=K(i,n),c=a?.id??(await s.createProject(i.id,n)).id,u=!a;a||h(`${b("\u2713")} Project ${n}`);let l=q(a),m=null;for(let f=0;f<o.length;f++){let w=l.idOf(o.slice(0,f+1));if(w){m=w;continue}m=(await s.createFolder(c,o[f],m)).id,l.add(o.slice(0,f+1),m),u=!0,h(`${b("\u2713")} Folder ${o.slice(0,f+1).join("/")}`)}u||$(g("Already there."))}async function jn(e){e||p("Name a doc: `dockito open <link or code>`");let t=`${E}/${M(e)}`;Ot(t)||h(t)}async function xn(e,t){e||p("Name a doc: `dockito get <link or code> [-o file]`"),t.outline&&(t.lines!==void 0||t.text)&&p("--outline is the headings only; leave out --lines and --text.");let n=T(),o=await n.doc(M(e));if(o.doc.kind==="sheet"){let u=["entry","outline","lines","text"].filter(m=>t[m]!==void 0);u.length&&p(`A sheet has no file to read by ${u.map(m=>`--${m}`).join(" or ")}: \`dockito read\` gives its rows, a range or totals.`);let l=await n.readSheet(o.doc.id,{outline:!0});return t.output?(bt(t.output,`${l.text.trimEnd()}
185
200
  `),$(`${b("\u2713")} ${t.output} ${g(`\u2190 ${n.linkOf(o.doc.slug)} outline`)}`)):de(l)}let s=t.entry?Number(t.entry):null;t.entry&&(!Number.isInteger(s)||s<1)&&p("--entry takes an entry number from `dockito history`.");let i=await n.content(o.doc.id,s,{outline:t.outline,lines:t.lines,text:t.text}),a=i.bytes.length&&i.lines!==null&&!t.output&&i.bytes[i.bytes.length-1]!==10?new Uint8Array([...i.bytes,10]):i.bytes;if(!t.output)return void process.stdout.write(a);bt(t.output,a);let c=t.outline?" outline":i.shown?` lines ${i.shown} of ${i.lines}`:t.text?" as text":"";$(`${b("\u2713")} ${t.output} ${g(`\u2190 ${n.linkOf(o.doc.slug)}${s?` entry ${s}`:""}${c}`)}`)}async function Tn(e,t){e||p("Name a doc: `dockito history <link or code>`");let n=await T().doc(M(e));if(n.doc.kind==="sheet"&&p(Ge),t.json)return h(JSON.stringify(n.versions,null,2));h(`${S(n.doc.title)} ${g(`${E}/${n.doc.slug}`)}`),ne(n.versions.map((o,s)=>[String(o.number),s===0?b("current"):g(me(o.createdAt)),s===0?g(me(o.createdAt)):"",o.byName??"",g(o.source),o.savedAt?`${R("saved")}${o.note?` ${o.note}`:""}`:"",o.gitCommit?g(o.gitCommit.slice(0,7)):""]))}async function On(e,t){let n=Number(t);(!e||!Number.isInteger(n)||n<1)&&p("`dockito restore <doc> <entry>`; entries are in `dockito history`.");let o=T(),s=await o.doc(M(e));s.doc.kind==="sheet"&&p(`${Ge} \`dockito apply <doc> --undo <version>\` takes back a change of yours.`);let i=await o.restore(s.doc.id,n,s.versions[0]?.number??null);h(`${b("\u2713")} Restored entry ${n} as entry ${i.version} ${g(o.linkOf(i.slug))}`)}async function Sn(e,t,n){e||p('`dockito save <doc> [entry] -m "note"`');let o=T(),s=await o.doc(M(e));s.doc.kind==="sheet"&&p(Ge);let i=t?Number(t):s.versions[0]?.number;(!Number.isInteger(i)||i<1)&&p("Entries are in `dockito history`."),await o.save(s.doc.id,i,n.message??null),h(`${b("\u2713")} Saved entry ${i}${n.message?g(` \xB7 ${n.message}`):""}`)}async function An(e,t){e||p("`dockito share <link or code> [--private]`"),t.public&&p("An existing doc can be made public only from Share in the app. `dockito publish <file> --public` makes a new doc public.");let n=T(),o=await n.doc(M(e)),s=n.linkOf(o.doc.slug);if(t.private)return o.doc.public&&await n.makePrivate(o.doc.id),t.json?h(JSON.stringify({public:!1,link:s},null,2)):h(`${b("\u2713")} Private: only people in ${o.workspace.name} can open it ${g(s)}`);if(t.json)return h(JSON.stringify({public:o.doc.public,link:s},null,2));h(o.doc.public?`${b("Public")}: anyone with the link can open it ${s}`:`Private: only people in ${o.workspace.name} can open it ${g(s)}`)}var Ke=e=>/\.csv$/i.test(e),Ge="Sheets don't keep History entries yet; `dockito changes <doc> --since <version>` lists what changed.";async function Te(e,t,n){t||p(`Name a sheet: \`dockito ${n}\``);let o=await e.doc(M(t));return o.doc.kind!=="sheet"&&p(`${o.doc.title} is a ${o.doc.kind==="md"?"Markdown":"HTML"} doc, not a sheet: \`dockito get\` reads it.`),o}function de(e,t){t?h(JSON.stringify(e,null,2)):h(e.text.trimEnd()),e.ok||(process.exitCode=1)}var le=(e,t,n)=>{if(e===void 0)return;let o=Number(e);return(!/^\d+$/.test(e.trim())||o<n)&&p(`--${t} takes a whole number, ${n} or more.`),o},Ue=e=>e===void 0?void 0:e.split(",").map(t=>t.trim()).filter(Boolean);async function Dn(e,t,n){let o=T(),s=await Te(o,e,"read <doc> [range]"),i=await o.readSheet(s.doc.id,{read:{range:t,sheet:n.sheet,where:n.where,select:Ue(n.select),orderBy:n["order-by"],group:Ue(n.group),totals:Ue(n.totals),from:le(n.from,"from",1),limit:le(n.limit,"limit",1),formulas:n.formulas,styles:n.styles,format:n.csv?"csv":void 0}});de(i,n.json)}async function Nn(e,t,n){let o=T(),s=await Te(o,e,"apply <doc> <changes.json>"),i=le(n.undo,"undo",1),a;if(i!==void 0)(t||n.base!==void 0)&&p("--undo goes alone: no changes file and no --base with it."),a={undo:i,note:n.message,dryRun:n["dry-run"]||void 0};else{!t&&process.stdin.isTTY&&p("Give the changes: `dockito apply <doc> changes.json`, or pipe them in with `-`. `dockito apply --help` shows their form.");let u=!t||t==="-"?xe(0,"utf8"):xt(t)?xe(t,"utf8"):p(`${t} isn't a file.`),l;try{l=JSON.parse(u)}catch{p(`${t&&t!=="-"?t:"The input"} isn't JSON: a list of changes, or {"base": N, "ops": [...]}.`)}let m=Array.isArray(l)?{ops:l}:l;(typeof m!="object"||m===null)&&p('The changes are a list, or {"base": N, "ops": [...]}.');let f=le(n.base,"base",0)??m.base;f===void 0&&p("--base is the version you read: v N in `dockito get` or `dockito read`."),a={...m,base:f,note:n.message??m.note,dryRun:n["dry-run"]||m.dryRun||void 0}}let c=n.key??Pn(a);de(await o.changeSheet(s.doc.id,{key:c,...a}),n.json)}var Pn=e=>St(new TextEncoder().encode(JSON.stringify(e))).slice(0,32);async function En(e,t){let n=T(),o=await Te(n,e,"check <doc>");de(await n.readSheet(o.doc.id,{check:t.sheet?{sheet:t.sheet}:{}}),t.json)}async function Cn(e,t){let n=T(),o=await Te(n,e,"changes <doc> --since <version>");t.since===void 0&&p('--since is a version (412) or a time in UTC (2026-10-13, "2026-10-13 09:00").');let s=/^\s*\d+\s*$/.test(t.since)?Number(t.since):t.since;de(await n.readSheet(o.doc.id,{changes:{since:s,max:le(t.max,"max",1)}}),t.json)}var We=`Dockito CLI ${qe}
186
201
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dockito",
3
- "version": "0.0.1-beta.8",
3
+ "version": "0.0.1-beta.9",
4
4
  "description": "Dockito CLI: publish the docs your AI writes as links you can share.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://dockito-site.dockito.workers.dev",