@vulcan-sql/build
Version:
VulcanSQL package for building projects
142 lines • 7.59 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CheckCache = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@vulcan-sql/core");
const middleware_1 = require("./middleware");
const constants_1 = require("./constants");
const ms_1 = require("ms");
class CheckCache extends middleware_1.SchemaParserMiddleware {
handle(schemas, next) {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
// check .yaml file has cache configuration
const caches = schemas === null || schemas === void 0 ? void 0 : schemas.cache;
const metadata = schemas.metadata;
const isUsedCache = (_a = metadata === null || metadata === void 0 ? void 0 : metadata[constants_1.CACHE_METADATA_NAME]) === null || _a === void 0 ? void 0 : _a['isUsedTag'];
if (!isUsedCache && !caches)
return next();
// throw if cache not used in .sql file
if (isUsedCache && !caches) {
throw new core_1.ConfigurationError(`{% cache %} tag was used in SQL file, but the cache configurations was not found in schema "${schemas.urlPath}".`);
}
if (!isUsedCache && caches) {
throw new core_1.ConfigurationError(`Can not configure the cache setting in schema "${schemas.urlPath}", {% cache %} tag not been used in SQL file.`);
}
this.checkCacheTableName(schemas);
this.checkSQLHasValue(schemas);
this.assignCacheProfile(schemas);
this.checkRefreshSettings(schemas);
this.checkIndexesHasValue(schemas);
yield next();
});
}
checkRefreshSettings(schemas) {
const { cache: caches, urlPath } = schemas;
for (const cache of caches) {
const { refreshTime, refreshExpression, cacheTableName } = cache;
if (!refreshTime && !refreshExpression)
continue;
if (refreshTime && refreshExpression) {
throw new core_1.ConfigurationError(`Can not set "refreshTime" and "refreshExpression" at the same time in cache "${cacheTableName}" of schema "${urlPath}"`);
}
const options = refreshTime
? { type: 'refreshTime', timeInterval: refreshTime.every }
: { type: 'refreshExpression', timeInterval: refreshExpression.every };
const message = this.checkRefreshInterval(options.timeInterval);
if (message)
throw new core_1.ConfigurationError(`The "${options.type}.every" of cache "${cacheTableName}" in schema "${urlPath}" is invalid: ${message}`);
}
}
checkRefreshInterval(timeInterval) {
if (!timeInterval)
return 'Should have a value.';
const interval = (0, ms_1.default)(timeInterval);
if (isNaN(interval))
return 'Invalid time string to convert.';
if (interval < 0)
return 'Time can not be negative.';
return '';
}
checkCacheTableName(schemas) {
const caches = schemas === null || schemas === void 0 ? void 0 : schemas.cache;
const cacheTableNames = [];
caches === null || caches === void 0 ? void 0 : caches.forEach((cache) => {
const { cacheTableName } = cache;
// should have table name
if (!cacheTableName) {
throw new core_1.ConfigurationError(`The "cacheTableName" of cache in schema "${schemas.urlPath}" is not defined.`);
}
// table name should be unique
if (cacheTableNames.includes(cacheTableName)) {
throw new core_1.ConfigurationError(`The cacheTableName "${cacheTableName}" of cache in schema "${schemas.urlPath}" is not unique.`);
}
// table naming pattern
// 1. start with a letter or underscore, and can only contain letters, numbers, and underscores
// 2. the sub-characters contain letters, numbers, underscore, and dollar sign
const pattern = /^[a-zA-Z_][a-zA-Z0-9_$]+$/;
if (!pattern.test(cacheTableName)) {
throw new core_1.ConfigurationError(`The cacheTableName "${cacheTableName}" in schema "${schemas.urlPath}" should meet the pattern "${pattern}".`);
}
cacheTableNames.push(cacheTableName);
});
}
// check sql is not empty
checkSQLHasValue(schemas) {
const { cache: caches, urlPath } = schemas;
caches === null || caches === void 0 ? void 0 : caches.forEach((cache) => {
const { sql, cacheTableName } = cache;
if (!sql) {
throw new core_1.ConfigurationError(`The "sql" of cache "${cacheTableName}" in schema "${urlPath}" is not defined or is empty.`);
}
});
}
// check indexes value is not empty
checkIndexesHasValue(schemas) {
const { cache: caches, urlPath } = schemas;
const indexNames = [];
caches === null || caches === void 0 ? void 0 : caches.forEach(({ indexes, cacheTableName }) => {
if (indexes) {
Object.entries(indexes).forEach(([indexName, columnName]) => {
if (!columnName || typeof columnName !== 'string') {
throw new core_1.ConfigurationError(`The index "${indexName}" of cache "${cacheTableName}" in schema "${urlPath}" should be a string.`);
}
// index name should be unique even in different cache table name (duckdb could not create same index name on different table)
if (indexNames.includes(indexName)) {
throw new core_1.ConfigurationError(`The indexName "${indexName}" of cache in schema "${schemas.urlPath}" is not unique.`);
}
// index naming pattern
// 1. start with a letter or underscore, and can only contain letters, numbers, and underscores
// 2. the sub-characters contain letters, numbers, underscore, and dollar sign
const pattern = /^[a-zA-Z_][a-zA-Z0-9_$]+$/;
if (!pattern.test(indexName)) {
throw new core_1.ConfigurationError(`The index name "${indexName}" in schema "${schemas.urlPath}" should meet the pattern "${pattern}".`);
}
indexNames.push(indexName);
});
}
});
}
// assign the first profile in the schemas.profiles to the cache.profile if cache.profile is not defined
// cache profile should exist in schemas.profiles
assignCacheProfile(schemas) {
const { cache: caches, profiles, urlPath } = schemas;
if (!profiles) {
throw new core_1.ConfigurationError(`The "profiles" of schema "${schemas.urlPath}" is not defined.`);
}
const defaultProfile = profiles[0];
for (const cache of caches) {
const { profile, cacheTableName } = cache;
if (!profile) {
cache.profile = defaultProfile;
continue;
}
// if cache.profile is not in profiles, throw error
if (!profiles.includes(profile)) {
throw new core_1.ConfigurationError(`The profile "${profile}" of cache "${cacheTableName}" in schema "${urlPath}" is not defined in the schema profiles.`);
}
}
}
}
exports.CheckCache = CheckCache;
//# sourceMappingURL=checkCache.js.map