fluent-file 0.2.1 → 0.2.2

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.d.ts CHANGED
@@ -303,7 +303,7 @@ declare class FluentFile<Content = string, ParsedContent = Content> {
303
303
  writeBuffer: (bufferContent: Buffer<ArrayBufferLike>, writeOptions?: WriteFileOptions | undefined) => ResultAsync<void, FileWriteError>;
304
304
  write: (content: Content, options?: FileWriteOptions) => ResultAsync<void, FileWriteError | zerde1.ValidationError | zerde1.StringifyError>;
305
305
  createWriteStream: (writeStreamOptions?: Parameters<typeof createWriteStream>[1]) => fs0.WriteStream;
306
- append: (data: string | Buffer<ArrayBufferLike>, writeOptions?: WriteFileOptions | undefined) => ResultAsync<void, FileAppendError>;
306
+ append: (data: string | Buffer<ArrayBufferLike>, writeOptions?: WriteFileOptions | undefined) => ResultAsync<unknown, unknown>;
307
307
  image: (sharpOptions?: SharpOptions) => {
308
308
  metadata: () => ResultAsync<sharpLib.Metadata, FileImageMetadataError>;
309
309
  resize: (resizeOptions: ImageResizeOptions) => ResultAsync<FluentFile<string, string>, FileImageResizeError>;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{constants as e,createReadStream as t,createWriteStream as n}from"node:fs";import{chmod as r,copyFile as i,opendir as a,readFile as o,stat as s}from"node:fs/promises";import{homedir as c,platform as l,tmpdir as u}from"node:os";import{inspect as d}from"node:util";import{fcmd as f}from"fluent-command";import{appendFile as ee}from"fs-extra";import{emptyDir as te,ensureDir as ne,ensureFile as re,ensureLink as ie,ensureSymlink as ae,move as oe,outputFile as p,remove as m}from"fs-extra/esm";import{ResultAsync as h}from"neverthrow";import g,{basename as se}from"pathe";import ce from"sharp";import le from"sharp-phash";import{parseString as ue,zparse as de,zstringify as fe}from"zerde";import _ from"zod";import pe from"picomatch";import{pipeline as me}from"node:stream/promises";const he={Append:`a`,AppendOrFail:`ax`,AppendAndRead:`a+`,AppendAndReadOrFail:`ax+`,Read:`r`,ReadAndWrite:`r+`,Write:`w`,WriteOrFailIfExists:`wx`};function v(...e){let t=e.map((e,t)=>{if(typeof e==`number`)return e.toString();if(t===0&&e===`~`)return c();if(e.toUpperCase()!==e)return e;let n=``;if(e.startsWith(`$`)&&(n=e.slice(1)),l()===`win32`&&e.startsWith(`%`)&&e.endsWith(`%`)&&(n=e.slice(1,-1)),n!==``){let t=process.env[n];if(!t)throw Error(`Missing Environment variable ${e}`);return t}return e});return g.resolve(...t)}function y(e){let t=e.lastIndexOf(`.`);return t<0?e:e.slice(t+1)}function ge(e){return y(g.extname(e))}const _e=4,ve=-5;var b=class extends Error{operation;path;constructor(e,t){super(),this.path=e,this.operation=this.constructor.name.slice(_e,ve),this.message=`Error trying to ${this.operation} file: ${e}`,this.cause=t,this.name=this.constructor.name}},x=class extends b{url;constructor(e,t,n){super(e,n),this.url=t,this.message=`Error trying to download url: ${t} to file: ${e}`}},S=class extends b{},C=class extends b{},w=class extends b{},T=class extends b{},E=class extends b{},D=class extends b{},O=class extends b{},k=class extends b{},A=class extends b{},j=class extends b{};const M=`DESTINATION_FALLBACK`;var N=class extends b{destinationPath;constructor(e,t,n){super(e,n),this.destinationPath=t??M}},P=class extends N{},F=class extends N{},I=class extends N{},L=class extends N{};const ye=6,be=[`avif`,`gif`,`jpeg`,`jpg`,`png`,`svg`,`tiff`,`webp`],R=64,xe=16,z=/^[01]+$/,B=_.codec(_.string().regex(z).length(R),_.hex().brand(`PhashString`),{decode:e=>BigInt(`0b${e}`).toString(xe),encode:e=>BigInt(`0x${e}`).toString(2).padStart(R,`0`)}),V=_.int().nonnegative().max(R).brand(`PhashThreshold`),Se=6,H=V.parse(Se);function Ce(e,t,n=H){if(e===t)return Object.freeze({level:`SAME`,diff:0});let r=B.encode(e),i=B.encode(t),a=0,o=R;for(;o--;)r[o]!==i[o]&&a++;let s=a<n?`SIMILAR`:`DIFFERENT`;return Object.freeze({level:s,diff:a})}function we(e,t,n=H){if(e===t)return!0;let r=B.encode(e),i=B.encode(t),a=0,o=R;for(;o--;)if(r[o]!==i[o]&&a++,a>=n)return!1;return!0}const Te=_.coerce.number().positive(),U=_.coerce.number().int(),Ee=U.nonnegative(),W=U.positive(),G=_.object({duration:Te,bit_rate:W}),De=1e3;function K(e){let t=Math.round(e*De),n=Math.trunc(e%60),r=Math.trunc(e/60%60),i=Math.trunc(e/60/60%60),a=[i,r,n].filter((e,t)=>t>0||e>0).map((e,t)=>{let n=e.toString();return t>0&&(n=n.padStart(2,`0`)),n}).join(`:`);return{millis:t,seconds:n,minutes:r,hours:i,hms:a}}const q=_.object({...G.shape,codec_name:_.string(),codec_long_name:_.string(),codec_tag_string:_.string(),nb_frames:W}),Oe=_.object({...q.shape,codec_type:_.literal(`audio`),channels:W,channel_layout:_.string()}),ke=_.object({...q.shape,codec_type:_.literal(`video`),height:W,width:W}),Ae=_.object({...G.shape,nb_streams:W,format_name:_.string(),format_long_name:_.string(),size:W}),je=_.object({format:Ae,streams:_.array(_.union([Oe,ke])).min(2)}).transform(({format:{duration:e,...t},streams:n},{addIssue:r})=>{let i=n.filter(e=>e.codec_type===`video`).map(({duration:e,...t})=>({...t,...K(e)})).at(0);if(!i)return r({code:`custom`,message:`Video was missing video stream`}),_.NEVER;let a=n.filter(e=>e.codec_type===`audio`).map(({duration:e,...t})=>({...t,...K(e)}));return a.length===0?(r({code:`custom`,message:`Video was missing audio stream`}),_.NEVER):{videoStream:i,audioStreams:a,...t,...K(e)}}),Me=[`avi`,`flv`,`mkv`,`mov`,`mp4`,`mpeg`,`mpg`,`rm`,`rmvb`,`webm`,`wmv`];function Ne(e){return f(`ffprobe`).opt(`hide_banner`).opt(`show_format`).opt(`show_streams`).opt({v:`error`,print_format:`json`}).args(e).read().andThen(e=>de(e.stdout,je,`json`))}var J=class extends Error{operation;path;constructor(e,t,n){let r=`Error trying to ${e} folder: ${t}`;super(r,{cause:n}),this.path=t,this.operation=e,this.name=this.constructor.name}},Pe=class extends J{constructor(e,t){super(`glob`,e,t)}};const Fe={CACHE:{darwin:[`~`,`Library`,`Caches`],linux:[`~`,`.cache`],win32:[`$LOCALAPPDATA`]},CONFIG:{darwin:[`~`,`Library`,`Preferences`],linux:[`~`,`.config`],win32:[`$APPDATA`]},DATA:{darwin:[`~`,`Library`,`Application Support`],linux:[`~`,`.local`,`share`],win32:[`$LOCALAPPDATA`]},STATE:{darwin:[`~`,`Library`,`Logs`],linux:[`~`,`.local`,`state`],win32:[`$LOCALAPPDATA`]}};function Y(e){let t=l();if(t===`win32`||t===`darwin`)return Fe[e][t];let n=process.env[`XDG_${e}_HOME`];return n?[n]:Fe[e].linux}function Ie(...e){return Q(...Y(`CACHE`),...e)}function Le(...e){return Q(...Y(`CONFIG`),...e)}function Re(...e){return Q(...Y(`DATA`),...e)}function ze(...e){return Q(...Y(`STATE`),...e)}function Be(...e){return Q(c(),...e)}function Ve(...e){return Q(u(),...e)}function X(){return Q(process.cwd())}var Z=class{path;name;constructor(...e){this.path=v(...e),this.name=se(this.path),this.name||=this.path}get info(){return{path:this.path,name:this.name}}folder=(...e)=>Q(this.path,...e);file=(e,...t)=>$(this.path,e,...t);relativePath=(e=X())=>{let t=this.path;return t.startsWith(e.path)&&(t=t.slice(e.path.length),t.startsWith(`/`))?t.slice(1):t};toString=()=>this.path;toJSON=()=>({FluentFolder:this.info});[d.custom]=()=>this.toJSON();stats=h.fromThrowable(async()=>{let e=await s(this.path);if(!e.isDirectory())throw new J(`stat`,this.path,`FolderWasNotFolder`);return e},e=>e instanceof J?e:new J(`stat`,this.path,e));exists=async()=>(await this.stats()).isOk();ensureExists=()=>ne(this.path);ensureEmpty=()=>te(this.path);remove=()=>m(this.path);findFolders=h.fromThrowable(async(e={})=>{let t=e.glob?pe(e.glob,{cwd:this.path}):null,n=await a(this.path,{recursive:e.recursive??!0}),r=[];for await(let e of n){if(!e.isDirectory())continue;let n=g.resolve(e.parentPath,e.name);if(t&&!t(n))continue;r.push(n)}return r.sort().map(e=>Q(e))},e=>new Pe(this.path,e));findFiles=h.fromThrowable(async(e={})=>{let t=e.glob?pe(e.glob,{cwd:this.path}):null,n=await a(this.path,{recursive:e.recursive??!0}),r=[],i=(e.exts??[]).map(y);for await(let e of n){if(!e.isFile())continue;let n=g.resolve(e.parentPath,e.name);if(i.length>0){let t=ge(e.name);if(!i.includes(t))continue}if(t&&!t(n))continue;r.push(n)}return r.sort().map(e=>$(e))},e=>new Pe(this.path,e))};function Q(...e){return new Z(...e)}const He=h.fromThrowable(async(e,t,n={})=>{try{let{overwrite:r=!1,progressThrottle:i=100,onProgress:a}=n;if(!r&&await t.exists())return`ALREADY_EXISTS`;await t.folder().ensureExists();let o=await fetch(e);if(!o.ok){let{status:t,statusText:n,redirected:r,type:i}=o,a={};throw o.headers.forEach((e,t)=>{a[t]=e}),Error(`Got ${o.status} ${o.statusText} for url: ${e}`,{cause:{status:t,statusText:n,headers:a,redirected:r,type:i}})}let s=W.parse(o.headers.get(`content-length`));if(!o.body)throw Error(`Request body was null for url: ${e}`,{cause:o});let c=o.body,l=t.createWriteStream();if(!a)return await me(c,l),`SUCCESS`;let u=0,d=null,f=e=>{u+=e,!d&&(a({downloadedBytes:u,totalBytes:s}),d=setTimeout(()=>{d=null},i))};return await me(c,async function*(e){for await(let t of e)f(t.length)},l),`SUCCESS`}catch(n){throw new x(t.path(),e,n)}},e=>e);var Ue=class a{#path;#folderPath;#name;#basename;#ext;#schema;#info;#ensureDestination=async e=>{let t=e instanceof a?e:e.file(this.#name);return await t.folder().ensureExists(),await t.remove(),t.path()};#prepareTarget=async e=>{let{newFolder:t=this.folder(),newBaseName:n=this.#basename,newExt:r=this.#ext}=e,i=t.file(`${n}.${r}`);return await i.remove(),await t.ensureExists(),i};constructor(e,t,...n){this.#path=v(t,...n),this.#schema=e;let r=We(this.#path);this.#folderPath=r.folderPath,this.#name=r.name,this.#basename=r.basename,this.#ext=r.ext,this.#info=r}toString=()=>this.#path;toJSON=()=>({FluentFile:this.info});[d.custom]=()=>this.toJSON();path=()=>this.#path;folderPath=()=>this.#folderPath;name(e){return e===void 0?this.#name:(this.#name=e,this.#path=`${this.#folderPath}/${e}`,this)}basename(e){return e===void 0?this.#basename:(this.#basename=e,this.#name=e+this.#ext,this.#path=`${this.#folderPath}/${this.#name}`,this)}ext(e){return e===void 0?this.#ext:(this.#ext=e,this.#name=this.#basename+e,this.#path=`${this.#folderPath}/${this.#name}`,this)}schema=e=>new a(e,this.#path);get info(){return this.#info}relativePath=(e=X())=>{let t=this.#path;return t.startsWith(e.path)&&(t=t.slice(e.path.length),t.startsWith(`/`))?t.slice(1):t};file=(e,...t)=>new a(this.#schema,this.#folderPath,e,...t);folder=(...e)=>new Z(this.#folderPath,...e);stats=h.fromThrowable(async()=>{let e=await s(this.#path);if(!e.isFile())throw new A(this.#path,`FileWasNotFile`);return e},e=>e instanceof A?e:new A(this.#path,e));exists=async()=>(await this.stats()).isOk();ensureExists=()=>re(this.#path);chmod=h.fromThrowable(async e=>{await r(this.#path,e)},e=>new C(this.#path,e));copyTo=h.fromThrowable(async t=>{let n=null;try{n=await this.#ensureDestination(t),await i(this.#path,n,e.COPYFILE_FICLONE)}catch(e){throw new P(this.#path,n,e)}},e=>e);moveTo=h.fromThrowable(async(e,t)=>{let n=null;try{n=await this.#ensureDestination(e),await oe(this.#path,n,{overwrite:!0,dereference:t})}catch(e){throw new F(this.#path,n,e)}},e=>e);linkTo=h.fromThrowable(async e=>{let t=null;try{t=await this.#ensureDestination(e),await ie(this.#path,t)}catch(e){throw new I(this.#path,t,e)}},e=>e);symlinkTo=h.fromThrowable(async e=>{let t=null;try{t=await this.#ensureDestination(e),await ae(this.#path,t)}catch(e){throw new L(this.#path,t,e)}},e=>e);remove=h.fromThrowable(()=>m(this.#path),e=>new k(this.#path,e));readText=h.fromThrowable((e={})=>o(this.#path,{encoding:`utf8`,...e}),e=>new O(this.#path,e));readBuffer=h.fromThrowable((e={})=>o(this.#path,e),e=>new O(this.#path,e));read=(e={})=>this.readText(e).andThen(t=>de(t,this.#schema,{format:this.#path,...e}));createReadStream=e=>t(this.#path,e);writeText=h.fromThrowable((e,t={})=>p(this.#path,e,t),e=>new j(this.#path,e));writeBuffer=h.fromThrowable((e,t={})=>p(this.#path,e,t),e=>new j(this.#path,e));write=(e,t={})=>fe(e,this.#schema,t).andThen(e=>this.writeText(e,t));createWriteStream=e=>n(this.#path,e);append=h.fromThrowable((e,t={})=>ee(this.#path,e,t),e=>new S(this.#path,e));image=(e={})=>{let t=ce(this.#path,e),n=h.fromThrowable(()=>t.metadata(),e=>new T(this.#path,e)),r=h.fromThrowable(async e=>{let n=await this.#prepareTarget(e);return await t.resize(e).toFile(n.path()),n},e=>new D(this.#path,e)),i=h.fromThrowable(async(e={})=>{let n=await this.#prepareTarget({...e,newExt:`avif`});return await t.resize(e).avif(e).toFile(n.path()),n},e=>new w(this.#path,e)),a=h.fromThrowable(async()=>{let t=await le(this.#path,e);return B.decode(t)},e=>new E(this.#path,e));return{...t,metadata:n,resize:r,toAVIF:i,phash:a}};video=()=>({metadata:()=>Ne(this.#path),extractFrame:async(e={})=>{let{time:t=1,unit:n=`s`,ext:r=`png`,...i}=e,a=n===`s`?t:`${t}${n}`,o=await this.#prepareTarget({newExt:r,...i});return f(`ffmpeg`).opt(`hide_banner`).opt({ss:a,i:this.#path,"frames:v":1,y:``}).args(o.path()).read().map(()=>o)}});download=(e,t={})=>He(e,this,t)};function We(e){let t=g.basename(e),n=g.dirname(e),r=``,i=``,a=t.lastIndexOf(`.`);return a<=0?(r=t,i=``):(r=t.slice(0,a),i=t.slice(a+1)),{absolutePath:e,folderPath:n,name:t,basename:r,ext:i}}function $(e,...t){return new Ue(ue(),e,...t)}function Ge(e,...t){return $(c(),e,...t)}export{H as DEFAULT_PHASH_THRESHOLD,M as DESTINATION_FALLBACK,S as FileAppendError,C as FileChmodError,P as FileCopyError,x as FileDownloadError,w as FileImageConvertError,T as FileImageMetadataError,E as FileImagePhashError,D as FileImageResizeError,I as FileLinkError,F as FileMoveError,O as FileReadError,k as FileRemoveError,A as FileStatError,L as FileSymLinkError,j as FileWriteError,Ue as FluentFile,Z as FluentFolder,he as FsFlags,be as IMAGE_EXTENSIONS,ye as MAX_DIFFERENCES,Me as VIDEO_EXTENSIONS,z as binaryStringRegex,Ie as cacheFolder,Ce as comparePhashes,Le as configFolder,X as currentFolder,Re as dataFolder,$ as ffile,Q as folder,Ne as getVideoMetaData,Ge as homeFile,Be as homeFolder,ze as logsFolder,B as phashStringSchema,V as phashThresholdSchema,we as phashesMatch,Ve as tempFolder};
1
+ import{appendFile as e,constants as t,createReadStream as n,createWriteStream as r}from"node:fs";import{chmod as i,copyFile as a,opendir as o,readFile as s,stat as c}from"node:fs/promises";import{homedir as l,platform as u,tmpdir as d}from"node:os";import{inspect as f}from"node:util";import{fcmd as p}from"fluent-command";import{emptyDir as ee,ensureDir as te,ensureFile as ne,ensureLink as re,ensureSymlink as ie,move as ae,outputFile as m,remove as h}from"fs-extra/esm";import{ResultAsync as g}from"neverthrow";import _,{basename as oe}from"pathe";import se from"sharp";import ce from"sharp-phash";import{parseString as le,zparse as ue,zstringify as de}from"zerde";import v from"zod";import fe from"picomatch";import{pipeline as pe}from"node:stream/promises";const me={Append:`a`,AppendOrFail:`ax`,AppendAndRead:`a+`,AppendAndReadOrFail:`ax+`,Read:`r`,ReadAndWrite:`r+`,Write:`w`,WriteOrFailIfExists:`wx`};function y(...e){let t=e.map((e,t)=>{if(typeof e==`number`)return e.toString();if(t===0&&e===`~`)return l();if(e.toUpperCase()!==e)return e;let n=``;if(e.startsWith(`$`)&&(n=e.slice(1)),u()===`win32`&&e.startsWith(`%`)&&e.endsWith(`%`)&&(n=e.slice(1,-1)),n!==``){let t=process.env[n];if(!t)throw Error(`Missing Environment variable ${e}`);return t}return e});return _.resolve(...t)}function b(e){let t=e.lastIndexOf(`.`);return t<0?e:e.slice(t+1)}function he(e){return b(_.extname(e))}const ge=4,_e=-5;var x=class extends Error{operation;path;constructor(e,t){super(),this.path=e,this.operation=this.constructor.name.slice(ge,_e),this.message=`Error trying to ${this.operation} file: ${e}`,this.cause=t,this.name=this.constructor.name}},S=class extends x{url;constructor(e,t,n){super(e,n),this.url=t,this.message=`Error trying to download url: ${t} to file: ${e}`}},C=class extends x{},w=class extends x{},T=class extends x{},E=class extends x{},D=class extends x{},O=class extends x{},k=class extends x{},A=class extends x{},j=class extends x{},M=class extends x{};const N=`DESTINATION_FALLBACK`;var P=class extends x{destinationPath;constructor(e,t,n){super(e,n),this.destinationPath=t??N}},F=class extends P{},I=class extends P{},L=class extends P{},R=class extends P{};const ve=6,ye=[`avif`,`gif`,`jpeg`,`jpg`,`png`,`svg`,`tiff`,`webp`],z=64,be=16,B=/^[01]+$/,V=v.codec(v.string().regex(B).length(z),v.hex().brand(`PhashString`),{decode:e=>BigInt(`0b${e}`).toString(be),encode:e=>BigInt(`0x${e}`).toString(2).padStart(z,`0`)}),H=v.int().nonnegative().max(z).brand(`PhashThreshold`),xe=6,U=H.parse(xe);function Se(e,t,n=U){if(e===t)return Object.freeze({level:`SAME`,diff:0});let r=V.encode(e),i=V.encode(t),a=0,o=z;for(;o--;)r[o]!==i[o]&&a++;let s=a<n?`SIMILAR`:`DIFFERENT`;return Object.freeze({level:s,diff:a})}function Ce(e,t,n=U){if(e===t)return!0;let r=V.encode(e),i=V.encode(t),a=0,o=z;for(;o--;)if(r[o]!==i[o]&&a++,a>=n)return!1;return!0}const we=v.coerce.number().positive(),W=v.coerce.number().int(),Te=W.nonnegative(),G=W.positive(),K=v.object({duration:we,bit_rate:G}),Ee=1e3;function q(e){let t=Math.round(e*Ee),n=Math.trunc(e%60),r=Math.trunc(e/60%60),i=Math.trunc(e/60/60%60),a=[i,r,n].filter((e,t)=>t>0||e>0).map((e,t)=>{let n=e.toString();return t>0&&(n=n.padStart(2,`0`)),n}).join(`:`);return{millis:t,seconds:n,minutes:r,hours:i,hms:a}}const De=v.object({...K.shape,codec_name:v.string(),codec_long_name:v.string(),codec_tag_string:v.string(),nb_frames:G}),Oe=v.object({...De.shape,codec_type:v.literal(`audio`),channels:G,channel_layout:v.string()}),ke=v.object({...De.shape,codec_type:v.literal(`video`),height:G,width:G}),Ae=v.object({...K.shape,nb_streams:G,format_name:v.string(),format_long_name:v.string(),size:G}),je=v.object({format:Ae,streams:v.array(v.union([Oe,ke])).min(2)}).transform(({format:{duration:e,...t},streams:n},{addIssue:r})=>{let i=n.filter(e=>e.codec_type===`video`).map(({duration:e,...t})=>({...t,...q(e)})).at(0);if(!i)return r({code:`custom`,message:`Video was missing video stream`}),v.NEVER;let a=n.filter(e=>e.codec_type===`audio`).map(({duration:e,...t})=>({...t,...q(e)}));return a.length===0?(r({code:`custom`,message:`Video was missing audio stream`}),v.NEVER):{videoStream:i,audioStreams:a,...t,...q(e)}}),Me=[`avi`,`flv`,`mkv`,`mov`,`mp4`,`mpeg`,`mpg`,`rm`,`rmvb`,`webm`,`wmv`];function Ne(e){return p(`ffprobe`).opt(`hide_banner`).opt(`show_format`).opt(`show_streams`).opt({v:`error`,print_format:`json`}).args(e).read().andThen(e=>ue(e.stdout,je,`json`))}var J=class extends Error{operation;path;constructor(e,t,n){let r=`Error trying to ${e} folder: ${t}`;super(r,{cause:n}),this.path=t,this.operation=e,this.name=this.constructor.name}},Pe=class extends J{constructor(e,t){super(`glob`,e,t)}};const Fe={CACHE:{darwin:[`~`,`Library`,`Caches`],linux:[`~`,`.cache`],win32:[`$LOCALAPPDATA`]},CONFIG:{darwin:[`~`,`Library`,`Preferences`],linux:[`~`,`.config`],win32:[`$APPDATA`]},DATA:{darwin:[`~`,`Library`,`Application Support`],linux:[`~`,`.local`,`share`],win32:[`$LOCALAPPDATA`]},STATE:{darwin:[`~`,`Library`,`Logs`],linux:[`~`,`.local`,`state`],win32:[`$LOCALAPPDATA`]}};function Y(e){let t=u();if(t===`win32`||t===`darwin`)return Fe[e][t];let n=process.env[`XDG_${e}_HOME`];return n?[n]:Fe[e].linux}function Ie(...e){return Q(...Y(`CACHE`),...e)}function Le(...e){return Q(...Y(`CONFIG`),...e)}function Re(...e){return Q(...Y(`DATA`),...e)}function ze(...e){return Q(...Y(`STATE`),...e)}function Be(...e){return Q(l(),...e)}function Ve(...e){return Q(d(),...e)}function X(){return Q(process.cwd())}var Z=class{path;name;constructor(...e){this.path=y(...e),this.name=oe(this.path),this.name||=this.path}get info(){return{path:this.path,name:this.name}}folder=(...e)=>Q(this.path,...e);file=(e,...t)=>$(this.path,e,...t);relativePath=(e=X())=>{let t=this.path;return t.startsWith(e.path)&&(t=t.slice(e.path.length),t.startsWith(`/`))?t.slice(1):t};toString=()=>this.path;toJSON=()=>({FluentFolder:this.info});[f.custom]=()=>this.toJSON();stats=g.fromThrowable(async()=>{let e=await c(this.path);if(!e.isDirectory())throw new J(`stat`,this.path,`FolderWasNotFolder`);return e},e=>e instanceof J?e:new J(`stat`,this.path,e));exists=async()=>(await this.stats()).isOk();ensureExists=()=>te(this.path);ensureEmpty=()=>ee(this.path);remove=()=>h(this.path);findFolders=g.fromThrowable(async(e={})=>{let t=e.glob?fe(e.glob,{cwd:this.path}):null,n=await o(this.path,{recursive:e.recursive??!0}),r=[];for await(let e of n){if(!e.isDirectory())continue;let n=_.resolve(e.parentPath,e.name);if(t&&!t(n))continue;r.push(n)}return r.sort().map(e=>Q(e))},e=>new Pe(this.path,e));findFiles=g.fromThrowable(async(e={})=>{let t=e.glob?fe(e.glob,{cwd:this.path}):null,n=await o(this.path,{recursive:e.recursive??!0}),r=[],i=(e.exts??[]).map(b);for await(let e of n){if(!e.isFile())continue;let n=_.resolve(e.parentPath,e.name);if(i.length>0){let t=he(e.name);if(!i.includes(t))continue}if(t&&!t(n))continue;r.push(n)}return r.sort().map(e=>$(e))},e=>new Pe(this.path,e))};function Q(...e){return new Z(...e)}const He=g.fromThrowable(async(e,t,n={})=>{try{let{overwrite:r=!1,progressThrottle:i=100,onProgress:a}=n;if(!r&&await t.exists())return`ALREADY_EXISTS`;await t.folder().ensureExists();let o=await fetch(e);if(!o.ok){let{status:t,statusText:n,redirected:r,type:i}=o,a={};throw o.headers.forEach((e,t)=>{a[t]=e}),Error(`Got ${o.status} ${o.statusText} for url: ${e}`,{cause:{status:t,statusText:n,headers:a,redirected:r,type:i}})}let s=G.parse(o.headers.get(`content-length`));if(!o.body)throw Error(`Request body was null for url: ${e}`,{cause:o});let c=o.body,l=t.createWriteStream();if(!a)return await pe(c,l),`SUCCESS`;let u=0,d=null,f=e=>{u+=e,!d&&(a({downloadedBytes:u,totalBytes:s}),d=setTimeout(()=>{d=null},i))};return await pe(c,async function*(e){for await(let t of e)f(t.length)},l),`SUCCESS`}catch(n){throw new S(t.path(),e,n)}},e=>e);var Ue=class o{#path;#folderPath;#name;#basename;#ext;#schema;#info;#ensureDestination=async e=>{let t=e instanceof o?e:e.file(this.#name);return await t.folder().ensureExists(),await t.remove(),t.path()};#prepareTarget=async e=>{let{newFolder:t=this.folder(),newBaseName:n=this.#basename,newExt:r=this.#ext}=e,i=t.file(`${n}.${r}`);return await i.remove(),await t.ensureExists(),i};constructor(e,t,...n){this.#path=y(t,...n),this.#schema=e;let r=We(this.#path);this.#folderPath=r.folderPath,this.#name=r.name,this.#basename=r.basename,this.#ext=r.ext,this.#info=r}toString=()=>this.#path;toJSON=()=>({FluentFile:this.info});[f.custom]=()=>this.toJSON();path=()=>this.#path;folderPath=()=>this.#folderPath;name(e){return e===void 0?this.#name:(this.#name=e,this.#path=`${this.#folderPath}/${e}`,this)}basename(e){return e===void 0?this.#basename:(this.#basename=e,this.#name=e+this.#ext,this.#path=`${this.#folderPath}/${this.#name}`,this)}ext(e){return e===void 0?this.#ext:(this.#ext=e,this.#name=this.#basename+e,this.#path=`${this.#folderPath}/${this.#name}`,this)}schema=e=>new o(e,this.#path);get info(){return this.#info}relativePath=(e=X())=>{let t=this.#path;return t.startsWith(e.path)&&(t=t.slice(e.path.length),t.startsWith(`/`))?t.slice(1):t};file=(e,...t)=>new o(this.#schema,this.#folderPath,e,...t);folder=(...e)=>new Z(this.#folderPath,...e);stats=g.fromThrowable(async()=>{let e=await c(this.#path);if(!e.isFile())throw new j(this.#path,`FileWasNotFile`);return e},e=>e instanceof j?e:new j(this.#path,e));exists=async()=>(await this.stats()).isOk();ensureExists=()=>ne(this.#path);chmod=g.fromThrowable(async e=>{await i(this.#path,e)},e=>new w(this.#path,e));copyTo=g.fromThrowable(async e=>{let n=null;try{n=await this.#ensureDestination(e),await a(this.#path,n,t.COPYFILE_FICLONE)}catch(e){throw new F(this.#path,n,e)}},e=>e);moveTo=g.fromThrowable(async(e,t)=>{let n=null;try{n=await this.#ensureDestination(e),await ae(this.#path,n,{overwrite:!0,dereference:t})}catch(e){throw new I(this.#path,n,e)}},e=>e);linkTo=g.fromThrowable(async e=>{let t=null;try{t=await this.#ensureDestination(e),await re(this.#path,t)}catch(e){throw new L(this.#path,t,e)}},e=>e);symlinkTo=g.fromThrowable(async e=>{let t=null;try{t=await this.#ensureDestination(e),await ie(this.#path,t)}catch(e){throw new R(this.#path,t,e)}},e=>e);remove=g.fromThrowable(()=>h(this.#path),e=>new A(this.#path,e));readText=g.fromThrowable((e={})=>s(this.#path,{encoding:`utf8`,...e}),e=>new k(this.#path,e));readBuffer=g.fromThrowable((e={})=>s(this.#path,e),e=>new k(this.#path,e));read=(e={})=>this.readText(e).andThen(t=>ue(t,this.#schema,{format:this.#path,...e}));createReadStream=e=>n(this.#path,e);writeText=g.fromThrowable((e,t={})=>m(this.#path,e,t),e=>new M(this.#path,e));writeBuffer=g.fromThrowable((e,t={})=>m(this.#path,e,t),e=>new M(this.#path,e));write=(e,t={})=>de(e,this.#schema,t).andThen(e=>this.writeText(e,t));createWriteStream=e=>r(this.#path,e);append=g.fromThrowable((t,n={})=>e(this.#path,t,n),e=>new C(this.#path,e));image=(e={})=>{let t=se(this.#path,e),n=g.fromThrowable(()=>t.metadata(),e=>new E(this.#path,e)),r=g.fromThrowable(async e=>{let n=await this.#prepareTarget(e);return await t.resize(e).toFile(n.path()),n},e=>new O(this.#path,e)),i=g.fromThrowable(async(e={})=>{let n=await this.#prepareTarget({...e,newExt:`avif`});return await t.resize(e).avif(e).toFile(n.path()),n},e=>new T(this.#path,e)),a=g.fromThrowable(async()=>{let t=await ce(this.#path,e);return V.decode(t)},e=>new D(this.#path,e));return{...t,metadata:n,resize:r,toAVIF:i,phash:a}};video=()=>({metadata:()=>Ne(this.#path),extractFrame:async(e={})=>{let{time:t=1,unit:n=`s`,ext:r=`png`,...i}=e,a=n===`s`?t:`${t}${n}`,o=await this.#prepareTarget({newExt:r,...i});return p(`ffmpeg`).opt(`hide_banner`).opt({ss:a,i:this.#path,"frames:v":1,y:``}).args(o.path()).read().map(()=>o)}});download=(e,t={})=>He(e,this,t)};function We(e){let t=_.basename(e),n=_.dirname(e),r=``,i=``,a=t.lastIndexOf(`.`);return a<=0?(r=t,i=``):(r=t.slice(0,a),i=t.slice(a+1)),{absolutePath:e,folderPath:n,name:t,basename:r,ext:i}}function $(e,...t){return new Ue(le(),e,...t)}function Ge(e,...t){return $(l(),e,...t)}export{U as DEFAULT_PHASH_THRESHOLD,N as DESTINATION_FALLBACK,C as FileAppendError,w as FileChmodError,F as FileCopyError,S as FileDownloadError,T as FileImageConvertError,E as FileImageMetadataError,D as FileImagePhashError,O as FileImageResizeError,L as FileLinkError,I as FileMoveError,k as FileReadError,A as FileRemoveError,j as FileStatError,R as FileSymLinkError,M as FileWriteError,Ue as FluentFile,Z as FluentFolder,me as FsFlags,ye as IMAGE_EXTENSIONS,ve as MAX_DIFFERENCES,Me as VIDEO_EXTENSIONS,B as binaryStringRegex,Ie as cacheFolder,Se as comparePhashes,Le as configFolder,X as currentFolder,Re as dataFolder,$ as ffile,Q as folder,Ne as getVideoMetaData,Ge as homeFile,Be as homeFolder,ze as logsFolder,V as phashStringSchema,H as phashThresholdSchema,Ce as phashesMatch,Ve as tempFolder};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluent-file",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A fluent TypeScript library for working with files and folders",
5
5
  "keywords": [
6
6
  "files",