Skip to content

Commit

Permalink
Move read convenience function to files.js
Browse files Browse the repository at this point in the history
  • Loading branch information
valadaptive committed Feb 3, 2024
1 parent 066d526 commit d0ad9c3
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 6 deletions.
2 changes: 1 addition & 1 deletion doc
Submodule doc updated from 5ddd9d to bebd04
3 changes: 2 additions & 1 deletion etc/browser/avsc-services.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
*/

let avroTypes = require('./avsc-types'),
files = require('../../lib/files'),
services = require('../../lib/services'),
specs = require('../../lib/specs'),
utils = require('../../lib/utils');


/** Slightly enhanced parsing, supporting IDL declarations. */
function parse(any, opts) {
let schemaOrProtocol = specs.read(any);
let schemaOrProtocol = files.readSchemaFromPathOrString(any);
return schemaOrProtocol.protocol ?
services.Service.forProtocol(schemaOrProtocol, opts) :
avroTypes.Type.forSchema(schemaOrProtocol, opts);
Expand Down
4 changes: 2 additions & 2 deletions etc/browser/lib/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ function createSyncImportHook() {
return function () { throw createError(); };
}


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

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

/** Default (asynchronous) file loading function for assembling IDLs. */
function createImportHook() {
Expand Down Expand Up @@ -52,11 +53,76 @@ 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.
*/
function readSchemaFromPathOrString(str) {
let schema;
if (
typeof str == 'string' &&
str.indexOf('/') !== -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;
}
}
}
}

module.exports = {
createImportHook,
createSyncImportHook,
// Proxy a few methods to better shim them for browserify.
existsSync: fs.existsSync,
readFileSync: fs.readFileSync
readFileSync: fs.readFileSync,
readSchemaFromPathOrString
};

0 comments on commit d0ad9c3

Please sign in to comment.