New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

phylo

Package Overview
Dependencies
Maintainers
2
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

phylo - npm Package Compare versions

Comparing version 0.0.2 to 1.0.0-beta.1

foo/foo.json

6

package.json
{
"name": "phylo",
"version": "0.0.2",
"version": "1.0.0-beta.1",
"description": "File operations class",

@@ -26,4 +26,6 @@ "main": "File.js",

"json5": "^0.5.0",
"mkdirp": "^0.5.1"
"mkdirp": "^0.5.1",
"rimraf": "^2.5.4",
"tmp": "0.0.30"
}
}
'use strict';
const File = require('./File');
const Globber = File.Globber;
File.COMPANY = 'Foobar';
var f;
var gg = Globber.get('i');
console.log(gg);
var re = gg.compile('**/*.txt');
console.log(re);
console.log('match:', re.exec('C:\\Program Files/foo.txt'));
var f = File.temp();
console.log(`home: ${File.home()}`);
console.log(`profile: ${File.profile('Acme')}`);
console.log(`profile: ${File.profile()}`);
//console.log(`profile.stat: `, File.profile().stat());
//console.log(`profile.access: `, File.profile().access());
f = File.cwd().upTo('package.json').load();
console.log(`package ${f.name}`);
File.asyncTemp().then(t => {
console.log(`asyncTemp: ${t}`);
});
f = new File('~/.sencha');
console.log(`temp: ${f}`);
console.log(`File.temp: ${File.temp()}`);
console.log(`tempFile: ${f.temp().absolutePath()}`);
console.log(`f: ${f}`);
console.log(`f.abssolute: ${f.absolutePath()}`);
console.log(`f.canonical: ${f.canonicalPath()}`);
console.log(`f.native: ${f.nativePath()}`);
console.log(`f.normalized: ${f.normalizedPath()}`);
console.log(`f.slashified: ${f.slashifiedPath()}`);
console.log(`f.join: ${f.join('foo')}`);
console.log(`f.parent: ${f.parent}`);
console.log(`f.parent.join: ${f.parent.join('foo')}`);
console.log(`f.parent.parent: ${f.parent.parent}`);
File.asyncTemp().then(t => {
console.log(`asyncTemp: ${t}`);
});
f.list('A').forEach(ff => {
let pkg = File.cwd().upTo('package.json').load();
console.log(`package ${pkg.name}`);
f.asyncTemp().then(ff => {
console.log(`ff: ${ff}`);
});
try {
File.from('C:\\Windows\\foobar.txt').save(pkg);
}
catch (e) {
console.log(`error: ${e.code} - ${e.message}`);
}
// f.join('foo.json').save(pkg, {
// indent: '\t'
// });
//
// f.list().forEach(ff => {
// console.log(`ff: ${ff.path}`);
// });
// f = new File('~/.sencha');
//
// console.log(`f: ${f}`);
// console.log(`f.absolute: ${f.absolutePath()}`);
// console.log(`f.canonical: ${f.canonicalPath()}`);
// console.log(`f.native: ${f.nativePath()}`);
// console.log(`f.normalized: ${f.normalizedPath()}`);
// console.log(`f.slashified: ${f.slashifiedPath()}`);
// console.log(`f.join: ${f.join('foo')}`);
// console.log(`f.parent: ${f.parent}`);
// console.log(`f.parent.join: ${f.parent.join('foo')}`);
// console.log(`f.parent.parent: ${f.parent.parent}`);
// f = File.cwd();
// f.list('A', '*.js').forEach(ff => {
// console.log(`ff: ${ff} ==> ${ff.name}`);
// });
var fd = File.cwd().join('foo');
fd.mkdir();
File.cwd().list('A', ff => {
console.log(`ff: ${ff}`);
});
// console.log(`rm ${fd}`);
// fd.remove();
// File.cwd().list('A', ff => {
// console.log(`ff: ${ff}`);
// });
f = fd.join('foo.json');
f.save(pkg, 'json5');
f.parent.list('A', '*.json').forEach(ff => {
console.log(`ff: ${ff} ==> ${ff.name}`);
});
f = new File('~~/.sencha');
console.log(`f: ${f}`);
console.log(`f.abssolute: ${f.absolutePath()}`);
//console.log(`f.canonical: ${f.canonicalPath()}`);
console.log(`f.native: ${f.nativePath()}`);
console.log(`f.normalized: ${f.normalizedPath()}`);
console.log(`f.slashified: ${f.slashifiedPath()}`);
console.log(`f.join: ${f.join('foo')}`);
console.log(`f.parent: ${f.parent}`);
console.log(`f.parent.join: ${f.parent.join('foo')}`);
console.log(`f.parent.parent: ${f.parent.parent}`);
console.log(`rm ${f.name}`);
f.remove();
f.parent.list('A', '*.json').forEach(ff => {
console.log(`ff: ${ff} ==> ${ff.name}`);
});
//f.save(pkg, 'json5');
fd.asyncRemove().then(ff => {
console.log(`ff: ${ff}`);
File.cwd().list('A', cc => {
console.log(`cc: ${cc}`);
});
},
e => {
console.log('rm err:', e.message);
});
// f.list('A', (name, f2) => { console.log('f2',f2); return name.endsWith('.js'); }).forEach(ff => {
// console.log(`ff: ${ff} ==> ${ff.name}`);
// });
// f.walk('A', '**/*.{js,json}', ff => {
// console.log(`walk: ${ff}`)
// });
// f = new File('~~/.sencha');
// console.log(`f: ${f}`);
// console.log(`f.absolute: ${f.absolutePath()}`);
// //console.log(`f.canonical: ${f.canonicalPath()}`);
// console.log(`f.native: ${f.nativePath()}`);
// console.log(`f.normalized: ${f.normalizedPath()}`);
// console.log(`f.slashified: ${f.slashifiedPath()}`);
// console.log(`f.join: ${f.join('foo')}`);
// console.log(`f.parent: ${f.parent}`);
// console.log(`f.parent.join: ${f.parent.join('foo')}`);
// console.log(`f.parent.parent: ${f.parent.parent}`);
//console.log(`load: ${f.join('don.license').load()}`);

@@ -63,4 +151,8 @@

// f.asyncWalk('Ad', (item, state) => {
// console.log(`${' '.repeat(state.stack.length * 4)}${item.name} - ${item._stat ? item._stat.attribs : ''}`);
// f = File.cwd();
// f.asyncWalk('', (item, state) => {
// //let c = item.isDirectory() ? '>' : ' ';
// //console.log(`${c} ${' '.repeat(state.stack.length * 4)}${item.name} - ${item._stat ? item._stat.attribs : ''}`);
// }, (item, state) => {
// console.log(`< ${' '.repeat(state.stack.length * 4)}${item.name} - ${item.stat().attrib.text}`);
// }).then(() => {

@@ -67,0 +159,0 @@ // console.log('done');

@@ -53,2 +53,9 @@ # phylo

- Callbacks passed to async methods can return immediate results or Promises.
- As much as possible, exceptions and `null` return values are avoided. For
example, `stat()` returns an object in all cases but that object may have an
`error` property.
- Where reasonable, objects are cached to avoid GC pressure. For example, things
like access masks, file attributes, status errors, directory list modes, etc. are
lazily cached as immutable (`Object.freeze()` enforced) instances and reused as
needed.

@@ -117,4 +124,5 @@ ## Path Manipulation

- `equals(o)` - Returns `true` if `this` is equal to `o` (`compare(o) === 0`)
- `prefixes(o)` - Returns `true` if `this` is a path prefix of `o`. Best to
use `absolutify()` on both instances first to avoid issues with `..` segments.
- `prefixes(o)` - Returns `true` if `this` is a path prefix of `o`. It is
recommended to use `absolutify()` on both instances first to avoid confusion with
`..` segments.

@@ -140,3 +148,4 @@ File name comparisons are case-insensitive on Windows and Mac OS X, so we have

- `access()` - Returns a `FileAccess` object or `null` if the file doesn't exist.
- `access()` - Returns a `File.Access` object. If the file does not exist (or some
other error is encountered), this object will have an `error` property.
- `can(mode)` - Returns `true` if this exists with the desired access (`mode` is "r",

@@ -148,9 +157,19 @@ "rw", "rwx", "w", "wx" or "x").

- `hasFile(rel)` - Returns `true` if a file exists at the `rel` path from this file.
- `isHidden()` - Returns `true` if this file does not exist or is hidden.
- `stat()` / `restat()` - Returns `fs.statSync(this.path)` (an `fs.Stats`).
- `statLink()` / `restatLink()` - Returns `fs.lstatSync(this.path)` (an `fs.Stats`).
- `isHidden()` - Returns `true` if this file does not exist or is hidden. Note that on
Windows, hidden state is not based on a file name convention (".hidden") but is a bit
stored in the file-system (see below).
- `stat()` / `restat()` - Returns `fs.statSync(this.path)` (an `fs.Stats`). If the
file does not exist (or some other error is encountered), this object will have an
`error` property.
- `statLink()` / `restatLink()` - Returns `fs.lstatSync(this.path)` (an `fs.Stats`). If
the file does not exist (or some other error is encountered), this object will have an
`error` property.
The `error` property will be a value like `"ENOENT"` (for file/folder not found), and
`"EACCES"` or `"EPERM"` for permission denied. These codes come directly from the
underlying API.
In asynchronous form:
- `asyncAccess()` - Promises a `FileAccess`
- `asyncAccess()` - Promises a `File.Access`
- `asyncCan(mode)` - Promises `true` or `false`.

@@ -165,22 +184,31 @@ - `asyncExists()` - Promises `true` or `false`.

### FileAccess
### File Status
`FileAccess` objects are succinct descriptions of read, write and execute permission
masks. These replace the use of fs.constants.R_OK, fs.constants.W_OK and
fs.constants.X_OK. For example:
let mode = fs.statSync(file).mode;
if (mode & fs.constants.R_OK && mode & fs.constants.W_OK) {
// path is R and W
}
The [`fs.Stat`](https://nodejs.org/api/fs.html#fs_class_fs_stats) structure is augmented
with an `attrib` property. This is an instance of `File.Attribute` and will have these
boolean properties:
Or using `File` and `FileAccess`:
- `A` - Archive
- `C` - Compressed
- `E` - Encrypted
- `H` - Hidden
- `O` - Offline
- `R` - Readonly
- `S` - System
if (file.access().rw) {
// path is R and W
}
The [`fswin`](https://www.npmjs.com/package/fswin) module is used to retrieve this
information on Windows. On other platforms, this object contains `false` values for all
of the above properties.
To handle the case where the file may not exist, compare:
An `fs.Stat` object is cached on the `File` instance by the `stat()` family of methods
and a separate instance is cached on by the `statLink()` family. These are lazily
retrieved and then stored for future use. To get fresh copies, use the `restat()` family
of methods.
### File.Access
`File.Access` objects are succinct descriptions of read, write and execute permission
masks. These replace the use of `fs.constants.R_OK`, `fs.constants.W_OK` and
`fs.constants.X_OK`. For example:
try {

@@ -197,4 +225,10 @@ let mode = fs.statSync(file).mode;

But using `File` this can be:
Or using `File` and `File.Access`:
if (file.access().rw) {
// file exists and is R & W
}
Alternatively, there is the `can()` method:
if (file.can('rw')) {

@@ -204,6 +238,25 @@ // file exists and is R & W

There are a fixed set of `FileAccess` objects, one for each combination of R, W and X
permissions: `r`, `rw`, `rx`, `rwx`, `w`, `wx`, `x`. Each instance also has these
same properties as boolean values. The full set of properties is a bit larger:
When the file does not exist, or an error is encountered, the object returned by the
`access()` method will have an `error` property. Since the access bits are all `false`
in this case, this distinction if often unimportant (as above).
To check for errors:
var acc = file.accecss();
if (acc.rw) {
// file exists and has R/W access
}
else if (acc.error === 'ENOENT') {
// file does not exist...
}
else if (acc.error === 'EACCES' || acc.error === 'EPERM') {
// access or permission error...
}
...
There are a fixed set of immutable `File.Access` objects, one for each combination of
R, W and X permissions: `r`, `rw`, `rx`, `rwx`, `w`, `wx`, `x`. Each instance also has
these same properties as boolean values. The full set of properties is a bit larger:
- `r` - True if `R_OK` is set.

@@ -222,34 +275,37 @@ - `rw` - True if `R_OK` and `W_OK` are both set.

It is often important to know if a file is a directory or other type of entity. This
information is fundamentally a result of the `stat()` family but for convenience is
information is fundamentally the business of the `stat()` family but for convenience is
also provided on the `File` instance:
- `isDirectory`
- `isFile`
- `isBlockDevice`
- `isCharacterDevice`
- `isFIFO`
- `isSocket`
- `isSymbolicLink`
- `isDirectory(mode)`
- `isFile(mode)`
- `isBlockDevice(mode)`
- `isCharacterDevice(mode)`
- `isFIFO(mode)`
- `isSocket(mode)`
- `isSymbolicLink(mode)`
In addition, the following shorthand methods are also available:
- `isDir` (alias for `isDirectory()`)
- `isSymLink` (alias for `isSymbolicLink()`)
- `isDir(mode)` (alias for `isDirectory()`)
- `isSymLink(mode)` (alias for `isSymbolicLink()`)
These are also available as async methods:
- `asyncIsDir`
- `asyncIsDirectory`
- `asyncIsFile`
- `asyncIsBlockDevice`
- `asyncIsCharacterDevice`
- `asyncIsFIFO`
- `asyncIsSocket`
- `asyncIsSymLink`
- `asyncIsSymbolicLink`
- `asyncIsDir(mode)`
- `asyncIsDirectory(mode)`
- `asyncIsFile(mode)`
- `asyncIsBlockDevice(mode)`
- `asyncIsCharacterDevice(mode)`
- `asyncIsFIFO(mode)`
- `asyncIsSocket(mode)`
- `asyncIsSymLink(mode)`
- `asyncIsSymbolicLink(mode)`
Since the nature of a file seldom changes on a whim, the results of these tests are
stored on the `File` instance. If this is undesired, it is better to stick with the
`stat()` family since it provides a way to refresh this information (`restat()`).
The optional `mode` parameter can be `'l'` (lowercase-L) to use the `statLink()` (or
`asyncStatLink()`) method to determine the result.
Since the nature of a file seldom changes on a whim, these methods use the `stat()`
methods and their cached information. If this is undesired, these results can be
refreshed using the `restat()` family of methods.
## Directory Listing

@@ -312,4 +368,4 @@

`join(rel)` from that location.
- `upDir(rel)` - Same as `upTo()` but using `hasDir(rel)` as the `test`.
- `upFile(rel)` - Same as `upTo()` but using `hasFile(rel)` as the `test`.
- `upToDir(rel)` - Same as `upTo()` but using `hasDir(rel)` as the `test`.
- `upToFile(rel)` - Same as `upTo()` but using `hasFile(rel)` as the `test`.

@@ -334,4 +390,4 @@ The different between these forms can be seen best by example:

- `asyncUpTo(rel)` - TODO
- `asyncUpDir(rel)` - TODO
- `asyncUpFile(rel)` - TODO
- `asyncUpToDir(rel)` - TODO
- `asyncUpToFile(rel)` - TODO

@@ -342,11 +398,13 @@ ### Descent

Once a match is found, no descent into that folder is made (hence, the "tips" of
the sub-tree).
- `walk(mode, handler)` - Calls `handler` for all items that `list(mode)` generates
recursively.
the sub-tree). Uses `walk(mode)` to descend the file-system.
- `walk(mode, before, after)` - Calls `before` for all items that
`list(mode)` generates recursively, then processes those items and
lastly calls `after`. Both `before` and `after` are optional but one
should be provided.
The `walk` method's `handler` looks like this:
The `walk` method's `before` and `after` handlers looks like this:
function handler (file, state) {
function beforeOrAfter (file, state) {
if (file.isDir() && ...) {
return false; // do not recurse into this dir
return false; // do not recurse into file (before only)
}

@@ -363,2 +421,3 @@

- `previous` - The `File` previously passed to the handler.
- `root` - The `File` used to start the descent.
- `stack` - A `File[]` of instances starting with the `File` used to start things.

@@ -377,3 +436,3 @@ - `stop` - A boolean property that can be set to `true` to abort the `walk`.

The `state` parameter is the same as for the `handler` on the `walk` method.
The `state` parameter is the same as for the `walk` method.

@@ -383,15 +442,24 @@ Asynchronous forms:

- `asyncTips(mode, test)`
- `asyncWalk(mode, handler)`
- `asyncWalk(mode, before, after)`
The `test` and `handler` methods of the asynchronous methods accept the same
parameters and can return the same results as with the synchronous forms. They
can alternatively return a Promise if their determination is also async.
The `test`, `before` and `after` handlers of the asynchronous methods
accept the same parameters and return the same results as with the
synchronous forms. They can, alternatively, return a Promise if their
determination is also async.
## Reading / Loading Files
## Reading and Writing Files
Basic file reading and decoding/parsing are provided by these methods:
- `load(options)` - Reads, decodes and parses the file according to `options`.
- `asyncLoad(options)` - Same as `load()` except a Promise is returned
- `asyncLoad(options)` - Same as `load()` except a Promise is returned.
- `load(options)` - Reads, decodes and parses the file according to
the provided `options`.
And serializing, encoding and writing is provided by:
- `asyncSave(data, options)` - Same as `save()` except a Promise is
returned.
- `save(data, options)` - Serializes and encodes the data and writes
it to this file using the specified `options`.
The act of loading a file consists initially of reading the data (obviously). To

@@ -403,13 +471,11 @@ get this part right, you need an `encoding` option which is tedious to setup in

var pkg = path.join(dir, 'package.json'); // a string
var pkg = path.join(dir, 'package.json');
var data = JSON.parse(fs.readfileSync(pkg, {
encoding: 'utf8'
}));
var data = JSON.parse(fs.readfileSync(pkg, 'utf8'));
To loading using `File`:
var pkg = dir.join('package.json'); // a File
var pkg = dir.join('package.json');
var data = pkg.load(); // a parsed Object
var data = pkg.load();

@@ -428,5 +494,44 @@ The basic advantage of the `File` approach is the error messages you get when

### Loader Options
When it is time to save the data, the process looks very symmetric:
The default loader is based on the file's type, but we can override this:
pkg.save(data);
Instead of the manual alternative:
fs.writeFileSync(pkg, JSON.stringify(data, null, ' '), 'utf8');
**NOTE:** Unlike most of the `File` API, these methods throw exceptions (or reject
Promises) on failure.
### Predefined Readers
Readers are objects that manage options for reading and parsing files. The following
readers come predefined:
- `bin` - An alias for `binary`.
- `binary` - Reads a file as a buffer.
- `json` - Extends the `text` reader and provides a `parse` method to
deserialize JSON data. This uses the [`json5`](https://www.npmjs.com/package/json5)
module to tolerate human friendly JSON.
- `json:strict` - Extends `text` reader and uses strict `JSON.parse()`.
- `text` - Reads a file as `utf8` encoding.
- `txt` - An alias for `text`.
### Predefined Writers
Writers are objects that manage options for serializing and writing files. The
following writers come predefined:
- `bin` - An alias for `binary`.
- `binary` - Writes a file from a buffer.
- `json` - Extends the `text` writer and provides a `serialize` method to
write JSON data.
- `json5` - Extends `json` writer and uses `json5.stringify()`.
- `text` - Writes a file as `utf8` encoding. Accepts a `join` string option to
join the data if the data is an array (of lines perhaps).
- `txt` - An alias for `text`.
### Reader Options
The default reader is selected based on the file's type, but we can override this:

@@ -442,16 +547,11 @@ var data = pkg.load('text'); // load as a simple text (not parsed)

This simplicity is accomplished using a `File.Loader` instance or simply a `loader`.
Loaders are identified by name such as `text`, `binary` or `json`. By default,
the file's extension (`extent` property) is used to select the `loader`. This will
default to `text` for files with unrecognized extensions.
Readers support the following configuration properties:
Loaders support the following configuration properties:
- `parse` - A function called to parse the file content. The method accepts two
arguments: `data` and `loader`. The `data` parameter is the file's content and
the `loader` is the fully configured `loader` instance.
arguments: `data` and `reader`. The `data` parameter is the file's content and
the `reader` is the fully configured `reader` instance.
- `split` - An optional `RegExp` or `String` for a call to `String.split()`. This
is used by the default `parse` method.
In addition to `loader` configuration, the `fs.readFile()` options can be supplied:
In addition to `reader` configuration, the `fs.readFile()` options can be supplied:

@@ -465,3 +565,3 @@ var content = file.load({

The `encoding` can be specified in the `options` or directly to the `loader`:
The `encoding` can be specified in the `options` or directly to the `reader`:

@@ -480,2 +580,51 @@ var content = file.load({

### Writer Options
The default writer is selected based on the file's type, but we can override this:
pkg.save(data, 'text');
Other options can be specified (e.g. to join lines in an array with new-lines):
pkg.save(data, {
type: 'text',
join: '\n'
});
Writers support the following configuration properties:
- `serialize` - A function called to convert the data and return what will be written
to disk. The method accepts two arguments: `data` and `writer`. The `data` parameter
is the raw file data and the `writer` is the fully configured `writer` instance.
- `join` - An optional `String` for a call to `Array.join()` when file data is
an array. This is used by the default `serialize` method.
The `json` writer also supports these properties:
- `indent` maps to the `space` parameter for `JSON.stringify`.
- `replacer` map to the `replacer` parameter for `JSON.stringify`.
In addition to `writer` configuration, the `fs.writeFile()` options can be supplied:
file.save(data, {
// The options object is passed directly to fs.writeFile()
options: {
...
}
});
The `encoding` can be specified in the `options` or directly to the `writer`:
file.save(data, {
encoding: 'utf16'
});
// Or on the fs options:
file.save(data, {
options: {
encoding: 'utf16'
}
});
## Static Methods

@@ -499,2 +648,11 @@

There is also `fspath()` that resolves `"~"` path elements:
var s = File.fspath(file);
If the argument is already a `String` it is simply returned (just like the `path()`
method). If the string may contain `"~"` elements, the safe conversion would be:
var s = File.from(file).fspath;
### Utility Methods

@@ -511,2 +669,3 @@

- `split(fs)`- Returns a `String[]` from the `File` or `String`.
- `stat(fs)` - Returns the `stat()` for the `File` or `String`.
- `sorter(fs1, fs2)` - Calls `File.from(fs1).compare(fs2)` (useful for sorting

@@ -535,3 +694,14 @@ `File[]` and `String[]`).

- `profile()` - Returns the platform-favored storage folder for app data.
- `temp()` - Temporary folder for this application.
### Temp
The `temp()` and `asyncTemp()` static methods use the [`tmp`](https://www.npmjs.com/package/tmp)
module to generate a temporary folder in the appropriate location for the platform.
When these methods are called with no `options` argument, they lazily
create (and cache for future requests) a single temporary folder.
### Profile
The `profile()` method handles the various OS preferences for storing application

@@ -538,0 +708,0 @@ data.

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc