UNPKG

noodl-loader

Version:

Loader for noodl applications

397 lines 19.5 kB
"use strict"; var _NoodlLoader_extractor, _NoodlLoader_state, _NoodlLoader_fs, _NoodlLoader_root; Object.defineProperty(exports, "__esModule", { value: true }); exports.getYml = void 0; const tslib_1 = require("tslib"); const noodl_core_1 = require("noodl-core"); const invariant_1 = tslib_1.__importDefault(require("invariant")); const yaml_1 = tslib_1.__importStar(require("yaml")); const path_1 = tslib_1.__importDefault(require("path")); const extractor_1 = require("../extractor"); const load_file_1 = tslib_1.__importDefault(require("../utils/load-file")); const config_1 = tslib_1.__importDefault(require("../config")); const cadlendpoint_1 = tslib_1.__importDefault(require("../cadlendpoint")); const type_of_1 = tslib_1.__importDefault(require("../utils/type-of")); const yml_1 = require("../utils/yml"); const create = tslib_1.__importStar(require("../utils/create")); const format_1 = require("../utils/format"); const replace_1 = require("../utils/replace"); const trim_1 = require("../utils/trim"); const loader_file_system_1 = tslib_1.__importDefault(require("./loader-file-system")); const is = tslib_1.__importStar(require("../utils/is")); const c = tslib_1.__importStar(require("../constants")); const t = tslib_1.__importStar(require("./loader-types")); function getYml(options) { return tslib_1.__awaiter(this, void 0, void 0, function* () { try { let _value = ''; let { config, cadlEndpoint, fs: _fs, mode, value } = options; if (noodl_core_1.is.obj(value)) { _value = (0, yml_1.stringify)(value); } else if (noodl_core_1.is.str(value)) { _value = value; } if (!mode) { const isAppKey = is.equalFileKey((config === null || config === void 0 ? void 0 : config.appKey) || '', _value); const isConfigKey = is.equalFileKey((config === null || config === void 0 ? void 0 : config.configKey) || '', _value); const isPreload = cadlEndpoint === null || cadlEndpoint === void 0 ? void 0 : cadlEndpoint.preloadExists(_value); const isPage = cadlEndpoint === null || cadlEndpoint === void 0 ? void 0 : cadlEndpoint.pageExists(_value); const isUrl = is.url(_value); mode = isUrl || isConfigKey || isPreload || isPage ? 'url' : 'file'; if (isAppKey || isConfigKey || isPreload || isPage) { const baseUrl = isConfigKey ? c.baseRemoteConfigUrl : config === null || config === void 0 ? void 0 : config.baseUrl; _value = `${baseUrl}`; } } switch (mode) { case 'file': { (0, invariant_1.default)(is.file, `Cannot retrieve from invalid filepath "${_value}"`); return (yield (_fs === null || _fs === void 0 ? void 0 : _fs.readFile(_value, 'utf8'))); } case 'url': { (0, invariant_1.default)(is.url(_value), `"${_value}" must be a valid url`); return (0, yml_1.fetchYml)(_value); } default: return _value; } } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); throw err; } }); } exports.getYml = getYml; function spreadToRoot(root, node) { if (yaml_1.default.isDocument(node)) { node = node.contents; } if (yaml_1.default.isMap(node)) { node.items.forEach((pair) => { root[String(pair.key)] = pair.value; }); } return root; } class NoodlLoader extends t.AbstractLoader { [(_NoodlLoader_extractor = new WeakMap(), _NoodlLoader_state = new WeakMap(), _NoodlLoader_fs = new WeakMap(), _NoodlLoader_root = new WeakMap(), Symbol.iterator)]() { const entries = noodl_core_1.fp.entries(this.root).reverse(); return { next() { return { get value() { return entries.pop(); }, get done() { return !entries.length; }, }; }, }; } [Symbol.for('nodejs.util.inspect.custom')]() { return { config: this.config.toJSON(), cadlEndpoint: this.cadlEndpoint.toJSON(), rootKeys: Object.keys(tslib_1.__classPrivateFieldGet(this, _NoodlLoader_root, "f")), }; } constructor() { super(); _NoodlLoader_extractor.set(this, void 0); _NoodlLoader_state.set(this, { /** * If languageSuffix is set, fetches to cadlMain/preload/pages will have the language code (taken from config) attached between the file name and extension. * @example * ```js * // When the languageSuffix is set to 'en" * const endpoint = 'https://public.aitmed.com/cadl/patd0.7d/BaseCSS_en.yml * ``` */ languageSuffix: '', }); _NoodlLoader_fs.set(this, void 0); _NoodlLoader_root.set(this, void 0); tslib_1.__classPrivateFieldSet(this, _NoodlLoader_fs, new loader_file_system_1.default(), "f"); tslib_1.__classPrivateFieldSet(this, _NoodlLoader_root, { Config: new config_1.default(), Global: {}, }, "f"); this.config = tslib_1.__classPrivateFieldGet(this, _NoodlLoader_root, "f").Config; this.config.rootConfigUrl = c.baseRemoteConfigUrl; this.config.set('web', { cadlVersion: { stable: null, test: null } }); this.cadlEndpoint = new cadlendpoint_1.default(); tslib_1.__classPrivateFieldSet(this, _NoodlLoader_extractor, (0, extractor_1.createExtractor)(this), "f"); } get appKey() { return (this.config.appKey || this.config.get('cadlMain') || ''); } get configKey() { return this.config.configKey; } get root() { return tslib_1.__classPrivateFieldGet(this, _NoodlLoader_root, "f"); } createURL(arg1, arg2) { let type = 'page'; let pathname = ''; const withLanguageSuffix = (str) => { str = (0, trim_1.trimPageName)(str); const { languageSuffix = '' } = this.getState(); if (languageSuffix) str += `_${languageSuffix}`; return (0, format_1.ensureSuffix)('.yml', str); }; if (['config', 'cadlEndpoint', 'page'].some((s) => arg1 === s)) { type = arg1; if (arg1 === 'config') { pathname = (0, format_1.ensureSuffix)('.yml', this.configKey); } else if (arg1 === 'cadlEndpoint') { pathname = (0, format_1.ensureSuffix)('.yml', this.appKey); } else { pathname = withLanguageSuffix(arg2); } } else { if (is.equalFileKey(this.configKey, arg1)) { return this.createURL('config', arg1); } else if (is.equalFileKey(this.appKey, arg1)) { return this.createURL('cadlEndpoint', arg1); } else { return this.createURL('page', arg1); } } switch (type) { case 'config': return `${this.config.rootConfigUrl}/${pathname}`; case 'cadlEndpoint': return `${this.config.resolve(this.cadlEndpoint.baseUrl || this.config.baseUrl)}${pathname}`; default: { return `${this.config.resolve(this.cadlEndpoint.baseUrl || this.config.baseUrl)}${pathname}`; } } } extract(node, options) { return tslib_1.__classPrivateFieldGet(this, _NoodlLoader_extractor, "f").call(this, node, options); } reduce(callback, initialValue = undefined) { return noodl_core_1.fp.entries(this.root).reduce((acc, [name, node], index) => { return callback(acc, [name, node], index, this.root); }, initialValue); } getLoadOptions(other) { return Object.assign({ config: this.config, cadlEndpoint: this.cadlEndpoint, fs: tslib_1.__classPrivateFieldGet(this, _NoodlLoader_fs, "f"), languageSuffix: this.getState().languageSuffix }, other); } getState() { return tslib_1.__classPrivateFieldGet(this, _NoodlLoader_state, "f"); } /** * @param value Config, cadlEndpoint, preload name, page name, URL, filepath * @param options */ load(value = '', options = {}) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const { dir, includePreload = true, includePages = true, mode = 'url', spread = true, } = options; if (mode === 'file') { (0, invariant_1.default)(!!dir, `Directory is required when mode === 'file'`); } const handlePreloadOrPage = (name, yml) => tslib_1.__awaiter(this, void 0, void 0, function* () { try { const isPreload = this.cadlEndpoint.preloadExists(name); const isPage = this.cadlEndpoint.pageExists(name); const doc = (0, yml_1.parseAs)('doc', yml); if (isPreload) { if (spread) spreadToRoot(this.root, doc.contents); else this.root[(0, format_1.removeSuffix)('.yml', name)] = doc.contents; } else if (isPage) { this.root[name] = doc; } else { throw new Error(`"${value}" (name: ${(0, format_1.quoteIfEmptyStr)(name)}) is not an item of preload or page list`); } } catch (error) { throw error instanceof Error ? error : new Error(String(error)); } }); const loadPreloadOrPages = (names) => Promise.all(names.map((name) => this.load(name, options))); if (this.configKey && is.equalFileKey(this.configKey, value)) { const configYml = yield getYml(Object.assign(Object.assign({}, this.getLoadOptions()), { dir, mode, value: mode === 'file' ? path_1.default.join(dir, (0, format_1.ensureSuffix)('.yml', value)) : create.configUri(value) })); yield this.loadConfig(configYml, options); yield this.load(this.appKey, options); if (includePreload) { yield loadPreloadOrPages(this.cadlEndpoint.getPreload()); } if (includePages) { yield loadPreloadOrPages(this.cadlEndpoint.getPages()); } } else if (this.appKey && is.equalFileKey(this.appKey, value)) { yield this.loadCadlEndpoint(yield getYml(Object.assign(Object.assign({}, this.getLoadOptions()), { dir, mode, value: mode === 'file' ? path_1.default.join(dir, (0, format_1.ensureSuffix)('.yml', this.appKey)) : this.createURL(value) })), Object.assign(Object.assign({}, this.getLoadOptions()), { dir, mode })); } else if ((value && this.cadlEndpoint.preloadExists(value)) || this.cadlEndpoint.pageExists(value)) { const name = value; const filename = (0, format_1.ensureSuffix)('.yml', value); let endpoint = mode === 'file' ? path_1.default.join(dir || '', filename) : this.createURL(filename); let { languageSuffix = '' } = this.getState(); if (languageSuffix) languageSuffix = `_${languageSuffix}`; endpoint = (0, format_1.ensureSuffix)('.yml', (0, format_1.ensureSuffix)(languageSuffix, (0, trim_1.trimPageName)(endpoint))); yield handlePreloadOrPage(name, yield getYml(Object.assign(Object.assign({}, this.getLoadOptions()), { dir, mode, value: endpoint }))); } else if (value && is.url(value)) { const { name } = path_1.default.parse(value); if ([this.configKey, this.appKey].some((key) => is.equalFileKey(key, name))) { yield this.load(name, options); } else { yield handlePreloadOrPage(name, yield (0, yml_1.fetchYml)(value)); } } else if (value && is.file(value)) { yield this.load(path_1.default.parse(value).name, Object.assign(Object.assign({}, options), { mode: 'file' })); } else if (this.configKey) { // Fallback to loading from the config return this.load(this.configKey, options); } else { throw new Error(`Missing configKey`); } }); } loadConfig(yml, { dir = '', mode } = {}) { return tslib_1.__awaiter(this, void 0, void 0, function* () { try { (0, invariant_1.default)(Boolean(yml), `yml cannot be empty`); if (is.equalFileKey(this.configKey, yml)) { let pathname = (0, format_1.ensureSuffix)('.yml', yml); let value = ''; if (mode === 'file') { (0, invariant_1.default)(!!dir, `Directory is required when mode === 'file'`); value = path_1.default.join(dir, pathname); } else { if (!mode) mode = 'url'; value = this.createURL('config', pathname); } yml = yield getYml(Object.assign(Object.assign({}, this.getLoadOptions()), { mode, value })); } const configJson = (0, yml_1.parse)('object', yml); (0, invariant_1.default)(noodl_core_1.is.obj(configJson), `Expected an object for config but received ${(0, type_of_1.default)(configJson)}`); noodl_core_1.fp.entries(configJson).forEach(([k, v]) => this.config.set(k, v)); } catch (error) { throw error instanceof Error ? error : new Error(String(error)); } }); } loadCadlEndpoint(arg1, arg2) { var _a, _b; return tslib_1.__awaiter(this, arguments, void 0, function* () { let _appKey = ''; let _props = {}; let _baseUrl = this.config.resolve(this.cadlEndpoint.baseUrl || this.config.baseUrl); if (!arguments.length) { _appKey = this.appKey || this.config.get('cadlMain'); (0, invariant_1.default)(!!_appKey, `Config must be loaded containing the app key (cadlMain) if no arguments are provided`); if (this.appKey !== _appKey || this.config.get('cadlMain') !== _appKey) { this.config.set('cadlMain', _appKey); } const options = {}; options.mode = 'url'; options.value = (0, format_1.endpoint)(_baseUrl, _appKey); noodl_core_1.fp.assign(_props, (0, yml_1.parseAs)('json', yield getYml(options))); } else { if (noodl_core_1.is.obj(arg1)) { if ((0, yml_1.isNode)(arg1) || (0, yaml_1.isPair)(arg1) || (0, yml_1.isDocument)(arg1)) { let node = arg1; if ((0, yml_1.isDocument)(node)) node = node.contents; if ((0, yml_1.isMap)(node)) { node.items.forEach((pair) => { _props[String(pair.key)] = (0, yml_1.isNode)(pair.value) ? pair.value.toJSON() : pair.value; }); } } else { let filename = (0, format_1.ensureSuffix)('.yml', this.appKey); let mode = arg1.mode || (arg2 === null || arg2 === void 0 ? void 0 : arg2.mode) || 'url'; if (mode === 'file') { const dir = arg1.dir || (arg2 === null || arg2 === void 0 ? void 0 : arg2.dir); (0, invariant_1.default)(!!dir, `Directory is required when loading cadlEndpoint and mode === 'file'`); const filepath = path_1.default.join(dir, filename); const yml = yield (0, load_file_1.default)(tslib_1.__classPrivateFieldGet(this, _NoodlLoader_fs, "f"), filepath); noodl_core_1.fp.assign(_props, (0, yml_1.parseAs)('json', yml)); } else { const url = (0, format_1.endpoint)(_baseUrl, filename); const yml = yield getYml({ mode, value: url }); noodl_core_1.fp.assign(_props, (0, yml_1.parseAs)('json', yml)); } } } else if (noodl_core_1.is.str(arg1)) { noodl_core_1.fp.assign(_props, (0, yml_1.parseAs)('json', arg1)); } else { console.error(new Error(`REMINDER: CONTINUE THIS IMPLEMENTATION`)); } } for (let [key, val] of noodl_core_1.fp.entries(_props)) { if (key === 'preload') { this.cadlEndpoint.getPreload().push(...val); } else if (key === 'page' || key === 'pages') { this.cadlEndpoint.getPages().push(...val); } else { const configProps = this.config.toJSON(); (_b = (_a = this.cadlEndpoint) === null || _a === void 0 ? void 0 : _a.set) === null || _b === void 0 ? void 0 : _b.call(_a, key, (0, replace_1.replacePlaceholders)(val, configProps)); } } }); } setAppKey(appKey) { this.config.appKey = appKey; return this; } setConfigKey(configKey) { this.config.configKey = configKey; return this; } setFileLanguageSuffix(languageSuffix) { this.getState().languageSuffix = languageSuffix; return this; } use(value) { if (is.fileSystemHost(value)) { tslib_1.__classPrivateFieldSet(this, _NoodlLoader_fs, value, "f"); } return this; } } exports.default = NoodlLoader; //# sourceMappingURL=loader.js.map