UNPKG

@kawix/core

Version:

The next generation module loader for nodejs

2,195 lines (1,821 loc) 56 kB
var Next, fs, Os, Path, Module, Url, browser, _require, Mod, nd, npmResolver, _module, _next, MD5, allowCacheCompress, allowCacheCompressExt Os = require("os") Mod = function () { } var deferred = function () { var def = {} def.promise = new Promise(function (a, b) { def.resolve = a def.reject = b }) return def } if (Os.platform() != 'browser') { //allowCacheCompress = 'gzip' //allowCacheCompressExt = '.cgz' //Zlib = require('zl' + 'ib') MD5 = function (str) { if (!MD5.crypt) { MD5.t = "cryp" + "to" MD5.crypt = require(MD5.t) } return MD5.crypt.createHash('md5').update(str).digest("hex") } npmResolver = function () { return Mod.import(Path.join(__dirname, "..", "..", "src", "npm-import")) } // THIS FOR AVOID ERRORS WITH WEBPACK Next = function () { var nd = __dirname + "/../async/src/NextJavascript.js" if (!_next) _next = require(nd) return _next } Next() nd = "f" + "s" fs = require(nd) nd = "mod" + "ule" _module = require(nd) Module = _module.Module _require = require } else { MD5 = require("./md5.js") Next = function () { if (global.___kmodule___basic && global.___kmodule___basic.__nextJavascript) return global.___kmodule___basic.__nextJavascript if (!_next) { _next = { transpile: function (code) { return { code: code } } } } return _next } _module = require("./module.js") Module = _module.Module npmResolver = function () { throw new Error("npm resolver not available in browser") return } browser = {} fs = require("./browser.fs.js") fs = fs(Mod) _require = _module.defaultRequire // enable loader window.KModuleLoader = Mod } var eval1 = function (str) { var wrapped = Function("", "return " + str) return wrapped() } var Path = require("path") var Url = require('url') var httpr = {} void (function () { var percentRegEx = /%/g var backslashRegEx = /\\/g var newlineRegEx = /\n/g var carriageReturnRegEx = /\r/g var tabRegEx = /\t/g var isWindows = Os.platform() == "win32" var CHAR_FORWARD_SLASH = 47 var CHAR_BACKWARD_SLASH = 92 var CHAR_UPPERCASE_A = 65 var CHAR_LOWERCASE_A = 97 var CHAR_UPPERCASE_Z = 90 var CHAR_LOWERCASE_Z = 122 if (typeof Url.pathToFileURL != "function") Url.pathToFileURL = pathToFileURL if (typeof Url.fileURLToPath != "function") Url.fileURLToPath = fileURLToPath function fileURLToPath(path) { if (typeof path === 'string') path = new Url.URL(path); else if (path == null || !path[searchParams] || !path[searchParams][searchParams]) throw new Error('Argument path is invalid', path); if (path.protocol !== 'file:') throw new Error('Schema not valid'); return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path); } var forwardSlashRegEx = /\//g; function getPathFromURLWin32(url) { var hostname = url.hostname; var pathname = url.pathname; for (var n = 0; n < pathname.length; n++) { if (pathname[n] === '%') { var third = pathname.codePointAt(n + 2) | 0x20; if ((pathname[n + 1] === '2' && third === 102) || // 2f 2F / (pathname[n + 1] === '5' && third === 99)) { // 5c 5C \ throw new Error( 'must not include encoded \\ or / characters' ); } } } pathname = pathname.replace(forwardSlashRegEx, '\\'); pathname = decodeURIComponent(pathname); if (hostname !== '') { // If hostname is set, then we have a UNC path // Pass the hostname through domainToUnicode just in case // it is an IDN using punycode encoding. We do not need to worry // about percent encoding because the URL parser will have // already taken care of that for us. Note that this only // causes IDNs with an appropriate `xn--` prefix to be decoded. return "\\\\" + (hostname) + pathname; } else { // Otherwise, it's a local path that requires a drive letter var letter = pathname.codePointAt(1) | 0x20; var sep = pathname[2]; if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z (sep !== ':')) { throw new Error('must be absolute'); } return pathname.slice(1); } } function getPathFromURLPosix(url) { if (url.hostname !== '') { throw new Error(platform); } var pathname = url.pathname; for (var n = 0; n < pathname.length; n++) { if (pathname[n] === '%') { var third = pathname.codePointAt(n + 2) | 0x20; if (pathname[n + 1] === '2' && third === 102) { throw new Error( 'must not include encoded / characters' ); } } } return decodeURIComponent(pathname); } function pathToFileURL(filepath) { var resolved = Path.resolve(filepath); // path.resolve strips trailing slashes so we must add them back var filePathLast = filepath.charCodeAt(filepath.length - 1); if ((filePathLast === CHAR_FORWARD_SLASH || isWindows && filePathLast === CHAR_BACKWARD_SLASH) && resolved[resolved.length - 1] !== Path.sep) resolved += '/'; var outURL = new Url.URL('file://'); if (resolved.includes('%')) resolved = resolved.replace(percentRegEx, '%25'); // In posix, "/" is a valid character in paths if (!isWindows && resolved.includes('\\')) resolved = resolved.replace(backslashRegEx, '%5C'); if (resolved.includes('\n')) resolved = resolved.replace(newlineRegEx, '%0A'); if (resolved.includes('\r')) resolved = resolved.replace(carriageReturnRegEx, '%0D'); if (resolved.includes('\t')) resolved = resolved.replace(tabRegEx, '%09'); outURL.pathname = resolved; return outURL; } })() if (Os.platform() != "browser") { if (process.env.KAWIX_CACHE_DIR) { process.env.KAWIX_CACHE_DIR = Path.resolve(process.env.KAWIX_CACHE_DIR) } } // Inline functions var isVirtualFile, transpile, createDefault, getKModule, _getCachedFilename, getCachedFilenameSync, getCachedFilename, changeSource, loadInjectImportFunc, readHttp, readNpm, virtualRedirection, realResolve, asynchelper asynchelper = "function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }\n\nfunction _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err); } _next(undefined); }); }; }" Module.prototype.realPathResolve = function (path) { var filename = this.filename, uri return realResolve(filename, path) } var builtinModules = _module.builtinModules; (function () { isVirtualFile = function (file) { if (Os.platform() == "win32" && file.startsWith("\\virtual")) return true; return file.startsWith("/virtual") } realResolve = function (filename, path) { if (filename[1] == ":") { return Path.resolve(Path.dirname(filename), path) } else { uri = Url.parse(filename) if (uri.protocol == "file:") { filename = Url.fileURLToPath(filename) } else if (uri.protocol) { filename = Url.resolve(filename, path) return filename } return Path.resolve(Path.dirname(filename), path) } } virtualRedirection = function (file) { if(Os.platform()=="win32") file = file.replace(/\\/g,'/') var data, name, redir for (var i = Mod._virtualredirect.length -1; i >= 0; i--) { data = Mod._virtualredirect[i] if (file.startsWith(data.platformResolvedpath) || file.startsWith(data.resolvedpath)) { name = Path.relative(data.resolvedpath, file) redir = data.redirect + (data.redirect.endsWith("/") ? "" : "/") + "default" //console.info("File:", realResolve(redir, name), redir, name, file) return realResolve(redir, name) } } } createDefault = function (options) { var defoptions = Mod.defaultOptions || exports.defaultOptions options = options || {} for (var id in defoptions) { if (options[id] === undefined) options[id] = defoptions[id] } return options } getKModule = function (filename) { var nmod = { filename: filename, require: Mod.require, import: Mod.import, addVirtualFile: Mod.addVirtualFile, extensions: Mod.extensions, extensionLoaders: Mod.extensionLoaders, languages: Mod.languages, replaceSyncRequire: Mod.replaceSyncRequire, removeCached: Mod.removeCached, _local: [] } return nmod } _getCachedFilename = function (uri, options) { options = options || {} if (!uri.protocol) { uri.protocol = "file:" uri.pathname = Path.normalize(uri.pathname) } var name, parts, full, kawi_dir, file_dir, cache_dir /*name= (options.mask || Url.format(uri)).replace(/\:|\?/g, '').replace(/\\/g, '/') if(uri.search){ name += uri.search.replace(/\:|\?|\\/g, '') } parts= name.split("/") parts= parts.filter(function(a){ return !!a }) if(options.virtual){ parts.shift() } full= parts.join(Path.sep) */ let o = '' //o = options.mask || uri.pathname || Url.format(uri) //o = Path.basename(o).replace(/\//g, '_').substring(0, 50) + "-" let md = o + MD5(options.mask || Url.format(uri)) if (allowCacheCompress) { md += allowCacheCompressExt } parts = ["gen", md] full = parts.join(Path.sep) kawi_dir = process.env.KAWIX_CACHE_DIR || Path.join(Os.homedir(), ".kawi") file_dir = Path.join(kawi_dir, full) cache_dir = Path.dirname(file_dir) return { kawi_dir: kawi_dir, file_dir: file_dir, cache_dir: cache_dir, parts: parts, full: full } } getCachedFilenameSync = function (uri, options) { var result = _getCachedFilename(uri, options) var kawi_dir = result.kawi_dir var cache_dir = result.cache_dir var file_dir = result.file_dir var parts = result.parts var full = result.full var part try { if (fs.accessSync(cache_dir, fs.constants.F_OK)) { return file_dir } } catch (e) { } var path = kawi_dir try { fs.accessSync(path, fs.constants.F_OK) } catch (e) { fs.mkdirSync(path) } for (var i = 0; i < parts.length - 1; i++) { part = parts[i] path = Path.join(path, part) try { fs.accessSync(path, fs.constants.F_OK) } catch (e) { fs.mkdirSync(path) } } return file_dir } getCachedFilename = function (uri, options) { var result = _getCachedFilename(uri, options) var kawi_dir = result.kawi_dir var cache_dir = result.cache_dir var file_dir = result.file_dir var parts = result.parts var full = result.full return new Promise(function (resolve, reject) { var i = 0, part var createTree = function (path) { try { if (!path) { path = kawi_dir } fs.access(path, fs.constants.F_OK, function (err) { if (err) { fs.mkdir(path, function (err) { if (err) return reject(err) part = parts[i] if (i == parts.length - 1) return resolve(file_dir) i++ return createTree(Path.join(path, part)) }) } else { part = parts[i] if (i == parts.length - 1) return resolve(file_dir) i++ return createTree(Path.join(path, part)) } }) } catch (e) { reject(e) } } fs.access(cache_dir, fs.constants.F_OK, function (err) { if (err) return createTree() return resolve(file_dir) }) }) } validateFileUrl = function (file) { var uri = Url.parse(file) if (Os.platform() == "win32") { if (file[1] == ":") uri = Url.pathToFileURL(file) } if (uri.protocol) { if (uri.protocol != "http:" && uri.protocol != "npm:" && uri.protocol != "npmi:" && uri.protocol != "https:" && uri.protocol != "file:") { throw new Error("Protocol " + uri.protocol + " not supported") } } return uri } changeSource = Mod.injectImports = function (source) { var import1 = { code: source } // detect if is injected loadInjectImportFunc(import1) if (import1.inject) { import1.inject = import1.injectCode import1.source = import1.code delete import1.injectCode delete import1.code return import1 } // this method works with transpiled code // that is known the generated style, can determine the modules imported with `import` var lines = source.split(/\r\n|\r|\n/g) var line var maybeRequire = [] var reg = /\=?\s?(_interopRequire.*\()?require\((.*)\)\)?[\;|\n|\r]/ var esm = false, req, required = [] for (var i = 0; i < lines.length; i++) { line = lines[i] if (line) { if (reg.test(line)) { maybeRequire.push({ line: line, index: i }) esm = true } /*else if(!maybeRequire.length && (line.startsWith("Object") || line.startsWith("exports") || line.indexOf("use strict") >= 0) ){ }*/ else if (maybeRequire.length) { // good, is a ESM module esm = true break } } } var num, json, code num = Mod.__num++ if (esm) { var z = -1 for (var i = 0; i < maybeRequire.length; i++) { req = maybeRequire[i] mod = null req.line = req.line.replace(reg, function (a, _, c) { var b = c if (c.endsWith(")")) c = c.substring(0, c.length - 1) if (c[0] == "\"") { try { c = JSON.parse(c) //if good is because is module // c.substring(1, c.length-1) if (builtinModules.indexOf(c) < 0) { mod = c z++ return a.replace(b, b.replace(c, z)) } } catch (e) { } } return a }) if (mod) { if (builtinModules.indexOf(mod) < 0) { required.push(mod) lines[req.index] = req.line } } } } if (required.length) { source = lines.join("\n") // create a preloader function json = JSON.stringify(required) code = "function (KModule, require, module){\n" code += " var resolve, reject\n" code += " var required= " + json + "\n" code += " var num=" + num + "\n" code += " var i=-1\n" code += " var __load= " + "function (value) {\n" + ' if(arguments.length > 0) KModule._local.push(value);\n' + ' i++\n' + ' var mod = required[i]\n' + ' if (!mod) return resolve()\n' + ' var promise = KModule.import(mod, {\n' + ' parent: KModule\n' + ' })\n' + ' if (promise && typeof promise.then == "function")\n' + ' promise.then(__load).catch(reject)\n' + ' else\n' + ' __load(promise)\n' + '}\n' code += " var promise= new Promise(function(a,b){ resolve=a; reject=b; })\n" code += " __load()\n" code += " return promise\n" code += "}" } var imports = {} imports.mods = required imports.inject = code imports.source = source + (code ? ("\nvar ___kawi__async = \n" + code) : "") return imports } loadInjectImportFunc = function (ast) { var code, injectCode, ucode if (!ast.injectCode) { var i = ast.code.indexOf("var ___kawi__async = \n") if (i < 0) { i = ast.code.indexOf("var ___kawi__async =\n") } if (i >= 0) { code = ast.code.substring(0, i) injectCode = ast.code.substring(i + 20) ast.code = code ast.injectCode = injectCode.trim() i = ast.injectCode.indexOf("function") ast.injectCode = ast.injectCode.substring(i) } } if (ast.injectCode && !ast.inject) { //console.info("acá: ", ast.injectCode) if (ast.injectCode.indexOf("regeneratorRuntime") >= 0) { ucode = "(function(){" + asynchelper + "\n\nreturn " + ast.injectCode + ";\n})()" ast.inject = eval(ucode) } else { ucode = "(" + ast.injectCode + ")" try { ast.inject = eval(ucode) } catch (e) { throw e } } } } getMask = function (url, value) { if (value.mask) { return value.mask } var name = Path.basename(value.redirect) if (url.endsWith(value)) { return url } else { return url + "/" + name } } readNpm = function (url, options, npmi) { var npmtext = 'npm' if (npmi) { npmtext = 'npmi' } //var uri= Url.parse(url) var module = url.substring(url.indexOf("://") + 3) var parts = module.split("/") var oparts = [].concat(parts) var subpath = "" while (parts.length > 2) { parts.pop() } if (parts.length > 1) { if (parts[0].startsWith("@")) { // valid } else { parts.pop() } } subpath = oparts.slice(parts.length) subpath = subpath.join("/") module = parts.join("/") options.uid = module.split("@").slice(0, -1).join("/") if (subpath) { options.uid += "/" + subpath } var moduledesc = Mod._npmcache[module] var continue3 = function (moduledesc) { if (moduledesc) { Mod._npmcache[module] = moduledesc // return if (subpath) { return { redirect: Path.join(moduledesc.folder, subpath), from: 'npm', mask: npmtext + "://" + moduledesc.name + "$v$" + moduledesc.version + "/" + subpath } } else { return { redirect: moduledesc.main, from: 'npm', mask: npmtext + "://" + moduledesc.name + "$v$" + moduledesc.version + "/" + (Path.relative(moduledesc.folder, moduledesc.main)) } } } } if (moduledesc) { return continue3(moduledesc) } return new Promise(function (resolve, reject) { var continue2 = function (moduledesc) { return resolve(continue3(moduledesc)) } var continue1 = function () { if (process.env.ENABLE_COMPILATION_INFO == 1) { console.info("\x1b[32m[kawix] NPM Module:", "\x1b[0m", url) } Mod._npmImport.resolve(module, { nativeEnabled: npmi }).then(continue2).catch(reject) } if (!Mod._npmImport) { npmResolver().then(function (loader) { Mod._npmImport = loader continue1() }).catch(reject) } else { continue1() } }) } readHttp = function (url, options, possibles, offset, originalUrl) { var xhttp = url.startsWith("http://") ? "http" : "https" var http = httpr[xhttp] if (!http) http = httpr[xhttp] = _require(xhttp) var uri = Url.parse(url) var promise = new Promise(function (resolve, reject) { var callback = function (resp) { var buf = [], code if (resp.statusCode == 302) { var loc = resp.headers.location if (!loc.startsWith("http:") && !loc.startsWith("https:")) { loc = Url.resolve(url, loc) } return resolve(readHttp(loc)) } else if(resp.statusCode == 404){ if(possibles && possibles.length){ offset++ var u = possibles[offset] if(!u) return reject(new Error("Status code 404 response from " + (originalUrl||url))) return resolve(readHttp(u, options, possibles, offset, originalUrl)) } else if(possibles == undefined){ possibles = [] for (var ext in Mod.extensions) { possibles.push(url + ext) } return resolve(readHttp(possibles[0], options, possibles, 0, url)) } return reject(new Error("Status code 404 response from " + (originalUrl || url))) } else if (resp.statusCode != 200) { return reject(new Error("Invalid response from " + url)) } else { resp.on("data", function (b) { if (!Buffer.isBuffer(b)) b = Buffer.from(b) buf.push(b) }) resp.on("error", reject) resp.on("end", function () { buf = Buffer.concat(buf) code = buf.toString('utf8') return resolve({ code: code, "type": resp.headers["content-type"], "name": uri.pathname }) }) } } http.get(url, callback).on("error", reject) }) return promise } transpile = function (file, basename, source, options) { var transpilerOptions, json, imports if (options.injectImport === undefined && Mod.__injected) { options.injectImport = true } if (options && options.language) { // specified by language if (Mod.languages[options.language]) basename += Mod.languages[options.language] } for (var ext in Mod.extensions) { if (basename.endsWith(ext)) { if (typeof Mod.extensions[ext] == "function") { json = Mod.extensions[ext](source, file, options) source = json.code } else { if (ext == ".json") { return { code: "module.exports= " + source } } } } } if (json && json.transpile === false) { options.transpile = false } if (basename.endsWith(".kwsh") || (source && source.startsWith("#!/usr/bin/env kwcore --kwsh\n#kwsh.0\n"))) { options.transpile = false } if (options.transpile !== false) { if (json && json.transpilerOptions) { transpilerOptions = json.transpilerOptions } else { transpilerOptions = { sourceMaps: true, comments: true, filename: file } if (basename.endsWith(".ts")) { if (!transpilerOptions.filename.endsWith(".ts")) { transpilerOptions.filename += ".ts" } /* transpilerOptions.presets = ["typescript", 'es2015', 'es2016', 'es2017', ['stage-2', { decoratorsBeforeExport: false }]]*/ } } if (transpilerOptions && options.transpilerOptions) { for (var id in options.transpilerOptions) { transpilerOptions[id] = options.transpilerOptions[id] } } json = Next().transpile(source, transpilerOptions) delete json.options if (options.injectImport) { imports = changeSource(json.code) json.code = imports.source json.injectCode = imports.inject loadInjectImportFunc(json) } } else { if (source.startsWith("#!/usr/bin/env kwcore --kwsh\n#kwsh.0\n")) { source = source.substring(37) json = JSON.parse(source) } else if (basename.endsWith(".kwsh")) { json = JSON.parse(source) } else { json = { code: source } } if (options.injectImport) { //imports = changeSource(json.code) //json.code = imports.source //json.injectCode = imports.inject loadInjectImportFunc(json) } } return json } })() Mod._Module = Module Mod._cache = {} Mod._cacherequire = {} Mod._cacheresolve = {} Mod._virtualfile = {} Mod._virtualredirect = [] Mod._npmcache = {} Mod.cachetime = 5000 Mod._namesid = 0 Mod.extensions = { ".json": null, ".js": null, ".es6": null, ".ts": null, ".kwsh": null // compiled file } Mod.extensionLoaders = { } Mod.languages = { "json": ".json", "javascript": ".js", "ecmascript": ".js", "typescript": ".ts", "kwshide": ".kwsh" } if (Module.isBrowser) { Module.extensions = Mod.extensions Module.languages = Mod.languages } Mod.__num = 0 Mod.__injected = true Mod.injectImport = function (value) { if (value === undefined) value = true Mod.__injected = value } Mod.disableInjectImport = function () { Mod.__injected = false } Module._originalResolveFilename = Module._resolveFilename Mod._resolveFilename = function (name, parent, resolve) { if (name.startsWith("___kawi__internal__")) { return name } else if (isVirtualFile(name)) { return Mod.resolveVirtual(name, parent, resolve) } else if (builtinModules.indexOf(name) >= 0) { return name } else if (!name.startsWith(".")) { parts = name.split(/\/|\\/) parts = Path.normalize("/virtual/" + parts[0]) if (Mod._virtualfile[parts]) { var uname = Mod.resolveVirtual(Path.normalize("/virtual/" + name), parent, resolve) if (uname) return uname } } if (Path.isAbsolute(name)) { try { var res0 = Module._originalResolveFilename(name, parent, resolve) if (res0) return res0 } catch (e) { } } if (parent && parent.filename && isVirtualFile(parent.filename)) { // Allow resolve result = Mod.resolveVirtual(name, parent) if (!result) { return null } return result } return null } Mod.resolveFilename = Module._resolveFilename = function (name, parent) { var result = Mod._resolveFilename(name, parent) if (!result) return Module._originalResolveFilename.apply(Module, arguments) else return result } Mod.resolveVirtual = function (name, parent, resolve) { var possibles = [], nname var path, dirname, path1, normalize = function (a) { return a } // again fix bug on windows, why windows always need be different ? if (Os.platform() == "win32" && !name.startsWith("./") && !name.startsWith("../")) name = Path.normalize(name) if (!resolve) { resolve = Mod.resolveFilename } if (isVirtualFile(name)) { nname = virtualRedirection(name) if (nname) return resolve(nname, null, resolve) || nname possibles.push(name) } else { dirname = Path.dirname(parent.filename) if (name.startsWith("./") || name.startsWith("../")) { path = normalize(Path.normalize(Path.join(dirname, name))) if (isVirtualFile(path)) { nname = virtualRedirection(path) if (nname) return resolve(nname, null, resolve) || nname } possibles.push(normalize(path)) } else { path = Path.join(dirname, "node_modules", name) if (isVirtualFile(path)) { nname = virtualRedirection(path) if (nname) return resolve(nname, null, resolve) || nname } possibles.push(path) path1 = dirname while (path1 && path1 != (Path.sep + "virtual") && path1 != Path.sep && path1 != "") { path1 = Path.dirname(path1) path = Path.join(path1, "node_modules", name) possibles.push(normalize(path)) } } } var possiblesFromFile = function (name) { var possibles = [] for (var ext in Mod.extensions) { possibles.push(name + ext) } return possibles } var possiblesFromFolder = function (name) { var possibles = {}, path, data, pjson, rpossibles = [] // package json? path = normalize(Path.join(name, "package.json")) data = Mod._virtualfile[path] if (data) { if (typeof data == "function") data = data() pjson = data.content.toString() pjson = JSON.parse(pjson) if (pjson.main) { path = normalize(Path.normalize(Path.join(name, pjson.main))) possibles[path] = true for (var ext in Mod.extensions) { possibles[path + ext] = true } } } possibles[normalize(Path.join(name, "index.js"))] = true for (var ext in Mod.extensions) { possibles[normalize(Path.join(name, "index" + ext))] = true } for (var id in possibles) { rpossibles.push(id) } return rpossibles } var processPossibles = function (possibles, deep = 0) { var possible, vfile, result, possibles1 for (var i = 0; i < possibles.length; i++) { possible = possibles[i] vfile = Mod._virtualfile[possible] if (vfile) { if (typeof vfile == "function") vfile = vfile() if (vfile.stat.isdirectory) { possibles1 = possiblesFromFolder(possible) result = processPossibles(possibles1, deep + 1) if (result) return result } else { if (vfile.content) { return possible } } } else { if (deep == 0) { possibles1 = possiblesFromFile(possible) result = processPossibles(possibles1, deep + 1) if (result) return result } } } } path = processPossibles(possibles) //if(!path) // throw new Error("Failed resolve " + name + " from " + parent.filename) return path } Mod.replaceSyncRequire = function (originalrequire, parent, KModule) { var nrequire = function (name) { if (nrequire._local[name]) { return nrequire._local[name] } if (builtinModules.indexOf(name) >= 0) return originalrequire(name) var file = Module._resolveFilename(name, parent) var parts if (isVirtualFile(file)) { return Mod.requireVirtualSync(file, parent) } else if (!file.startsWith("/") && !file.startsWith(".")) { parts = file.split(/\/|\\/) parts = Path.normalize("/virtual/" + parts[0]) if (Mod._virtualfile[parts]) { var ufile = Mod.resolveVirtual(Path.normalize("/virtual/" + ufile), parent) if (ufile) return Mod.requireVirtualSync(ufile, parent) } } return originalrequire(name, parent) } // local requires nrequire._local = KModule._local for (var id in require) { nrequire[id] = require[id] } var kmodule = this nrequire.ensure = function (a, callback) { return callback(kmodule.import.bind(kmodule)) } return nrequire } Mod.generateModule = function (file) { if (!file && Os.platform() == "browser") { file = location.href if (!file.endsWith("/")) { file += "/" } file += Mod._namesid + ".js" Mod._namesid++ } var nmod = getKModule(file) module = new Module(file, parent) module.filename = file module.KModule = nmod Module._cache[file] = module Mod._cacherequire[file] = module return module } Mod.requireVirtualSync = function (file, parent) { var module = Mod._cacherequire[file] if (module) { return module.exports } var ast = Mod.compileSync(file) var nmod = getKModule(file) module = new Module(file, parent) module.filename = file module.dirname = Path.dirname(file) module.KModule = nmod Mod._cacherequire[file] = module Module._cache[file] = module var code = "exports.__kawi= function(KModule){ " + "\trequire= KModule.replaceSyncRequire(require,module, KModule); " + ast.code + "\n}" module._compile(code, file) module.exports.__kawi(nmod, nmod.import.bind(nmod)) Mod._cacherequire[file] = module return module.exports } Mod._writeCache = function (cache, file, data) { var cache_file = (cache.file || cache) var content try { content = fs.readFileSync(cache_file) if(allowCacheCompress == "gzip"){ content = Zlib.gunzipSync(content.reverse()) } content = JSON.parse(content.toString('utf8')) } catch (e) { content = {} } var d = {} for (var id in data) { d[id] = data[id] } if (cache && cache.stats && cache.stats[1]) { d.stat = { mtimeMs: cache.stats[1].mtimeMs, atimeMs: cache.stats[1].atimeMs } } else { d.stat = { mtimeMs: Date.now(), atimeMs: Date.now() } } content[file] = d content = JSON.stringify(content) if (allowCacheCompress == "gzip") { content = Zlib.gzipSync(Buffer.from(content),{level:5}).reverse() } fs.writeFileSync(cache_file, content) } Mod.compileSync = function (file, options) { var vfile = Mod._virtualfile[file] options = createDefault(options) if (typeof vfile == "function") { vfile = vfile() } var ext = Path.extname(file) var cached2, stat1, stat2, compile, transpilerOptions, ast, content var uri = validateFileUrl(file) if (ext == ".json") { ast = { "code": "module.exports=" + vfile.content.toString() } return ast } else { cached2 = getCachedFilenameSync(uri, { virtual: true }) if (!options.force) { /*try{ stat1= fs.statSync(cached2) }catch(e){ if(e.code != "ENOENT"){ throw e } stat1= null } if(stat1){ stat2= vfile.stat if(!(stat2.mtime instanceof Date)) stat2.mtime= new Date(stat2.mtime) if(stat1.mtime.getTime() < stat2.mtime.getTime()) compile= true }else{ compile= true }*/ try { content = fs.readFileSync(cached2) if(allowCacheCompress == "gzip"){ content = Zlib.gunzipSync(content.reverse()) } content = JSON.parse(content.toString('utf8')) content = content[file] } catch (e) { } if (content) { stat1 = content.stat stat2 = vfile.stat if (!stat2.mtimeMs) { if (!(stat2.mtime instanceof Date)) stat2.mtime = new Date(stat2.mtime) stat2.mtimeMs = stat2.mtime.getTime() } if (stat1.mtimeMs < stat2.mtimeMs) compile = true } else { compile = true } } else { compile = true } if (compile) { if (vfile.transpiled) { options.transpile = false } ast = transpile(file, file, vfile.content.toString(), options) if (ast) { // str= JSON.stringify(ast) // fs.writeFileSync(cached2, str) if(!ast.ignore) Mod._writeCache(cached2, file, ast) delete ast.options ast.time = Date.now() Mod._cache[file] = ast } return ast } else { ast = content if (!ast) { ast = JSON.parse(fs.readFileSync(cached2, 'utf8')) ast = ast[file] } return ast } } } var importing = {} Mod.import = function (file, options) { var id = this.filename, def, c, def2, self if (file.startsWith("gh+/")) { // Change automatically to github var pars = file.split("/") var d = { user: pars[1], mod: pars[2], version: 'master', path: pars.slice(3).join("/") } var y = d.mod.lastIndexOf("@") if (y > 0) { d.version = d.mod.substring(y + 1) d.mod = d.mod.substring(0, y) } file = "https://raw.githubusercontent.com/" + d.user + "/" + d.mod + "/" + d.version + "/" + d.path } if (this._local && this._local[file]) { return this._local[file] } if (!id && options && options.parent) { id = options.parent.filename if (!id) id = "/default.js" } id += "-" + file if (importing[id]) { def = deferred() importing[id].push(def) if (options && options.uid) { // save in _local self = this def2 = deferred() def.promise.then(function (v) { self._local && (self._local[options.uid] = v) return def2.resolve(v) }).catch(def2.reject) return def2.promise } return def.promise } var result = Mod._import.call(this, file, options) if (result && result.then) { def = deferred() c = importing[id] || (importing[id] = []) result.then(function (a) { def.resolve(a) for (var i = 0; i < c.length; i++) { c[i].resolve(a) } delete importing[id] }).catch(function (e) { def.reject(e) for (var i = 0; i < c.length; i++) { c[i].reject(e) } delete importing[id] }) if (options && options.uid) { // save in _local self = this def2 = deferred() def.promise.then(function (v) { self._local && (self._local[options.uid] = v) return def2.resolve(v) }).catch(def2.reject) return def2.promise } return def.promise } if (options && options.uid) { this._local && (this._local[options.uid] = result) } return result } Mod._import = function (file, options) { var uri2, promise, original, filename, uri, parts, resolved, self = this original = file options = createDefault(options) if (builtinModules.indexOf(file) >= 0) { return _require(file) } filename = this.filename || "/default.js" var getBetter = function (a) { if (a) file = a var ids = Object.keys(Mod.extensions).filter(Boolean) promise = new Promise(function (resolve, reject) { var i = -1 var f = function (file, ext) { var cfile = file if (ext) { cfile = file + ext } fs.access(cfile, fs.constants.F_OK, function (err) { if (err) { ext = ids[++i] if (!ext) return reject(new Error("Cannot resolve " + original + " from " + filename + ". Resolved file: " + file + ". Available extensions=" + ids.toString())) return f(file, ext) } return resolve(Mod.require.call(self, cfile, options)) }) } f(file) }) return promise } //resolved = file //if(!Path.isAbsolute(resolved)) resolved = Mod._resolveFilename(file, options.parent, Mod._resolveFilename) if (resolved) { if (isVirtualFile(resolved)) return Mod.require.call(self, resolved) if (resolved.startsWith("https:") || resolved.startsWith("http:") || resolved.startsWith("npm:") || resolved.startsWith("npmi:")) return Mod.require.call(self, resolved, options) return getBetter(resolved) } var uri = validateFileUrl(file) if (uri.protocol || Path.isAbsolute(file)) { if (uri.protocol && uri.protocol != "file:") { return Mod.require.call(self, file, options) } else { if (uri.protocol) file = Url.fileURLToPath(uri.href) file = Path.normalize(file) } return getBetter() } else { if (!this.filename) { this.filename = options.parent && options.parent.filename if (!this.filename) this.filename = "/default.js" } if (file.startsWith("./") || file.startsWith("../") || !Path.isAbsolute(file)) { uri2 = Url.parse(this.filename) if (uri2.protocol && !Path.isAbsolute(this.filename)) { if (file.startsWith("./")) file = file.substring(2) file = Url.resolve(this.filename, file) return Mod.require.call(self, file, options) } else { if (!file.startsWith(".")) { parts = file.split(/\/|\\/) parts = Path.normalize("/virtual/" + parts[0]) if (Mod._virtualfile[parts]) { var ufile = Mod.resolveVirtual(Path.normalize("/virtual/" + ufile), parent) if (ufile) return Mod.require.call(self, ufile, options) } } // find this or with extensions file = Path.join(Path.dirname(this.filename), file) return getBetter() } } else { file = require.resolve(file) return Mod.require.call(self, file, options) } } } Mod.removeCached = function (file) { var cached = Mod._cacherequire[file] if (cached) { /* if (cached.__kawi_uid && cached.__kawi_uid.length) { for (var i = 0; i < cached.__kawi_uid.length; i++) { delete Module._cache[cached.__kawi_uid[i]] } }*/ delete Module._cache[file] delete Mod._cacherequire[file] } //delete Mod._cache[file] } Mod.addVirtualFile = function (file, data) { var path = Path.join("/virtual", file) Mod._virtualfile[path] = data data.platformResolvedpath = path if(Os.platform() == "win32") data.resolvedpath = path.replace(/\\/g,'/') else data.resolvedpath = path if (data.redirect) { Mod._virtualredirect.push(data) } data.time = Date.now() } /** require a module (file or url) */ requiring = {} Mod.require = function (file, options) { var def, result, c if (requiring[file]) { def = deferred() requiring[file].def.push(def) return def.promise } result = Mod._require.call(this, file, options) if (result && typeof result.then == "function") { def = deferred() c = requiring[file] = { def: [def] } result.then(function (a) { for (var i = 0; i < c.def.length; i++) { c.def[i].resolve(a) } delete requiring[file] }).catch(function (e) { for (var i = 0; i < c.def.length; i++) { c.def[i].reject(e) } delete requiring[file] }) return def.promise } return result } Mod._require = function (file, options) { options = options || {} var cached = Mod._cacherequire[file] var promise, promise2, generate, module, self = this var generate = function (ast, resolve, reject) { module = new Module(file, options.parent) module.filename = file module.__kawi_time = Date.now() var nmod = getKModule(file) module.KModule = nmod var p var continue1 = function () { // custom mod for each file Module._cache[file] = module Mod._cacherequire[file] = module //console.info("exports.__kawi= function(KModule){" + ast.code + "}") module._compile("exports.__kawi= function(KModule){" + "\trequire= KModule.replaceSyncRequire(require,module,KModule);" + ast.code + "\n}", file) /* module.__kawi_uid = {} if (options.uid) module.__kawi_uid[options.uid] = true */ var maybePromise = module.exports.__kawi(nmod, nmod.import.bind(nmod)) if (module.exports && module.exports.then) { /** this will be Deprecated, now is used on bundles */ module.exports.then(function (result) { module.exports = result cached = module resolve(returnData(true)) }).catch(reject) } else if (module.exports && typeof module.exports.kawixPreload == "function") { var r0 = module.exports.kawixPreload() if (r0 && r0.then) { r0.then(function () { cached = module resolve(returnData(true)) }).catch(reject) } else { cached = module resolve(returnData(true)) } } else { cached = module resolve(returnData(true)) } } if (ast.injectCode && !ast.inject) { loadInjectImportFunc(ast) } if (ast.inject) { p = ast.inject(nmod) if (p && typeof p.then == "function") { p.then(function () { continue1() }).catch(reject) } else { continue1() } } else { continue1() } } var returnData = function (novalidate) { Module._cache[file] = cached if (options.uid) { self._local[options.uid] = cached.exports /* cached.__kawi_uid = cached.__kawi_uid || {} cached.__kawi_uid[options.uid] = true */ } //Module._cache[options.uid || "_internal_kawi_last.js"] = cached return cached.exports } if (cached) { if (cached.exports.kawixDynamic && ((Date.now() - cached.__kawi_time) > (cached.exports.kawixDynamic.time || Mod.cachetime))) { // exported as dynamicMethod // get if changed ... options.ignoreonunchanged = true if (!options.precompiled) { promise = Mod.compile(file, options) } promise2 = new Promise(function (resolve, reject) { var nc = function (ast) { if (!ast) { return resolve(returnData()) } else { if (ast.redirect) { options.mask = getMask(file, ast) if (ast.from == "npm") { module = new Module(ast.redirect, options.parent) module.load(ast.redirect) cached = module return resolve(returnData(true)) } return resolve(Mod.require(ast.redirect, options)) } Mod.removeCached(file) return generate(ast, function () { // this allow hot reloading modules if (module.exports.kawixDynamic && typeof module.exports.kawixDynamic.reload == "function") { module.exports.kawixDynamic.reload(cached.exports, module.exports) return resolve(module.exports) } return resolve(module.exports) }, reject) } } if (options.precompiled) { loadInjectImportFunc(options.precompiled) nc(options.precompiled) } else { promise.then(nc).catch(reject) } }) return promise2 } else { return returnData() } } if (!options.precompiled) { promise = Mod.compile(file, options) } promise2 = new Promise(function (resolve, reject) { var nc = function (ast) { if (ast && ast.redirect) { options.mask = getMask(file, ast) if (ast.from == "npm") { module = new Module(ast.redirect, options.parent) module.load(Module._originalResolveFilename(ast.redirect)) cached = module return resolve(returnData()) } return resolve(Mod.require(ast.redirect, options)) } return generate(ast, resolve, reject) } if (options.precompiled) { loadInjectImportFunc(options.precompiled) nc(options.precompiled) } else { promise.then(nc).catch(reject) } }) return promise2 } Mod.transpile = transpile var helper = { getCachedFilename: function (uri, options) { return getCachedFilename(uri, options) }, getCachedFilenameSync: function (uri, options) { return getCachedFilenameSync(uri, options) }, // protect concurrency, loading the same file at time lock: function (file) { if (Os.platform() == "browser") { return } var def = deferred() var check, continue1, time, locks, check1 locks = this._locks = this._locks || {} check1 = function () { if (locks[file]) { setImmediate(check1) } else { check() } } time = Date.now() continue1 = function () { locks[file] = true def.resolve() } check = function () { if (Date.now() - time >= 30000) { return def.reject(new Error("Timedout requiring exclusive access for compile: " + file)) } fs.mkdir(file, function (err) { if (err && err.code == 'EEXISTS') err = null if (err) { fs.stat(file, function (err, stat) { if (!err) { if (Date.now() - stat.mtimeMs > 10000) { fs.rmdir(file, function () { check() }) } else { setTimeout(check, 1) } } else { setTimeout(check, 1) } }) } else { continue1() } }) } check1() return def.promise }, unlock: function (file) { var locks = this._locks if (locks && locks[file]) { fs.rmdir(file, function (er) { }) delete locks[file] } }, getContent: function (cache_file, file) { if (!Mod._cachecontent) { Mod._cachecontent = {} } var cache, stat, read cache = Mod._cachecontent[cache_file] if (cache) { stat = fs.statSync(cache_file) if (stat.mtimeMs > cache.mtime) { read = true } } else { read = true } if (read) { cache = fs.readFileSync(cache_file) if(allowCacheCompress == "gzip"){ cache = Zlib.gunzipSync(cache.reverse()) } cache = JSON.parse(cache.toString('utf8')) cache.mtime = (stat && stat.mtimeMs) || Date.now() Mod._cachecontent[cache_file] = cache } return cache[file] }, getCachedData: function (file, uri, options, autounlock) { var def = deferred() var promise = helper.getCachedFilename(uri, options) var cache_file, cache_dir, stat1, stat2, data, vfile, locked, self, lockfile, updatetime self = this var getstat2 = function () { vfile = Mod._virtualfile[file] if (vfile) { if (typeof vfile == "function") { vfile = vfile() } stat2 = vfile.stat } else { stat2 = fs.statSync(file) } } var beautyResponse = function (value) { if (!stat2 && !options.fromremote) { getstat2() } var op = { file: cache_file, folder: cache_dir, stats: [stat1, stat2], lockfile: lockfile, locked: locked } op.data = value if (value && value.unchanged) { op.unchanged = true } if (value) { if (!Mod._cache[file]) { value.time = (stat2 && (stat2.mtimeMs)) || Date.now() Mod._cache[file] = value } else { Mod._cache[file].time = (stat2 && (stat2.mtimeMs)) || Date.now() } } return op } if (autounlock !== false) { var realResolve = def.resolve var realReject = def.reject def.resolve = function (data) { if (locked) { self.unlock(lockfile) } return realResolve(data) } def.reject = function (e) { if (locked) { self.unlock(lockfile) } return realReject(e) } } var actioner = function (value1) { var dir, content cache_file = value1 try { dir = Path.dirname(value1) if (!fs.existsSync(dir)) { fs.mkdirSync(dir) } if (options.force && options.fromremote) { return def.resolve(beautyResponse()) } content = self.getContent(value1, file) /* content = fs.readFileSync(value1, 'utf8') content= JSON.parse(content) content= content[file]*/ } catch (e) { content = null } try { if (options.fromremote) { return def.resolve(beautyResponse(content)) if (content) { return def.resolve(beautyResponse(content)) } else { if (autounlock === false) { lockfile = cache_file + ".lock1" self.lock(lockfile).then(function () { locked = true return def.resolve(beautyResponse()) }).catch(def.reject) } else { return def.resolve(beautyResponse()) } } } if (!content) { return def.resolve(beautyResponse()) } stat1 = content.stat getstat2() var check = function (back) { if (stat1.mtimeMs >= stat2.mtimeMs) { // return unchanged if (options.ignoreonunchanged) { ucached = Mod._cache[file] if ((ucached && ucached.time) >= stat2.mtimeMs) { def.resolve(beautyResponse({ unchanged: true })) return } } updatetime = true return def.resolve(beautyResponse(content)) } else if (back) { return def.resolve(beautyResponse()) } else { return false } } if (check() === false) { if (!vfile) { lockfile = cache_file + ".lock1" self.lock(lockfile).then(function () { locked = true stat2 = fs.statSync(file) check(true) }).catch(def.reject) return } else { return def.resolve(beautyResponse()) } } } catch (e) { return def.resolve(beautyResponse()) } } /* var actioner= function(action, result, result2){ var ucached try{ if(action == 1){ cache_file= result cache_dir = Path.dirname(result) fs.access(cache_dir, fs.constants.F_OK, actioner.bind(this,2)) } else if(action == 2){ if(result){ // err fs.mkdir(cache_dir, actioner.bind(this,3)) } else{ actioner(3) } } else if(action == 3){ if(options.force && options.fromremote){ return def.resolve(beautyResponse()) } // read the stat of cached file if(options.fromremote){ fs.readFile(cache_file, 'utf8', actioner.bind(this, 4)) } else{ fs.stat(cache_file, actioner.bind(this, 5)) } } else if(action == 4){ // file readed if(result){ return def.resolve(beautyResponse()) } return def.resolve(beautyResponse(JSON.parse(result2))) } else if(action == 5){ if(result){ return def.resolve(beautyResponse()) } stat1= result2 if(isVirtualFile(file)){ vfile= Mod._virtualfile[file] if(typeof vfile == "function"){ vfile= vfile() } actioner(6, null, vfile.stat) } else{ fs.stat(file, actioner.bind(this, 6)) } } else if(action >= 6 && action <= 6.5){ if(result) return def.reject(result) if(action == 6) stat2= result2 else stat1= result2 if(stat1.mtimeMs >= stat2.mtimeMs){ // return unchanged if(options.ignoreonunchanged){ ucached= Mod._cache[file] if(ucached && ucached.time >= stat1.mtimeMs){ return def.resolve(beautyResponse({ unchanged: true })) } } return fs.readFile(cache_file, 'utf8' , actioner.bind(this,7)) } // NEED COMPILE if(action == 6){ lockfile= cache_file + ".lock1" return self.lock(lockfile).then(function(){ locked= true fs.stat(cache_file, actioner.bind(this, 6.5)) }).catch(def.reject) } else{ return def.resolve(beautyResponse()) } } else if(action == 7){ if(result) return def.reject(result) updatetime= true try{ var dat