Skip to content

Commit

Permalink
Abstract into tryReadFileSync
Browse files Browse the repository at this point in the history
  • Loading branch information
valadaptive committed Feb 22, 2024
1 parent d0ad9c3 commit 6cd780c
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 71 deletions.
5 changes: 4 additions & 1 deletion etc/browser/lib/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ function createSyncImportHook() {
return function () { throw createError(); };
}

function tryReadFileSync() { return null; }

module.exports = {
createImportHook,
createSyncImportHook,
existsSync: function () { return false; },
readFileSync: function () { throw createError(); },
readSchemaFromPathOrString: function () { throw createError(); }
tryReadFileSync,
readSchemaFromPathOrString: function () { throw createError(); },
};
69 changes: 10 additions & 59 deletions lib/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
*/

let fs = require('fs'),
path = require('path'),
specs = require('./specs');
path = require('path');

/** Default (asynchronous) file loading function for assembling IDLs. */
function createImportHook() {
Expand Down Expand Up @@ -54,68 +53,20 @@ function createSyncImportHook() {
}

/**
* Convenience function to parse multiple inputs into protocols and schemas.
*
* It should cover most basic use-cases but has a few limitations:
*
* + It doesn't allow passing options to the parsing step.
* + The protocol/type inference logic can be deceived.
*
* The parsing logic is as follows:
*
* + If `str` contains `path.sep` (on windows `\`, otherwise `/`) and is a path
* to an existing file, it will first be read as JSON, then as an IDL
* specification if JSON parsing failed. If either succeeds, the result is
* returned, otherwise the next steps are run using the file's content
* instead of the input path.
* + If `str` is a valid JSON string, it is parsed then returned.
* + If `str` is a valid IDL protocol specification, it is parsed and returned
* if no imports are present (and an error is thrown if there are any
* imports).
* + If `str` is a valid IDL type specification, it is parsed and returned.
* + If neither of the above cases apply, `str` is returned.
* Check if the given input string is "path-like" or a path to an existing file,
* and if so, read it. This requires it to contain a path separator
* (`path.sep`). If not, this will return `null`.
*/
function readSchemaFromPathOrString(str) {
let schema;
function tryReadFileSync(str) {
if (
typeof str == 'string' &&
str.indexOf('/') !== -1 &&
str.indexOf(path.sep) !== -1 &&
fs.existsSync(str)
) {
// Try interpreting `str` as path to a file contain a JSON schema or an IDL
// protocol. Note that we add the second check to skip primitive references
// (e.g. `"int"`, the most common use-case for `avro.parse`).
let contents = fs.readFileSync(str, {encoding: 'utf8'});
try {
return JSON.parse(contents);
} catch (err) {
let opts = {importHook: createSyncImportHook()};
specs.assembleProtocol(str, opts, (err, protocolSchema) => {
schema = err ? contents : protocolSchema;
});
}
} else {
schema = str;
}
if (typeof schema != 'string' || schema === 'null') {
// This last predicate is to allow `read('null')` to work similarly to
// `read('int')` and other primitives (null needs to be handled separately
// since it is also a valid JSON identifier).
return schema;
}
try {
return JSON.parse(schema);
} catch (err) {
try {
return specs.readProtocol(schema);
} catch (err) {
try {
return specs.readSchema(schema);
} catch (err) {
return schema;
}
}
// Try interpreting `str` as path to a file.
return fs.readFileSync(str, {encoding: 'utf8'});
}
return null;
}

module.exports = {
Expand All @@ -124,5 +75,5 @@ module.exports = {
// Proxy a few methods to better shim them for browserify.
existsSync: fs.existsSync,
readFileSync: fs.readFileSync,
readSchemaFromPathOrString
tryReadFileSync
};
16 changes: 5 additions & 11 deletions lib/specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,11 @@ function assembleProtocol(fpath, opts, cb) {
*/
function read(str) {
let schema;
if (
typeof str == 'string' &&
str.indexOf('/') !== -1 &&
files.existsSync(str)
) {
// Try interpreting `str` as path to a file contain a JSON schema or an IDL
// protocol. Note that we add the second check to skip primitive references
// (e.g. `"int"`, the most common use-case for `avro.parse`).
let contents = files.readFileSync(str, {encoding: 'utf8'});
let contents = files.tryReadFileSync(str);

if (contents === null) {
schema = str;
} else {
try {
return JSON.parse(contents);
} catch (err) {
Expand All @@ -227,8 +223,6 @@ function read(str) {
schema = err ? contents : protocolSchema;
});
}
} else {
schema = str;
}
if (typeof schema != 'string' || schema === 'null') {
// This last predicate is to allow `read('null')` to work similarly to
Expand Down

0 comments on commit 6cd780c

Please sign in to comment.