Socket
Socket
Sign inDemoInstall

impress

Package Overview
Dependencies
Maintainers
4
Versions
719
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

impress - npm Package Compare versions

Comparing version 2.1.0 to 2.1.1

lib/cache.js

10

CHANGELOG.md

@@ -5,2 +5,9 @@ # Changelog

## [2.1.1][] - 2021-03-30
- Use metawatch instead of internal watcher
- Remove resources from memory on metawatch 'delete'
- Decompose class Application into Cache, Modules, Interfaces, Resources
- Fix domain and lib live reload bugs
## [2.1.0][] - 2021-03-15

@@ -124,3 +131,4 @@

[unreleased]: https://github.com/metarhia/impress/compare/v2.1.0...HEAD
[unreleased]: https://github.com/metarhia/impress/compare/v2.1.1...HEAD
[2.1.1]: https://github.com/metarhia/impress/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/metarhia/impress/compare/v2.0.14...v2.1.0

@@ -127,0 +135,0 @@ [2.0.14]: https://github.com/metarhia/impress/compare/v2.0.13...v2.0.14

232

lib/application.js
'use strict';
const { node, npm, metarhia } = require('./dependencies.js');
const { path, events, fs, fsp } = node;
const { metautil, metavm } = metarhia;
const { Procedure } = require('./procedure.js');
const { path, events, fs } = node;
const { metavm, metawatch } = metarhia;
const MODULE = 2;
const win = process.platform === 'win32';
const { Interfaces } = require('./interfaces.js');
const { Modules } = require('./modules.js');
const { Resources } = require('./resources.js');

