@knapsack/app
Version:
Build Design Systems on top of knapsack, by Basalt
208 lines (174 loc) • 6.82 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AssetSets = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _getFileSizes = require("get-file-sizes");
var _path = require("path");
var _chokidar = _interopRequireDefault(require("chokidar"));
var _fileDb = require("./dbs/file-db");
var _schemaKnapsackAssetSetsConfig = _interopRequireDefault(require("../json-schemas/schemaKnapsackAssetSetsConfig"));
var _serverUtils = require("./server-utils");
var log = _interopRequireWildcard(require("../cli/log"));
var _events = require("./events");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
/**
* Collections of CSS & JS assets
* @todo use Express to serve it from wherever it is on file system and not just inside the `config.public` dir
*/
class AssetSets extends _fileDb.FileDb2 {
constructor({
dataDir,
publicDir
}) {
super({
filePath: (0, _path.join)(dataDir, 'knapsack.asset-sets.json'),
type: 'json',
validationSchema: _schemaKnapsackAssetSetsConfig.default,
defaults: {
globalAssetSetIds: [],
allAssetSets: {
example: {
id: 'example',
title: 'Example',
inlineCss: '',
inlineJs: '',
assets: [{
src: 'https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css'
}, {
src: 'https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js'
}]
}
}
}
});
(0, _defineProperty2.default)(this, "data", void 0);
(0, _defineProperty2.default)(this, "dataDir", void 0);
(0, _defineProperty2.default)(this, "publicDir", void 0);
this.dataDir = dataDir;
this.publicDir = publicDir;
const userConfig = super.getDataSync();
this.data = this.convertConfigToData(userConfig);
}
convertConfigToData(config) {
const {
allAssetSets,
globalAssetSetIds
} = config;
const data = {
globalAssetSetIds,
allAssetSets: {}
};
if (!allAssetSets) return data;
Object.keys(allAssetSets).forEach(assetSetId => {
const assetSet = allAssetSets[assetSetId];
data.allAssetSets[assetSetId] = _objectSpread({}, assetSet, {
assets: assetSet.assets.map(asset => {
const isRemote = (0, _serverUtils.isRemoteUrl)(asset.src);
const src = isRemote ? asset.src : (0, _path.resolve)(this.dataDir, asset.src);
const {
ext
} = (0, _path.parse)(src);
if (!isRemote) {
(0, _serverUtils.fileExistsOrExit)(src);
if ((0, _path.relative)(this.publicDir, src).includes('..')) {
log.error(`Some CSS or JS is not publically accessible! These must be either remote or places inside the "public" dir (${this.publicDir})`, {
asset
});
process.exit(1);
}
} else {
return _objectSpread({}, asset, {
src,
publicPath: src,
type: ext.replace('.', '')
});
}
const [size] = (0, _getFileSizes.getFileSizes)([src]);
return _objectSpread({}, asset, {
src,
// isInHead: asset.isInHead === true,
publicPath: isRemote ? src : `/${(0, _path.relative)(this.publicDir, src)}`,
type: ext.replace('.', ''),
sizeRaw: size.sizeRaw,
sizeKb: size.sizeKb
});
})
});
});
return data;
}
/**
* @todo evaluate - perhaps it's best to compute these type of values as needed instead of all up front when "config" is turned into "data"?
* @param assetSrc
*/
getAssetPublicPath(assetSrc) {
const isRemote = (0, _serverUtils.isRemoteUrl)(assetSrc);
const src = isRemote ? assetSrc : (0, _path.resolve)(this.dataDir, assetSrc);
if (!isRemote) {
(0, _serverUtils.fileExistsOrExit)(src);
if ((0, _path.relative)(this.publicDir, src).includes('..')) {
log.error(`Some CSS or JS is not publically accessible! These must be either remote or places inside the "public" dir (${this.publicDir})`);
process.exit(1);
}
}
return isRemote ? src : `/${(0, _path.relative)(this.publicDir, src)}`;
}
static convertDataToConfig(data) {
const {
allAssetSets,
globalAssetSetIds
} = data;
const config = {
globalAssetSetIds,
allAssetSets: {}
};
Object.keys(allAssetSets).forEach(assetSetId => {
const assetSet = allAssetSets[assetSetId];
config.allAssetSets[assetSetId] = _objectSpread({}, assetSet, {
assets: assetSet.assets.map(({
src
}) => {
return {
src
};
})
});
});
return data;
}
async getData() {
const userConfig = await super.getData(); // this.config = this.config;
this.data = this.convertConfigToData(userConfig);
return this.data;
}
getAssetSet(assetSetId) {
return this.data.allAssetSets[assetSetId];
}
getGlobalAssetSets() {
return this.data.globalAssetSetIds.map(id => this.data.allAssetSets[id]);
}
watch() {
const paths = new Set();
Object.values(this.data.allAssetSets).forEach(({
assets
}) => {
assets.forEach(asset => paths.add(asset.src));
});
const localAssetPaths = [...paths];
const assetWatcher = _chokidar.default.watch(localAssetPaths, {
ignoreInitial: true
});
assetWatcher.on('all', (event, path) => {
_events.knapsackEvents.emit(_events.EVENTS.PATTERN_ASSET_CHANGED, {
event,
path
});
});
}
}
exports.AssetSets = AssetSets;