noodl-loader
Version:
Loader for noodl applications
397 lines • 19.5 kB
JavaScript
"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