@north-light/cli 0.3.497 → 0.3.498
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/clients/attach/viewer.js +9 -9
- package/dist/core/canvas/migrations.js +61 -55
- package/dist/core/graph/documents.js +5 -5
- package/dist/core/graph/kinds/document.js +4 -4
- package/dist/core/graph/names.js +3 -3
- package/dist/core/graph/objects.d.ts +2 -0
- package/dist/core/graph/objects.js +8 -8
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/repo-sync/repos.js +3 -3
- package/dist/core/peer/stubs.js +1 -1
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/reader.js +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var ne=Object.defineProperty;var s=(t,n)=>ne(t,"name",{value:n,configurable:!0});import{prepared as c}from"../sqlite-statements.js";import{randomUUID as re}from"node:crypto";import{CrtrError as O,notFound as R,usage as m}from"../errors.js";import{ExitCode as D}from"../../types.js";import{canChange as k,canRead as J,missingMemoryScope as oe,missingMemoryScopeUnder as ie,ownerChain as se}from"./access.js";import{bodyOf as ae,get as ue,put as P}from"./bodies.js";import{recordActedOn as N,setLinks as ce}from"./edges.js";import{publish as x}from"./events.js";import{resolveName as le}from"./names.js";import{createObject as me,getById as we,getByRowid as d}from"./objects.js";import{replaceRules as B,setRulesOwner as pe}from"./rules.js";import{recordWatch as $}from"./watches.js";function y(t){return t.class==="node"?t.node:t.class==="app"?t.app:t.class==="object"?t.object:t.person}s(y,"actorOf");let de=0;function E(t,n){const e=`graph_doc_${++de}`;t.exec(`SAVEPOINT ${e}`);try{const r=n();return t.exec(`RELEASE ${e}`),r}catch(r){throw t.exec(`ROLLBACK TO ${e}`),t.exec(`RELEASE ${e}`),r}}s(E,"atomic");function fe(t,n){return new O("conflict",t,D.GENERAL,n)}s(fe,"conflict");function _(t){if(t.type!=="document")throw m(`${t.type} ${t.id} is not a document`)}s(_,"assertDocument");function K(t,n){const e=se(t,n);return(e.length?e[e.length-1]:n).type}s(K,"spaceType");function I(t,n,e){if(e!=="public"&&K(t,n)==="repo")throw m(`a repo owns only public documents; ${n.name} cannot own a ${e} one`,{rule:"repo-public-only",next:"Write it as public, or give it another owner (your own documents can carry `if: {repo: <handle>}`)."})}s(I,"assertPublicInRepo");function H(t,n,e,r){if(e.trim()===""||e!==e.trim())throw m(`invalid document name ${JSON.stringify(e)}`);const o=c(t,"SELECT id FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL").get(n.rowid,e);if(o&&o.id!==r?.id)throw fe(`${n.name} already has a document named ${e}`,{name:e,holder:o.id})}s(H,"assertNameFree");function C(t,n,e){if(!J(t,n,e))throw R(`no document ${e.id}`)}s(C,"readable");function G(t){return new O("scope_missing",`missing scope ${t}`,D.GENERAL,{scope:t})}s(G,"scopeMissing");function T(t,n,e){C(t,n,e);const r=oe(t,n,e,"rw");if(r!==null)throw G(r);if(!k(t,n,e))throw new O("forbidden",`you cannot change ${e.name}`,D.GENERAL,{id:e.id})}s(T,"changeable");function V(t,n){const e=c(t,`SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rowid = rp.parent
|
|
1
|
+
var ne=Object.defineProperty;var s=(t,n)=>ne(t,"name",{value:n,configurable:!0});import{prepared as c}from"../sqlite-statements.js";import{randomUUID as re}from"node:crypto";import{CrtrError as O,notFound as R,usage as m}from"../errors.js";import{ExitCode as D}from"../../types.js";import{canChange as k,canRead as J,missingMemoryScope as oe,missingMemoryScopeUnder as ie,ownerChain as se}from"./access.js";import{bodyOf as ae,get as ue,put as P}from"./bodies.js";import{recordActedOn as N,setLinks as ce}from"./edges.js";import{publish as x}from"./events.js";import{resolveName as le}from"./names.js";import{createObject as me,getById as we,getByRowid as d}from"./objects.js";import{replaceRules as B,setRulesOwner as pe}from"./rules.js";import{recordWatch as $}from"./watches.js";function y(t){return t.class==="node"?t.node:t.class==="app"?t.app:t.class==="object"?t.object:t.person}s(y,"actorOf");let de=0;function E(t,n){const e=`graph_doc_${++de}`;t.exec(`SAVEPOINT ${e}`);try{const r=n();return t.exec(`RELEASE ${e}`),r}catch(r){throw t.exec(`ROLLBACK TO ${e}`),t.exec(`RELEASE ${e}`),r}}s(E,"atomic");function fe(t,n){return new O("conflict",t,D.GENERAL,n)}s(fe,"conflict");function _(t){if(t.type!=="document")throw m(`${t.type} ${t.id} is not a document`)}s(_,"assertDocument");function K(t,n){const e=se(t,n);return(e.length?e[e.length-1]:n).type}s(K,"spaceType");function I(t,n,e){if(e!=="public"&&K(t,n)==="repo")throw m(`a repo owns only public documents; ${n.name} cannot own a ${e} one`,{rule:"repo-public-only",next:"Write it as public, or give it another owner (your own documents can carry `if: {repo: <handle>}`)."})}s(I,"assertPublicInRepo");function H(t,n,e,r){if(e.trim()===""||e!==e.trim())throw m(`invalid document name ${JSON.stringify(e)}`);const o=c(t,"SELECT id FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(n.rowid,e);if(o&&o.id!==r?.id)throw fe(`${n.name} already has a document named ${e}`,{name:e,holder:o.id})}s(H,"assertNameFree");function C(t,n,e){if(!J(t,n,e))throw R(`no document ${e.id}`)}s(C,"readable");function G(t){return new O("scope_missing",`missing scope ${t}`,D.GENERAL,{scope:t})}s(G,"scopeMissing");function T(t,n,e){C(t,n,e);const r=oe(t,n,e,"rw");if(r!==null)throw G(r);if(!k(t,n,e))throw new O("forbidden",`you cannot change ${e.name}`,D.GENERAL,{id:e.id})}s(T,"changeable");function V(t,n){const e=c(t,`SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rowid = rp.parent
|
|
2
2
|
WHERE rp.child = ? ORDER BY p.rev_id`).all(n.rowid);return{rowid:n.rowid,rev_id:n.rev_id,number:n.number,body_hash:n.body_hash,author:n.author===null?null:d(t,n.author)?.id??null,rationale:n.rationale,verbatim:n.verbatim===1,created_at:n.created_at,parents:e.map(r=>r.rev_id)}}s(V,"toRevision");function W(t,n){return c(t,`SELECT * FROM revisions r WHERE r.document = ?
|
|
3
|
-
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid) ORDER BY r.number DESC, r.rev_id`).all(n.rowid).map(r=>V(t,r))}s(W,"heads");function he(t){return t.map(n=>n.rev_id).sort().join(",")}s(he,"headsKeyOf");function A(t,n){const e=c(t,"SELECT * FROM documents WHERE object = ?").get(n.rowid);if(!e)throw R(`no document record for ${n.id}`);return{summary:e.summary,heads_key:e.heads_key,revision:e.revision,why_it_exists:e.why_it_exists,unlisted:e.unlisted===1,lint_ignore:e.lint_ignore_json===null?null:JSON.parse(e.lint_ignore_json),extensions:e.extensions_json===null?null:JSON.parse(e.extensions_json),source_path:e.source_path}}s(A,"documentRecord");function
|
|
4
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(n.rowid,e.rev_id??re(),e.number,e.body_hash,e.author?.rowid??null,e.rationale,e.verbatim?1:0,e.created_at??new Date().toISOString()),o=c(t,"INSERT INTO revision_parents (child, parent) VALUES (?, ?)");for(const i of e.parents)o.run(r.rowid,i);return r}s(
|
|
3
|
+
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid) ORDER BY r.number DESC, r.rev_id`).all(n.rowid).map(r=>V(t,r))}s(W,"heads");function he(t){return t.map(n=>n.rev_id).sort().join(",")}s(he,"headsKeyOf");function A(t,n){const e=c(t,"SELECT * FROM documents WHERE object = ?").get(n.rowid);if(!e)throw R(`no document record for ${n.id}`);return{summary:e.summary,heads_key:e.heads_key,revision:e.revision,why_it_exists:e.why_it_exists,unlisted:e.unlisted===1,lint_ignore:e.lint_ignore_json===null?null:JSON.parse(e.lint_ignore_json),extensions:e.extensions_json===null?null:JSON.parse(e.extensions_json),source_path:e.source_path}}s(A,"documentRecord");function L(t,n,e){const r=c(t,`INSERT INTO revisions (document, rev_id, number, body_hash, author, rationale, verbatim, created_at)
|
|
4
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(n.rowid,e.rev_id??re(),e.number,e.body_hash,e.author?.rowid??null,e.rationale,e.verbatim?1:0,e.created_at??new Date().toISOString()),o=c(t,"INSERT INTO revision_parents (child, parent) VALUES (?, ?)");for(const i of e.parents)o.run(r.rowid,i);return r}s(L,"insertRevision");function Ee(t){const n=new Set;for(const e of t.matchAll(/\[\[([^[\]\n]+?)\]\]/g))n.add(e[1].trim());return[...n]}s(Ee,"linksIn");function Y(t,n,e,r){const o=[],i=[];for(const a of Ee(r)){const u=le(t,n,a);"object"in u?o.push({written_as:a,dst:u.object}):"deleted"in u?o.push({written_as:a,dst:u.deleted}):"remote"in u||i.push(a)}return b(t,ce(t,e,o)),i}s(Y,"setRevisionLinks");function _e(t,n,e){return n.type==="node"?n.id:c(t,`SELECT 1 FROM objects o JOIN objects d ON d.owner = o.rowid
|
|
5
5
|
WHERE o.name = ? AND o.type <> ? AND o.type IN ('person','app','repo','profile')
|
|
6
6
|
AND d.type = 'document' AND d.name = ? AND d.deleted_at IS NULL LIMIT 1`).get(n.name,n.type,e)?`${n.type}:${n.name}`:n.name}s(_e,"ownerPrefix");function X(t,n,e){const r=c(t,`SELECT e.written_as, o.* FROM edges e JOIN objects o ON o.rowid = e.dst
|
|
7
|
-
WHERE e.type = 'links-to' AND e.src = ? AND e.written_as IS NOT NULL`).all(n.rowid);if(r.length===0)return e;const o=new Map;for(const i of r){if(i.deleted_at||i.written_as===i.id)continue;const a=!i.written_as.includes("/");if(a&&i.name===i.written_as)continue;const u=i.owner===null?null:d(t,i.owner),l=u?`${_e(t,u,i.name)}/${i.name}`:i.name,w=a&&i.owner===n.owner?i.name:l;w!==i.written_as&&o.set(i.written_as,w)}return o.size===0?e:e.replace(/\[\[([^[\]\n]+?)\]\]/g,(i,a)=>{const u=o.get(a.trim());return u===void 0?i:`[[${u}]]`})}s(X,"withCurrentNames");function
|
|
7
|
+
WHERE e.type = 'links-to' AND e.src = ? AND e.written_as IS NOT NULL`).all(n.rowid);if(r.length===0)return e;const o=new Map;for(const i of r){if(i.deleted_at||i.written_as===i.id)continue;const a=!i.written_as.includes("/");if(a&&i.name===i.written_as)continue;const u=i.owner===null?null:d(t,i.owner),l=u?`${_e(t,u,i.name)}/${i.name}`:i.name,w=a&&i.owner===n.owner?i.name:l;w!==i.written_as&&o.set(i.written_as,w)}return o.size===0?e:e.replace(/\[\[([^[\]\n]+?)\]\]/g,(i,a)=>{const u=o.get(a.trim());return u===void 0?i:`[[${u}]]`})}s(X,"withCurrentNames");function U(t,n,e){if(e.preview!==void 0){if(e.preview.trim()==="")throw m("a document needs a preview",{field:"preview"});c(t,"UPDATE objects SET preview = ? WHERE rowid = ?").run(e.preview,n.rowid)}e.privacy!==void 0&&(I(t,d(t,n.owner),e.privacy),c(t,"UPDATE objects SET privacy = ? WHERE rowid = ?").run(e.privacy,n.rowid));const r=s((i,a)=>t.prepare(`UPDATE documents SET ${i} = ? WHERE object = ?`).run(a,n.rowid),"set");e.summary!==void 0&&r("summary",e.summary),e.whyItExists!==void 0&&r("why_it_exists",e.whyItExists),e.unlisted!==void 0&&r("unlisted",e.unlisted?1:0),e.lintIgnore!==void 0&&r("lint_ignore_json",e.lintIgnore===null?null:JSON.stringify(e.lintIgnore)),e.extensions!==void 0&&r("extensions_json",e.extensions===null?null:JSON.stringify(e.extensions));const o=d(t,n.rowid);return e.rules!==void 0&&B(t,o,e.rules),o}s(U,"applyDocumentFields");function q(t,n){if(n.owner.deleted_at)throw m(`${n.owner.name} is deleted`);if(n.preview.trim()==="")throw m("a document needs a preview",{field:"preview"});I(t,n.owner,n.privacy),H(t,n.owner,n.name);const e=me(t,{...n.id?{id:n.id}:{},type:"document",kind:n.kind,owner:n.owner.rowid,privacy:n.privacy,name:n.name,preview:n.preview});return c(t,"INSERT INTO documents (object, heads_key, revision) VALUES (?, '', 0)").run(e.rowid),U(t,e,{...n,preview:void 0,privacy:void 0,rules:n.rules??[]})}s(q,"createDocument");function M(t,n){const e=W(t,n),r=he(e),o=Math.max(0,...e.map(i=>i.number));return c(t,"UPDATE documents SET heads_key = ?, revision = ? WHERE object = ?").run(r,o,n.rowid),{heads_key:r,revision:o,headCount:e.length}}s(M,"setHeads");function Ie(t,n,e,r,o){const i=P(r);return E(t,()=>{const a=y(n),u=ie(t,n,e.owner,"rw");if(u!==null)throw G(u);const l=q(t,e),w=L(t,l,{number:1,body_hash:i,author:a,rationale:null,parents:[]}),{heads_key:f}=M(t,l);if(!k(t,n,l))throw R(`no owner ${e.owner.name} you can write to`);const p=Y(t,n,l,r);return N(t,a,l),$(t,a,l,"write",{readHeadsKey:f}),x(t,{event:"created",object:l,actor:a,attrs:{revision:1},pointer:w.rev_id},o),{object:l,revision:1,unresolved:p}})}s(Ie,"writeDocument");function He(t,n,e){return c(t,"SELECT read_heads_key FROM watches WHERE watcher = ? AND object = ?").get(y(n).rowid,e.rowid)?.read_heads_key??null}s(He,"readBase");function ye(t,n){let e=t;for(const[r,{old:o,new:i}]of n.entries()){if(o==="")throw m(`block ${r+1}: a replacement needs non-empty old text`,{field:"replace"});const a=e.indexOf(o);if(a<0)throw m(`block ${r+1}: old text not found: ${JSON.stringify(o.slice(0,120))}`,{field:"replace",old:o});if(e.indexOf(o,a+1)>=0)throw m(`block ${r+1}: old text occurs more than once: ${JSON.stringify(o.slice(0,120))}`,{field:"replace",old:o});e=e.slice(0,a)+i+e.slice(a+o.length)}return e}s(ye,"applyReplacements");function Ce(t,n,e,r,o,i,a={},u){if(_(e),T(t,n,e),e.deleted_at)throw m(`${e.name} is deleted`);if(i===null)throw new O("read_first",`read ${e.name} before editing it`,D.GENERAL,{id:e.id});if(o.trim()==="")throw m("an edit needs a rationale",{field:"rationale"});const l=A(t,e);if(l.heads_key!==i)return{stale:{heads_key:l.heads_key,revision:l.revision}};const w=W(t,e);let f;if("body"in r)f=r.body;else{if(w.length!==1)throw m(`${e.name} has ${w.length} heads and needs a merge; pass the whole merged body`,{heads:w.length});f=ye(X(t,e,ue(w[0].body_hash)),r.replace)}const p=P(f);try{return E(t,()=>{const h=y(n),g=1+Math.max(0,...w.map(v=>v.number)),F=L(t,e,{number:g,body_hash:p,author:h,rationale:o,verbatim:r.verbatim===!0,parents:w.map(v=>v.rowid)}),j=F.rev_id,ee=c(t,"UPDATE documents SET heads_key = ?, revision = ? WHERE object = ? AND heads_key = ?").run(j,g,e.rowid,i);if(Number(ee.changes)===0){const v=A(t,e);throw new z(v.heads_key,v.revision)}const S=U(t,e,a),te=Y(t,n,S,f);return N(t,h,S),$(t,h,S,"write",{readHeadsKey:j}),x(t,{event:"edited",object:S,actor:h,pointer:F.rev_id,attrs:{revision:g,from_revision:l.revision,rationale:o}},u),{revision:g,heads_key:j,unresolved:te}})}catch(h){if(h instanceof z)return{stale:{heads_key:h.heads_key,revision:h.revision}};throw h}}s(Ce,"editDocument");class z extends Error{static{s(this,"StaleEdit")}heads_key;revision;constructor(n,e){super("stale"),this.heads_key=n,this.revision=e}}function We(t,n,e,r){return _(e),n&&T(t,n,e),E(t,()=>{const o=U(t,e,r);return n&&N(t,y(n),o),o})}s(We,"setDocumentRecord");function ve(t,n,e,r){const o=y(n),{heads_key:i}=A(t,e);$(t,o,e,"read",{readHeadsKey:i}),x(t,{event:"read",object:e,actor:o,attrs:{}},r)}s(ve,"recordRead");function Ue(t,n,e,r){return _(e),C(t,n,e),E(t,()=>{const o=A(t,e),i=W(t,e).map(u=>({...u,body:X(t,e,ae(u.body_hash,o.source_path))})),a=c(t,"SELECT dst, written_as FROM edges WHERE type = 'links-to' AND src = ? ORDER BY written_as").all(e.rowid).map(u=>({written_as:u.written_as??"",object:d(t,u.dst)})).filter(u=>u.object&&J(t,n,u.object)).map(u=>({...u,deleted:u.object.deleted_at!==null}));return e.deleted_at||ve(t,n,e,r),{object:e,record:o,heads:i,needsMerge:i.length>1,links:a}})}s(Ue,"readDocument");function Me(t,n,e){return _(e),C(t,n,e),c(t,"SELECT * FROM revisions WHERE document = ? ORDER BY number DESC, created_at DESC, rowid DESC").all(e.rowid).map(o=>V(t,o))}s(Me,"history");function Fe(t,n,e,r){if(_(e),e.deleted_at)throw m(`${e.name} is deleted`);return n&&T(t,n,e),E(t,()=>{const o=r.owner??d(t,e.owner),i=r.name??e.name;H(t,o,i,e),I(t,o,e.privacy),c(t,"UPDATE objects SET name = ?, owner = ? WHERE rowid = ?").run(i,o.rowid,e.rowid);const a=d(t,e.rowid);if(o.rowid!==e.owner&&(pe(t,a),n&&!k(t,n,a)))throw R(`no owner ${o.name} you can move documents to`);return n&&N(t,y(n),a),a})}s(Fe,"moveDocument");function Je(t,n,e,r,o){return _(e),e.deleted_at?e:(n&&T(t,n,e),E(t,()=>{const i=Q(t,n,e,r,o);return b(t,Z(t,e.rowid),r),i}))}s(Je,"deleteDocument");function Pe(t,n,e){return _(n),n.deleted_at?E(t,()=>(H(t,d(t,n.owner),e,n),c(t,"UPDATE objects SET deleted_at = NULL, name = ? WHERE rowid = ?").run(e,n.rowid),d(t,n.rowid))):n}s(Pe,"restoreDocument");function Q(t,n,e,r,o){c(t,"UPDATE objects SET deleted_at = ? WHERE rowid = ?").run(o??new Date().toISOString(),e.rowid);const i=d(t,e.rowid),a=n?y(n):null;return a&&N(t,a,i),x(t,{event:"deleted",object:i,actor:a,attrs:{}},r),c(t,"DELETE FROM watches WHERE object = ?").run(e.rowid),B(t,i,[]),i}s(Q,"markDeleted");function Z(t,n){return c(t,"SELECT dst FROM edges WHERE type = 'links-to' AND src = ?").all(n).map(({dst:e})=>e)}s(Z,"linkTargets");function b(t,n,e){const r=c(t,`SELECT 1 FROM objects d JOIN objects w ON w.rowid = d.owner
|
|
8
8
|
WHERE d.rowid = ? AND d.type = 'document' AND d.deleted_at IS NULL AND w.deleted_at IS NOT NULL
|
|
9
9
|
AND NOT EXISTS (SELECT 1 FROM edges e JOIN objects s ON s.rowid = e.src
|
|
10
|
-
WHERE e.type = 'links-to' AND e.dst = d.rowid AND e.src != d.rowid AND s.deleted_at IS NULL)`),o=[...n];for(;o.length>0;){const i=o.pop();r.get(i)!==void 0&&(Q(t,null,d(t,i),e),o.push(...Z(t,i)))}}s(b,"collectUnlinked");function Be(t,n){if(n.revisions.length===0)throw m(`import of ${n.name}: no revisions`);return E(t,()=>{const e=q(t,n);c(t,"UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.revisions[0].created_at,e.rowid);let r=null;return n.revisions.forEach((o,i)=>{r=
|
|
10
|
+
WHERE e.type = 'links-to' AND e.dst = d.rowid AND e.src != d.rowid AND s.deleted_at IS NULL)`),o=[...n];for(;o.length>0;){const i=o.pop();r.get(i)!==void 0&&(Q(t,null,d(t,i),e),o.push(...Z(t,i)))}}s(b,"collectUnlinked");function Be(t,n){if(n.revisions.length===0)throw m(`import of ${n.name}: no revisions`);return E(t,()=>{const e=q(t,n);c(t,"UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.revisions[0].created_at,e.rowid);let r=null;return n.revisions.forEach((o,i)=>{r=L(t,e,{...o,number:i+1,parents:r===null?[]:[r]}).rowid}),M(t,e),d(t,e.rowid)})}s(Be,"importDocument");function Ke(t,n,e){if(_(n),n.privacy!=="public"&&K(t,n)==="repo")throw m(`a repo owns only public documents; refusing revisions of ${n.name}`);return E(t,()=>{const r=c(t,"SELECT rowid, number, document FROM revisions WHERE rev_id = ?");let o=e.filter(u=>!r.get(u.rev_id));for(;o.length>0;){const u=[];for(const l of o){const w=l.parents.map(p=>r.get(p));if(w.some(p=>p===void 0)){u.push(l);continue}const f=w;if(f.some(p=>p.document!==n.rowid))throw m(`revision ${l.rev_id} names a parent of another document`);L(t,n,{...l,author:null,number:1+Math.max(0,...f.map(p=>p.number)),parents:f.map(p=>p.rowid)})}if(u.length===o.length)throw m(`revisions of ${n.name} name unknown parents: ${u.map(l=>l.rev_id).join(", ")}`);o=u}const{heads_key:i,headCount:a}=M(t,n);return{heads_key:i,headCount:a}})}s(Ke,"insertImportedRevisions");function Ge(t,n){const e=we(t,n);if(!e||e.type!=="document")throw R(`no document ${n}`);return e}s(Ge,"documentById");export{y as actorOf,U as applyDocumentFields,ye as applyReplacements,b as collectUnlinked,Je as deleteDocument,Ge as documentById,A as documentRecord,Ce as editDocument,W as heads,Me as history,Be as importDocument,Ke as insertImportedRevisions,Ee as linksIn,Fe as moveDocument,He as readBase,Ue as readDocument,ve as recordRead,Pe as restoreDocument,We as setDocumentRecord,Y as setRevisionLinks,X as withCurrentNames,Ie as writeDocument};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var y=Object.defineProperty;var m=(e,t)=>y(e,"name",{value:t,configurable:!0});import{prepared as
|
|
2
|
-
AND substr(name, 1, ?) = ? ORDER BY name`).all(n.owner,r.length,r).filter(s=>!s.name.slice(r.length).includes("/")&&
|
|
1
|
+
var y=Object.defineProperty;var m=(e,t)=>y(e,"name",{value:t,configurable:!0});import{prepared as _}from"../../sqlite-statements.js";import{recordMemoryReadsIn as v}from"../../canvas/memory-reads.js";import{deliveryDocOf as x,nodeSubject as S,ownerHandle as $}from"../../substrate/delivery/corpus.js";import{recordContentDelivery as D}from"../../substrate/delivery/deliver.js";import{renderExplicitRead as R}from"../../substrate/delivery/render-event.js";import{canRead as N}from"../access.js";import{documentRecord as j,readDocument as k}from"../documents.js";import{loadLedger as E,saveLedger as O}from"../exposures.js";import{getByRowid as A}from"../objects.js";import{rulesOf as h}from"../rules.js";import{objectDTO as d}from"./dto.js";import{withBase as L}from"./kind.js";import{attr as l,header as I,section as M}from"./render.js";function b(e,t,n){const r=`${n.name}/`;return _(e,`SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND home_machine IS NULL AND owner IS ?
|
|
2
|
+
AND substr(name, 1, ?) = ? ORDER BY name`).all(n.owner,r.length,r).filter(s=>!s.name.slice(r.length).includes("/")&&N(e,t,s)).map(s=>d(e,s))}m(b,"listingOf");function B(e,t,n){const r=t.class==="node",o=r?E(e,t.node.rowid):{node:0,preferenceSnapshot:null,objects:new Map,listed:new Map},s={db:e,reader:t,subject:r?S(e,t):null,ledger:o,channel:"transcript"},a=R(s,x(e,t,n));return r&&(D(e,t,a.delivered),O(e,o)),{attachments:a.attachments,linked:a.linked.map(u=>u.object)}}m(B,"explicitReadAttachments");function T(e,t,n){if(t.class!=="node"||n.kind!=="knowledge"&&n.kind!=="preference"||n.owner===null)return;const r=A(e,n.owner);r!==null&&v(e,t.node.id,[{name:n.name,scope:$(r),at:new Date().toISOString(),type:"read"}])}m(T,"recordExplicitMemoryRead");function W(e,t){const n=[];if(t.attachments&&n.push(t.attachments,""),n.push(I("object",e,l("privacy",e.privacy)+l("revision",t.revision))),n.push(`Preview: ${e.preview}`),t.summary&&n.push(`Summary: ${t.summary}`),t.fields!==void 0&&n.push(`<fields>
|
|
3
3
|
${JSON.stringify(t.fields,null,2)}
|
|
4
|
-
</fields>`),t.needs_merge?(t.heads.forEach((r,o)=>{n.push(`<head${l("rev",r.rev_id)}${l("number",r.number)}${l("author",r.author_id)}>`,t.bodies[o]??"","</head>")}),n.push(`This document has ${t.heads.length} heads. Your next \`crtr doc edit\` writes the merged body and joins them into one revision.`)):n.push("",t.bodies[0]??""),t.listing&&t.listing.length>0){const r=t.listing.some(a=>a.owner?.id===e.owner?.id&&a.name.startsWith(`${e.name}/`)),o=t.listing.some(a=>a.owner?.id!==e.owner?.id||!a.name.startsWith(`${e.name}/`)),s=r&&o?`Names under ${e.name}/ and documents it links to`:r?`Names under ${e.name}/`:"Documents it links to";n.push("",...
|
|
5
|
-
`)}m(W,"render");function C(e){const t=e.attrs.revision,n=e.attrs.from_revision??(typeof t=="number"?t-1:null),r=e.attrs.rationale;return{...e.attrs,from_revision:n,revision:t,authors:e.actor?[e.actor.id]:[],rationales:typeof r=="string"?[r]:[]}}m(C,"editAttrs");const H=m((e,t)=>{const n=C(t);if(e===null)return n;const r=e.authors??[];return{...n,from_revision:e.from_revision??null,authors:[...r,...n.authors.filter(o=>!r.includes(o))],rationales:[...e.rationales??[],...n.rationales]}},"mergeEdits"),te={name:"document",addressable:"name",events:
|
|
4
|
+
</fields>`),t.needs_merge?(t.heads.forEach((r,o)=>{n.push(`<head${l("rev",r.rev_id)}${l("number",r.number)}${l("author",r.author_id)}>`,t.bodies[o]??"","</head>")}),n.push(`This document has ${t.heads.length} heads. Your next \`crtr doc edit\` writes the merged body and joins them into one revision.`)):n.push("",t.bodies[0]??""),t.listing&&t.listing.length>0){const r=t.listing.some(a=>a.owner?.id===e.owner?.id&&a.name.startsWith(`${e.name}/`)),o=t.listing.some(a=>a.owner?.id!==e.owner?.id||!a.name.startsWith(`${e.name}/`)),s=r&&o?`Names under ${e.name}/ and documents it links to`:r?`Names under ${e.name}/`:"Documents it links to";n.push("",...M(s,t.listing))}return n.join(`
|
|
5
|
+
`)}m(W,"render");function C(e){const t=e.attrs.revision,n=e.attrs.from_revision??(typeof t=="number"?t-1:null),r=e.attrs.rationale;return{...e.attrs,from_revision:n,revision:t,authors:e.actor?[e.actor.id]:[],rationales:typeof r=="string"?[r]:[]}}m(C,"editAttrs");const H=m((e,t)=>{const n=C(t);if(e===null)return n;const r=e.authors??[];return{...n,from_revision:e.from_revision??null,authors:[...r,...n.authors.filter(o=>!r.includes(o))],rationales:[...e.rationales??[],...n.rationales]}},"mergeEdits"),te={name:"document",addressable:"name",events:L({edited:{level:8,supersedes:!0,merge:H},deleted:{level:8}}),listItem(e,t){return{summary:j(e,t).summary??null,rules:h(e,t).length}},read(e,t,n,r){const o=k(e,t,n,r.reposFn);T(e,t,n);const s=o.record,a=b(e,t,n),{attachments:u,linked:p}=B(e,t,n),g=new Set(a.map(i=>i.id)),f=[...a,...p.filter(i=>!g.has(i.id)).map(i=>d(e,i))],c={summary:s.summary??null,revision:s.revision,heads:o.heads.map(i=>({rev_id:i.rev_id,number:i.number,author_id:i.author,created_at:i.created_at})),bodies:o.heads.map(i=>i.body),needs_merge:o.needsMerge,...f.length>0?{listing:f}:{},...u===""?{}:{attachments:u}};return r.fields&&(c.fields={why_it_exists:s.why_it_exists??null,unlisted:s.unlisted,lint_ignore:s.lint_ignore??[],extensions:s.extensions??{},rules:h(e,n).map(({matchFrontmatter:i,...w})=>({...w,...i===void 0?{}:{match_frontmatter:i}}))}),{data:c,text:W(d(e,n),c)}}};export{te as documentKind};
|
package/dist/core/graph/names.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
AND deleted_at IS ${l?"NOT NULL ORDER BY deleted_at DESC":"NULL"}`).all(e.rowid,s)}
|
|
3
|
-
OR (type IN ('person','app','repo','profile') AND (name = ? OR id = ?))`).all(e,e,e)}
|
|
1
|
+
var j=Object.defineProperty;var m=(t,e)=>j(t,"name",{value:e,configurable:!0});import{prepared as R}from"../sqlite-statements.js";import{isSafeNodeId as I}from"../canvas/paths.js";import{canRead as y,toolApps as g}from"./access.js";import{getById as T}from"./objects.js";function _(t,e){const s=R(t,"SELECT * FROM objects WHERE type = 'person' AND name = 'user' AND home_machine IS NULL").get(),l=g(t,e),o=e.class==="node"?[e.node,...e.repos,...e.projectRepos,e.profile,e.app]:e.class==="app"?[e.app]:e.class==="object"?[e.owner,...e.repos,e.app]:[],a=new Set;return[...o,s,...l].filter(r=>!!r&&!a.has(r.rowid)&&!!a.add(r.rowid))}m(_,"viewOf");function E(t,e,s,l){return t.prepare(`SELECT * FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND home_machine IS NULL
|
|
2
|
+
AND deleted_at IS ${l?"NOT NULL ORDER BY deleted_at DESC":"NULL"}`).all(e.rowid,s)}m(E,"namedObjects");const F=["person","app","repo","profile"],h=/^(person|app|repo|profile|node):([^/]+)\/(.+)$/;function x(t,e,s){return s==="node"?R(t,"SELECT * FROM objects WHERE type = 'node' AND id = ?").all(e):s?R(t,"SELECT * FROM objects WHERE type = ? AND (name = ? OR id = ?) AND home_machine IS NULL").all(s,e,e):R(t,`SELECT * FROM objects WHERE (type = 'node' AND id = ?)
|
|
3
|
+
OR (type IN ('person','app','repo','profile') AND (name = ? OR id = ?) AND home_machine IS NULL)`).all(e,e,e)}m(x,"ownersByHandle");function W(t,e,s,l){let o=s.trim().replace(/^\[\[(.*)\]\]$/,"$1").trim();const a=/^([^:/]+):reports\/(.+?)(?:\.md)?$/.exec(o);a&&!h.test(o)&&(o=`${a[1]}/reports/${a[2]}`);const r=l?.readable??(c=>y(t,e,c)),u=T(t,o);if(u&&r(u))return u.deleted_at?{deleted:u}:{object:u};const L=l?.view??_(t,e);for(const c of L){const i=E(t,c,o,!1).find(r);if(i)return{object:i}}const p=h.exec(o),w=o.indexOf("/");if(p||w>0){const c=p?p[2]:o.slice(0,w),i=p?p[3]:o.slice(w+1),d=x(t,c,p?.[1]),D=m(n=>{const f=L.findIndex(O=>O.rowid===n.rowid);return f<0?1/0:f},"rank"),A=d.filter(n=>D(n)<1/0).sort((n,f)=>D(n)-D(f));for(const n of A){const f=E(t,n,i,!1).find(r);if(f)return{object:f}}const N=d.flatMap(n=>E(t,n,i,!1)).filter(r);if(N.length===1)return{object:N[0]};if(N.length>1)return{ambiguous:N};const S=d.flatMap(n=>E(t,n,i,!0)).find(r);return S?{deleted:S}:!p&&d.length===0&&I(c)?{remote:o}:{missing:!0}}for(const c of L){const i=E(t,c,o,!0).find(r);if(i)return{deleted:i}}return{missing:!0}}m(W,"resolveName");export{F as HANDLE_TYPES,x as ownersByHandle,W as resolveName,_ as viewOf};
|
|
@@ -11,6 +11,8 @@ export declare function createObject(db: DatabaseSync, spec: {
|
|
|
11
11
|
privacy: Privacy;
|
|
12
12
|
name: string;
|
|
13
13
|
preview: string;
|
|
14
|
+
/** Set for a stub, in the insert itself: the name indexes cover only rows without it. */
|
|
15
|
+
home_machine?: string;
|
|
14
16
|
}): ObjectRow;
|
|
15
17
|
/** The owner object for an identity, created on first sight. Idempotent on
|
|
16
18
|
* (scheme, externalId). Handles are unique per owner type: a handle already held
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
var
|
|
2
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(e.id??
|
|
3
|
-
WHERE i.scheme = ? AND i.external_id = ?`).get(o,i);if(
|
|
1
|
+
var _=Object.defineProperty;var s=(t,e)=>_(t,"name",{value:e,configurable:!0});import{prepared as d}from"../sqlite-statements.js";import{CrtrError as O,notFound as b}from"../errors.js";import{ExitCode as R}from"../../types.js";import{newNodeId as A}from"../runtime/nodes.js";import{kindOf as I}from"./kinds/registry.js";import{canRead as h}from"./access.js";import{bodyOf as T}from"./bodies.js";const y=new Set(["person","app","repo","profile"]);function N(t){return t||null}s(N,"rowFrom");function x(t,e){return N(d(t,"SELECT * FROM objects WHERE id = ?").get(e))}s(x,"getById");function P(t,e){return N(d(t,"SELECT * FROM objects WHERE rowid = ?").get(e))}s(P,"getByRowid");function D(t,e){return I(t,e.type),d(t,`INSERT INTO objects (id, type, kind, owner, privacy, name, preview, created_at, home_machine)
|
|
2
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(e.id??A(),e.type,e.kind,e.owner,e.privacy,e.name,e.preview,new Date().toISOString(),e.home_machine??null)}s(D,"createObject");function S(t,e,o,i,n,r){if(!y.has(e))throw new Error(`ensureOwner: ${e} is not an owner type`);const E=d(t,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
|
|
3
|
+
WHERE i.scheme = ? AND i.external_id = ?`).get(o,i);if(E)return E;const a=d(t,`SELECT o.id, o.type, i.scheme, i.external_id FROM objects o
|
|
4
4
|
LEFT JOIN identities i ON i.object = o.rowid
|
|
5
|
-
WHERE o.name = ? AND o.type =
|
|
5
|
+
WHERE o.name = ? AND o.type = ? AND o.home_machine IS NULL`).get(n,e);if(a)throw new O("conflict",`handle "${n}" is held by ${a.type} ${a.id} (${a.scheme}:${a.external_id}); cannot give it to ${e} ${o}:${i}`,R.GENERAL,{handle:n,holder:a.id});const u=D(t,{type:e,kind:null,owner:e==="profile"?r?.rowid??null:null,privacy:"public",name:n,preview:""});return d(t,"INSERT INTO identities (object, scheme, external_id) VALUES (?, ?, ?)").run(u.rowid,o,i),u}s(S,"ensureOwner");function J(t,e,o){const i=d(t,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
|
|
6
6
|
WHERE i.scheme = 'profile' AND i.external_id = ? AND o.type = 'profile' AND o.deleted_at IS NULL`).get(e),n=d(t,`SELECT o.id FROM objects o
|
|
7
|
-
WHERE o.name = ? AND o.type = 'profile' AND o.deleted_at IS NULL AND o.rowid <> ?`).get(o,i?i.rowid:-1);if(n)throw new
|
|
7
|
+
WHERE o.name = ? AND o.type = 'profile' AND o.deleted_at IS NULL AND o.home_machine IS NULL AND o.rowid <> ?`).get(o,i?i.rowid:-1);if(n)throw new O("conflict",`handle "${o}" is already held by profile object ${n.id}; cannot rename profile ${e} to it`,R.GENERAL,{handle:o,holder:n.id});if(!i)return!1;const r=i;return r.name===o?!1:(g(t,r,o),!0)}s(J,"renameProfileObject");function B(t,e){if(e==="user:local")return S(t,"person","local-user",e,"user");if(/^app:[a-z0-9][a-z0-9._-]*$/.test(e))return S(t,"app","app",e,e.slice(4));throw new Error(`node grantee ${JSON.stringify(e)} is neither app:<name> nor user:local`)}s(B,"ownerForGrantee");function G(t,e,o){return N(d(t,"SELECT * FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,o))}s(G,"liveDocumentNamed");function K(t,e){const o=x(t,e);if(!o||o.type!=="node")throw b(`no node object ${e}`);return o}s(K,"nodeObject");function g(t,e,o){d(t,"UPDATE objects SET name = ? WHERE rowid = ?").run(o,e.rowid)}s(g,"setObjectName");function Y(t,e,o){d(t,"UPDATE objects SET kind = ? WHERE rowid = ?").run(o,e.rowid)}s(Y,"setObjectKind");function z(t,e,o,i={}){const n=["rowid > ?"],r=[i.after_rowid??0];return o.type!==void 0&&(n.push("type = ?"),r.push(o.type)),o.kind!==void 0&&(n.push("kind = ?"),r.push(o.kind)),o.owner!==void 0&&(n.push("owner = ?"),r.push(o.owner.rowid)),o.privacy!==void 0&&(n.push("privacy = ?"),r.push(o.privacy)),o.name!==void 0&&(n.push("name = ?"),r.push(o.name)),n.push("home_machine IS NULL"),n.push(o.deleted?"deleted_at IS NOT NULL":"deleted_at IS NULL"),C(t,e,`SELECT * FROM objects WHERE ${n.join(" AND ")}`,r,Math.min(i.limit??100,100))}s(z,"listObjects");function V(t,e,o){const n=[],r=`%${o.text.replace(/[\\%_]/g,c=>`\\${c}`)}%`;if(!o.grep){const c=d(t,`SELECT o.*, d.summary AS _summary FROM objects o LEFT JOIN documents d ON d.object = o.rowid
|
|
8
8
|
WHERE o.deleted_at IS NULL AND o.home_machine IS NULL AND (o.name LIKE ?1 ESCAPE '\\' OR o.preview LIKE ?1 ESCAPE '\\' OR d.summary LIKE ?1 ESCAPE '\\')
|
|
9
|
-
ORDER BY o.rowid`).all(r),
|
|
10
|
-
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid)`);for(const c of
|
|
11
|
-
`),w
|
|
9
|
+
ORDER BY o.rowid`).all(r),p=o.text.toLowerCase();for(const l of c){const{_summary:w,...m}=l,f=m;if(!h(t,e,f))continue;const L=f.name.toLowerCase().includes(p)?"name":f.preview.toLowerCase().includes(p)?"preview":"summary";if(n.push({object:f,field:L,...L==="summary"?{text:String(w)}:{}}),n.length>=100)return n}}if(!o.body&&!o.grep)return n;const E=new Set(n.map(c=>c.object.rowid)),a=o.grep?(c=>p=>c.test(p))(new RegExp(o.text)):c=>c.includes(o.text),u=d(t,"SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL ORDER BY rowid").all(),j=d(t,`SELECT r.body_hash, d.source_path FROM revisions r JOIN documents d ON d.object = r.document WHERE r.document = ?
|
|
10
|
+
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid)`);for(const c of u)if(!(E.has(c.rowid)||!h(t,e,c)))for(const{body_hash:p,source_path:l}of j.all(c.rowid)){const w=T(p,l).split(`
|
|
11
|
+
`),m=w.findIndex(a);if(!(m<0)){if(n.push({object:c,field:"body",line:m+1,text:w[m]}),n.length>=100)return n;break}}return n}s(V,"searchObjects");function C(t,e,o,i,n){const r=[],E=t.prepare(`${o} ORDER BY rowid LIMIT ${n*4}`);for(;;){const a=E.all(...i);for(const u of a)if(h(t,e,u)&&r.push(u),r.length===n)return r;if(a.length<n*4)return r;i[0]=a[a.length-1].rowid}}s(C,"readablePages");export{D as createObject,S as ensureOwner,x as getById,P as getByRowid,z as listObjects,G as liveDocumentNamed,K as nodeObject,B as ownerForGrantee,J as renameProfileObject,V as searchObjects,Y as setObjectKind,g as setObjectName};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var C=Object.defineProperty;var p=(o,e)=>C(o,"name",{value:e,configurable:!0});import{prepared as f}from"../sqlite-statements.js";import{coveredByAny as m,isSandboxedNode as
|
|
2
|
-
sub, grant_id, scopes_json, cwd, profile_id FROM nodes WHERE node_id = ?`).get(n?.owner??null,e);if(!n||!c)throw new Error(`no node ${e}`);const{grantee:l,sub:a,grant_id:u,scopes_json:i,cwd:d,profile_id:h}=c,_=n.owner===null?null:s.object(n.owner);if(!_)throw new Error(`node ${e} has no owner`);const R=i===null?null:JSON.parse(i);return{class:"node",node:n,app:_,scopes:H(l,a??"",u,R,s,r),launched:R,cwd:d,...x(d,h,t,s),profile:h===null?null:s.profile(h,_)}}p(
|
|
3
|
-
WHERE i.scheme = 'profile' AND i.external_id = ?`).get(e)??S(o,"profile","profile",e,
|
|
1
|
+
var C=Object.defineProperty;var p=(o,e)=>C(o,"name",{value:e,configurable:!0});import{prepared as f}from"../sqlite-statements.js";import{coveredByAny as m,isSandboxedNode as L}from"../../shared/env.js";import{existsSync as A}from"node:fs";import{CrtrError as b}from"../errors.js";import{getStoredProfile as $}from"../scoped-state/profiles.js";import{userScopeRoot as M}from"../scope.js";import{parseScope as O}from"@north-light/identity";import{activeGrant as v,grantFor as N}from"../grants/mirror.js";import{prepared as F}from"../canvas/db.js";import{ApiError as T}from"../../api/errors.js";import{readConfig as W}from"../config.js";import{pluginAppToken as D}from"../secrets.js";import{SCOPE_VOCABULARY as E}from"../scopes.js";import{loadExactProfileManifest as B}from"../profiles/manifest.js";import{ensureOwner as S,getByRowid as P,nodeObject as I}from"./objects.js";function x(o,e,t,s){const r=e===null?[]:s.projectPaths(e),n=t(o),c=new Set(n.map(a=>a.repo.rowid)),l=[];for(const a of r){if(!A(a))continue;let u;try{u=t(a)}catch(i){if(i instanceof b&&i.code==="git-lookup-failed")continue;throw i}for(const i of u)c.has(i.repo.rowid)||(c.add(i.repo.rowid),l.push(i))}return{repos:n.map(a=>a.repo),checkouts:n,projectRepos:l.map(a=>a.repo),projectCheckouts:l}}p(x,"viewRepos");function ae(o,e,t){if(e.class==="anonymous")throw new Error("a publish token cannot read as a principal");if(e.class==="person")return{class:"person",person:g(o)};if(e.class==="app")return{class:"app",app:j(o,e.app),scopes:e.scopes};if(e.class==="machine")throw new Error("a machine token cannot read as a principal");if(e.class==="forwarded"){if(e.actor.kind==="person")return{class:"person",person:g(o)};const l=N(e.actor.app,e.sub);if(!l)throw new T(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);const a=e.actor.node_scopes;return{class:"app",app:j(o,e.actor.app),place:e.actor.place,launched:a,scopes:a===null?l.resolved:a.filter(u=>m(l.resolved,u))}}if(e.class==="cron"){const l=e.grant?v(e.grant)?.resolved??[]:E,a=e.scopes;return{class:"app",app:j(o,e.app),scopes:a===null?l:a.filter(u=>m(l,u)),launched:a,place:{run:e.origin_run??"",isolated:e.isolated}}}const s=w(o),r=I(o,e.node),n=r.owner===null?null:s.object(r.owner);if(!n)throw new Error(`node ${e.node} has no owner`);const c=f(o,"SELECT cwd, profile_id FROM nodes WHERE node_id = ?").get(e.node);return{class:"node",node:r,app:n,scopes:H(e.app,e.sub,e.grant,e.scopes,s),launched:e.scopes,cwd:c.cwd,...x(c.cwd,c.profile_id,t,s),profile:c.profile_id===null?null:s.profile(c.profile_id,n)}}p(ae,"readerFor");function J(o,e,t,s=w(o),r=!1){const n=F(o,"SELECT o.* FROM objects o WHERE o.id = ? AND o.type = 'node'").get(e),c=F(o,`SELECT (SELECT external_id FROM identities WHERE object = ?) AS grantee,
|
|
2
|
+
sub, grant_id, scopes_json, cwd, profile_id FROM nodes WHERE node_id = ?`).get(n?.owner??null,e);if(!n||!c)throw new Error(`no node ${e}`);const{grantee:l,sub:a,grant_id:u,scopes_json:i,cwd:d,profile_id:h}=c,_=n.owner===null?null:s.object(n.owner);if(!_)throw new Error(`node ${e} has no owner`);const R=i===null?null:JSON.parse(i);return{class:"node",node:n,app:_,scopes:H(l,a??"",u,R,s,r),launched:R,cwd:d,...x(d,h,t,s),profile:h===null?null:s.profile(h,_)}}p(J,"readerForNode");function pe(o,e,t=()=>[],s=w(o)){const r=f(o,"SELECT envelope_json FROM peer_stubs WHERE object = ?").get(e.rowid);if(r!==void 0)return y(o,e,r.envelope_json===null?null:JSON.parse(r.envelope_json),s);if(e.type==="node")return J(o,e.id,t,s,!0);const n=e.owner===null?null:s.object(e.owner);if(!n)throw new Error(`watcher ${e.id} has no owner`);const l=(n.type==="app"?n:n.type==="profile"&&n.owner!==null?s.object(n.owner):null)??f(o,"SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object WHERE i.external_id = 'app:terminal' AND i.scheme = 'app'").get()??f(o,"SELECT * FROM objects WHERE type = 'person' AND name = 'user' AND home_machine IS NULL").get();if(!l)throw new Error("no terminal app or person object");const a=f(o,"SELECT external_id FROM identities WHERE object = ? AND scheme = 'app'").get(l.rowid)?.external_id??"app:terminal",u=f(o,"SELECT resolved_scopes_json FROM grants WHERE grantee = ? AND status = 'active'").all(a),i=n.type==="person"?null:u.length===0?a==="app:terminal"&&!s.terminalHasIssuer()?E:s.pluginScopes(a):u.length===1?JSON.parse(u[0].resolved_scopes_json).filter(d=>d.mode==="always").map(d=>O(d.scope)):null;return{class:"object",object:e,node:e,owner:n,app:l,scopes:i,repos:n.type==="repo"?[n]:[]}}p(pe,"readerForObject");function le(o,e,t){const s=f(o,"SELECT external_id FROM identities WHERE object = ? AND scheme = 'app'").get(e.rowid)?.external_id;if(s===void 0)return null;const r=f(o,"SELECT resolved_scopes_json FROM grants WHERE grantee = ? AND status = 'active'").all(s);return r.length===0?s==="app:terminal"&&!t.terminalHasIssuer()?E:t.pluginScopes(s):r.length>1?null:JSON.parse(r[0].resolved_scopes_json).filter(n=>n.mode==="always").map(n=>O(n.scope))}p(le,"appScopesNow");function y(o,e,t,s){const r=g(o);if(t!==null&&t.app===null)return{class:"object",object:e,node:e,owner:r,app:r,scopes:null,repos:[]};const n=t?.app==null?null:j(o,t.app),c=t?.app==null?null:s.grantFor(t.app,t.sub),l=t===null||c===null?null:t.node_scopes===null?c.resolved:t.node_scopes.filter(u=>m(c.resolved,u)),a=n??(e.owner===null?r:s.object(e.owner)??r);return{class:"object",object:e,node:e,owner:a,app:a,scopes:l,launched:t?.node_scopes??null,repos:[],...t?.place==null?{}:{place:t.place}}}p(y,"readerForStub");function w(o){return{grantById:v,grantFor:N,terminalHasIssuer:p(()=>!!W("user").runtime?.issuer,"terminalHasIssuer"),pluginScopes:p(e=>D(e.replace(/^app:/,""))?.scopes??null,"pluginScopes"),object:p(e=>P(o,e),"object"),profile:p((e,t)=>U(o,e,t),"profile"),projectPaths:p(e=>L()?[]:$(M(),e)?.manifest.projects.map(t=>t.path)??[],"projectPaths")}}p(w,"liveLookups");function ce(o){const e=w(o),t=new Map,s=p((r,n)=>(t.has(r)||t.set(r,n()),t.get(r)),"memo");return{grantById:p(r=>s(`g\0${r}`,()=>e.grantById(r)),"grantById"),grantFor:p((r,n)=>s(`a\0${r}\0${n}`,()=>e.grantFor(r,n)),"grantFor"),terminalHasIssuer:p(()=>s("issuer",()=>e.terminalHasIssuer()),"terminalHasIssuer"),pluginScopes:p(r=>s(`t\0${r}`,()=>e.pluginScopes(r)),"pluginScopes"),object:p(r=>s(`o\0${r}`,()=>e.object(r)),"object"),profile:p((r,n)=>s(`p\0${r}\0${n.rowid}`,()=>e.profile(r,n)),"profile"),projectPaths:p(r=>s(`j\0${r}`,()=>e.projectPaths(r)),"projectPaths")}}p(ce,"publishLookups");function H(o,e,t,s,r,n=!1){const c=t?r.grantById(t):r.grantFor(o,e),l=c&&c.grantee===o?c.resolved:o==="app:terminal"&&!r.terminalHasIssuer()?E:null;if(l===null){if(n)return null;throw new Error(`the grant of ${o} is not active`)}return s===null?l:s.filter(a=>m(l,a))}p(H,"nodeScopes");function g(o){return S(o,"person","local-user","user:local","user")}p(g,"personObject");function j(o,e){return e==="user:local"?g(o):S(o,"app","app",e,e.replace(/^app:/,""))}p(j,"appObject");function U(o,e,t){return f(o,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
|
|
3
|
+
WHERE i.scheme = 'profile' AND i.external_id = ?`).get(e)??S(o,"profile","profile",e,B(e).manifest.name,t)}p(U,"profileObject");export{le as appScopesNow,w as liveLookups,U as profileObject,ce as publishLookups,ae as readerFor,J as readerForNode,pe as readerForObject,x as viewRepos};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var h=Object.defineProperty;var s=(t,e)=>h(t,"name",{value:e,configurable:!0});import{prepared as a}from"../../sqlite-statements.js";import{resolve as d,sep as f}from"node:path";import{CrtrError as
|
|
2
|
-
WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`).get(e,r)??null}s(
|
|
3
|
-
WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{path:o,...i}of p)(r===o||r.startsWith(o.endsWith(f)?o:o+f))&&n.push({root:o,repo:i});n.sort((o,i)=>i.root.length-o.root.length);const c=new Set;return n.filter(({repo:o})=>!c.has(o.rowid)&&(c.add(o.rowid),!0))}s(R,"checkoutsForCwd");export{R as checkoutsForCwd,O as ensureRepo,
|
|
1
|
+
var h=Object.defineProperty;var s=(t,e)=>h(t,"name",{value:e,configurable:!0});import{prepared as a}from"../../sqlite-statements.js";import{resolve as d,sep as f}from"node:path";import{CrtrError as m}from"../../errors.js";import{realpathOrSelf as l}from"../../fs-utils.js";import{ExitCode as u}from"../../../types.js";import{ensureOwner as E}from"../objects.js";import{checkoutChain as w,handleHint as N}from"./identity.js";function x(t,e,r){return a(t,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
|
|
2
|
+
WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`).get(e,r)??null}s(x,"existingRepo");function O(t,e,r){const n=x(t,e.scheme,e.externalId);if(n)return n;const p=r??e.handleHint,c=a(t,"SELECT 1 FROM objects WHERE name = ? AND type = 'repo' AND home_machine IS NULL");let o=p;for(let i=2;c.get(o);i++)o=`${p}-${i}`;return E(t,"repo",e.scheme,e.externalId,o)}s(O,"ensureRepo");function F(t,e){return R(t,e).map(r=>r.repo)}s(F,"reposForCwd");function R(t,e){const r=l(d(e)),n=[];for(const o of w(r)){if(!o.ok)throw new m("git-lookup-failed",`cannot identify the repo at ${o.dir}: ${o.reason}`,u.GENERAL,{dir:o.dir});n.push({root:o.root,repo:O(t,o)})}const p=a(t,`SELECT o.*, i.external_id AS path FROM identities i JOIN objects o ON o.rowid = i.object
|
|
3
|
+
WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{path:o,...i}of p)(r===o||r.startsWith(o.endsWith(f)?o:o+f))&&n.push({root:o,repo:i});n.sort((o,i)=>i.root.length-o.root.length);const c=new Set;return n.filter(({repo:o})=>!c.has(o.rowid)&&(c.add(o.rowid),!0))}s(R,"checkoutsForCwd");export{R as checkoutsForCwd,O as ensureRepo,N as handleHint,F as reposForCwd};
|
package/dist/core/peer/stubs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var x=Object.defineProperty;var o=(n,e)=>x(n,"name",{value:e,configurable:!0});import{prepared as i}from"../sqlite-statements.js";import{createObject as A,ensureOwner as h,getById as y,getByRowid as p}from"../graph/objects.js";import{upsertKind as b}from"../graph/custom.js";import{CrtrError as f}from"../errors.js";import{ExitCode as m}from"../../types.js";import{normalizeMachineId as H}from"./names.js";const
|
|
1
|
+
var x=Object.defineProperty;var o=(n,e)=>x(n,"name",{value:e,configurable:!0});import{prepared as i}from"../sqlite-statements.js";import{createObject as A,ensureOwner as h,getById as y,getByRowid as p}from"../graph/objects.js";import{upsertKind as b}from"../graph/custom.js";import{CrtrError as f}from"../errors.js";import{ExitCode as m}from"../../types.js";import{normalizeMachineId as H}from"./names.js";const N=["public","friends","private"],W=o(n=>{const e=n.act.act;return e===void 0?{sub:n.sub,app:null,node:null,node_scopes:null,place:null}:{sub:n.sub,app:e.sub,node:e.node,node_scopes:e.node_scopes,place:e.place}},"identityOfEnvelope");function S(n,e){const r=typeof e=="string"?y(n,e):e;if(r===null)return null;const t=i(n,"SELECT home_machine, envelope_json FROM peer_stubs WHERE object = ?").get(r.rowid);return t?{object:r,home_machine:t.home_machine,identity:t.envelope_json===null?null:JSON.parse(t.envelope_json)}:null}o(S,"stubOf");const I=o((n,e)=>i(n,"SELECT 1 FROM peer_stubs WHERE object = ?").get(e.rowid)!==void 0,"isStub");function d(n){return h(n,"person","local-user","user:local","user")}o(d,"localPerson");function w(n,e){return e==="user:local"?d(n):h(n,"app","app",e,e.replace(/^app:/,""))}o(w,"localApp");function F(n,e){return e.type==="app"?w(n,`app:${e.name}`):e.type==="person"?d(n):null}o(F,"localOwnerActor");function v(n,e,r){if(e!==null)return e.app===null?d(n):w(n,e.app);const t=r?.owner;return t?.type==="app"?w(n,t.external_id??`app:${t.handle}`):d(n)}o(v,"ownerFor");function g(n,e,r,t,_,u){const l=_===void 0?null:W(_),s=u?.privacy??"public";if(!N.includes(s))throw new f("invalid_event",`invalid privacy ${JSON.stringify(s)}`,m.GENERAL,{id:e});const c=y(n,e);if(c!==null){const a=S(n,c);if(a===null)throw new f("conflict",`${e} is a local ${c.type}, not a stub of ${t}`,m.GENERAL,{id:e});if(a.home_machine!==t)throw new f("conflict",`${e} is already a stub of ${a.home_machine}, not ${t}`,m.GENERAL,{id:e,home_machine:a.home_machine});return l!==null&&(i(n,"UPDATE peer_stubs SET envelope_json = ? WHERE object = ?").run(JSON.stringify(l),c.rowid),i(n,"UPDATE objects SET reception = 2 WHERE rowid = ?").run(c.rowid)),u!==void 0&&(R(n,r,u),u.privacy!==void 0&&c.privacy!==s)?(i(n,"UPDATE objects SET privacy = ? WHERE rowid = ?").run(s,c.rowid),p(n,c.rowid)):c}const O=v(n,l,u);R(n,r,u);const E=A(n,{id:e,type:r,kind:u?.kind??null,owner:O.rowid,privacy:s,name:u?.name??e,preview:u?.preview??"",home_machine:t});return i(n,"INSERT INTO peer_stubs (object, home_machine, envelope_json, created_at) VALUES (?, ?, ?, ?)").run(E.rowid,t,l===null?null:JSON.stringify(l),new Date().toISOString()),l!==null&&i(n,"UPDATE objects SET reception = 2 WHERE rowid = ?").run(E.rowid),p(n,E.rowid)}o(g,"ensureStub");function R(n,e,r){const t=r?.kind_decl;t===void 0||t.name!==e||b(n,{name:t.name,owner:v(n,null,{...r,owner:t.owner}),description:t.description,events:t.events,read:null,source:"peer"})}o(R,"holdKind");function J(n,e,r){const t=g(n,e,"node",H(r));return i(n,"UPDATE objects SET reception = 2 WHERE rowid = ?").run(t.rowid),p(n,t.rowid)}o(J,"ensureNodeStub");function M(n,e,r){const t=S(n,e);t===null||t.home_machine===r||(i(n,"UPDATE peer_stubs SET home_machine = ? WHERE object = ?").run(r,t.object.rowid),i(n,"UPDATE objects SET home_machine = ? WHERE rowid = ?").run(r,t.object.rowid))}o(M,"rehomeStub");function G(n,e){const r=j(n,e.owner===null?null:p(n,e.owner)),t=T(n,e.type);return{id:e.id,type:e.type,kind:e.kind,name:e.name,preview:e.preview,owner:r,privacy:e.privacy,...t===null?{}:{kind_decl:t}}}o(G,"describeObject");function j(n,e){if(e===null||e.type!=="person"&&e.type!=="app"&&e.type!=="repo"&&e.type!=="profile")return null;const r=i(n,"SELECT scheme, external_id FROM identities WHERE object = ?").get(e.rowid);return{id:e.id,type:e.type,scheme:r?.scheme??null,external_id:r?.external_id??null,handle:e.name}}o(j,"ownerRefOf");function T(n,e){const r=i(n,"SELECT owner, description, events_json FROM object_kinds WHERE name = ?").get(e),t=r===void 0?null:j(n,p(n,r.owner));return r===void 0||t===null?null:{name:e,description:r.description,events:JSON.parse(r.events_json),owner:t}}o(T,"kindDeclarationOf");function K(n,e,r){const t=T(n,e.type);return t===null?r:{...r,kind_decl:t}}o(K,"withKindDecl");export{G as describeObject,J as ensureNodeStub,g as ensureStub,W as identityOfEnvelope,I as isStub,T as kindDeclarationOf,F as localOwnerActor,M as rehomeStub,S as stubOf,K as withKindDecl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var re=Object.defineProperty;var u=(t,e)=>re(t,"name",{value:e,configurable:!0});import{prepared as P}from"../../../core/sqlite-statements.js";import{ApiError as _}from"../../../api/errors.js";import{DOC_KINDS as q,DOC_UNSET_FIELDS as H}from"../../../api/dto/docs.js";import{PRIVACY_LEVELS_DTO as V}from"../../../api/dto/objects.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{CrtrError as ie}from"../../../core/errors.js";import{emitEvent as se}from"../../../core/events/emit.js";import{canChange as K,spaceOf as ae}from"../../../core/graph/access.js";import{get as A}from"../../../core/graph/bodies.js";import{deleteDocument as ce,documentRecord as F,editDocument as de,heads as I,history as ue,linksIn as U,moveDocument as fe,readBase as le,setDocumentRecord as me,withCurrentNames as pe,writeDocument as he}from"../../../core/graph/documents.js";import{resolveName as X}from"../../../core/graph/names.js";import{getByRowid as M}from"../../../core/graph/objects.js";import{noteRepoDocumentsChanged as we}from"../../../core/graph/repo-sync/index.js";import{checkoutsForCwd as ye}from"../../../core/graph/repo-sync/repos.js";import{lintRules as ve,rulesOf as ge}from"../../../core/graph/rules.js";import{unifiedDiff as _e}from"../../../core/graph/diff.js";import{ownerFromFlag as W,readerFor as E,resolveRef as z}from"../reader.js";function v(t,e,n,o,s={}){return new _(t,e,n,{...s,error:e,message:n,next:o})}u(v,"refuse");const b=u((t,e)=>new _(400,"invalid_request",t,e),"invalid");function D(t){const e=t.body;if(e===void 0)return{};if(typeof e!="object"||e===null||Array.isArray(e))throw b("the request body must be a JSON object");return e}u(D,"bodyOf");const L=u(t=>e=>ye(t,e),"reposFnFor");function C(t,e){if(t instanceof ie){const n=t.details;if(t.code==="read_first")throw v(409,"read_first",t.message,`Read it first with \`crtr canvas read ${e?.id??"<ref>"}\`, then rerun the edit.`,n??{});if(t.code==="conflict")throw new _(409,"name_taken",t.message,n);if(t.code==="forbidden")throw new _(403,"forbidden",t.message,n);if(t.code==="scope_missing")throw v(403,"scope_missing",t.message,`Launch the run with \`${String(n?.scope)}\` in its scopes list.`,n??{});if(n?.rule==="repo-public-only")throw v(422,"repo_documents_are_public",t.message,'Own it as `user` and add a rule with `if: {"repo": "<handle>"}` so it loads only in that repo.')}throw t}u(C,"mapGraphError");function x(t,e,n){const o=z(t,e,decodeURIComponent(n));if("remote"in o)throw v(404,"not_found",G(o.remote),"Check the name with `crtr canvas search`.");if("deleted"in o)throw new _(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});if(o.type!=="document")throw b(`${n} is a ${o.type}, not a document`);return o}u(x,"refDocument");function G(t){return`no object named ${t} on this runtime; it may be on another runtime, or the name may be misspelled`}u(G,"remoteMessage");function be(t,e){const n=e.owner===null?null:M(t,e.owner);return n?n.type==="node"?n.id:n.name:""}u(be,"ownerHandle");function j(t,e){const n=be(t,e);return n?`${n}/${e.name}`:e.name}u(j,"canonicalName");function ke(t,e){const n=e.owner===null?null:M(t,e.owner),o=n?{id:n.id,type:n.type,handle:n.type==="node"?n.id:n.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:o,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}u(ke,"objectDTO");function Ee(t,e){const n=e.owner===null?null:M(t,e.owner);return n?.type==="repo"?n:null}u(Ee,"repoOwner");function S(t,e,n,o){const s=[...new Map(n.flatMap(f=>{const i=Ee(t,f);return i?[[i.id,i]]:[]})).values()],a=e.class==="node"?e.cwd:o,r=e.class==="node"?[...e.checkouts,...e.projectCheckouts].map(f=>f.root):[];return{repos:s,dirs:[...new Set([...a!==void 0?[a]:[],...r])]}}u(S,"repoChange");function T(t){for(const e of t.repos)try{we(e,t.dirs)}catch(n){se({level:"warn",event:"repo_sync.failed",outcome:"failed",error:n,fields:{repo:e.name,step:"export",reason:n instanceof Error?n.message:String(n)}})}}u(T,"syncChanged");const Y=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;function $e(t,e){if(t===void 0)return;if(!Array.isArray(t)){e.push("`rules` must be a list");return}const n=t.map(s=>{if(typeof s!="object"||s===null||Array.isArray(s))return s;const{match_frontmatter:a,...r}=s;return"matchFrontmatter"in r?{...r,match_frontmatter:r.matchFrontmatter}:a===void 0?r:{...r,matchFrontmatter:a}}),o=ve(n);if(o){e.push(o.replaceAll("matchFrontmatter","match_frontmatter"));return}return n}u($e,"rulesFromDTO");function Z(t,e){const n={},o=u(i=>{const c=t[i];if(c!==void 0){if(typeof c!="string"){e.push(`\`${i}\` must be a string`);return}return c}},"str"),s=o("preview");s!==void 0&&(s.trim()===""||/[\r\n]/.test(s)?e.push("`preview` must be one non-empty line"):n.preview=s);const a=o("summary");a!==void 0&&(n.summary=a);const r=o("why_it_exists");if(r!==void 0&&(n.whyItExists=r),t.privacy!==void 0&&(V.includes(t.privacy)?n.privacy=t.privacy:e.push(`\`privacy\` must be one of ${V.join(", ")}`)),t.unlisted!==void 0&&(typeof t.unlisted!="boolean"?e.push("`unlisted` must be a boolean"):n.unlisted=t.unlisted),t.lint_ignore!==void 0){const i=t.lint_ignore;!Array.isArray(i)||i.some(c=>typeof c!="string")?e.push("`lint_ignore` must be a list of strings"):n.lintIgnore=i}if(t.extensions!==void 0){const i=t.extensions;typeof i!="object"||i===null||Array.isArray(i)||Object.values(i).some(c=>typeof c!="object"||c===null||Array.isArray(c))?e.push("`extensions` must map each plugin to an object of fields"):n.extensions=i}const f=$e(t.rules,e);return f!==void 0&&(n.rules=f),n}u(Z,"fieldsFrom");function J(t){if(t.length>0)throw b(t.join("; "),{errors:t})}u(J,"failOn");function Q(t,e,n,o){const s=U(n).filter(a=>"remote"in X(t,e,a));return{...o.length>0?{unresolved_links:o}:{},...s.length>0?{remote_links:s}:{}}}u(Q,"linkReport");function Oe(t){const e=D(t),n=[],o=e.name;(typeof o!="string"||!Y.test(o))&&n.push("`name` must be segments of letters, digits, `_` or `-` joined by `/`"),typeof e.body!="string"&&n.push("`body` must be a string"),typeof e.preview!="string"&&n.push("`preview` is required");const s=e.kind??"knowledge";q.includes(s)||n.push(s==="report"?"reports are written only by `crtr push`":`\`kind\` must be one of ${q.join(", ")}`);const a=Z(e,n);e.cwd!==void 0&&typeof e.cwd!="string"&&n.push("`cwd` must be a string"),J(n);const r=e,{dto:f,change:i}=k(c=>{const h=E(c,t),d=W(c,h,r.owner,r.cwd);if(!K(c,h,d))throw new _(404,"not_found",`no owner ${d.name} you can write to`);try{const{object:p,unresolved:l}=he(c,h,{...a,owner:d,name:r.name,kind:s,preview:a.preview,privacy:a.privacy??"public"},r.body,L(c));return{dto:{id:p.id,name:j(c,p),...Q(c,h,r.body,l)},change:S(c,h,[p],r.cwd)}}catch(p){C(p)}});return T(i),f}u(Oe,"write");function Ae(t,e){let n=t;e.forEach(({old:o,new:s},a)=>{const r=o===""?-1:n.indexOf(o);if(r<0)throw v(422,"replace_no_match",`replace[${a}]: old text not found in the revision you read`,"Copy the old text exactly from your last read and rerun.",{index:a});if(n.indexOf(o,r+1)>=0)throw v(422,"replace_ambiguous",`replace[${a}]: old text occurs more than once`,"Include more surrounding text so the old text matches once, and rerun.",{index:a});n=n.slice(0,r)+s+n.slice(r+o.length)})}u(Ae,"checkReplacements");function je(t){const e=D(t),n=[],o=e.body!==void 0,s=e.replace!==void 0;o&&s&&n.push("give `body` or `replace`, not both"),o&&typeof e.body!="string"&&n.push("`body` must be a string");const a=e.replace;s&&(!Array.isArray(a)||a.length===0||a.some(d=>typeof d!="object"||d===null||typeof d.old!="string"||typeof d.new!="string"))&&n.push("`replace` must be a non-empty list of {old, new} strings"),(typeof e.rationale!="string"||e.rationale.trim()==="")&&n.push("`rationale` is required"),e.verbatim!==void 0&&typeof e.verbatim!="boolean"&&n.push("`verbatim` must be a boolean"),e.base!==void 0&&(typeof e.base!="string"||e.base==="")&&n.push("`base` must be a non-empty heads key"),e.base!==void 0&&!o&&!s&&n.push("`base` applies only to a `body` or `replace` edit");const r=Z(e,n),f=e.unset??[];if(!Array.isArray(f)||f.some(d=>!H.includes(d)))n.push(`\`unset\` takes only ${H.join(", ")}`);else for(const d of f)d==="summary"&&(r.summary=null),d==="why_it_exists"&&(r.whyItExists=null),d==="unlisted"&&(r.unlisted=!1),d==="lint_ignore"&&(r.lintIgnore=null),d==="extensions"&&(r.extensions=null),d==="rules"&&(r.rules=[]);n.length===0&&!o&&!s&&Object.keys(r).length===0&&n.push("nothing to change: give `body`, `replace`, or a field"),J(n);const i=e,{dto:c,synced:h}=k(d=>{const p=E(d,t),l=x(d,p,t.params.ref),g=j(d,l),O=S(d,p,[l]);try{if(!o&&!s)return me(d,p,l,r),{dto:{id:l.id,name:g,revision:F(d,l).revision},synced:O};const w=i.base??le(d,p,l);if(s&&w!==null){const oe=F(d,l),B=I(d,l);oe.heads_key===w&&B.length===1&&Ae(pe(d,l,A(B[0].body_hash)),i.replace)}const R=i.verbatim===!0,m=o?{body:i.body,verbatim:R}:{replace:i.replace,verbatim:R},y=de(d,p,l,m,i.rationale,w,r,L(d));if("stale"in y)throw v(409,"stale_revision",`${g} changed after your read; it is now at revision ${y.stale.revision}`,`Read it again with \`crtr canvas read ${g}\`, then redo your change on the current text.`,{stale:y.stale});const N=A(I(d,l)[0].body_hash);return{dto:{id:l.id,name:g,revision:y.revision,...Q(d,p,N,y.unresolved)},synced:O}}catch(w){C(w,l)}});return T(h),c}u(je,"edit");function Re(t){const e=D(t);if(e.new_name===void 0&&e.owner===void 0)throw b("give a new name, an owner, or both");if(e.new_name!==void 0&&(typeof e.new_name!="string"||!Y.test(e.new_name)))throw b("`new_name` must be segments of letters, digits, `_` or `-` joined by `/`");const{dto:n,change:o}=k(s=>{const a=E(s,t),r=x(s,a,t.params.ref),f=e.owner===void 0?void 0:W(s,a,e.owner,e.cwd);try{const i=fe(s,a,r,{...e.new_name!==void 0?{name:e.new_name}:{},...f?{owner:f}:{}});return{dto:{id:i.id,name:j(s,i)},change:S(s,a,[r,i],e.cwd)}}catch(i){C(i,r)}});return T(o),n}u(Re,"move");function De(t){const{dto:e,change:n}=k(o=>{const s=E(o,t),a=x(o,s,t.params.ref),r=j(o,a),f=S(o,s,[a]);try{ce(o,s,a,L(o))}catch(i){C(i,a)}return{dto:{id:a.id,name:r},change:f}});return T(n),e}u(De,"remove");function Ce(t){const e=t.query.get("diff"),n=e===null?void 0:Number(e);if(n!==void 0&&!(Number.isInteger(n)&&n>0))throw b("`diff` must be a revision number");return k(o=>{const s=E(o,t),a=z(o,s,decodeURIComponent(t.params.ref));if("remote"in a)throw v(404,"not_found",G(a.remote),"Check the name with `crtr canvas search`.");const r="deleted"in a?a.deleted:a;if(r.type!=="document")throw b(`${r.name} is a ${r.type}, not a document`);const f=ue(o,s,r),i={object:ke(o,r),revisions:f.map(c=>({rev_id:c.rev_id,number:c.number,author_id:c.author,rationale:c.rationale,verbatim:c.verbatim,created_at:c.created_at,parents:c.parents}))};if(n!==void 0){const c=f.find(d=>d.number===n);if(!c)throw new _(404,"not_found",`${r.name} has no revision ${n}`);const h=c.parents[0]===void 0?void 0:f.find(d=>d.rev_id===c.parents[0]);i.diff=_e(h?A(h.body_hash):"",A(c.body_hash))}return i})}u(Ce,"revisionHistory");const ee=1e3,ne=1e3,te=3e3,Se=/^When\b.+\bbecause\b.+/,Te=u(t=>{const e=t.trim();return e===""?0:e.split(/\s+/).length},"words");function Ne(t,e){if(t.some(o=>o.on==="boot"&&o.deliver==="content")&&e>ee)return`body is ${e} words, over the ${ee}-word cap for a boot rule at content (the whole body enters every node's context). Keep the core here and move separate subjects into [[linked]] documents.`;const n=[...new Set(t.filter(o=>o.on!=="boot"&&o.deliver==="content").map(o=>o.on))];return n.length>0&&e>ne?`body is ${e} words, over the ${ne}-word cap for a content rule on ${n.join("/")}. Keep the core here and move separate subjects into [[linked]] documents.`:t.some(o=>o.on==="boot"&&o.deliver==="preview")&&e>te?`body is ${e} words, over the ${te}-word cap for a boot rule at preview. Keep the core here and move separate subjects into [[linked]] documents.`:null}u(Ne,"lengthFinding");function Fe(t){const e=D(t);return k(n=>{const o=E(n,t),s=e.owner===void 0?null:W(n,o,e.owner,e.cwd),a=P(n,"SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND kind != 'report' ORDER BY name").all(),r=[],f=new Map;for(const i of a){if(s&&i.owner!==s.rowid||!K(n,o,i))continue;const c=F(n,i),h=new Set(c.lint_ignore??[]),d=j(n,i),p=u((m,y,N)=>{h.has(m)||r.push({name:d,severity:y,rule:m,message:N})},"add"),l=ge(n,i),g=I(n,i)[0],O=g?A(g.body_hash):"",w=Ne(l,Te(O));w&&p("length","error",w),l.some(m=>m.deliver==="preview")&&!Se.test(i.preview??"")&&p("preview-shape","error",`a rule delivers this document at preview, so the preview must read "When <situation in the reader's work>, read this because <what the reader gains>"`);const R=new Set(P(n,"SELECT written_as FROM edges WHERE type = 'links-to' AND src = ?").all(i.rowid).map(m=>m.written_as));for(const m of U(O))R.has(m)||"remote"in X(n,o,m)||p("links","warning",`[[${m}]] names no object in your view`);if(l.some(m=>m.on==="workspace-open"&&m.deliver==="content")){const m=ae(n,i);m.type==="repo"&&!h.has("workspace-open")&&f.set(m.name,[...f.get(m.name)??[],d])}}for(const[i,c]of f)if(!(c.length<2))for(const h of c)r.push({name:h,severity:"warning",rule:"workspace-open",message:`repo ${i} has ${c.length} documents delivered at content on workspace-open (${c.join(", ")}); keep one and link the rest from it`});return{findings:r}})}u(Fe,"lint");const $=u((t,e=200)=>n=>({status:e,body:t(n)}),"ok"),Qe=[{method:"POST",pattern:"/v1/docs",handler:$(Oe,201)},{method:"PATCH",pattern:"/v1/docs/:ref",handler:$(je)},{method:"POST",pattern:"/v1/docs/:ref/move",handler:$(Re)},{method:"DELETE",pattern:"/v1/docs/:ref",handler:$(De)},{method:"GET",pattern:"/v1/docs/:ref/history",handler:$(Ce)},{method:"POST",pattern:"/v1/docs/lint",handler:$(Fe)}];export{Qe as docRoutes};
|
|
1
|
+
var re=Object.defineProperty;var u=(t,e)=>re(t,"name",{value:e,configurable:!0});import{prepared as P}from"../../../core/sqlite-statements.js";import{ApiError as _}from"../../../api/errors.js";import{DOC_KINDS as q,DOC_UNSET_FIELDS as H}from"../../../api/dto/docs.js";import{PRIVACY_LEVELS_DTO as U}from"../../../api/dto/objects.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{CrtrError as ie}from"../../../core/errors.js";import{emitEvent as se}from"../../../core/events/emit.js";import{canChange as V,spaceOf as ae}from"../../../core/graph/access.js";import{get as A}from"../../../core/graph/bodies.js";import{deleteDocument as ce,documentRecord as F,editDocument as de,heads as I,history as ue,linksIn as K,moveDocument as fe,readBase as me,setDocumentRecord as le,withCurrentNames as pe,writeDocument as he}from"../../../core/graph/documents.js";import{resolveName as X}from"../../../core/graph/names.js";import{getByRowid as L}from"../../../core/graph/objects.js";import{noteRepoDocumentsChanged as we}from"../../../core/graph/repo-sync/index.js";import{checkoutsForCwd as ye}from"../../../core/graph/repo-sync/repos.js";import{lintRules as ve,rulesOf as ge}from"../../../core/graph/rules.js";import{unifiedDiff as _e}from"../../../core/graph/diff.js";import{ownerFromFlag as M,readerFor as E,resolveRef as z}from"../reader.js";function v(t,e,n,o,s={}){return new _(t,e,n,{...s,error:e,message:n,next:o})}u(v,"refuse");const b=u((t,e)=>new _(400,"invalid_request",t,e),"invalid");function R(t){const e=t.body;if(e===void 0)return{};if(typeof e!="object"||e===null||Array.isArray(e))throw b("the request body must be a JSON object");return e}u(R,"bodyOf");const W=u(t=>e=>ye(t,e),"reposFnFor");function S(t,e){if(t instanceof ie){const n=t.details;if(t.code==="read_first")throw v(409,"read_first",t.message,`Read it first with \`crtr canvas read ${e?.id??"<ref>"}\`, then rerun the edit.`,n??{});if(t.code==="conflict")throw new _(409,"name_taken",t.message,n);if(t.code==="forbidden")throw new _(403,"forbidden",t.message,n);if(t.code==="scope_missing")throw v(403,"scope_missing",t.message,`Launch the run with \`${String(n?.scope)}\` in its scopes list.`,n??{});if(n?.rule==="repo-public-only")throw v(422,"repo_documents_are_public",t.message,'Own it as `user` and add a rule with `if: {"repo": "<handle>"}` so it loads only in that repo.')}throw t}u(S,"mapGraphError");function x(t,e,n){const o=z(t,e,decodeURIComponent(n));if("remote"in o)throw v(404,"not_found",G(o.remote),"Check the name with `crtr canvas search`.");if("deleted"in o)throw new _(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});if(o.type!=="document")throw b(`${n} is a ${o.type}, not a document`);return o}u(x,"refDocument");function G(t){return`no object named ${t} on this runtime; it may be on another runtime, or the name may be misspelled`}u(G,"remoteMessage");function be(t,e){const n=e.owner===null?null:L(t,e.owner);return n?n.type==="node"?n.id:n.name:""}u(be,"ownerHandle");function j(t,e){const n=be(t,e);return n?`${n}/${e.name}`:e.name}u(j,"canonicalName");function ke(t,e){const n=e.owner===null?null:L(t,e.owner),o=n?{id:n.id,type:n.type,handle:n.type==="node"?n.id:n.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:o,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}u(ke,"objectDTO");function Ee(t,e){const n=e.owner===null?null:L(t,e.owner);return n?.type==="repo"?n:null}u(Ee,"repoOwner");function C(t,e,n,o){const s=[...new Map(n.flatMap(f=>{const i=Ee(t,f);return i?[[i.id,i]]:[]})).values()],a=e.class==="node"?e.cwd:o,r=e.class==="node"?[...e.checkouts,...e.projectCheckouts].map(f=>f.root):[];return{repos:s,dirs:[...new Set([...a!==void 0?[a]:[],...r])]}}u(C,"repoChange");function N(t){for(const e of t.repos)try{we(e,t.dirs)}catch(n){se({level:"warn",event:"repo_sync.failed",outcome:"failed",error:n,fields:{repo:e.name,step:"export",reason:n instanceof Error?n.message:String(n)}})}}u(N,"syncChanged");const Y=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;function $e(t,e){if(t===void 0)return;if(!Array.isArray(t)){e.push("`rules` must be a list");return}const n=t.map(s=>{if(typeof s!="object"||s===null||Array.isArray(s))return s;const{match_frontmatter:a,...r}=s;return"matchFrontmatter"in r?{...r,match_frontmatter:r.matchFrontmatter}:a===void 0?r:{...r,matchFrontmatter:a}}),o=ve(n);if(o){e.push(o.replaceAll("matchFrontmatter","match_frontmatter"));return}return n}u($e,"rulesFromDTO");function Z(t,e){const n={},o=u(i=>{const c=t[i];if(c!==void 0){if(typeof c!="string"){e.push(`\`${i}\` must be a string`);return}return c}},"str"),s=o("preview");s!==void 0&&(s.trim()===""||/[\r\n]/.test(s)?e.push("`preview` must be one non-empty line"):n.preview=s);const a=o("summary");a!==void 0&&(n.summary=a);const r=o("why_it_exists");if(r!==void 0&&(n.whyItExists=r),t.privacy!==void 0&&(U.includes(t.privacy)?n.privacy=t.privacy:e.push(`\`privacy\` must be one of ${U.join(", ")}`)),t.unlisted!==void 0&&(typeof t.unlisted!="boolean"?e.push("`unlisted` must be a boolean"):n.unlisted=t.unlisted),t.lint_ignore!==void 0){const i=t.lint_ignore;!Array.isArray(i)||i.some(c=>typeof c!="string")?e.push("`lint_ignore` must be a list of strings"):n.lintIgnore=i}if(t.extensions!==void 0){const i=t.extensions;typeof i!="object"||i===null||Array.isArray(i)||Object.values(i).some(c=>typeof c!="object"||c===null||Array.isArray(c))?e.push("`extensions` must map each plugin to an object of fields"):n.extensions=i}const f=$e(t.rules,e);return f!==void 0&&(n.rules=f),n}u(Z,"fieldsFrom");function J(t){if(t.length>0)throw b(t.join("; "),{errors:t})}u(J,"failOn");function Q(t,e,n,o){const s=K(n).filter(a=>"remote"in X(t,e,a));return{...o.length>0?{unresolved_links:o}:{},...s.length>0?{remote_links:s}:{}}}u(Q,"linkReport");function Oe(t){const e=R(t),n=[],o=e.name;(typeof o!="string"||!Y.test(o))&&n.push("`name` must be segments of letters, digits, `_` or `-` joined by `/`"),typeof e.body!="string"&&n.push("`body` must be a string"),typeof e.preview!="string"&&n.push("`preview` is required");const s=e.kind??"knowledge";q.includes(s)||n.push(s==="report"?"reports are written only by `crtr push`":`\`kind\` must be one of ${q.join(", ")}`);const a=Z(e,n);e.cwd!==void 0&&typeof e.cwd!="string"&&n.push("`cwd` must be a string"),J(n);const r=e,{dto:f,change:i}=k(c=>{const h=E(c,t),d=M(c,h,r.owner,r.cwd);if(!V(c,h,d))throw new _(404,"not_found",`no owner ${d.name} you can write to`);try{const{object:p,unresolved:m}=he(c,h,{...a,owner:d,name:r.name,kind:s,preview:a.preview,privacy:a.privacy??"public"},r.body,W(c));return{dto:{id:p.id,name:j(c,p),...Q(c,h,r.body,m)},change:C(c,h,[p],r.cwd)}}catch(p){S(p)}});return N(i),f}u(Oe,"write");function Ae(t,e){let n=t;e.forEach(({old:o,new:s},a)=>{const r=o===""?-1:n.indexOf(o);if(r<0)throw v(422,"replace_no_match",`replace[${a}]: old text not found in the revision you read`,"Copy the old text exactly from your last read and rerun.",{index:a});if(n.indexOf(o,r+1)>=0)throw v(422,"replace_ambiguous",`replace[${a}]: old text occurs more than once`,"Include more surrounding text so the old text matches once, and rerun.",{index:a});n=n.slice(0,r)+s+n.slice(r+o.length)})}u(Ae,"checkReplacements");function je(t){const e=R(t),n=[],o=e.body!==void 0,s=e.replace!==void 0;o&&s&&n.push("give `body` or `replace`, not both"),o&&typeof e.body!="string"&&n.push("`body` must be a string");const a=e.replace;s&&(!Array.isArray(a)||a.length===0||a.some(d=>typeof d!="object"||d===null||typeof d.old!="string"||typeof d.new!="string"))&&n.push("`replace` must be a non-empty list of {old, new} strings"),(typeof e.rationale!="string"||e.rationale.trim()==="")&&n.push("`rationale` is required"),e.verbatim!==void 0&&typeof e.verbatim!="boolean"&&n.push("`verbatim` must be a boolean"),e.base!==void 0&&(typeof e.base!="string"||e.base==="")&&n.push("`base` must be a non-empty heads key"),e.base!==void 0&&!o&&!s&&n.push("`base` applies only to a `body` or `replace` edit");const r=Z(e,n),f=e.unset??[];if(!Array.isArray(f)||f.some(d=>!H.includes(d)))n.push(`\`unset\` takes only ${H.join(", ")}`);else for(const d of f)d==="summary"&&(r.summary=null),d==="why_it_exists"&&(r.whyItExists=null),d==="unlisted"&&(r.unlisted=!1),d==="lint_ignore"&&(r.lintIgnore=null),d==="extensions"&&(r.extensions=null),d==="rules"&&(r.rules=[]);n.length===0&&!o&&!s&&Object.keys(r).length===0&&n.push("nothing to change: give `body`, `replace`, or a field"),J(n);const i=e,{dto:c,synced:h}=k(d=>{const p=E(d,t),m=x(d,p,t.params.ref),g=j(d,m),O=C(d,p,[m]);try{if(!o&&!s)return le(d,p,m,r),{dto:{id:m.id,name:g,revision:F(d,m).revision},synced:O};const w=i.base??me(d,p,m);if(s&&w!==null){const oe=F(d,m),B=I(d,m);oe.heads_key===w&&B.length===1&&Ae(pe(d,m,A(B[0].body_hash)),i.replace)}const D=i.verbatim===!0,l=o?{body:i.body,verbatim:D}:{replace:i.replace,verbatim:D},y=de(d,p,m,l,i.rationale,w,r,W(d));if("stale"in y)throw v(409,"stale_revision",`${g} changed after your read; it is now at revision ${y.stale.revision}`,`Read it again with \`crtr canvas read ${g}\`, then redo your change on the current text.`,{stale:y.stale});const T=A(I(d,m)[0].body_hash);return{dto:{id:m.id,name:g,revision:y.revision,...Q(d,p,T,y.unresolved)},synced:O}}catch(w){S(w,m)}});return N(h),c}u(je,"edit");function De(t){const e=R(t);if(e.new_name===void 0&&e.owner===void 0)throw b("give a new name, an owner, or both");if(e.new_name!==void 0&&(typeof e.new_name!="string"||!Y.test(e.new_name)))throw b("`new_name` must be segments of letters, digits, `_` or `-` joined by `/`");const{dto:n,change:o}=k(s=>{const a=E(s,t),r=x(s,a,t.params.ref),f=e.owner===void 0?void 0:M(s,a,e.owner,e.cwd);try{const i=fe(s,a,r,{...e.new_name!==void 0?{name:e.new_name}:{},...f?{owner:f}:{}});return{dto:{id:i.id,name:j(s,i)},change:C(s,a,[r,i],e.cwd)}}catch(i){S(i,r)}});return N(o),n}u(De,"move");function Re(t){const{dto:e,change:n}=k(o=>{const s=E(o,t),a=x(o,s,t.params.ref),r=j(o,a),f=C(o,s,[a]);try{ce(o,s,a,W(o))}catch(i){S(i,a)}return{dto:{id:a.id,name:r},change:f}});return N(n),e}u(Re,"remove");function Se(t){const e=t.query.get("diff"),n=e===null?void 0:Number(e);if(n!==void 0&&!(Number.isInteger(n)&&n>0))throw b("`diff` must be a revision number");return k(o=>{const s=E(o,t),a=z(o,s,decodeURIComponent(t.params.ref));if("remote"in a)throw v(404,"not_found",G(a.remote),"Check the name with `crtr canvas search`.");const r="deleted"in a?a.deleted:a;if(r.type!=="document")throw b(`${r.name} is a ${r.type}, not a document`);const f=ue(o,s,r),i={object:ke(o,r),revisions:f.map(c=>({rev_id:c.rev_id,number:c.number,author_id:c.author,rationale:c.rationale,verbatim:c.verbatim,created_at:c.created_at,parents:c.parents}))};if(n!==void 0){const c=f.find(d=>d.number===n);if(!c)throw new _(404,"not_found",`${r.name} has no revision ${n}`);const h=c.parents[0]===void 0?void 0:f.find(d=>d.rev_id===c.parents[0]);i.diff=_e(h?A(h.body_hash):"",A(c.body_hash))}return i})}u(Se,"revisionHistory");const ee=1e3,ne=1e3,te=3e3,Ce=/^When\b.+\bbecause\b.+/,Ne=u(t=>{const e=t.trim();return e===""?0:e.split(/\s+/).length},"words");function Te(t,e){if(t.some(o=>o.on==="boot"&&o.deliver==="content")&&e>ee)return`body is ${e} words, over the ${ee}-word cap for a boot rule at content (the whole body enters every node's context). Keep the core here and move separate subjects into [[linked]] documents.`;const n=[...new Set(t.filter(o=>o.on!=="boot"&&o.deliver==="content").map(o=>o.on))];return n.length>0&&e>ne?`body is ${e} words, over the ${ne}-word cap for a content rule on ${n.join("/")}. Keep the core here and move separate subjects into [[linked]] documents.`:t.some(o=>o.on==="boot"&&o.deliver==="preview")&&e>te?`body is ${e} words, over the ${te}-word cap for a boot rule at preview. Keep the core here and move separate subjects into [[linked]] documents.`:null}u(Te,"lengthFinding");function Fe(t){const e=R(t);return k(n=>{const o=E(n,t),s=e.owner===void 0?null:M(n,o,e.owner,e.cwd),a=P(n,"SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND home_machine IS NULL AND kind != 'report' ORDER BY name").all(),r=[],f=new Map;for(const i of a){if(s&&i.owner!==s.rowid||!V(n,o,i))continue;const c=F(n,i),h=new Set(c.lint_ignore??[]),d=j(n,i),p=u((l,y,T)=>{h.has(l)||r.push({name:d,severity:y,rule:l,message:T})},"add"),m=ge(n,i),g=I(n,i)[0],O=g?A(g.body_hash):"",w=Te(m,Ne(O));w&&p("length","error",w),m.some(l=>l.deliver==="preview")&&!Ce.test(i.preview??"")&&p("preview-shape","error",`a rule delivers this document at preview, so the preview must read "When <situation in the reader's work>, read this because <what the reader gains>"`);const D=new Set(P(n,"SELECT written_as FROM edges WHERE type = 'links-to' AND src = ?").all(i.rowid).map(l=>l.written_as));for(const l of K(O))D.has(l)||"remote"in X(n,o,l)||p("links","warning",`[[${l}]] names no object in your view`);if(m.some(l=>l.on==="workspace-open"&&l.deliver==="content")){const l=ae(n,i);l.type==="repo"&&!h.has("workspace-open")&&f.set(l.name,[...f.get(l.name)??[],d])}}for(const[i,c]of f)if(!(c.length<2))for(const h of c)r.push({name:h,severity:"warning",rule:"workspace-open",message:`repo ${i} has ${c.length} documents delivered at content on workspace-open (${c.join(", ")}); keep one and link the rest from it`});return{findings:r}})}u(Fe,"lint");const $=u((t,e=200)=>n=>({status:e,body:t(n)}),"ok"),Qe=[{method:"POST",pattern:"/v1/docs",handler:$(Oe,201)},{method:"PATCH",pattern:"/v1/docs/:ref",handler:$(je)},{method:"POST",pattern:"/v1/docs/:ref/move",handler:$(De)},{method:"DELETE",pattern:"/v1/docs/:ref",handler:$(Re)},{method:"GET",pattern:"/v1/docs/:ref/history",handler:$(Se)},{method:"POST",pattern:"/v1/docs/lint",handler:$(Fe)}];export{Qe as docRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var E=Object.defineProperty;var
|
|
1
|
+
var E=Object.defineProperty;var c=(n,e)=>E(n,"name",{value:e,configurable:!0});import{prepared as h}from"../../core/sqlite-statements.js";import{ApiError as d}from"../../api/index.js";import{readerFor as R}from"../../core/graph/reader.js";import{canRead as v}from"../../core/graph/access.js";import{ownersByHandle as y,resolveName as x,viewOf as F}from"../../core/graph/names.js";import{ensureOwner as $}from"../../core/graph/objects.js";import{checkoutsForCwd as N,reposForCwd as j}from"../../core/graph/repo-sync/repos.js";import{lookupProfile as L}from"../../core/profiles/manifest.js";function M(n,e){return R(n,e.principal,o=>N(n,o))}c(M,"readerFor");function T(n,e,o){const t=x(n,e,o);if("object"in t)return t.object;if("deleted"in t||"remote"in t)return t;if("ambiguous"in t){const p=t.ambiguous.map(m=>`${_(n,m)}/${m.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one object: ${p.join(", ")}`,{candidates:p,next:"Read one of them by its full `<type>:<owner>/<name>`."})}const r=o.replace(/^\s*\[\[(.*)\]\]\s*$/,"$1").trim(),i=/^(person|app|repo|profile):([^/]+)$/.exec(r),s=(i?y(n,i[2],i[1]):y(n,r).filter(p=>p.type!=="node")).filter(p=>v(n,e,p));if(s.length>0){const p=F(n,e),m=c(u=>{const f=p.findIndex(g=>g.rowid===u.rowid);return f<0?1/0:f},"rank"),w=[...s].sort((u,f)=>m(u)-m(f))[0];if(m(w)===1/0&&s.length>1){const u=s.map(f=>`${f.type}:${f.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one owner: ${u.join(", ")}`,{candidates:u,next:"Name one as `<type>:<handle>`."})}return w.deleted_at?{deleted:w}:w}const a=`'${o}' not found: no object by that name in your view`,l=`Search for it with \`crtr canvas search ${r}\`.`;throw new d(404,"not_found",a,{error:"not_found",message:a,next:l})}c(T,"resolveRef");function _(n,e){if(e.owner===null)return"";const o=h(n,"SELECT type, id, name FROM objects WHERE rowid = ?").get(e.owner);return o.type==="node"?o.id:`${o.type}:${o.name}`}c(_,"typedOwnerHandle");function U(n,e,o,t){const r=o??(e.class==="node"?"node":e.class==="person"?"user":"app"),i=c(s=>new d(400,"invalid_owner",s,{next:"Run `crtr doc write --owner -h`."}),"refuse");if(r==="node"){if(e.class!=="node")throw i("`--owner node` needs a node; you are not running as one");return e.node}if(r==="user")return $(n,"person","local-user","user:local","user");if(r==="app"){if(e.class==="person")throw i("`--owner app` needs an app; a person has none \u2014 use `--owner user`");return e.app}if(r==="profile"){if(e.class!=="node"||!e.profile)throw i("`--owner profile` needs a profile; you have none");return e.profile}if(r==="repo"){const s=t?j(n,t):[],a=s[0]?s:e.class==="node"?e.repos:[];if(!a[0])throw i(`\`--owner repo\` needs a repo; ${t??(e.class==="node"?e.cwd:"your directory")} is not inside one`);return a[0]}if(r.startsWith("repo:"))return S(n,"repo",r.slice(5),i);if(r.startsWith("profile:")){const s=r.slice(8),a=h(n,"SELECT * FROM objects WHERE type = 'profile' AND name = ? AND home_machine IS NULL").get(s);if(a)return a;const l=L(s);if(l.kind!=="resolved")throw i(`no profile named '${s}'`);const p=e.class==="person"?e.person:e.app;return $(n,"profile","profile",l.entry.profileId,l.entry.manifest.name,p)}throw i(`unknown --owner value '${r}'`)}c(U,"ownerFromFlag");function S(n,e,o,t){const r=h(n,"SELECT * FROM objects WHERE type = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,o);if(!r)throw t(`no ${e} named '${o}'`);return r}c(S,"namedOwner");export{U as ownerFromFlag,M as readerFor,T as resolveRef};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.498",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
"license": "UNLICENSED",
|
|
140
140
|
"dependencies": {
|
|
141
|
-
"@north-light/identity": "0.3.
|
|
141
|
+
"@north-light/identity": "0.3.498",
|
|
142
142
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
143
143
|
"@earendil-works/pi-ai": "1.1.0",
|
|
144
144
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.498",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.498",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "1.1.0",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
20
20
|
"@earendil-works/pi-tui": "1.1.0",
|
|
21
|
-
"@north-light/identity": "0.3.
|
|
21
|
+
"@north-light/identity": "0.3.498",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -12116,17 +12116,17 @@
|
|
|
12116
12116
|
},
|
|
12117
12117
|
"packages/crouter-api": {
|
|
12118
12118
|
"name": "@north-light/api",
|
|
12119
|
-
"version": "0.3.
|
|
12119
|
+
"version": "0.3.498",
|
|
12120
12120
|
"license": "UNLICENSED"
|
|
12121
12121
|
},
|
|
12122
12122
|
"packages/crouter-env-docker": {
|
|
12123
12123
|
"name": "@north-light/env-docker",
|
|
12124
|
-
"version": "0.3.
|
|
12124
|
+
"version": "0.3.498",
|
|
12125
12125
|
"license": "UNLICENSED"
|
|
12126
12126
|
},
|
|
12127
12127
|
"packages/crouter-identity": {
|
|
12128
12128
|
"name": "@north-light/identity",
|
|
12129
|
-
"version": "0.3.
|
|
12129
|
+
"version": "0.3.498",
|
|
12130
12130
|
"license": "UNLICENSED",
|
|
12131
12131
|
"dependencies": {
|
|
12132
12132
|
"jose": "^6.2.1"
|
|
@@ -12134,20 +12134,20 @@
|
|
|
12134
12134
|
},
|
|
12135
12135
|
"packages/crouter-plugin": {
|
|
12136
12136
|
"name": "@north-light/plugin",
|
|
12137
|
-
"version": "0.3.
|
|
12137
|
+
"version": "0.3.498",
|
|
12138
12138
|
"license": "UNLICENSED",
|
|
12139
12139
|
"dependencies": {
|
|
12140
|
-
"@north-light/api": "0.3.
|
|
12141
|
-
"@north-light/identity": "0.3.
|
|
12140
|
+
"@north-light/api": "0.3.498",
|
|
12141
|
+
"@north-light/identity": "0.3.498"
|
|
12142
12142
|
}
|
|
12143
12143
|
},
|
|
12144
12144
|
"packages/crouter-sdk": {
|
|
12145
12145
|
"name": "@north-light/sdk",
|
|
12146
|
-
"version": "0.3.
|
|
12146
|
+
"version": "0.3.498",
|
|
12147
12147
|
"license": "UNLICENSED",
|
|
12148
12148
|
"dependencies": {
|
|
12149
|
-
"@north-light/api": "0.3.
|
|
12150
|
-
"@north-light/identity": "0.3.
|
|
12149
|
+
"@north-light/api": "0.3.498",
|
|
12150
|
+
"@north-light/identity": "0.3.498",
|
|
12151
12151
|
"jose": "^6.2.1"
|
|
12152
12152
|
},
|
|
12153
12153
|
"bin": {
|