mirror of
				https://github.com/NativeScript/NativeScript.git
				synced 2025-11-04 12:58:38 +08:00 
			
		
		
		
	refactor(core): zero circulars + esm ready (#10770)
This commit is contained in:
		
							
								
								
									
										38
									
								
								packages/core/module-name-resolver/helpers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								packages/core/module-name-resolver/helpers.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
export type ModuleListProvider = () => string[];
 | 
			
		||||
 | 
			
		||||
let appForModuleResolverCallback: () => void;
 | 
			
		||||
export function prepareAppForModuleResolver(callback: () => void) {
 | 
			
		||||
	appForModuleResolverCallback = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function initAppForModuleResolver() {
 | 
			
		||||
	if (appForModuleResolverCallback) {
 | 
			
		||||
		appForModuleResolverCallback();
 | 
			
		||||
		appForModuleResolverCallback = undefined;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ModuleNameResolverType {
 | 
			
		||||
	resolveModuleName(path: string, ext: string): string;
 | 
			
		||||
	clearCache(): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let resolverInstance: ModuleNameResolverType;
 | 
			
		||||
 | 
			
		||||
export function getResolveInstance() {
 | 
			
		||||
	return resolverInstance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used to set a global singular instance of ModuleNameResolver
 | 
			
		||||
 * @param resolver instance
 | 
			
		||||
 */
 | 
			
		||||
export function _setResolver(resolver: ModuleNameResolverType) {
 | 
			
		||||
	resolverInstance = resolver;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function clearResolverCache() {
 | 
			
		||||
	if (resolverInstance) {
 | 
			
		||||
		resolverInstance.clearCache();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								packages/core/module-name-resolver/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								packages/core/module-name-resolver/index.d.ts
									
									
									
									
										vendored
									
									
								
							@ -1,24 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Provides ModuleNameResolver class used for loading files based on device capabilities.
 | 
			
		||||
 */ /** */
 | 
			
		||||
 | 
			
		||||
import { PlatformContext } from './qualifier-matcher';
 | 
			
		||||
 | 
			
		||||
export { PlatformContext } from './qualifier-matcher';
 | 
			
		||||
 | 
			
		||||
export type ModuleListProvider = () => string[];
 | 
			
		||||
 | 
			
		||||
export class ModuleNameResolver {
 | 
			
		||||
	constructor(context: PlatformContext, moduleListProvider?: ModuleListProvider);
 | 
			
		||||
	resolveModuleName(path: string, ext: string): string;
 | 
			
		||||
	clearCache(): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function resolveModuleName(path: string, ext: string): string;
 | 
			
		||||
export function clearCache(): void;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used to set a global singular instance of ModuleNameResolver
 | 
			
		||||
 * @param resolver instance
 | 
			
		||||
 */
 | 
			
		||||
export function _setResolver(resolver: ModuleNameResolver);
 | 
			
		||||
@ -1,21 +1,18 @@
 | 
			
		||||
import { Screen, Device } from '../platform';
 | 
			
		||||
import { PlatformContext, findMatch, stripQualifiers } from './qualifier-matcher';
 | 
			
		||||
import { registerModulesFromFileSystem } from './non-bundle-workflow-compat';
 | 
			
		||||
import { Trace } from '../trace';
 | 
			
		||||
import { Application } from '../application';
 | 
			
		||||
import { ModuleNameResolverType, ModuleListProvider, initAppForModuleResolver, getResolveInstance, _setResolver } from './helpers';
 | 
			
		||||
 | 
			
		||||
export type { PlatformContext } from './qualifier-matcher';
 | 
			
		||||
 | 
			
		||||
export type ModuleListProvider = () => string[];
 | 
			
		||||
 | 
			
		||||
export class ModuleNameResolver {
 | 
			
		||||
export class ModuleNameResolver implements ModuleNameResolverType {
 | 
			
		||||
	private _cache = {};
 | 
			
		||||
 | 
			
		||||
	constructor(private context: PlatformContext, private moduleListProvider: ModuleListProvider = global.getRegisteredModules) {
 | 
			
		||||
		Application.on('livesync', (args) => clearCache());
 | 
			
		||||
		Application.on('orientationChanged', (args) => {
 | 
			
		||||
			resolverInstance = undefined;
 | 
			
		||||
		});
 | 
			
		||||
	constructor(
 | 
			
		||||
		private context: PlatformContext,
 | 
			
		||||
		private moduleListProvider: ModuleListProvider = global.getRegisteredModules,
 | 
			
		||||
	) {
 | 
			
		||||
		initAppForModuleResolver();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public resolveModuleName(path: string, ext: string): string {
 | 
			
		||||
@ -46,34 +43,32 @@ export class ModuleNameResolver {
 | 
			
		||||
 | 
			
		||||
		const candidates = this.getCandidates(path, ext);
 | 
			
		||||
		result = findMatch(path, ext, candidates, this.context);
 | 
			
		||||
 | 
			
		||||
		return result;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private getCandidates(path: string, ext: string): Array<string> {
 | 
			
		||||
		const candidates = this.moduleListProvider().filter((moduleName) => moduleName.startsWith(path) && (!ext || moduleName.endsWith(ext)));
 | 
			
		||||
 | 
			
		||||
		return candidates;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let resolverInstance: ModuleNameResolver;
 | 
			
		||||
 | 
			
		||||
export function resolveModuleName(path: string, ext: string): string {
 | 
			
		||||
	if (global.__snapshot) {
 | 
			
		||||
		return resolveModuleSnapshot(path, ext);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!resolverInstance) {
 | 
			
		||||
		resolverInstance = new ModuleNameResolver({
 | 
			
		||||
			width: Screen.mainScreen.widthDIPs,
 | 
			
		||||
			height: Screen.mainScreen.heightDIPs,
 | 
			
		||||
			os: Device.os,
 | 
			
		||||
			deviceType: Device.deviceType,
 | 
			
		||||
		});
 | 
			
		||||
	if (!getResolveInstance()) {
 | 
			
		||||
		_setResolver(
 | 
			
		||||
			new ModuleNameResolver({
 | 
			
		||||
				width: Screen.mainScreen.widthDIPs,
 | 
			
		||||
				height: Screen.mainScreen.heightDIPs,
 | 
			
		||||
				os: Device.os,
 | 
			
		||||
				deviceType: Device.deviceType,
 | 
			
		||||
			}),
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return resolverInstance.resolveModuleName(path, ext);
 | 
			
		||||
	return getResolveInstance().resolveModuleName(path, ext);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resolveModuleSnapshot(path, ext) {
 | 
			
		||||
@ -89,13 +84,3 @@ function resolveModuleSnapshot(path, ext) {
 | 
			
		||||
		deviceType: 'Phone',
 | 
			
		||||
	}).resolveModuleName(path, ext);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function clearCache() {
 | 
			
		||||
	if (resolverInstance) {
 | 
			
		||||
		resolverInstance.clearCache();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function _setResolver(resolver: ModuleNameResolver) {
 | 
			
		||||
	resolverInstance = resolver;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
import { Application } from '../application';
 | 
			
		||||
import * as fs from '../file-system';
 | 
			
		||||
import { knownFolders, File, path, Folder } from '../file-system';
 | 
			
		||||
import { Trace } from '../trace';
 | 
			
		||||
 | 
			
		||||
const cache = new Set<string>();
 | 
			
		||||
@ -20,13 +19,13 @@ function register(name: string, loader: (name?: string) => void) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function processFile(file: fs.File) {
 | 
			
		||||
	const filePathRelativeToApp = file.path.substr(fs.knownFolders.currentApp().path.length + 1);
 | 
			
		||||
function processFile(file: File) {
 | 
			
		||||
	const filePathRelativeToApp = file.path.substring(knownFolders.currentApp().path.length + 1);
 | 
			
		||||
	const loadContent = () => file.readTextSync();
 | 
			
		||||
 | 
			
		||||
	switch (file.extension.toLocaleLowerCase()) {
 | 
			
		||||
		case '.js': {
 | 
			
		||||
			const noExtPath = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - '.js'.length);
 | 
			
		||||
		case 'js': {
 | 
			
		||||
			const noExtPath = filePathRelativeToApp.substring(0, filePathRelativeToApp.length - '.js'.length);
 | 
			
		||||
 | 
			
		||||
			register(filePathRelativeToApp, function () {
 | 
			
		||||
				return global.require(file.path);
 | 
			
		||||
@ -37,11 +36,23 @@ function processFile(file: fs.File) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case '.css':
 | 
			
		||||
		case 'mjs': {
 | 
			
		||||
			const noExtPath = filePathRelativeToApp.substring(0, filePathRelativeToApp.length - '.mjs'.length);
 | 
			
		||||
 | 
			
		||||
			register(filePathRelativeToApp, function () {
 | 
			
		||||
				return global.require(file.path);
 | 
			
		||||
			});
 | 
			
		||||
			register(noExtPath, function () {
 | 
			
		||||
				return global.require(file.path);
 | 
			
		||||
			});
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case 'css':
 | 
			
		||||
			register(filePathRelativeToApp, loadContent);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case '.xml':
 | 
			
		||||
		case 'xml':
 | 
			
		||||
			register(filePathRelativeToApp, loadContent);
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
@ -49,8 +60,8 @@ function processFile(file: fs.File) {
 | 
			
		||||
	if (file.name === 'package.json') {
 | 
			
		||||
		const json = global.require(file.path);
 | 
			
		||||
		if (json.main) {
 | 
			
		||||
			const name = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - 'package.json'.length - 1);
 | 
			
		||||
			const requirePath = fs.path.join(file.parent.path, json.main);
 | 
			
		||||
			const name = filePathRelativeToApp.substring(0, filePathRelativeToApp.length - 'package.json'.length - 1);
 | 
			
		||||
			const requirePath = path.join(file.parent.path, json.main);
 | 
			
		||||
 | 
			
		||||
			register(name, () => global.require(requirePath));
 | 
			
		||||
		}
 | 
			
		||||
@ -73,11 +84,11 @@ function processFolder(path: string): boolean {
 | 
			
		||||
 | 
			
		||||
	let folderEmpty = true;
 | 
			
		||||
 | 
			
		||||
	if (fs.Folder.exists(path)) {
 | 
			
		||||
		const folder = fs.Folder.fromPath(path);
 | 
			
		||||
	if (Folder.exists(path)) {
 | 
			
		||||
		const folder = Folder.fromPath(path);
 | 
			
		||||
 | 
			
		||||
		folder.eachEntity((file) => {
 | 
			
		||||
			if (file instanceof fs.File) {
 | 
			
		||||
			if (file instanceof File) {
 | 
			
		||||
				processFile(file);
 | 
			
		||||
				folderEmpty = false;
 | 
			
		||||
			}
 | 
			
		||||
@ -100,15 +111,15 @@ export function registerModulesFromFileSystem(moduleName: string) {
 | 
			
		||||
	let folderProcessed = false;
 | 
			
		||||
	let parentFolderProcessed = false;
 | 
			
		||||
	// moduleName is a folder with package.json
 | 
			
		||||
	const path = fs.path.join(fs.knownFolders.currentApp().path, moduleName);
 | 
			
		||||
	if (fs.Folder.exists(path)) {
 | 
			
		||||
		folderProcessed = processFolder(path);
 | 
			
		||||
	const filePath = path.join(knownFolders.currentApp().path, moduleName);
 | 
			
		||||
	if (Folder.exists(filePath)) {
 | 
			
		||||
		folderProcessed = processFolder(filePath);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// moduleName is file - load all files in its parent folder
 | 
			
		||||
	const parentName = moduleName.substr(0, moduleName.lastIndexOf(fs.path.separator));
 | 
			
		||||
	const parentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, parentName);
 | 
			
		||||
	if (fs.Folder.exists(parentFolderPath)) {
 | 
			
		||||
	const parentName = moduleName.substring(0, moduleName.lastIndexOf(path.separator));
 | 
			
		||||
	const parentFolderPath = path.join(knownFolders.currentApp().path, parentName);
 | 
			
		||||
	if (Folder.exists(parentFolderPath)) {
 | 
			
		||||
		parentFolderProcessed = processFolder(parentFolderPath);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -120,15 +131,15 @@ export function registerModulesFromFileSystem(moduleName: string) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// moduleName is a folder in tns_modules ex. "nativescript-ui-chart"
 | 
			
		||||
	const tnsModulesPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', moduleName);
 | 
			
		||||
	if (fs.Folder.exists(tnsModulesPath)) {
 | 
			
		||||
	const tnsModulesPath = path.join(knownFolders.currentApp().path, 'tns_modules', moduleName);
 | 
			
		||||
	if (Folder.exists(tnsModulesPath)) {
 | 
			
		||||
		processFolder(tnsModulesPath);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// moduleName a file in tns_modules/plugin. Avoid traversing the whole tns_modules folder if parentName is empty
 | 
			
		||||
	if (parentName) {
 | 
			
		||||
		const tnsParentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', parentName);
 | 
			
		||||
		if (fs.Folder.exists(tnsParentFolderPath)) {
 | 
			
		||||
		const tnsParentFolderPath = path.join(knownFolders.currentApp().path, 'tns_modules', parentName);
 | 
			
		||||
		if (Folder.exists(tnsParentFolderPath)) {
 | 
			
		||||
			processFolder(tnsParentFolderPath);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -136,7 +147,7 @@ export function registerModulesFromFileSystem(moduleName: string) {
 | 
			
		||||
 | 
			
		||||
function initialize() {
 | 
			
		||||
	if (!initialized) {
 | 
			
		||||
		Application.on('livesync', (args) => cache.clear());
 | 
			
		||||
		// Application.on('livesync', (args) => cache.clear());
 | 
			
		||||
		initialized = true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Provides ModuleNameResolver class used for loading files based on device capabilities.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used with qualifier matchers and module resolution
 | 
			
		||||
 */
 | 
			
		||||
export interface PlatformContext {
 | 
			
		||||
	width: number;
 | 
			
		||||
	height: number;
 | 
			
		||||
	os: string;
 | 
			
		||||
	deviceType: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function findMatch(path: string, ext: string, candidates: Array<string>, context: PlatformContext): string;
 | 
			
		||||
 | 
			
		||||
export function stripQualifiers(path: string): string;
 | 
			
		||||
@ -27,7 +27,7 @@ const minWidthHeightQualifier: QualifierSpec = {
 | 
			
		||||
		return path.match(new RegExp(`.${MIN_WH}\\d+`, 'g'));
 | 
			
		||||
	},
 | 
			
		||||
	getMatchValue(value: string, context: PlatformContext): number {
 | 
			
		||||
		const numVal = parseInt(value.substr(MIN_WH.length + 1));
 | 
			
		||||
		const numVal = parseInt(value.substring(MIN_WH.length + 1));
 | 
			
		||||
		if (isNaN(numVal)) {
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
@ -49,7 +49,7 @@ const minWidthQualifier: QualifierSpec = {
 | 
			
		||||
		return path.match(new RegExp(`.${MIN_W}\\d+`, 'g'));
 | 
			
		||||
	},
 | 
			
		||||
	getMatchValue(value: string, context: PlatformContext): number {
 | 
			
		||||
		const numVal = parseInt(value.substr(MIN_W.length + 1));
 | 
			
		||||
		const numVal = parseInt(value.substring(MIN_W.length + 1));
 | 
			
		||||
		if (isNaN(numVal)) {
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
@ -71,7 +71,7 @@ const minHeightQualifier: QualifierSpec = {
 | 
			
		||||
		return path.match(new RegExp(`.${MIN_H}\\d+`, 'g'));
 | 
			
		||||
	},
 | 
			
		||||
	getMatchValue(value: string, context: PlatformContext): number {
 | 
			
		||||
		const numVal = parseInt(value.substr(MIN_H.length + 1));
 | 
			
		||||
		const numVal = parseInt(value.substring(MIN_H.length + 1));
 | 
			
		||||
		if (isNaN(numVal)) {
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
@ -93,7 +93,7 @@ const platformQualifier: QualifierSpec = {
 | 
			
		||||
		return path.match(new RegExp('\\.android|\\.ios', 'g'));
 | 
			
		||||
	},
 | 
			
		||||
	getMatchValue(value: string, context: PlatformContext): number {
 | 
			
		||||
		const val = value.substr(1);
 | 
			
		||||
		const val = value.substring(1);
 | 
			
		||||
 | 
			
		||||
		return val === context.os.toLowerCase() ? 1 : -1;
 | 
			
		||||
	},
 | 
			
		||||
@ -107,7 +107,7 @@ const orientationQualifier: QualifierSpec = {
 | 
			
		||||
		return path.match(new RegExp('\\.land|\\.port', 'g'));
 | 
			
		||||
	},
 | 
			
		||||
	getMatchValue(value: string, context: PlatformContext): number {
 | 
			
		||||
		const val = value.substr(1);
 | 
			
		||||
		const val = value.substring(1);
 | 
			
		||||
		const isLandscape: number = context.width > context.height ? 1 : -1;
 | 
			
		||||
 | 
			
		||||
		return val === 'land' ? isLandscape : -isLandscape;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user