@@ -20,9 +20,2 @@ class Error extends global.Error {

const getSignature = (method) => {
const src = method.toString();
const signature = metautil.between(src, '({', '})');
if (signature === '') return [];
return signature.split(',').map((s) => s.trim());
};
class Application extends events.EventEmitter {

@@ -33,14 +26,12 @@ constructor() {

this.finalization = false;
this.api = {};
this.signatures = {};
this.static = new Map();
this.resources = new Map();
this.root = process.cwd();
this.path = path.join(this.root, 'application');
this.apiPath = path.join(this.path, 'api');
this.libPath = path.join(this.path, 'lib');
this.domainPath = path.join(this.path, 'domain');
this.staticPath = path.join(this.path, 'static');
this.resourcesPath = path.join(this.path, 'resources');
this.api = new Interfaces('api', this);
this.static = new Resources('static', this);
this.resources = new Resources('resources', this);
this.lib = new Modules('lib', this);
this.domain = new Modules('domain', this);
this.starts = [];
this.Application = Application;

@@ -53,13 +44,19 @@ this.Error = Error;

this.auth = null;
this.watcher = null;
}
absolute(relative) {
return path.join(this.path, relative);
}
async init() {
this.startWatch();
this.createSandbox();
await Promise.allSettled([
this.loadPlace('static', this.staticPath),
this.loadPlace('resources', this.resourcesPath),
this.loadPlace('api', this.apiPath),
this.static.load(),
this.resources.load(),
this.api.load(),
(async () => {
await this.loadPlace('lib', this.libPath);
await this.loadPlace('domain', this.domainPath);
await this.lib.load();
await this.domain.load();
})(),

@@ -97,25 +94,9 @@ ]);

sandbox.api = {};
sandbox.lib = {};
sandbox.domain = {};
sandbox.lib = this.lib.tree;
sandbox.domain = this.domain.tree;
this.sandbox = metavm.createContext(sandbox);
}
async createScript(fileName) {
try {
const code = await fsp.readFile(fileName, 'utf8');
if (!code) return null;
const src = 'context => ' + code;
const options = { context: this.sandbox };
const { exports } = new metavm.MetaScript(fileName, src, options);
return exports;
} catch (err) {
if (err.code !== 'ENOENT') {
this.console.error(err.stack);
}
return null;
}
}
getMethod(iname, ver, methodName) {
const iface = this.api[iname];
const iface = this.api.collection[iname];
if (!iface) return null;

@@ -129,81 +110,2 @@ const version = ver === '*' ? iface.default : parseInt(ver, 10);

async loadMethod(fileName) {
const rel = fileName.substring(this.apiPath.length + 1);
if (!rel.includes(path.sep)) return;
const [interfaceName, methodFile] = rel.split(path.sep);
if (!methodFile.endsWith('.js')) return;
const name = path.basename(methodFile, '.js');
const [iname, ver] = interfaceName.split('.');
const version = parseInt(ver, 10);
const script = await this.createScript(fileName);
if (!script) return;
const proc = new Procedure(script, this);
let iface = this.api[iname];
const { api } = this.sandbox;
let internalInterface = api[iname];
if (!iface) {
this.api[iname] = iface = { default: version };
api[iname] = internalInterface = {};
}
if (version > iface.default) iface.default = version;
let methods = iface[ver];
if (!methods) iface[ver] = methods = {};
const { method } = proc;
methods[name] = proc;
internalInterface[name] = method;
this.cacheSignature(iname + '.' + version, name, method);
}
cacheSignature(interfaceName, methodName, method) {
let interfaceMethods = this.signatures[interfaceName];
if (!interfaceMethods) {
this.signatures[interfaceName] = interfaceMethods = {};
}
interfaceMethods[methodName] = getSignature(method);
}
addModule(namespaces, exports, iface) {
let level = this.sandbox;
const last = namespaces.length - 1;
for (let depth = 0; depth <= last; depth++) {
const namespace = namespaces[depth];
let next = level[namespace];
if (next) {
if (depth === MODULE && namespace === 'stop') {
if (iface === null && level.stop) this.execute(level.stop);
}
} else {
if (depth === last) {
next = iface.method || iface;
exports.parent = level;
} else {
next = {};
}
level[namespace] = next;
if (depth === MODULE && namespace === 'start') {
this.starts.push(iface.method);
}
}
level = next;
}
}
async loadModule(fileName) {
const rel = fileName.substring(this.path.length + 1);
if (!rel.endsWith('.js')) return;
const name = path.basename(rel, '.js');
const namespaces = rel.split(path.sep);
namespaces[namespaces.length - 1] = name;
const options = { context: this.sandbox, filename: fileName };
try {
const script = await metavm.readScript(fileName, options);
let exports = script.exports;
if (typeof exports === 'function') exports = { method: exports };
const iface = metautil.makePrivate(exports);
this.addModule(namespaces, exports, iface);
} catch (err) {
this.console.error(err.stack);
}
}
execute(method) {

@@ -215,63 +117,31 @@ return method().catch((err) => {

async loadFile(filePath) {
let key = filePath.substring(this.staticPath.length);
if (win) key = metautil.replace(key, path.sep, '/');
try {
const data = await fsp.readFile(filePath);
this.static.set(key, data);
} catch (err) {
if (err.code !== 'ENOENT') {
this.console.error(err.stack);
}
}
}
startWatch() {
const timeout = this.config.server.timeouts.watch;
this.watcher = new metawatch.DirectoryWatcher({ timeout });
async loadResource(filePath) {
let key = filePath.substring(this.resourcesPath.length);
if (win) key = metautil.replace(key, path.sep, '/');
try {
const data = await fsp.readFile(filePath);
this.resources.set(key, data);
} catch (err) {
if (err.code !== 'ENOENT') {
this.console.error(err.stack);
}
}
}
async loadPlace(place, placePath) {
const files = await fsp.readdir(placePath, { withFileTypes: true });
for (const file of files) {
if (file.name.startsWith('.')) continue;
const filePath = path.join(placePath, file.name);
if (file.isDirectory()) await this.loadPlace(place, filePath);
else if (place === 'api') await this.loadMethod(filePath);
else if (place === 'static') await this.loadFile(filePath);
else if (place === 'resources') await this.loadResource(filePath);
else await this.loadModule(filePath);
}
this.watch(place, placePath);
}
watch(place, placePath) {
fs.watch(placePath, async (event, fileName) => {
if (fileName.startsWith('.')) return;
const filePath = path.join(placePath, fileName);
try {
const stat = await node.fsp.stat(filePath);
this.watcher.on('change', (filePath) => {
const relPath = filePath.substring(this.path.length + 1);
const sepIndex = relPath.indexOf(path.sep);
const place = relPath.substring(0, sepIndex);
fs.stat(filePath, (err, stat) => {
if (err) return;
if (stat.isDirectory()) {
this.loadPlace(place, filePath);
this[place].load(filePath);
return;
}
} catch {
return;
}
if (node.worker.threadId === 1) {
this.console.debug('Reload: /' + relPath);
}
this[place].change(filePath);
});
});
this.watcher.on('delete', async (filePath) => {
const relPath = filePath.substring(this.path.length + 1);
const sepIndex = relPath.indexOf(path.sep);
const place = relPath.substring(0, sepIndex);
this[place].delete(filePath);
if (node.worker.threadId === 1) {
const relPath = filePath.substring(this.path.length);
this.console.debug('Reload: ' + relPath);
this.console.debug('Deleted: /' + relPath);
}
if (place === 'api') this.loadMethod(filePath);
else if (place === 'static') this.loadFile(filePath);
else if (place === 'resources') this.loadResource(filePath);
else this.loadModule(filePath);
});

@@ -284,6 +154,6 @@ }

const [iname, ver = '*'] = interfaceName.split('.');
const iface = this.api[iname];
const iface = this.api.collection[iname];
if (!iface) continue;
const version = ver === '*' ? iface.default : parseInt(ver);
intro[iname] = this.signatures[iname + '.' + version];
intro[iname] = this.api.signatures[iname + '.' + version];
}

@@ -290,0 +160,0 @@ return intro;

@@ -16,3 +16,3 @@ 'use strict';

const metalibs = ['@metarhia/config'];
const metacore = ['metautil', 'metavm', 'metacom', 'metalog'];
const metacore = ['metautil', 'metavm', 'metacom', 'metalog', 'metawatch'];
const metaoptional = ['metaschema', 'metasql'];

@@ -19,0 +19,0 @@ const metapkg = [...metalibs, ...metacore, ...metaoptional];

{
"name": "impress",
"version": "2.1.0",
"version": "2.1.1",
"author": "Timur Shemsedinov <timur.shemsedinov@gmail.com>",

@@ -74,7 +74,8 @@ "description": "Enterprise application server for Node.js",

"metautil": "^3.5.1",
"metavm": "^1.0.0"
"metavm": "^1.0.0",
"metawatch": "^1.0.2"
},
"devDependencies": {
"@types/node": "^14.14.35",
"eslint": "^7.22.0",
"@types/node": "^14.14.37",
"eslint": "^7.23.0",
"eslint-config-metarhia": "^7.0.1",

@@ -81,0 +82,0 @@ "eslint-config-prettier": "^8.1.0",

@@ -1,2 +0,2 @@

interface MetarhiaApplication {
interface Application {
worker: Dictionary<any>;

@@ -14,3 +14,3 @@ server: Dictionary<any>;

declare var application: MetarhiaApplication;
declare var application: Application;
declare var node: Dictionary<any>;

@@ -17,0 +17,0 @@ declare var npm: Dictionary<any>;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc