All files db.js

97.37% Statements 37/38
91.67% Branches 11/12
100% Functions 3/3
97.37% Lines 37/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84    1x 1x 1x 1x 1x 1x   1x         138x 138x                     2022x 2022x 2022x     2022x 2442x 2442x   2442x 1786x 656x 72x   2442x 1858x     1858x           2022x 99x 99x 99x 99x   99x 99x   99x 262x   262x             262x     262x   262x     2022x         1x  
'use strict';
 
const Bluebird = require( 'bluebird' );
const fetch = require( 'node-fetch' );
const normalize = require( '../function-schemata/javascript/src/normalize' );
const { containsError } = require( './utils.js' );
const { ZWrapper } = require( './ZWrapper' );
const { getError } = require( '../function-schemata/javascript/src/utils.js' );
 
fetch.Promise = Bluebird;
 
class ReferenceResolver {
 
	constructor( wikiUri ) {
		this.wikiUri_ = wikiUri;
		this.referenceMap = new Map();
	}
 
	/**
	 * Gets the ZObjects of a list of ZIDs.
	 *
	 * @param {Array} ZIDs A list of ZIDs to fetch.
	 * @return {Object} An object mapping ZIDs to ZWrappers
	 */
	async dereference( ZIDs ) {
		// Importing here instead of at top-level to avoid circular reference.
		const { resolveBuiltinReference } = require( './builtins.js' );
		const unresolved = new Set( ZIDs );
		const dereferenced = {};
 
		// Resolve references to builtins directly within the orchestrator.
		for ( const ZID of unresolved ) {
			const builtin = resolveBuiltinReference( ZID );
			const previouslyDereferenced = this.referenceMap.get( ZID );
			let dereferencedZObject;
			if ( builtin !== null ) {
				dereferencedZObject = { Z2K1: { Z1K1: 'Z6', Z6K1: ZID }, Z2K2: builtin };
			} else if ( previouslyDereferenced !== undefined ) {
				dereferencedZObject = previouslyDereferenced.asJSON();
			}
			if ( dereferencedZObject !== undefined ) {
				unresolved.delete( ZID );
				// stringify / parse are used here to create a deep copy. Otherwise, we'd
				// end up with circular references in some of the results here.
				dereferenced[ ZID ] = ZWrapper.create(
					JSON.parse( JSON.stringify( dereferencedZObject ) ) );
			}
		}
 
		// Otherwise, consult the wiki.
		if ( ( this.wikiUri_ !== null ) && ( unresolved.size > 0 ) ) {
			const url = new URL( this.wikiUri_ );
			url.searchParams.append( 'action', 'wikilambda_fetch' );
			url.searchParams.append( 'format', 'json' );
			url.searchParams.append( 'zids', [ ...unresolved ].join( '|' ) );
 
			const fetched = await fetch( url, { method: 'GET' } );
			const result = await fetched.json();
 
			await Promise.all( [ ...unresolved ].map( async ( ZID ) => {
				const zobject = JSON.parse( result[ ZID ].wikilambda_fetch );
				const normalized =
					ZWrapper.create( await normalize( zobject,
						/* generically= */true, /* withVoid= */ true ) );
				// TODO (T304971): We should include the entire Z22 in the result.
				// We should also generate Z22s when the call to the wiki fails.
				// Given that the wiki will return no results if any single ZID
				// fails, we should provisionally consider making separate calls
				// to the wiki for each ZID.
				Iif ( containsError( normalized ) ) {
					dereferenced[ ZID ] = getError( normalized );
				} else {
					dereferenced[ ZID ] = normalized.Z22K1;
				}
				this.referenceMap.set( ZID, dereferenced[ ZID ] );
			} ) );
		}
		return dereferenced;
	}
 
}
 
module.exports = { ReferenceResolver };