nemar-cli 0.9.10-dev.2136 → 0.9.10-dev.2140
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/index.js +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -102,7 +102,7 @@ ${u.dim(`eta: ${e.eta}`)}`:"";process.stderr.write(`${t}
|
|
|
102
102
|
${r} ${e.message}
|
|
103
103
|
${n}${i}
|
|
104
104
|
${t}
|
|
105
|
-
`)}var Sz=!1;var nD=A(()=>{He()});var Cz;var $z=A(()=>{Cz={name:"nemar-cli",version:"0.9.10-dev.2136",description:"CLI for NEMAR (Neuroelectromagnetic Data Archive and Tools Resource) dataset management",type:"module",main:"dist/index.js",bin:{nemar:"dist/index.js"},scripts:{dev:"bun run src/index.ts",build:"bun build src/index.ts --outdir dist --target bun --minify && sed '1s|#!/usr/bin/env node|#!/usr/bin/env bun|' dist/index.js > dist/index.js.tmp && mv dist/index.js.tmp dist/index.js",test:"bun test",lint:"biome check src/","lint:fix":"biome check --fix src/",format:"biome format --write src/",typecheck:"tsc --noEmit && tsc --noEmit -p backend",prepublishOnly:"bun run build",prepare:"husky",postinstall:"bun scripts/postinstall-check.mjs",deploy:"wrangler deploy",preview:"wrangler dev"},keywords:["nemar","bids","neuroimaging","eeg","emg","datalad","cli"],author:"NEMAR Team",license:"CC-BY-NC-ND-4.0",repository:{type:"git",url:"git+https://github.com/nemarOrg/nemar-cli.git"},bugs:{url:"https://github.com/nemarOrg/nemar-cli/issues"},homepage:"https://docs.nemar.org",engines:{bun:">=1.0.0"},files:["dist","scripts/postinstall-check.mjs","README.md","LICENSE"],dependencies:{chalk:"^5.3.0",commander:"^12.1.0",conf:"^13.0.1","fuse.js":"^7.1.0",inquirer:"^9.2.15",ora:"^8.0.1",zod:"^3.23.8"},"lint-staged":{"src/**/*.{ts,tsx}":["biome check --fix"],"backend/src/**/*.{ts,tsx}":["biome check --fix"]},devDependencies:{"@biomejs/biome":"1.9.4","@types/bcryptjs":"^3.0.0","@types/bun":"latest","@types/inquirer":"^9.0.7",ajv:"^8.20.0","ajv-formats":"^3.0.1",bcryptjs:"^3.0.3",husky:"^9.1.7","lint-staged":"^16.3.2",typescript:"^5.5.4",wrangler:"^4.70.0",yaml:"^2.8.4"}}});var To;var Om=A(()=>{$z();To=Cz.version});function V(e){if(e instanceof Error)return e.message;return String(e)}var q,No;var er=A(()=>{q=class q extends Error{statusCode;details;step;constructor(e,t,r,n){super(t);this.statusCode=e;this.details=r;this.step=n;this.name="ApiError"}};No=class No extends q{mode;eta;constructor(e,t,r,n){super(503,t,n);this.mode=e;this.eta=r;this.name="MaintenanceError"}}});function Fz(){if(process.env.TEST_API_URL)return process.env.TEST_API_URL;if(sD)return iD;return ht().apiUrl||iD}async function I(e,t={},r=!1,n){let i=`${Fz()}${e}`,s={"Content-Type":"application/json","X-CLI-Version":To,...t.headers};if(r){let c=ht();if(!c.apiKey&&r===!0)throw new q(401,"Not authenticated. Run 'nemar auth login' first.");if(c.apiKey)s.Authorization=`Bearer ${c.apiKey}`}let o;try{o=await fetch(i,{...t,headers:s})}catch(c){throw new q(0,`Network error: Could not connect to ${Fz()}`,{originalError:c instanceof Error?c.message:String(c)})}let a;try{a=await o.json()}catch{throw new q(o.status,`Invalid response from server (status ${o.status})`)}if(!o.ok){if(o.status===503&&(a.mode==="read-only"||a.mode==="full")){let c=typeof a.message==="string"?a.message:"NEMAR is in maintenance mode. Please retry shortly.",l=typeof a.eta==="string"?a.eta:null,d=new No(a.mode,c,l,a.details);throw Rm(d),d}throw new q(o.status,a.error||a.message||"Request failed",a.details,typeof a.step==="string"?a.step:void 0)}if(n){let c=n.safeParse(a);if(!c.success)throw new q(o.status,`Response for ${e} did not match the expected NEMAR contract`,{issues:c.error.issues});return c.data}return a}var iD="https://nemar-api-dev.sccn-org.workers.dev",sD;var Ns=A(()=>{Ts();nD();Om();er();sD=iD.includes("workers.dev")});async function Rz(e,t){let r=new URLSearchParams;if(e)r.set("status",e);if(t)r.set("role",t);let n=r.toString()?`?${r.toString()}`:"";return I(`/admin/users${n}`,{},!0)}async function Oz(e){return I(`/admin/approve/${e}`,{method:"POST"},!0)}async function Az(e){return I(`/admin/approve/by-id/${e}`,{method:"POST"},!0)}async function kz(e){return I(`/admin/revoke/${e}`,{method:"POST"},!0)}async function Pz(e,t){return I(`/admin/users/${e}/role`,{method:"POST",body:JSON.stringify({role:t})},!0)}async function oD(e,t){return I(`/admin/datasets/${e}/visibility`,{method:"PATCH",body:JSON.stringify({visibility:t})},!0)}async function Iz(e){return I(`/datasets/${e}/publish`,{method:"POST"},!0)}async function Tz(e){return I(`/admin/datasets/${e}/ci`,{},!0)}async function Ai(e){return I(`/admin/datasets/${e}/ci`,{method:"POST"},!0)}async function aD(e){return I(`/admin/datasets/${e}/ci/validate`,{method:"POST"},!0)}async function cD(e){return I(`/admin/datasets/${e}/ci/sync`,{method:"POST"},!0)}async function Nz(e,t){return I(`/admin/datasets/${e}/doi/concept`,{method:"POST",body:JSON.stringify(t)},!0)}async function vd(e){return I(`/admin/datasets/${e}/doi`,{},!0)}async function uD(e,t){return I(`/admin/datasets/${e}/doi/update`,{method:"POST",body:JSON.stringify(t)},!0)}async function qz(e,t){return I(`/admin/datasets/${e}/withdraw`,{method:"POST",body:JSON.stringify({reason:t.reason,dry_run:t.dryRun})},!0)}async function jz(e,t){return I(`/admin/datasets/${e}/restore`,{method:"POST",body:JSON.stringify({dry_run:t.dryRun})},!0)}async function Mz(e){return I(`/admin/datasets/${e}/reset`,{method:"POST"},!0)}async function Bz(e,t=!1){return I(`/admin/datasets/${e}`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({force:t})},!0)}async function Lz(e){return I("/admin/datasets/bulk-delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({dataset_ids:e})},!0)}async function Uz(e){return I("/admin/datasets/import",{method:"POST",body:JSON.stringify(e)},!0)}async function Vz(e){return I("/admin/datasets/exemplar",{method:"POST",body:JSON.stringify(e)},!0)}async function zz(e){return I(`/admin/datasets/${e}/exemplar/remint-dois`,{method:"POST"},!0)}async function lD(e,t){let r=new URLSearchParams;if(e)r.set("status",e);if(t!==void 0)r.set("blocklisted",t?"1":"0");let n=r.toString();return I(`/admin/imports${n?`?${n}`:""}`,{},!0)}async function Hz(e){return I(`/admin/imports/${e}/rollback`,{method:"POST"},!0)}async function Wz(e){return I(`/admin/imports/${e}/retry`,{method:"POST"},!0)}async function dD(e){return I(`/admin/imports/${e}/verify`,{method:"POST"},!0)}async function Gz(e){return I("/admin/imports/dispatch-cooldown",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({dataset_ids:e})},!0)}async function qc(e,t){return I(`/admin/datasets/${e}/reindex`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t??{})},!0)}async function Kz(e,t){return I("/admin/datasets/reindex/bulk",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filter:e,...t??{}})},!0)}async function Yz(e){let t=e?.limit??15;return I(`/admin/datasets/hed-sweep?limit=${encodeURIComponent(String(t))}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Jz(){return I("/admin/datasets/hed-sweep?reset=1",{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Xz(e){let t=e?.limit??15,r=new URLSearchParams({limit:String(t)});if(e?.olderThan!=null)r.set("older-than",String(e.olderThan));if(e?.before!=null)r.set("before",e.before);return I(`/admin/datasets/data-integrity-sweep?${r.toString()}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Qz(){return I("/admin/datasets/data-integrity-sweep?reset=1",{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Zz(e,t){let r=t?.write?"":"?dry_run=1";return I(`/admin/datasets/${e}/availability-report${r}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function eH(e){let t=e?.limit??30,r=new URLSearchParams({limit:String(t)});if(e?.missingOnly)r.set("missing-only","1");return I(`/admin/datasets/availability-report-sweep?${r.toString()}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function tH(){return I("/admin/datasets/availability-report-sweep?reset=1",{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function rH(e){let t=new URLSearchParams;if(e?.prefix)t.set("prefix",e.prefix);if(e?.visibility)t.set("visibility",e.visibility);if(e?.limit)t.set("limit",String(e.limit));let r=t.toString()?`?${t.toString()}`:"";return I(`/admin/fleet/drift${r}`,{},!0)}async function jc(e,t){return I(`/admin/datasets/${e}/enforce`,{method:"POST",body:JSON.stringify({dry_run:t})},!0)}async function nH(e){return I("/admin/datasets/enforce/bulk",{method:"POST",body:JSON.stringify({prefix:e.prefix,visibility:e.visibility,limit:e.limit,dry_run:e.dryRun})},!0)}async function iH(e,t=!1){return I(`/admin/datasets/${e}/revalidate${t?"?force=true":""}`,{method:"POST"},!0)}async function sH(e){let t=e?`?user=${encodeURIComponent(e)}`:"";return I(`/admin/email-preferences${t}`,{},!0)}async function oH(e,t){let r=t?`?user=${encodeURIComponent(t)}`:"";return I(`/admin/email-preferences${r}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)},!0)}async function fD(e){return I("/admin/notify",{method:"POST",body:JSON.stringify(e)},!0)}async function aH(){return I("/admin/summary/coverage",{},!0)}async function cH(e,t,r){return I("/admin/manifest/dispatch",{method:"POST",body:JSON.stringify({dataset_id:e,version:t,skip_canary:r?.skipCanary??!1})},!0)}async function pD(e){return I("/admin/doctor/scan",{method:"POST",body:JSON.stringify({...e?.check&&{check:e.check},...e?.datasetId&&{dataset_id:e.datasetId}})},!0)}async function mD(e){return I("/admin/doctor/fix",{method:"POST",body:JSON.stringify({check:e.check,...e.datasetId&&{dataset_id:e.datasetId},...e.dryRun&&{dry_run:!0}})},!0)}var Mc=A(()=>{Ns()});async function ti(e,t){return I(`/datasets/${e}/upload-credentials`,{method:"POST",body:JSON.stringify({duration_seconds:t})},!0)}async function hD(e,t){return I(`/datasets/${e}/download-credentials`,{method:"POST",body:JSON.stringify({duration_seconds:t})},!0)}async function uH(e){return I(`/admin/datasets/${e}/files`,{},!0)}async function lH(e){let t,r=0,n=[],i=!0;while(i){let s=await I(`/admin/datasets/${e}/s3-lock`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({continuation_token:t})},!0);if(r+=s.locked,s.failed?.length)n.push(...s.failed);if(i=s.hasMore,t=s.continuation_token,i&&!t)throw new q(500,"S3 lock paginated response missing continuation_token; aborting to avoid infinite loop")}return{locked:r,failed:n}}var Bc=A(()=>{Ns();er()});function GIe(e){return e.startsWith("v")?e:`v${e}`}var HIe,WIe,dH,aQe;var gD=A(()=>{Ic();HIe=/^v?\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\d*)?$/,WIe=/^v\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\d*)?$/;dH=S.string().regex(HIe,"must be a semver version, optionally v-prefixed").transform(GIe),aQe=S.string().regex(WIe,"must be the canonical v-prefixed tag (vX.Y.Z)")});var KIe,YIe,fH;var pH=A(()=>{Ic();KIe=S.object({id:S.number().int(),username:S.string().nullable(),email:S.string(),github_username:S.string().nullable(),role:S.string(),orcid:S.string().nullable().optional(),created_at:S.string().optional(),approved_at:S.string().nullable().optional(),dataset_count:S.number().int().optional(),sandbox_completed:S.boolean().optional(),sandbox_completed_at:S.string().nullable().optional(),sandbox_dataset_id:S.string().nullable().optional()}).passthrough(),YIe=S.object({prefix:S.string(),created_at:S.string(),last_used_at:S.string().nullable()}).passthrough().nullable(),fH=S.object({user:KIe,token:YIe.optional()}).passthrough()});var JIe="0.4.0",yD,_d,mH,XIe,QIe,hH,pQe,gH,mQe,ki,ZIe,Am,hQe;var xD=A(()=>{Ic();gD();yD=S.enum(["openneuro","nemar","gin","other"]),_d=S.union([S.literal(0),S.literal(1)]).nullable(),mH=S.object({dataset_id:S.string(),id:S.string().optional(),name:S.string(),description:S.string().nullable().optional(),status:S.string(),visibility:S.string(),concept_doi:S.string().nullable().optional(),doi:S.string().nullable().optional(),created_at:S.string(),updated_at:S.string().optional(),owner_username:S.string().nullable().optional(),source:S.string().nullable().optional(),modalities:S.string().optional(),participants:S.number().int().nonnegative(),tasks:S.string().optional(),authors:S.string().optional(),license:S.string().optional(),file_size:S.number().nonnegative(),file_size_formatted:S.string().optional(),total_files:S.number().nonnegative().nullable().optional(),num_citations:S.number().int().nonnegative().optional(),n_channels:S.number().int().nullable().optional(),electrode_system:S.string().nullable().optional(),has_hed:_d.optional(),hed_version:S.string().nullable().optional(),data_complete:_d.optional(),bytes_present:S.number().nonnegative().nullable().optional(),latest_version:dH.nullable().optional(),subject_count:S.number().int().nullable().optional(),file_size_bytes:S.number().nullable().optional(),sessions_count:S.number().int().nullable().optional(),age_min:S.number().nullable().optional(),age_max:S.number().nullable().optional(),bids_version:S.string().nullable().optional(),zarr_status:S.enum(["pending","ready","failed"]).nullable().optional(),total_recording_duration:S.number().nullable().optional(),recording_duration_min:S.number().nullable().optional(),recording_duration_max:S.number().nullable().optional(),recording_count:S.number().int().nullable().optional(),recordings_unavailable:S.number().int().nullable().optional(),channel_count_min:S.number().int().nullable().optional(),channel_count_max:S.number().int().nullable().optional(),sampling_frequency:S.number().nullable().optional(),power_line_frequency:S.number().nullable().optional(),eeg_reference:S.string().nullable().optional(),placement_scheme:S.string().nullable().optional()}).passthrough(),XIe=mH.extend({file_size:S.number().nonnegative().nullable(),modalities:S.string().nullable().optional(),tasks:S.string().nullable().optional(),authors:S.string().nullable().optional(),license:S.string().nullable().optional(),owner_github:S.string().nullable().optional(),attestation_deposit_type:S.enum(["owner","redistribution"]).nullable().optional(),attestation_key_status:S.enum(["destroyed","retained"]).nullable().optional(),attestation_deidentified:_d.optional(),attestation_no_duplicate:_d.optional(),attestation_upstream_source:S.string().nullable().optional(),attestation_accepted_at:S.string().nullable().optional()}).passthrough(),QIe=S.object({id:S.string(),name:S.string(),modalities:S.string().nullable().optional(),participants:S.number().int().nullable().optional(),doi:S.string().nullable().optional(),tasks:S.string().nullable().optional(),authors:S.string().nullable().optional(),has_hed:_d.optional(),score:S.number().optional(),snippet:S.string().optional()}).passthrough(),hH=S.record(S.string(),S.number().int().nonnegative()),pQe=S.object({datasets:S.array(mH),count:S.number().int().nonnegative(),total_count:S.number().int().nonnegative().optional(),limit:S.number().int().optional(),offset:S.number().int().optional(),excluded_unknown:S.number().int().nonnegative().optional(),excluded_unknown_by_facet:hH.optional()}).passthrough(),gH=S.object({results:S.array(QIe),count:S.number().int().nonnegative(),returned:S.number().int().nonnegative().optional(),offset:S.number().int().nonnegative().optional(),limit:S.number().int().optional(),candidate_ceiling:S.number().int().optional(),truncated:S.boolean().optional(),method:S.enum(["exact_id","text","text_fallback","semantic","unavailable"]).optional(),min_score:S.number().optional(),warning:S.string().optional(),excluded_unknown:S.number().int().nonnegative().optional(),excluded_unknown_by_facet:hH.optional()}).passthrough(),mQe=S.object({dataset:XIe}).passthrough(),ki=S.object({value:S.string(),count:S.number().int().nonnegative()}),ZIe=S.object({values:S.array(ki),distinct_total:S.number().int().nonnegative(),truncated:S.boolean()}),Am=S.object({"electrode-system":S.array(ki).optional(),source:S.array(ki).optional(),zarr:S.array(ki).optional(),powerline:S.array(ki).optional(),"bids-version":S.array(ki).optional(),"hed-version":S.array(ki).optional(),license:S.array(ki).optional(),modality:S.array(ki).optional(),task:ZIe.optional(),warning:S.string().optional()}).passthrough(),hQe=S.object({schema_version:S.literal(JIe),doc_type:S.literal("dataset"),dataset_id:S.string().regex(/^[a-z]{2}\d+$/,"neuroschema dataset_id pattern"),name:S.string(),source:yD,recording_modality:S.array(S.string()).min(1),description:S.string().nullable().optional(),bids_version:S.string().nullable().optional(),license:S.string().nullable().optional()}).passthrough()});var km=A(()=>{gD();pH();xD()});async function Im(e){return I(`/datasets/${e}/ci/status`,{},!0)}async function yH(e){return I(`/datasets/${e}/manifest`,{},!0)}async function Tm(e,t){return I(`/datasets/${e}/manifest/${t}`,{},!0)}function xH(e){let t=e;if(!t.status)t.status="active";else if(!["active","archived","deleted"].includes(t.status))throw Error(`Invalid dataset status: ${t.status}`);if(!t.visibility)t.visibility="private";else if(!["public","private"].includes(t.visibility))throw Error(`Invalid dataset visibility: ${t.visibility}`);return t}async function Lc(e={}){let t=new URLSearchParams;if(e.mine)t.set("mine","true");if(e.search)t.set("search",e.search);if(e.modality)t.set("modality",e.modality);if(e.author)t.set("author",e.author);if(e.task)t.set("task",e.task);if(e.license)t.set("license",e.license);if(e.hasDoi)t.set("has_doi","true");if(e.hasHed)t.set("has_hed","1");if(e.dataComplete)t.set("data_complete","1");if(e.recent)t.set("recent",String(e.recent));if(e.sort)t.set("sort",e.sort);if(e.limit!=null)t.set("limit",String(e.limit));if(e.offset!=null)t.set("offset",String(e.offset));if(e.owner)t.set("owner",e.owner);if(e.facets)for(let[i,s]of Object.entries(e.facets))t.set(i,s);if(e.includeUnknown)t.set("include_unknown","1");let r=t.toString()?`?${t.toString()}`:"",n=await I(`/datasets${r}`,{},e.mine?!0:"optional");return n.datasets=n.datasets.map(xH),n}async function bH(e){return I(`/datasets/resolve/${e}`,{},"optional")}async function vH(){return I("/datasets/facets",{signal:AbortSignal.timeout(5000)},"optional",Am)}async function _H(e,t={}){let r=new URLSearchParams({q:e});if(t.modality)r.set("modality",t.modality);if(t.limit)r.set("limit",String(t.limit));if(t.hasHed)r.set("has_hed","1");if(t.author)r.set("author",t.author);if(t.task)r.set("task",t.task);if(t.license)r.set("license",t.license);if(t.hasDoi)r.set("has_doi","true");if(t.dataComplete)r.set("data_complete","1");if(t.recent)r.set("recent",String(t.recent));if(t.facets)for(let[i,s]of Object.entries(t.facets))r.set(i,s);if(t.includeUnknown)r.set("include_unknown","1");return await I(`/datasets/search?${r.toString()}`,{},"optional",gH)}async function gt(e){let t=await I(`/datasets/${e}`,{},"optional");return xH(t.dataset)}async function DH(e){return I(`/datasets/${e}/versions`,{},!0)}async function Nm(e){return I("/datasets",{method:"POST",body:JSON.stringify(e)},!0)}async function qm(e){return I(`/datasets/${e}/finalize`,{method:"POST"},!0)}async function bD(e){return I(`/datasets/${e}/request-access`,{method:"POST"},!0)}async function wH(e,t){let r=t?`?status=${t}`:"";return I(`/datasets/${e}/access-requests${r}`,{},!0)}async function EH(e,t){return I(`/datasets/${e}/access-requests/${t}/approve`,{method:"POST"},!0)}async function SH(e,t){return I(`/datasets/${e}/access-requests/${t}/deny`,{method:"POST"},!0)}async function $H(e,t){return I(`/datasets/${e}/invite`,{method:"POST",body:JSON.stringify({username:t})},!0)}async function CH(e){return I(`/datasets/${e}/collaborators`,{},!0)}async function FH(e,t){return I(`/admin/datasets/${e}/enrichment`,{method:"POST",body:JSON.stringify(t)},!0)}var Pm;var qs=A(()=>{km();Ns();Pm=/^\d{4}-\d{4}-\d{4}-\d{3}[\dX]$/});var Uc;var PH=A(()=>{Uc=["ci_check","enrichment_check","s3_public_read","repo_public","tag_protect","doi_create","update_metadata","update_readme","create_tag","create_release","upload_to_zenodo","publish_doi","version_doi","s3_lock","sync_nemar","notify_user"]});async function Vc(e){return I(`/datasets/${e}/publish/request`,{method:"POST"},!0)}async function TH(e){return I(`/datasets/${e}/publish/status`,{},!0)}async function NH(e){return I(`/datasets/${e}/publish/resend`,{method:"POST"},!0)}async function qH(e){let t=e?`?status=${e}`:"";return I(`/admin/publish/requests${t}`,{},!0)}async function jH(e,t){return I(`/admin/publish/${e}/deny`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:t})},!0)}function eTe(e,t=[]){if(e){let r=Uc.indexOf(e);if(r>=0)return r+1}return Math.min(t.length+1,Uc.length)}function tTe(e){if(!(e instanceof q))return!1;if(e.statusCode===0)return!0;if(e.statusCode===429)return!0;if(e.statusCode>=500&&e.statusCode<600)return!0;if(e.statusCode===403&&/repository has been locked/i.test(e.message))return!0;return!1}async function zc(e,t=!1,r=!1,n=!1,i,s){let c,l,d=0,f=!1,m,p=t,g=[],y;function x(v,_,E,C){if(!s)return;s({step:v,stepIndex:eTe(v,_),stepTotal:Uc.length,s3LockLocked:E,s3LockTotal:C,s3LockResumed:v==="s3_lock"&&f?!0:void 0})}for(let v=1;v<=5;v++)try{let _,E=!0;do{if(_=await I(`/admin/publish/${e}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resume:E?p:!0,sandbox:r,s3_lock_continuation_token:c,s3_lock_total:l,skip_ci_check:n})},!0),E=!1,_.step_results)g.push(..._.step_results);if(_.s3_lock_total!==void 0)l=_.s3_lock_total;if(_.s3_lock_batch_count!==void 0)d+=_.s3_lock_batch_count;let C=_.step??_.step_results?.[_.step_results.length-1]?.step;if(C&&(C!==m||C==="s3_lock"))x(C,_.steps_completed??[],C==="s3_lock"?d:void 0,C==="s3_lock"?l:void 0),m=C;if(_.hasMore&&_.s3_lock_continuation_token!==void 0)c=_.s3_lock_continuation_token;else break}while(_.hasMore);if(g.length>0)_.step_results=IH(g);return _}catch(_){if(y=_,v===5||!tTe(_)){if(_ instanceof q&&g.length>0)_.stepResults=IH(g);throw _}let C=_;if(i?.({attempt:v,maxAttempts:5,delayMs:1e4,step:C.step,error:C.message}),await new Promise((D)=>setTimeout(D,1e4)),p=!0,c!==void 0)f=!0}throw y}function IH(e){let t=new Map;for(let r of e)t.set(r.step,r);return Array.from(t.values())}var Dd=A(()=>{PH();Ns();er()});function LH(e){DD=e}function wD(){return DD}function wd(e){if(DD)process.stderr.write(`${e}
|
|
105
|
+
`)}var Sz=!1;var nD=A(()=>{He()});var Cz;var $z=A(()=>{Cz={name:"nemar-cli",version:"0.9.10-dev.2140",description:"CLI for NEMAR (Neuroelectromagnetic Data Archive and Tools Resource) dataset management",type:"module",main:"dist/index.js",bin:{nemar:"dist/index.js"},scripts:{dev:"bun run src/index.ts",build:"bun build src/index.ts --outdir dist --target bun --minify && sed '1s|#!/usr/bin/env node|#!/usr/bin/env bun|' dist/index.js > dist/index.js.tmp && mv dist/index.js.tmp dist/index.js",test:"bun test",lint:"biome check src/","lint:fix":"biome check --fix src/",format:"biome format --write src/",typecheck:"tsc --noEmit && tsc --noEmit -p backend",prepublishOnly:"bun run build",prepare:"husky",postinstall:"bun scripts/postinstall-check.mjs",deploy:"wrangler deploy",preview:"wrangler dev"},keywords:["nemar","bids","neuroimaging","eeg","emg","datalad","cli"],author:"NEMAR Team",license:"CC-BY-NC-ND-4.0",repository:{type:"git",url:"git+https://github.com/nemarOrg/nemar-cli.git"},bugs:{url:"https://github.com/nemarOrg/nemar-cli/issues"},homepage:"https://docs.nemar.org",engines:{bun:">=1.0.0"},files:["dist","scripts/postinstall-check.mjs","README.md","LICENSE"],dependencies:{chalk:"^5.3.0",commander:"^12.1.0",conf:"^13.0.1","fuse.js":"^7.1.0",inquirer:"^9.2.15",ora:"^8.0.1",zod:"^3.23.8"},"lint-staged":{"src/**/*.{ts,tsx}":["biome check --fix"],"backend/src/**/*.{ts,tsx}":["biome check --fix"]},devDependencies:{"@biomejs/biome":"1.9.4","@types/bcryptjs":"^3.0.0","@types/bun":"latest","@types/inquirer":"^9.0.7",ajv:"^8.20.0","ajv-formats":"^3.0.1",bcryptjs:"^3.0.3",husky:"^9.1.7","lint-staged":"^16.3.2",typescript:"^5.5.4",wrangler:"^4.70.0",yaml:"^2.8.4"}}});var To;var Om=A(()=>{$z();To=Cz.version});function V(e){if(e instanceof Error)return e.message;return String(e)}var q,No;var er=A(()=>{q=class q extends Error{statusCode;details;step;constructor(e,t,r,n){super(t);this.statusCode=e;this.details=r;this.step=n;this.name="ApiError"}};No=class No extends q{mode;eta;constructor(e,t,r,n){super(503,t,n);this.mode=e;this.eta=r;this.name="MaintenanceError"}}});function Fz(){if(process.env.TEST_API_URL)return process.env.TEST_API_URL;if(sD)return iD;return ht().apiUrl||iD}async function I(e,t={},r=!1,n){let i=`${Fz()}${e}`,s={"Content-Type":"application/json","X-CLI-Version":To,...t.headers};if(r){let c=ht();if(!c.apiKey&&r===!0)throw new q(401,"Not authenticated. Run 'nemar auth login' first.");if(c.apiKey)s.Authorization=`Bearer ${c.apiKey}`}let o;try{o=await fetch(i,{...t,headers:s})}catch(c){throw new q(0,`Network error: Could not connect to ${Fz()}`,{originalError:c instanceof Error?c.message:String(c)})}let a;try{a=await o.json()}catch{throw new q(o.status,`Invalid response from server (status ${o.status})`)}if(!o.ok){if(o.status===503&&(a.mode==="read-only"||a.mode==="full")){let c=typeof a.message==="string"?a.message:"NEMAR is in maintenance mode. Please retry shortly.",l=typeof a.eta==="string"?a.eta:null,d=new No(a.mode,c,l,a.details);throw Rm(d),d}throw new q(o.status,a.error||a.message||"Request failed",a.details,typeof a.step==="string"?a.step:void 0)}if(n){let c=n.safeParse(a);if(!c.success)throw new q(o.status,`Response for ${e} did not match the expected NEMAR contract`,{issues:c.error.issues});return c.data}return a}var iD="https://nemar-api-dev.sccn-org.workers.dev",sD;var Ns=A(()=>{Ts();nD();Om();er();sD=iD.includes("workers.dev")});async function Rz(e,t){let r=new URLSearchParams;if(e)r.set("status",e);if(t)r.set("role",t);let n=r.toString()?`?${r.toString()}`:"";return I(`/admin/users${n}`,{},!0)}async function Oz(e){return I(`/admin/approve/${e}`,{method:"POST"},!0)}async function Az(e){return I(`/admin/approve/by-id/${e}`,{method:"POST"},!0)}async function kz(e){return I(`/admin/revoke/${e}`,{method:"POST"},!0)}async function Pz(e,t){return I(`/admin/users/${e}/role`,{method:"POST",body:JSON.stringify({role:t})},!0)}async function oD(e,t){return I(`/admin/datasets/${e}/visibility`,{method:"PATCH",body:JSON.stringify({visibility:t})},!0)}async function Iz(e){return I(`/datasets/${e}/publish`,{method:"POST"},!0)}async function Tz(e){return I(`/admin/datasets/${e}/ci`,{},!0)}async function Ai(e){return I(`/admin/datasets/${e}/ci`,{method:"POST"},!0)}async function aD(e){return I(`/admin/datasets/${e}/ci/validate`,{method:"POST"},!0)}async function cD(e){return I(`/admin/datasets/${e}/ci/sync`,{method:"POST"},!0)}async function Nz(e,t){return I(`/admin/datasets/${e}/doi/concept`,{method:"POST",body:JSON.stringify(t)},!0)}async function vd(e){return I(`/admin/datasets/${e}/doi`,{},!0)}async function uD(e,t){return I(`/admin/datasets/${e}/doi/update`,{method:"POST",body:JSON.stringify(t)},!0)}async function qz(e,t){return I(`/admin/datasets/${e}/withdraw`,{method:"POST",body:JSON.stringify({reason:t.reason,dry_run:t.dryRun})},!0)}async function jz(e,t){return I(`/admin/datasets/${e}/restore`,{method:"POST",body:JSON.stringify({dry_run:t.dryRun})},!0)}async function Mz(e){return I(`/admin/datasets/${e}/reset`,{method:"POST"},!0)}async function Bz(e,t=!1){return I(`/admin/datasets/${e}`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({force:t})},!0)}async function Lz(e){return I("/admin/datasets/bulk-delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({dataset_ids:e})},!0)}async function Uz(e){return I("/admin/datasets/import",{method:"POST",body:JSON.stringify(e)},!0)}async function Vz(e){return I("/admin/datasets/exemplar",{method:"POST",body:JSON.stringify(e)},!0)}async function zz(e){return I(`/admin/datasets/${e}/exemplar/remint-dois`,{method:"POST"},!0)}async function lD(e,t){let r=new URLSearchParams;if(e)r.set("status",e);if(t!==void 0)r.set("blocklisted",t?"1":"0");let n=r.toString();return I(`/admin/imports${n?`?${n}`:""}`,{},!0)}async function Hz(e){return I(`/admin/imports/${e}/rollback`,{method:"POST"},!0)}async function Wz(e){return I(`/admin/imports/${e}/retry`,{method:"POST"},!0)}async function dD(e){return I(`/admin/imports/${e}/verify`,{method:"POST"},!0)}async function Gz(e){return I("/admin/imports/dispatch-cooldown",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({dataset_ids:e})},!0)}async function qc(e,t){return I(`/admin/datasets/${e}/reindex`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t??{})},!0)}async function Kz(e,t){return I("/admin/datasets/reindex/bulk",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filter:e,...t??{}})},!0)}async function Yz(e){let t=e?.limit??15;return I(`/admin/datasets/hed-sweep?limit=${encodeURIComponent(String(t))}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Jz(){return I("/admin/datasets/hed-sweep?reset=1",{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Xz(e){let t=e?.limit??15,r=new URLSearchParams({limit:String(t)});if(e?.olderThan!=null)r.set("older-than",String(e.olderThan));if(e?.before!=null)r.set("before",e.before);return I(`/admin/datasets/data-integrity-sweep?${r.toString()}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Qz(){return I("/admin/datasets/data-integrity-sweep?reset=1",{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function Zz(e,t){let r=t?.write?"":"?dry_run=1";return I(`/admin/datasets/${e}/availability-report${r}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function eH(e){let t=e?.limit??30,r=new URLSearchParams({limit:String(t)});if(e?.missingOnly)r.set("missing-only","1");return I(`/admin/datasets/availability-report-sweep?${r.toString()}`,{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function tH(){return I("/admin/datasets/availability-report-sweep?reset=1",{method:"POST",headers:{"Content-Type":"application/json"}},!0)}async function rH(e){let t=new URLSearchParams;if(e?.prefix)t.set("prefix",e.prefix);if(e?.visibility)t.set("visibility",e.visibility);if(e?.limit)t.set("limit",String(e.limit));let r=t.toString()?`?${t.toString()}`:"";return I(`/admin/fleet/drift${r}`,{},!0)}async function jc(e,t){return I(`/admin/datasets/${e}/enforce`,{method:"POST",body:JSON.stringify({dry_run:t})},!0)}async function nH(e){return I("/admin/datasets/enforce/bulk",{method:"POST",body:JSON.stringify({prefix:e.prefix,visibility:e.visibility,limit:e.limit,dry_run:e.dryRun})},!0)}async function iH(e,t=!1){return I(`/admin/datasets/${e}/revalidate${t?"?force=true":""}`,{method:"POST"},!0)}async function sH(e){let t=e?`?user=${encodeURIComponent(e)}`:"";return I(`/admin/email-preferences${t}`,{},!0)}async function oH(e,t){let r=t?`?user=${encodeURIComponent(t)}`:"";return I(`/admin/email-preferences${r}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)},!0)}async function fD(e){return I("/admin/notify",{method:"POST",body:JSON.stringify(e)},!0)}async function aH(){return I("/admin/summary/coverage",{},!0)}async function cH(e,t,r){return I("/admin/manifest/dispatch",{method:"POST",body:JSON.stringify({dataset_id:e,version:t,skip_canary:r?.skipCanary??!1})},!0)}async function pD(e){return I("/admin/doctor/scan",{method:"POST",body:JSON.stringify({...e?.check&&{check:e.check},...e?.datasetId&&{dataset_id:e.datasetId}})},!0)}async function mD(e){return I("/admin/doctor/fix",{method:"POST",body:JSON.stringify({check:e.check,...e.datasetId&&{dataset_id:e.datasetId},...e.dryRun&&{dry_run:!0}})},!0)}var Mc=A(()=>{Ns()});async function ti(e,t){return I(`/datasets/${e}/upload-credentials`,{method:"POST",body:JSON.stringify({duration_seconds:t})},!0)}async function hD(e,t){return I(`/datasets/${e}/download-credentials`,{method:"POST",body:JSON.stringify({duration_seconds:t})},!0)}async function uH(e){return I(`/admin/datasets/${e}/files`,{},!0)}async function lH(e){let t,r=0,n=[],i=!0;while(i){let s=await I(`/admin/datasets/${e}/s3-lock`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({continuation_token:t})},!0);if(r+=s.locked,s.failed?.length)n.push(...s.failed);if(i=s.hasMore,t=s.continuation_token,i&&!t)throw new q(500,"S3 lock paginated response missing continuation_token; aborting to avoid infinite loop")}return{locked:r,failed:n}}var Bc=A(()=>{Ns();er()});function GIe(e){return e.startsWith("v")?e:`v${e}`}var HIe,WIe,dH,aQe;var gD=A(()=>{Ic();HIe=/^v?\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\d*)?$/,WIe=/^v\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\d*)?$/;dH=S.string().regex(HIe,"must be a semver version, optionally v-prefixed").transform(GIe),aQe=S.string().regex(WIe,"must be the canonical v-prefixed tag (vX.Y.Z)")});var KIe,YIe,fH;var pH=A(()=>{Ic();KIe=S.object({id:S.number().int(),username:S.string().nullable(),email:S.string(),github_username:S.string().nullable(),role:S.string(),orcid:S.string().nullable().optional(),created_at:S.string().optional(),approved_at:S.string().nullable().optional(),dataset_count:S.number().int().optional(),sandbox_completed:S.boolean().optional(),sandbox_completed_at:S.string().nullable().optional(),sandbox_dataset_id:S.string().nullable().optional()}).passthrough(),YIe=S.object({prefix:S.string(),created_at:S.string(),last_used_at:S.string().nullable()}).passthrough().nullable(),fH=S.object({user:KIe,token:YIe.optional()}).passthrough()});var JIe="0.4.0",yD,_d,mH,XIe,QIe,hH,pQe,gH,mQe,ki,ZIe,Am,hQe;var xD=A(()=>{Ic();gD();yD=S.enum(["openneuro","nemar","gin","other"]),_d=S.union([S.literal(0),S.literal(1)]).nullable(),mH=S.object({dataset_id:S.string(),id:S.string().optional(),name:S.string(),description:S.string().nullable().optional(),status:S.string(),visibility:S.string(),concept_doi:S.string().nullable().optional(),doi:S.string().nullable().optional(),created_at:S.string(),updated_at:S.string().optional(),owner_username:S.string().nullable().optional(),source:S.string().nullable().optional(),modalities:S.string().optional(),participants:S.number().int().nonnegative(),tasks:S.string().optional(),authors:S.string().optional(),license:S.string().optional(),file_size:S.number().nonnegative(),file_size_formatted:S.string().optional(),total_files:S.number().nonnegative().nullable().optional(),num_citations:S.number().int().nonnegative().optional(),n_channels:S.number().int().nullable().optional(),electrode_system:S.string().nullable().optional(),has_hed:_d.optional(),hed_version:S.string().nullable().optional(),data_complete:_d.optional(),bytes_present:S.number().nonnegative().nullable().optional(),latest_version:dH.nullable().optional(),subject_count:S.number().int().nullable().optional(),file_size_bytes:S.number().nullable().optional(),sessions_count:S.number().int().nullable().optional(),age_min:S.number().nullable().optional(),age_max:S.number().nullable().optional(),bids_version:S.string().nullable().optional(),zarr_status:S.enum(["pending","ready","failed"]).nullable().optional(),total_recording_duration:S.number().nullable().optional(),recording_duration_min:S.number().nullable().optional(),recording_duration_max:S.number().nullable().optional(),recording_count:S.number().int().nullable().optional(),recordings_unavailable:S.number().int().nullable().optional(),channel_count_min:S.number().int().nullable().optional(),channel_count_max:S.number().int().nullable().optional(),sampling_frequency:S.number().nullable().optional(),power_line_frequency:S.number().nullable().optional(),eeg_reference:S.string().nullable().optional(),placement_scheme:S.string().nullable().optional()}).passthrough(),XIe=mH.extend({file_size:S.number().nonnegative().nullable(),modalities:S.string().nullable().optional(),tasks:S.string().nullable().optional(),authors:S.string().nullable().optional(),license:S.string().nullable().optional(),owner_github:S.string().nullable().optional(),attestation_deposit_type:S.enum(["owner","redistribution"]).nullable().optional(),attestation_key_status:S.enum(["destroyed","retained"]).nullable().optional(),attestation_deidentified:_d.optional(),attestation_no_duplicate:_d.optional(),attestation_upstream_source:S.string().nullable().optional(),attestation_accepted_at:S.string().nullable().optional()}).passthrough(),QIe=S.object({id:S.string(),name:S.string(),modalities:S.string().nullable().optional(),participants:S.number().int().nullable().optional(),doi:S.string().nullable().optional(),tasks:S.string().nullable().optional(),authors:S.string().nullable().optional(),has_hed:_d.optional(),score:S.number().optional(),snippet:S.string().optional()}).passthrough(),hH=S.record(S.string(),S.number().int().nonnegative()),pQe=S.object({datasets:S.array(mH),count:S.number().int().nonnegative(),total_count:S.number().int().nonnegative().optional(),limit:S.number().int().optional(),offset:S.number().int().optional(),excluded_unknown:S.number().int().nonnegative().optional(),excluded_unknown_by_facet:hH.optional()}).passthrough(),gH=S.object({results:S.array(QIe),count:S.number().int().nonnegative(),returned:S.number().int().nonnegative().optional(),offset:S.number().int().nonnegative().optional(),limit:S.number().int().optional(),candidate_ceiling:S.number().int().optional(),truncated:S.boolean().optional(),method:S.enum(["exact_id","text","text_fallback","semantic","unavailable"]).optional(),min_score:S.number().optional(),warning:S.string().optional(),excluded_unknown:S.number().int().nonnegative().optional(),excluded_unknown_by_facet:hH.optional()}).passthrough(),mQe=S.object({dataset:XIe}).passthrough(),ki=S.object({value:S.string(),count:S.number().int().nonnegative()}),ZIe=S.object({values:S.array(ki),distinct_total:S.number().int().nonnegative(),truncated:S.boolean()}),Am=S.object({"electrode-system":S.array(ki).optional(),source:S.array(ki).optional(),zarr:S.array(ki).optional(),powerline:S.array(ki).optional(),"bids-version":S.array(ki).optional(),"hed-version":S.array(ki).optional(),license:S.array(ki).optional(),modality:S.array(ki).optional(),task:ZIe.optional(),warning:S.string().optional()}).passthrough(),hQe=S.object({schema_version:S.literal(JIe),doc_type:S.literal("dataset"),dataset_id:S.string().regex(/^[a-z]{2}\d+$/,"neuroschema dataset_id pattern"),name:S.string(),source:yD,recording_modality:S.array(S.string()).min(1),description:S.string().nullable().optional(),bids_version:S.string().nullable().optional(),license:S.string().nullable().optional()}).passthrough()});var km=A(()=>{gD();pH();xD()});async function Im(e){return I(`/datasets/${e}/ci/status`,{},!0)}async function yH(e){return I(`/datasets/${e}/manifest`,{},!0)}async function Tm(e,t){return I(`/datasets/${e}/manifest/${t}`,{},!0)}function xH(e){let t=e;if(!t.status)t.status="active";else if(!["active","archived","deleted"].includes(t.status))throw Error(`Invalid dataset status: ${t.status}`);if(!t.visibility)t.visibility="private";else if(!["public","private"].includes(t.visibility))throw Error(`Invalid dataset visibility: ${t.visibility}`);return t}async function Lc(e={}){let t=new URLSearchParams;if(e.mine)t.set("mine","true");if(e.search)t.set("search",e.search);if(e.modality)t.set("modality",e.modality);if(e.author)t.set("author",e.author);if(e.task)t.set("task",e.task);if(e.license)t.set("license",e.license);if(e.hasDoi)t.set("has_doi","true");if(e.hasHed)t.set("has_hed","1");if(e.dataComplete)t.set("data_complete","1");if(e.recent)t.set("recent",String(e.recent));if(e.sort)t.set("sort",e.sort);if(e.limit!=null)t.set("limit",String(e.limit));if(e.offset!=null)t.set("offset",String(e.offset));if(e.owner)t.set("owner",e.owner);if(e.facets)for(let[i,s]of Object.entries(e.facets))t.set(i,s);if(e.includeUnknown)t.set("include_unknown","1");let r=t.toString()?`?${t.toString()}`:"",n=await I(`/datasets${r}`,{},e.mine?!0:"optional");return n.datasets=n.datasets.map(xH),n}async function bH(e){return I(`/datasets/resolve/${e}`,{},"optional")}async function vH(){return I("/datasets/facets",{signal:AbortSignal.timeout(5000)},"optional",Am)}async function _H(e,t={}){let r=new URLSearchParams({q:e});if(t.modality)r.set("modality",t.modality);if(t.limit)r.set("limit",String(t.limit));if(t.hasHed)r.set("has_hed","1");if(t.author)r.set("author",t.author);if(t.task)r.set("task",t.task);if(t.license)r.set("license",t.license);if(t.hasDoi)r.set("has_doi","true");if(t.dataComplete)r.set("data_complete","1");if(t.recent)r.set("recent",String(t.recent));if(t.facets)for(let[i,s]of Object.entries(t.facets))r.set(i,s);if(t.includeUnknown)r.set("include_unknown","1");return await I(`/datasets/search?${r.toString()}`,{},"optional",gH)}async function gt(e){let t=await I(`/datasets/${e}`,{},"optional");return xH(t.dataset)}async function DH(e){return I(`/datasets/${e}/versions`,{},!0)}async function Nm(e){return I("/datasets",{method:"POST",body:JSON.stringify(e)},!0)}async function qm(e){return I(`/datasets/${e}/finalize`,{method:"POST"},!0)}async function bD(e){return I(`/datasets/${e}/request-access`,{method:"POST"},!0)}async function wH(e,t){let r=t?`?status=${t}`:"";return I(`/datasets/${e}/access-requests${r}`,{},!0)}async function EH(e,t){return I(`/datasets/${e}/access-requests/${t}/approve`,{method:"POST"},!0)}async function SH(e,t){return I(`/datasets/${e}/access-requests/${t}/deny`,{method:"POST"},!0)}async function $H(e,t){return I(`/datasets/${e}/invite`,{method:"POST",body:JSON.stringify({username:t})},!0)}async function CH(e){return I(`/datasets/${e}/collaborators`,{},!0)}async function FH(e,t){return I(`/admin/datasets/${e}/enrichment`,{method:"POST",body:JSON.stringify(t)},!0)}var Pm;var qs=A(()=>{km();Ns();Pm=/^\d{4}-\d{4}-\d{4}-\d{3}[\dX]$/});var Uc;var PH=A(()=>{Uc=["ci_check","enrichment_check","s3_public_read","repo_public","tag_protect","doi_create","update_metadata","update_readme","create_tag","create_release","upload_to_zenodo","publish_doi","version_doi","s3_lock","sync_nemar","notify_user"]});async function Vc(e){return I(`/datasets/${e}/publish/request`,{method:"POST"},!0)}async function TH(e){return I(`/datasets/${e}/publish/status`,{},!0)}async function NH(e){return I(`/datasets/${e}/publish/resend`,{method:"POST"},!0)}async function qH(e){let t=e?`?status=${e}`:"";return I(`/admin/publish/requests${t}`,{},!0)}async function jH(e,t){return I(`/admin/publish/${e}/deny`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:t})},!0)}function eTe(e,t=[]){if(e){let r=Uc.indexOf(e);if(r>=0)return r+1}return Math.min(t.length+1,Uc.length)}function tTe(e){if(!(e instanceof q))return!1;if(e.statusCode===0)return!0;if(e.statusCode===429)return!0;if(e.statusCode>=500&&e.statusCode<600)return!0;if(e.statusCode===403&&/repository has been locked/i.test(e.message))return!0;return!1}async function zc(e,t=!1,r=!1,n=!1,i,s){let c,l,d=0,f=!1,m,p=t,g=[],y;function x(v,_,E,C){if(!s)return;s({step:v,stepIndex:eTe(v,_),stepTotal:Uc.length,s3LockLocked:E,s3LockTotal:C,s3LockResumed:v==="s3_lock"&&f?!0:void 0})}for(let v=1;v<=5;v++)try{let _,E=!0;do{if(_=await I(`/admin/publish/${e}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resume:E?p:!0,sandbox:r,s3_lock_continuation_token:c,s3_lock_total:l,skip_ci_check:n})},!0),E=!1,_.step_results)g.push(..._.step_results);if(_.s3_lock_total!==void 0)l=_.s3_lock_total;if(_.s3_lock_batch_count!==void 0)d+=_.s3_lock_batch_count;let C=_.step??_.step_results?.[_.step_results.length-1]?.step;if(C&&(C!==m||C==="s3_lock"))x(C,_.steps_completed??[],C==="s3_lock"?d:void 0,C==="s3_lock"?l:void 0),m=C;if(_.hasMore&&_.s3_lock_continuation_token!==void 0)c=_.s3_lock_continuation_token;else break}while(_.hasMore);if(g.length>0)_.step_results=IH(g);return _}catch(_){if(y=_,v===5||!tTe(_)){if(_ instanceof q&&g.length>0)_.stepResults=IH(g);throw _}let C=_;if(i?.({attempt:v,maxAttempts:5,delayMs:1e4,step:C.step,error:C.message}),await new Promise((D)=>setTimeout(D,1e4)),p=!0,c!==void 0)f=!0}throw y}function IH(e){let t=new Map;for(let r of e)t.set(r.step,r);return Array.from(t.values())}var Dd=A(()=>{PH();Ns();er()});function LH(e){DD=e}function wD(){return DD}function wd(e){if(DD)process.stderr.write(`${e}
|
|
106
106
|
`)}var DD=!1;var UH={};ji(UH,{runCommand:()=>R});var{spawn:rTe}=globalThis.Bun;async function R(e,t={}){let r={...process.env,GIT_TERMINAL_PROMPT:"0",...t.env};for(let l of t.unsetEnv??[])delete r[l];let n=rTe({cmd:e,cwd:t.cwd,stdout:"pipe",stderr:"pipe",env:r}),i=!1,s;if(t.timeout)s=setTimeout(()=>{i=!0,n.kill()},t.timeout);if(wD()){let l=t.cwd?` (cwd=${t.cwd})`:"";wd(u.dim(`$ ${e.join(" ")}${l}`))}let o=await new Response(n.stdout).text(),a=await new Response(n.stderr).text(),c=await n.exited;if(s)clearTimeout(s);if(wD()){if(o.trim())wd(u.dim(o.trimEnd()));if(a.trim())wd(u.yellow(a.trimEnd()));wd(u.dim(`(exit ${c})`))}if(i)return{stdout:o,stderr:a||`Command timed out after ${Math.round(t.timeout/1000)}s`,exitCode:c??1};return{stdout:o,stderr:a,exitCode:c}}var Ut=A(()=>{He()});async function nTe(){try{let{exitCode:e,stderr:t}=await R(["ssh","-T","-o","BatchMode=yes","-o","ConnectTimeout=5","git@github.com"]),r=t.includes("successfully authenticated");if(!r)console.warn("SSH test to github.com failed:",{exitCode:e,stderr:t.trim().slice(0,500)});return{works:r,error:r?void 0:t.trim().slice(0,500)}}catch(e){let t=e instanceof Error?e.message:String(e);return console.warn("SSH test exception:",t),{works:!1,error:t}}}async function Ed(){try{let{stdout:e,exitCode:t,stderr:r}=await R(["gh","auth","token"]);if(t!==0)return console.warn("gh CLI returned non-zero exit code:",t),console.warn("stderr:",r),{token:null,error:`gh auth token failed: ${r.trim()||"unknown error"}`};if(!e.trim())return console.warn("gh auth token returned empty output"),{token:null,error:"gh CLI returned empty token"};return{token:e.trim()}}catch(e){let t=e instanceof Error?e.message:String(e);if(console.error("Failed to get GitHub token from gh CLI:",t),t.includes("ENOENT")||t.includes("not found"))return{token:null,error:"gh CLI not installed (command not found)"};return{token:null,error:`gh CLI error: ${t}`}}}async function jm(e){try{let{stdout:t,exitCode:r,stderr:n}=await R(["gh","api","user","--jq",".login"]);if(r!==0){if(n.includes("not logged in")||n.includes("auth login"))return{authenticated:!1,error:"gh CLI not authenticated. Run 'gh auth login' to authenticate."};return{authenticated:!1,error:`gh CLI error: ${n.trim()||"unknown error"}`}}let i=t.trim();if(!i)return{authenticated:!1,error:"gh CLI returned empty username"};if(e){let s=i.toLowerCase()===e.toLowerCase();return{authenticated:!0,username:i,matches:s,error:s?void 0:`gh CLI authenticated as '${i}', expected '${e}'`}}return{authenticated:!0,username:i}}catch(t){let r=t instanceof Error?t.message:String(t);if(r.includes("ENOENT")||r.includes("not found"))return{authenticated:!1,error:"gh CLI not installed. Install from https://cli.github.com/"};return{authenticated:!1,error:`Failed to verify gh CLI: ${r}`}}}async function Mm(e){if(!/^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/.test(e))return{accepted:!1,error:`Invalid repository format: ${e}`};let{stdout:t,exitCode:r,stderr:n}=await R(["gh","api","/user/repository_invitations"]);if(r!==0){if(n.includes("not logged in")||n.includes("auth login"))return{accepted:!1,error:"gh CLI not authenticated. Run 'gh auth login' to authenticate."};if(n.includes("API rate limit")||n.includes("403"))return{accepted:!1,error:"GitHub API rate limit exceeded. Please try again in a few minutes."};if(n.includes("ENOENT")||n.includes("not found"))return{accepted:!1,error:"gh CLI not installed. Install from https://cli.github.com/"};return{accepted:!1,error:`Failed to list invitations: ${n.trim()||"unknown error"}`}}let i=null;try{i=JSON.parse(t||"[]").find((l)=>l.repository.full_name===e)?.id??null}catch(a){let c=a instanceof Error?a.message:String(a);return console.error("Failed to parse GitHub invitations response:",c),console.error(" Raw response (first 500 chars):",(t||"").slice(0,500)),{accepted:!1,error:`Failed to parse GitHub API response: ${c}`}}if(!i){let{exitCode:a}=await R(["gh","api",`/repos/${e}`,"--silent"]);if(a===0)return{accepted:!0,alreadyCollaborator:!0};return{accepted:!1,error:`No pending invitation found for ${e}. You may need to accept it manually via GitHub.`}}let{exitCode:s,stderr:o}=await R(["gh","api","--method","PATCH",`/user/repository_invitations/${i}`]);if(s!==0)return{accepted:!1,error:`Failed to accept invitation: ${o.trim()||"unknown error"}`};return{accepted:!0}}async function ri(e,t,r="origin"){let n=t;if(process.env.GH_TOKEN&&t.startsWith("git@github.com:")){let i=process.env.GH_TOKEN.trim();if(!i||/\s/.test(i))return{success:!1,error:"GH_TOKEN environment variable is set but appears malformed (empty or contains whitespace)"};n=`https://github.com/${t.replace("git@github.com:","")}`,await R(["git","config","credential.https://github.com.helper",`!printf 'username=x-access-token\\npassword=${i}'`],{cwd:e})}else if(t.startsWith("git@github.com:")){let i=t.replace("git@github.com:",""),s=await Ed();if(s.token)n=`https://github.com/${i}`,await R(["git","config","credential.https://github.com.helper",`!printf 'username=x-access-token\\npassword=${s.token}'`],{cwd:e});else{let o=await nTe();if(o.works)n=t;else return{success:!1,error:`GitHub authentication not configured.
|
|
107
107
|
|
|
108
108
|
gh CLI failed: ${s.error||"could not get token"}
|
|
@@ -244,7 +244,7 @@ Deploy CI workflows to: ${e}
|
|
|
244
244
|
`)),console.log("This will add the following workflows:"),console.log(" 1. BIDS Validation (runs on PRs)"),console.log(" 2. Version Check (ensures version bump on PRs)"),console.log(" 3. PR Merge Handler (creates releases, publishes DOIs)"),r)console.log(u.dim(" (post-deploy parseability poll disabled via --no-validate)"));console.log();let n=await Fe(`Deploy CI workflows to ${e}?`,t);if(n!=="confirmed"){console.log(u.dim(n==="declined"?"Skipped":"Cancelled"));return}let i=w(`Deploying CI workflows to ${e}...`).start(),s;try{s=await Ai(e)}catch(o){tt(o,i,"Failed to deploy CI workflows",{404:"Dataset not found"});return}i.succeed("CI workflows deployed"),console.log();for(let o of s.workflows_deployed)console.log(` ${u.green("[x]")} ${o}`);if(!r){let o=w("Verifying GitHub Actions can parse the workflows...").start(),a=await H5e(e);if(!a)o.warn("Could not verify workflow parseability (deploy succeeded)");else if(a.missing.length===0&&a.errors.length===0)o.succeed("All workflows parseable by GitHub Actions");else{let c=a.missing.length>0?"Some workflows missing from GitHub Actions listing":"Could not fully verify workflow parseability (GitHub API error)";o.warn(c),zG(a)}}console.log()});qd.command("validate").description("Check whether GitHub Actions can parse the deployed CI workflows").argument("<dataset-id>","Dataset ID (e.g., nm000104)").action(async(e)=>{if(!oe())return;let t=w(`Validating CI workflows for ${e}...`).start();try{let r=await aD(e);if(r.missing.length===0&&r.errors.length===0)t.succeed(`All ${r.valid.length} workflows parseable by GitHub Actions`);else t.warn("Some workflows missing or unreadable"),zG({missing:r.missing,errors:r.errors})}catch(r){tt(r,t,"Failed to validate CI workflows",{404:"Dataset not found"})}});qd.command("sync").description("Sync deployed CI workflows to current templates (only writes drifted/missing files)").argument("[dataset-id]","Dataset ID (e.g., nm000104)").option("--all","Sync across all dataset repositories").option(Re,Oe).option(je,Te).action(async(e,t)=>{if(!oe())return;if(t.all){let n=w("Fetching dataset list...").start(),i;try{if(i=(await Lc({limit:1000})).datasets,n.succeed(`Found ${i.length} datasets`),i.length>=1000)console.log(u.yellow("Warning: reached 1000 dataset limit; some datasets may be skipped"))}catch(l){tt(l,n,"Failed to fetch datasets");return}console.log(u.cyan(`
|
|
245
245
|
Sync CI templates across ${i.length} datasets (writes only diffs)
|
|
246
246
|
`));let s=await Fe(`Sync templates on all ${i.length} datasets?`,t);if(s!=="confirmed"){console.log(u.dim(s==="declined"?"Skipped":"Cancelled"));return}let o=0,a=0,c=0;for(let l of i){let d=w(`Syncing ${l.dataset_id}...`).start();try{let f=await cD(l.dataset_id),m=f.changed.length+f.added.length;if(f.errors.length>0)d.warn(`${l.dataset_id}: ${m} updated, ${f.errors.length} error(s)`),c++;else if(m===0)d.succeed(`${l.dataset_id}: up to date`),o++;else{let p=[];if(f.added.length>0)p.push(`+${f.added.length} added`);if(f.changed.length>0)p.push(`~${f.changed.length} updated`);d.succeed(`${l.dataset_id}: ${p.join(", ")}`),a++}}catch(f){let m=f instanceof q?f.message:String(f);d.fail(`${l.dataset_id}: ${m}`),c++}}console.log(),console.log(u.cyan(`Done: ${o} up-to-date, ${a} updated, ${c} with errors`));return}if(!e){console.error(u.red("Error: dataset-id is required (or use --all)"));return}let r=w(`Syncing CI templates for ${e}...`).start();try{let n=await cD(e),i=n.changed.length+n.added.length;if(n.errors.length>0)r.warn(`${e}: ${n.errors.length} error(s)`);else if(i===0)r.succeed(`${e}: already up to date`);else r.succeed(`${e}: synced`);if(console.log(),console.log(` ${u.dim("Checked:")} ${n.checked.join(", ")}`),n.added.length>0)console.log(` ${u.green("Added:")} ${n.added.join(", ")}`);if(n.changed.length>0)console.log(` ${u.yellow("Updated:")} ${n.changed.join(", ")}`);if(!n.committed&&i>0&&n.errors.length===0)console.log(` ${u.yellow("Note:")} listed changes were not committed`);if(n.list_failed)console.log(` ${u.red("Warning:")} workflow directory listing failed; presence is unknown`);if(n.errors.length>0){console.log(` ${u.red("Errors:")}`);for(let s of n.errors)console.log(` - ${s}`)}console.log()}catch(n){tt(n,r,"Failed to sync CI templates",{404:"Dataset not found"})}});Ie.addCommand(qd);var jd=new ve("doi").description("DOI management");jd.command("create").description("Create concept DOI for a dataset").argument("<dataset-id>","Dataset ID (e.g., nm000104)").option("--title <title>","DOI title (defaults to dataset name)").option("--description <desc>","DOI description").option("--provider <provider>","DOI provider: ezid (default) or zenodo","ezid").option("--sandbox","Use sandbox/test DOI").option(Re,Oe).option(je,Te).action(async(e,t)=>{if(!oe())return;let r=w("Fetching dataset info...").start(),n;try{n=await gt(e),r.succeed(`Found dataset: ${n.name}`)}catch(c){if(c instanceof q){if(r.fail(c.message),c.statusCode===404)console.log(u.dim(" Dataset not found"))}else r.fail("Failed to fetch dataset");return}try{let c=await vd(e);if(c.concept_doi){if(console.log(u.yellow(`
|
|
247
|
-
Dataset already has a concept DOI:`)),console.log(` Concept DOI: ${u.cyan(c.concept_doi)}`),c.zenodo_concept_url)console.log(` Zenodo URL: ${c.zenodo_concept_url}`);return}}catch(c){if(process.env.DEBUG)console.error("[debug] DOI info fetch:",c)}if(console.log(),console.log(u.cyan("Dataset Information:")),console.log(` ID: ${n.dataset_id}`),console.log(` Name: ${n.name}`),n.github_repo)console.log(` GitHub: ${n.github_repo}`);if(t.sandbox)console.log(` Mode: ${u.yellow("SANDBOX (test DOI)")}`);console.log();let i=t.provider==="zenodo"?"zenodo":"ezid";if(t.sandbox){if(console.log(u.yellow("\u2501".repeat(60))),console.log(u.yellow.bold(" SANDBOX MODE ENABLED")),console.log(u.yellow("\u2501".repeat(60))),i==="zenodo")console.log(u.yellow(" \u2022 Using Zenodo sandbox (sandbox.zenodo.org)"));else console.log(u.yellow(" \u2022 Using EZID test shoulder (doi:10.5072/FK2)")),console.log(u.yellow(" \u2022 Test DOIs auto-delete after 2 weeks"));console.log(u.yellow(" \u2022 DOI will NOT be indexed by DataCite")),console.log(u.yellow(" \u2022 DOI will NOT resolve in production")),console.log(u.yellow(" \u2022 Use this for testing workflows only")),console.log(u.yellow("\u2501".repeat(60))),console.log()}console.log(u.red("WARNING: DOIs are PERMANENT and cannot be deleted!")),console.log(u.dim("The DOI will be pre-reserved but not published until the first version release.")),console.log(` Provider: ${u.cyan(i.toUpperCase())}`),console.log();let s=t.sandbox?`Create TEST concept DOI via ${i.toUpperCase()} SANDBOX?`:`Create PERMANENT concept DOI via ${i.toUpperCase()} PRODUCTION?`,o=await Fe(s,t);if(o!=="confirmed"){console.log(u.dim(o==="declined"?"Skipped":"Cancelled"));return}let a=w(`Creating concept DOI via ${i.toUpperCase()}...`).start();try{let c=await Nz(e,{title:t.title,description:t.description,sandbox:t.sandbox,provider:i});a.succeed("Concept DOI created successfully");let l=w("Finalizing repository setup...").start();try{let d=await qm(e);if(d.warnings&&d.warnings.length>0){l.warn("Repository setup finalized with warnings");for(let f of d.warnings)console.log(u.yellow(` Warning: ${f}`))}else l.succeed("Repository setup finalized")}catch(d){if(l.warn("Could not finalize repository setup"),d instanceof q){if(console.log(u.dim(` ${d.message}`)),d.statusCode===403)console.log(u.dim(" Check admin credentials and permissions"))}else console.log(u.dim(` ${d instanceof Error?d.message:"Unknown error"}`))}if(console.log(),console.log(u.green("DOI Information:")),console.log(` Concept DOI: ${u.cyan(c.concept_doi)}`),console.log(` Provider: ${c.provider.toUpperCase()}`),c.provider==="ezid")console.log(` DOI URL: ${c.doi_url}`),console.log(` EZID ID: ${c.ezid_identifier}`);else console.log(` Zenodo URL: ${c.zenodo_url}`);if(c.metadata_warning)console.log(u.yellow(` Warning: ${c.metadata_warning}`));if(console.log(),console.log(u.yellow("Next steps:")),console.log(" 1. Update dataset_description.json with DatasetDOI field"),console.log(" 2. Create a PR and merge it to trigger version DOI publication"),console.log(),t.sandbox)console.log(u.dim("Note: This is a sandbox DOI and will not resolve in production."))}catch(c){if(c instanceof q){if(a.fail(c.message),c.statusCode===403)console.log(u.dim(" This command requires admin privileges"))}else a.fail("Failed to create concept DOI"),console.log(u.dim(` ${V(c)}`))}});jd.command("info").description("Get DOI info for a dataset").argument("<dataset-id>","Dataset ID (e.g., nm000104)").action(async(e)=>{if(!oe())return;let t=w("Fetching DOI info...").start();try{let r=await vd(e);if(t.stop(),console.log(),console.log(u.cyan(`DOI Information for ${e}:`)),console.log(` Dataset Name: ${r.name}`),console.log(),r.concept_doi){if(console.log(u.green("Concept DOI:")),console.log(` DOI: ${r.concept_doi}`),console.log(` URL: https://doi.org/${r.concept_doi}`),console.log(` Provider: ${(r.doi_provider||"zenodo").toUpperCase()}`),r.doi_provider==="ezid"){if(r.ezid_identifier)console.log(` EZID ID: ${r.ezid_identifier}`);if(r.ezid_status){let n=r.ezid_status==="public"?u.green:u.yellow;console.log(` Status: ${n(r.ezid_status)}`)}}if(r.zenodo_concept_url){if(console.log(` Zenodo: ${r.zenodo_concept_url}`),r.zenodo_concept_url.includes("sandbox.zenodo.org"))console.log(),console.log(u.yellow("Mode: SANDBOX (test DOI)")),console.log(u.yellow(" This DOI is not indexed by DataCite and will not resolve in production"))}}else console.log(u.yellow("No concept DOI created yet")),console.log(u.dim(" Use 'nemar admin doi create' to create one"));if(console.log(),r.latest_version_doi){if(console.log(u.green("Latest Version DOI:")),console.log(` DOI: ${r.latest_version_doi}`),console.log(` URL: https://doi.org/${r.latest_version_doi}`),r.zenodo_latest_version_url)console.log(` Zenodo: ${r.zenodo_latest_version_url}`)}else if(r.concept_doi)console.log(u.yellow("No version DOI published yet")),console.log(u.dim(" Version DOIs are created automatically on PR merge"))}catch(r){if(r instanceof q){if(t.fail(r.message),r.statusCode===404)console.log(u.dim(" Dataset not found"));else if(r.statusCode===403)console.log(u.dim(" This command requires admin privileges"))}else t.fail("Failed to fetch DOI info")}});jd.command("update").description("Update EZID DOI metadata or status").argument("<dataset-id>","Dataset ID (e.g., nm000104)").option("--make-public","Transition DOI from reserved to public (permanent)").option("--unavailable","Tombstone the concept DOI (EZID _status=unavailable); concept-only, reversible via --make-public. For a full withdrawal (visibility + every version DOI) use 'nemar admin withdraw' instead.").option("--refresh","Refresh metadata from dataset_description.json and .nemar/metadata.json").option(Re,Oe).option(je,Te).action(async(e,t)=>{if(!oe())return;if(t.makePublic&&t.unavailable){console.log(u.red("Use --make-public or --unavailable, not both."));return}if(!t.makePublic&&!t.unavailable&&!t.refresh){console.log(u.yellow("No action specified. Use --make-public, --unavailable, and/or --refresh."));return}if(t.makePublic){console.log(u.red("WARNING: Making a DOI public is PERMANENT!")),console.log(u.dim(" The DOI will be findable in DataCite and cannot be reverted.")),console.log();let n=await Fe(`Make DOI for ${e} PUBLIC and permanent?`,t);if(n!=="confirmed"){console.log(u.dim(n==="declined"?"Skipped":"Cancelled"));return}}if(t.unavailable){console.log(u.yellow("This tombstones the concept DOI (EZID _status=unavailable).")),console.log(u.dim(" Reversible with --make-public. Version DOIs are untouched.")),console.log();let n=await Fe(`Mark DOI for ${e} unavailable (tombstone)?`,t);if(n!=="confirmed"){console.log(u.dim(n==="declined"?"Skipped":"Cancelled"));return}}let r=w("Updating DOI...").start();try{let n=await uD(e,{status:t.makePublic?"public":t.unavailable?"unavailable":void 0,refresh_metadata:t.refresh});r.succeed("DOI updated successfully"),console.log(),console.log(` EZID ID: ${u.cyan(n.ezid_identifier)}`),console.log(` Status: ${n.status==="public"?u.green(n.status):u.yellow(n.status)}`),console.log(` URL: ${n.doi_url}`)}catch(n){if(n instanceof q){if(r.fail(n.message),n.statusCode===400)console.log(u.dim(" DOI update is only supported for EZID-managed DOIs"))}else r.fail("Failed to update DOI"),console.log(u.dim(` ${V(n)}`))}});jd.command("enrich").description("Enrich DOI metadata with ORCIDs, descriptions, funding, and more").argument("<dataset-id>","Dataset ID (e.g., nm000104)").option("--no-llm","Skip LLM-based enrichment from README").option("--sandbox","Use sandbox DOI").option(Re,Oe).option(je,Te).action(async(e,t)=>{if(!oe())return;let r=w("Fetching dataset and existing enrichment...").start(),n;try{n=await gt(e),r.succeed(`Dataset: ${n.name}`)}catch(p){if(p instanceof q)r.fail(p.message);else r.fail("Failed to fetch dataset");return}let i,s=!1;try{i=await vd(e)}catch(p){if(p instanceof q&&p.statusCode===404);else s=!0,console.log(u.yellow(` Warning: Could not fetch DOI info: ${V(p)}`))}if(i?.concept_doi)console.log(` DOI: ${u.cyan(i.concept_doi)}`);let o={version:"2.0"};if(n.github_repo){let p=w("Reading existing metadata...").start(),g=await jG(n.github_repo,".nemar/metadata.json");if(g)try{let y=JSON.parse(g);if(y&&typeof y==="object"&&y.version==="2.0")o=y,p.succeed(`Loaded existing metadata (stage: ${y.pipeline_stage||"unknown"})`);else p.warn("Existing metadata has unsupported version, starting fresh")}catch(y){p.warn(`Could not parse existing metadata (${y instanceof Error?y.message:String(y)}), starting fresh`)}else p.info("No existing .nemar/metadata.json found, starting fresh")}if(t.llm!==!1&&n.github_repo){console.log(),console.log(u.cyan("--- Running LLM enrichment pipeline (CI workflow) ---"));let p=w("Triggering run-enrichment workflow...").start();try{let{spawn:g}=awaitPromise.resolve(globalThis.Bun),y=n.github_repo,x="nemarDatasets/.github",v="run-enrichment.yml",_=g({cmd:["gh","workflow","run","run-enrichment.yml","--repo","nemarDatasets/.github","--ref","main","-f",`dataset_id=${e}`,"-f","ref=main","-f","force=true"],stdout:"pipe",stderr:"pipe"}),E=await new Response(_.stderr).text();if(await _.exited!==0)throw Error(`Failed to trigger workflow: ${E.trim()}`);p.text="Waiting for workflow to register...",await new Promise((k)=>setTimeout(k,3000)),p.text="Polling workflow status...";let D=60,O="",F=0;for(let k=0;k<D;k++){let j=g({cmd:["gh","run","list","--repo","nemarDatasets/.github","--workflow","run-enrichment.yml","-L","10","--json","databaseId,status,conclusion,displayTitle,event"],stdout:"pipe",stderr:"pipe"}),Z=await new Response(j.stdout).text(),_e=await new Response(j.stderr).text();if(await j.exited!==0){if(F++,F>=3){p.warn(`gh CLI error: ${_e.trim()}`);break}await new Promise((Me)=>setTimeout(Me,5000));continue}try{let Me=JSON.parse(Z.trim());F=0;let T=Me.find((B)=>B.event==="workflow_dispatch");if(T){if(T.status==="completed"){O=T.conclusion||"unknown";break}p.text=`Workflow ${T.status}... (${k*5}s)`}}catch(Me){if(F++,F>=3){p.warn(`Unable to parse workflow status: ${Me instanceof Error?Me.message:String(Me)} (raw: ${Z.trim().slice(0,200)})`);break}}await new Promise((Me)=>setTimeout(Me,5000))}let M=!1;if(!O)p.warn("Workflow timed out after 5 minutes (may still be running)");else if(O==="success"){p.succeed("LLM enrichment workflow completed successfully");let k=await jG(y,".nemar/metadata.json");if(k)try{let j=JSON.parse(k);if(j&&typeof j==="object"&&j.version==="2.0"){Object.assign(o,j),M=!0;let Z=j.pipeline_stage||"unknown";if(console.log(u.dim(` Pipeline stage: ${Z}`)),o.authors){let _e=Object.keys(o.authors).length;console.log(u.dim(` Authors: ${_e}`))}}}catch(j){console.log(u.yellow(` Warning: Could not parse updated metadata: ${j instanceof Error?j.message:String(j)}`)),console.log(u.dim(" Using pre-workflow enrichment data"))}else console.log(u.yellow(" Warning: Could not fetch updated metadata after successful workflow.")),console.log(u.dim(" Author data below may be from a previous run."))}else p.fail(`LLM enrichment workflow failed (conclusion: ${O})`);if(!M)console.log(u.yellow(" ORCID discovery did not complete. Authors below may be from previous metadata."))}catch(g){p.fail("LLM enrichment pipeline failed"),console.log(u.dim(` ${V(g)}`)),console.log(u.yellow(" ORCID discovery did not run. You will need to enter ORCIDs manually."))}}console.log(),console.log(u.cyan("--- Author ORCIDs ---"));let a=o.authors||{},c=Object.keys(a);if(c.length>0){let p=c.filter((y)=>a[y]?.orcid),g=c.filter((y)=>!a[y]?.orcid);console.log(u.dim(` Discovered ${c.length} authors from pipeline:`));for(let y of p)console.log(u.green(` [x] ${y}: ${a[y]?.orcid}`));for(let y of g)console.log(u.yellow(` [ ] ${y}: no ORCID found`));if(g.length>0)console.log(u.dim(` ${g.length} author(s) missing ORCIDs.`))}let{updateAuthors:l}=await X.prompt([{type:"confirm",name:"updateAuthors",message:c.length>0?"Add or correct author ORCIDs?":"Add author ORCIDs manually?",default:!1}]);if(l){let p={},g=!0;while(g){let{authorName:y}=await X.prompt([{type:"input",name:"authorName",message:'Author name (as in BIDS, e.g., "Shirazi, Yahya"):'}]);if(!y)break;let x=a[y];if(x?.orcid)console.log(u.dim(` Current ORCID: ${x.orcid}`));let{orcid:v}=await X.prompt([{type:"input",name:"orcid",message:`ORCID for "${y}" (Enter to ${x?.orcid?"keep current":"skip"}):`,validate:(D)=>{if(!D)return!0;return Pm.test(D)||"Invalid ORCID format (XXXX-XXXX-XXXX-XXXX)"}}]),_={};if(v)_.orcid=v;let{affiliation:E}=await X.prompt([{type:"input",name:"affiliation",message:`Affiliation for "${y}" (optional):`}]);if(E)_.affiliations=[{name:E}];if(_.orcid||_.affiliations)p[y]=_;let{more:C}=await X.prompt([{type:"confirm",name:"more",message:"Add another author?",default:!0}]);g=C}if(Object.keys(p).length>0){let y={...o.authors||{}};for(let[x,v]of Object.entries(p)){let _=y[x]||{};y[x]={..._,...v,orcid:v.orcid||_.orcid}}o.authors=y}}console.log(),console.log(u.cyan("--- Dataset stats ---"));let d=w("Computing dataset sizes and formats...").start();try{let p=await uH(e),g=Ze(p.total_size);o.sizes=[`${g} (${p.file_count} files)`],o.formats=p.extensions,d.succeed(`Sizes: ${g} (${p.file_count} files), Formats: ${p.extensions.join(", ")}`)}catch(p){d.warn("Could not compute dataset stats"),console.log(u.dim(` ${V(p)}`))}console.log(),console.log(u.cyan("--- Review ---")),console.log(JSON.stringify(o,null,2)),console.log();let f=await Fe("Commit to repo and refresh DOI?",t,!0);if(f!=="confirmed"){console.log(u.dim(f==="declined"?"Skipped":"Cancelled"));return}let m=w("Saving enrichment...").start();try{let p=await FH(e,o);if(m.succeed(p.message),p.bidsignore_updated)console.log(u.dim(" .bidsignore updated to include .nemar/"));if(!i&&s)try{i=await vd(e)}catch(g){if(process.env.DEBUG)console.error("[debug] DOI info re-fetch:",g)}if(i?.ezid_identifier){let g=w("Refreshing DOI metadata...").start();try{await uD(e,{refresh_metadata:!0}),g.succeed("DOI metadata refreshed")}catch(y){g.warn("Could not refresh DOI metadata"),console.log(u.dim(` ${V(y)}`))}}else if(s)console.log(u.yellow(" DOI refresh skipped: could not verify DOI exists. Run 'nemar admin doi update --refresh' manually."))}catch(p){if(p instanceof q)m.fail(p.message);else m.fail("Failed to save enrichment"),console.log(u.dim(` ${V(p)}`))}});Ie.addCommand(jd);var uh=new ve("publish").description("Publication workflow management");uh.command("list").description("List publication requests").option("-s, --status <status>","Filter by status (requested, approving, published, denied)").addHelpText("after",`
|
|
247
|
+
Dataset already has a concept DOI:`)),console.log(` Concept DOI: ${u.cyan(c.concept_doi)}`),c.zenodo_concept_url)console.log(` Zenodo URL: ${c.zenodo_concept_url}`);return}}catch(c){if(process.env.DEBUG)console.error("[debug] DOI info fetch:",c)}if(console.log(),console.log(u.cyan("Dataset Information:")),console.log(` ID: ${n.dataset_id}`),console.log(` Name: ${n.name}`),n.github_repo)console.log(` GitHub: ${n.github_repo}`);if(t.sandbox)console.log(` Mode: ${u.yellow("SANDBOX (test DOI)")}`);console.log();let i=t.provider==="zenodo"?"zenodo":"ezid";if(t.sandbox){if(console.log(u.yellow("\u2501".repeat(60))),console.log(u.yellow.bold(" SANDBOX MODE ENABLED")),console.log(u.yellow("\u2501".repeat(60))),i==="zenodo")console.log(u.yellow(" \u2022 Using Zenodo sandbox (sandbox.zenodo.org)"));else console.log(u.yellow(" \u2022 Using EZID test shoulder (doi:10.5072/FK2)")),console.log(u.yellow(" \u2022 Test DOIs auto-delete after 2 weeks"));console.log(u.yellow(" \u2022 DOI will NOT be indexed by DataCite")),console.log(u.yellow(" \u2022 DOI will NOT resolve in production")),console.log(u.yellow(" \u2022 Use this for testing workflows only")),console.log(u.yellow("\u2501".repeat(60))),console.log()}console.log(u.red("WARNING: DOIs are PERMANENT and cannot be deleted!")),console.log(u.dim("The DOI will be pre-reserved but not published until the first version release.")),console.log(` Provider: ${u.cyan(i.toUpperCase())}`),console.log();let s=t.sandbox?`Create TEST concept DOI via ${i.toUpperCase()} SANDBOX?`:`Create PERMANENT concept DOI via ${i.toUpperCase()} PRODUCTION?`,o=await Fe(s,t);if(o!=="confirmed"){console.log(u.dim(o==="declined"?"Skipped":"Cancelled"));return}let a=w(`Creating concept DOI via ${i.toUpperCase()}...`).start();try{let c=await Nz(e,{title:t.title,description:t.description,sandbox:t.sandbox,provider:i});a.succeed("Concept DOI created successfully");let l=w("Finalizing repository setup...").start();try{let d=await qm(e);if(d.warnings&&d.warnings.length>0){l.warn("Repository setup finalized with warnings");for(let f of d.warnings)console.log(u.yellow(` Warning: ${f}`))}else l.succeed("Repository setup finalized")}catch(d){if(l.warn("Could not finalize repository setup"),d instanceof q){if(console.log(u.dim(` ${d.message}`)),d.statusCode===403)console.log(u.dim(" Check admin credentials and permissions"))}else console.log(u.dim(` ${d instanceof Error?d.message:"Unknown error"}`))}if(console.log(),console.log(u.green("DOI Information:")),console.log(` Concept DOI: ${u.cyan(c.concept_doi)}`),console.log(` Provider: ${c.provider.toUpperCase()}`),c.provider==="ezid")console.log(` DOI URL: ${c.doi_url}`),console.log(` EZID ID: ${c.ezid_identifier}`);else console.log(` Zenodo URL: ${c.zenodo_url}`);if(c.metadata_warning)console.log(u.yellow(` Warning: ${c.metadata_warning}`));if(console.log(),console.log(u.yellow("Next steps:")),console.log(" 1. Update dataset_description.json with DatasetDOI field"),console.log(" 2. Create a PR and merge it to trigger version DOI publication"),console.log(),t.sandbox)console.log(u.dim("Note: This is a sandbox DOI and will not resolve in production."))}catch(c){if(c instanceof q){if(a.fail(c.message),c.statusCode===403)console.log(u.dim(" This command requires admin privileges"))}else a.fail("Failed to create concept DOI"),console.log(u.dim(` ${V(c)}`))}});jd.command("info").description("Get DOI info for a dataset").argument("<dataset-id>","Dataset ID (e.g., nm000104)").action(async(e)=>{if(!oe())return;let t=w("Fetching DOI info...").start();try{let r=await vd(e);if(t.stop(),console.log(),console.log(u.cyan(`DOI Information for ${e}:`)),console.log(` Dataset Name: ${r.name}`),console.log(),r.concept_doi){if(console.log(u.green("Concept DOI:")),console.log(` DOI: ${r.concept_doi}`),console.log(` URL: https://doi.org/${r.concept_doi}`),console.log(` Provider: ${(r.doi_provider||"zenodo").toUpperCase()}`),r.doi_provider==="ezid"){if(r.ezid_identifier)console.log(` EZID ID: ${r.ezid_identifier}`);if(r.ezid_status){let n=r.ezid_status==="public"?u.green:u.yellow;console.log(` Status: ${n(r.ezid_status)}`)}}if(r.zenodo_concept_url){if(console.log(` Zenodo: ${r.zenodo_concept_url}`),r.zenodo_concept_url.includes("sandbox.zenodo.org"))console.log(),console.log(u.yellow("Mode: SANDBOX (test DOI)")),console.log(u.yellow(" This DOI is not indexed by DataCite and will not resolve in production"))}}else console.log(u.yellow("No concept DOI created yet")),console.log(u.dim(" Use 'nemar admin doi create' to create one"));if(console.log(),r.latest_version_doi)console.log(u.green("Latest Version DOI:")),console.log(` DOI: ${r.latest_version_doi}`),console.log(` URL: https://doi.org/${r.latest_version_doi}`);else if(r.concept_doi)console.log(u.yellow("No version DOI published yet")),console.log(u.dim(" Version DOIs are created automatically on PR merge"))}catch(r){if(r instanceof q){if(t.fail(r.message),r.statusCode===404)console.log(u.dim(" Dataset not found"));else if(r.statusCode===403)console.log(u.dim(" This command requires admin privileges"))}else t.fail("Failed to fetch DOI info")}});jd.command("update").description("Update EZID DOI metadata or status").argument("<dataset-id>","Dataset ID (e.g., nm000104)").option("--make-public","Transition DOI from reserved to public (permanent)").option("--unavailable","Tombstone the concept DOI (EZID _status=unavailable); concept-only, reversible via --make-public. For a full withdrawal (visibility + every version DOI) use 'nemar admin withdraw' instead.").option("--refresh","Refresh metadata from dataset_description.json and .nemar/metadata.json").option(Re,Oe).option(je,Te).action(async(e,t)=>{if(!oe())return;if(t.makePublic&&t.unavailable){console.log(u.red("Use --make-public or --unavailable, not both."));return}if(!t.makePublic&&!t.unavailable&&!t.refresh){console.log(u.yellow("No action specified. Use --make-public, --unavailable, and/or --refresh."));return}if(t.makePublic){console.log(u.red("WARNING: Making a DOI public is PERMANENT!")),console.log(u.dim(" The DOI will be findable in DataCite and cannot be reverted.")),console.log();let n=await Fe(`Make DOI for ${e} PUBLIC and permanent?`,t);if(n!=="confirmed"){console.log(u.dim(n==="declined"?"Skipped":"Cancelled"));return}}if(t.unavailable){console.log(u.yellow("This tombstones the concept DOI (EZID _status=unavailable).")),console.log(u.dim(" Reversible with --make-public. Version DOIs are untouched.")),console.log();let n=await Fe(`Mark DOI for ${e} unavailable (tombstone)?`,t);if(n!=="confirmed"){console.log(u.dim(n==="declined"?"Skipped":"Cancelled"));return}}let r=w("Updating DOI...").start();try{let n=await uD(e,{status:t.makePublic?"public":t.unavailable?"unavailable":void 0,refresh_metadata:t.refresh});r.succeed("DOI updated successfully"),console.log(),console.log(` EZID ID: ${u.cyan(n.ezid_identifier)}`),console.log(` Status: ${n.status==="public"?u.green(n.status):u.yellow(n.status)}`),console.log(` URL: ${n.doi_url}`)}catch(n){if(n instanceof q){if(r.fail(n.message),n.statusCode===400)console.log(u.dim(" DOI update is only supported for EZID-managed DOIs"))}else r.fail("Failed to update DOI"),console.log(u.dim(` ${V(n)}`))}});jd.command("enrich").description("Enrich DOI metadata with ORCIDs, descriptions, funding, and more").argument("<dataset-id>","Dataset ID (e.g., nm000104)").option("--no-llm","Skip LLM-based enrichment from README").option("--sandbox","Use sandbox DOI").option(Re,Oe).option(je,Te).action(async(e,t)=>{if(!oe())return;let r=w("Fetching dataset and existing enrichment...").start(),n;try{n=await gt(e),r.succeed(`Dataset: ${n.name}`)}catch(p){if(p instanceof q)r.fail(p.message);else r.fail("Failed to fetch dataset");return}let i,s=!1;try{i=await vd(e)}catch(p){if(p instanceof q&&p.statusCode===404);else s=!0,console.log(u.yellow(` Warning: Could not fetch DOI info: ${V(p)}`))}if(i?.concept_doi)console.log(` DOI: ${u.cyan(i.concept_doi)}`);let o={version:"2.0"};if(n.github_repo){let p=w("Reading existing metadata...").start(),g=await jG(n.github_repo,".nemar/metadata.json");if(g)try{let y=JSON.parse(g);if(y&&typeof y==="object"&&y.version==="2.0")o=y,p.succeed(`Loaded existing metadata (stage: ${y.pipeline_stage||"unknown"})`);else p.warn("Existing metadata has unsupported version, starting fresh")}catch(y){p.warn(`Could not parse existing metadata (${y instanceof Error?y.message:String(y)}), starting fresh`)}else p.info("No existing .nemar/metadata.json found, starting fresh")}if(t.llm!==!1&&n.github_repo){console.log(),console.log(u.cyan("--- Running LLM enrichment pipeline (CI workflow) ---"));let p=w("Triggering run-enrichment workflow...").start();try{let{spawn:g}=awaitPromise.resolve(globalThis.Bun),y=n.github_repo,x="nemarDatasets/.github",v="run-enrichment.yml",_=g({cmd:["gh","workflow","run","run-enrichment.yml","--repo","nemarDatasets/.github","--ref","main","-f",`dataset_id=${e}`,"-f","ref=main","-f","force=true"],stdout:"pipe",stderr:"pipe"}),E=await new Response(_.stderr).text();if(await _.exited!==0)throw Error(`Failed to trigger workflow: ${E.trim()}`);p.text="Waiting for workflow to register...",await new Promise((k)=>setTimeout(k,3000)),p.text="Polling workflow status...";let D=60,O="",F=0;for(let k=0;k<D;k++){let j=g({cmd:["gh","run","list","--repo","nemarDatasets/.github","--workflow","run-enrichment.yml","-L","10","--json","databaseId,status,conclusion,displayTitle,event"],stdout:"pipe",stderr:"pipe"}),Z=await new Response(j.stdout).text(),_e=await new Response(j.stderr).text();if(await j.exited!==0){if(F++,F>=3){p.warn(`gh CLI error: ${_e.trim()}`);break}await new Promise((Me)=>setTimeout(Me,5000));continue}try{let Me=JSON.parse(Z.trim());F=0;let T=Me.find((B)=>B.event==="workflow_dispatch");if(T){if(T.status==="completed"){O=T.conclusion||"unknown";break}p.text=`Workflow ${T.status}... (${k*5}s)`}}catch(Me){if(F++,F>=3){p.warn(`Unable to parse workflow status: ${Me instanceof Error?Me.message:String(Me)} (raw: ${Z.trim().slice(0,200)})`);break}}await new Promise((Me)=>setTimeout(Me,5000))}let M=!1;if(!O)p.warn("Workflow timed out after 5 minutes (may still be running)");else if(O==="success"){p.succeed("LLM enrichment workflow completed successfully");let k=await jG(y,".nemar/metadata.json");if(k)try{let j=JSON.parse(k);if(j&&typeof j==="object"&&j.version==="2.0"){Object.assign(o,j),M=!0;let Z=j.pipeline_stage||"unknown";if(console.log(u.dim(` Pipeline stage: ${Z}`)),o.authors){let _e=Object.keys(o.authors).length;console.log(u.dim(` Authors: ${_e}`))}}}catch(j){console.log(u.yellow(` Warning: Could not parse updated metadata: ${j instanceof Error?j.message:String(j)}`)),console.log(u.dim(" Using pre-workflow enrichment data"))}else console.log(u.yellow(" Warning: Could not fetch updated metadata after successful workflow.")),console.log(u.dim(" Author data below may be from a previous run."))}else p.fail(`LLM enrichment workflow failed (conclusion: ${O})`);if(!M)console.log(u.yellow(" ORCID discovery did not complete. Authors below may be from previous metadata."))}catch(g){p.fail("LLM enrichment pipeline failed"),console.log(u.dim(` ${V(g)}`)),console.log(u.yellow(" ORCID discovery did not run. You will need to enter ORCIDs manually."))}}console.log(),console.log(u.cyan("--- Author ORCIDs ---"));let a=o.authors||{},c=Object.keys(a);if(c.length>0){let p=c.filter((y)=>a[y]?.orcid),g=c.filter((y)=>!a[y]?.orcid);console.log(u.dim(` Discovered ${c.length} authors from pipeline:`));for(let y of p)console.log(u.green(` [x] ${y}: ${a[y]?.orcid}`));for(let y of g)console.log(u.yellow(` [ ] ${y}: no ORCID found`));if(g.length>0)console.log(u.dim(` ${g.length} author(s) missing ORCIDs.`))}let{updateAuthors:l}=await X.prompt([{type:"confirm",name:"updateAuthors",message:c.length>0?"Add or correct author ORCIDs?":"Add author ORCIDs manually?",default:!1}]);if(l){let p={},g=!0;while(g){let{authorName:y}=await X.prompt([{type:"input",name:"authorName",message:'Author name (as in BIDS, e.g., "Shirazi, Yahya"):'}]);if(!y)break;let x=a[y];if(x?.orcid)console.log(u.dim(` Current ORCID: ${x.orcid}`));let{orcid:v}=await X.prompt([{type:"input",name:"orcid",message:`ORCID for "${y}" (Enter to ${x?.orcid?"keep current":"skip"}):`,validate:(D)=>{if(!D)return!0;return Pm.test(D)||"Invalid ORCID format (XXXX-XXXX-XXXX-XXXX)"}}]),_={};if(v)_.orcid=v;let{affiliation:E}=await X.prompt([{type:"input",name:"affiliation",message:`Affiliation for "${y}" (optional):`}]);if(E)_.affiliations=[{name:E}];if(_.orcid||_.affiliations)p[y]=_;let{more:C}=await X.prompt([{type:"confirm",name:"more",message:"Add another author?",default:!0}]);g=C}if(Object.keys(p).length>0){let y={...o.authors||{}};for(let[x,v]of Object.entries(p)){let _=y[x]||{};y[x]={..._,...v,orcid:v.orcid||_.orcid}}o.authors=y}}console.log(),console.log(u.cyan("--- Dataset stats ---"));let d=w("Computing dataset sizes and formats...").start();try{let p=await uH(e),g=Ze(p.total_size);o.sizes=[`${g} (${p.file_count} files)`],o.formats=p.extensions,d.succeed(`Sizes: ${g} (${p.file_count} files), Formats: ${p.extensions.join(", ")}`)}catch(p){d.warn("Could not compute dataset stats"),console.log(u.dim(` ${V(p)}`))}console.log(),console.log(u.cyan("--- Review ---")),console.log(JSON.stringify(o,null,2)),console.log();let f=await Fe("Commit to repo and refresh DOI?",t,!0);if(f!=="confirmed"){console.log(u.dim(f==="declined"?"Skipped":"Cancelled"));return}let m=w("Saving enrichment...").start();try{let p=await FH(e,o);if(m.succeed(p.message),p.bidsignore_updated)console.log(u.dim(" .bidsignore updated to include .nemar/"));if(!i&&s)try{i=await vd(e)}catch(g){if(process.env.DEBUG)console.error("[debug] DOI info re-fetch:",g)}if(i?.ezid_identifier){let g=w("Refreshing DOI metadata...").start();try{await uD(e,{refresh_metadata:!0}),g.succeed("DOI metadata refreshed")}catch(y){g.warn("Could not refresh DOI metadata"),console.log(u.dim(` ${V(y)}`))}}else if(s)console.log(u.yellow(" DOI refresh skipped: could not verify DOI exists. Run 'nemar admin doi update --refresh' manually."))}catch(p){if(p instanceof q)m.fail(p.message);else m.fail("Failed to save enrichment"),console.log(u.dim(` ${V(p)}`))}});Ie.addCommand(jd);var uh=new ve("publish").description("Publication workflow management");uh.command("list").description("List publication requests").option("-s, --status <status>","Filter by status (requested, approving, published, denied)").addHelpText("after",`
|
|
248
248
|
Description:
|
|
249
249
|
List all publication requests from users, with optional filtering by status.
|
|
250
250
|
Shows dataset ID, status, requesting user, and current progress.
|
package/package.json
CHANGED