Comparing version 1.1.2 to 1.2.0
40
api.md
@@ -83,3 +83,43 @@ # ModuleProxy | ||
[chokidar](https://github.com/paulmillr/chokidar). | ||
- `setLoader(loader: ModuleLoader): void` Sets a custom loader to resolve the | ||
module. | ||
# ModuleLoader | ||
```typescript | ||
export interface ModuleLoader { | ||
extesion: string, | ||
load(path: string): any; | ||
remove(path: string): void; | ||
} | ||
``` | ||
By default, Alar supports JavaScript modules and (TypeScript modules in | ||
**ts-node**), By setting a custom loader, a ModuleProxy instance can resolve any | ||
kind of module wanted. | ||
- `extesion` Extension name of the module file, by default, it's `.js` (or `.ts` | ||
in ts-node). | ||
- `load(path: string): any` Loads module from the given `path` (`extension` | ||
excluded) or cache. | ||
- `remove(path: string): void` Removes module from cache when watcher is running. | ||
```typescript | ||
// Add a loader to resolve JSON modules. | ||
var json = new alar.ModuleProxy("json", __dirname + "/json"); | ||
var cache = {}; | ||
json.setLoader({ | ||
extesion: ".json", | ||
load(path) { | ||
return cache[path] || ( | ||
cache[path] = JSON.parse(fs.readFileSync(path + this.extesion, "utf8")) | ||
); | ||
}, | ||
remove(path) { | ||
cache[path] && (delete cache[path]); | ||
} | ||
}); | ||
``` | ||
# RpcOptions | ||
@@ -86,0 +126,0 @@ |
@@ -15,6 +15,15 @@ "use strict"; | ||
const util_1 = require("./util"); | ||
const isTsNode = process.execArgv.join(" ").includes("ts-node"); | ||
const defaultLoader = { | ||
extesion: isTsNode ? ".ts" : ".js", | ||
load: require, | ||
remove(path) { | ||
delete require.cache[path + this.extesion]; | ||
} | ||
}; | ||
let ModuleProxy = ModuleProxy_1 = class ModuleProxy { | ||
constructor(name, path, singletons = {}) { | ||
constructor(name, path) { | ||
this.name = name; | ||
this.singletons = singletons; | ||
this.loader = defaultLoader; | ||
this.singletons = {}; | ||
this.remoteSingletons = {}; | ||
@@ -31,19 +40,25 @@ this.children = {}; | ||
get exports() { | ||
return require(this.path); | ||
return this.loader.load(this.path); | ||
} | ||
get proto() { | ||
let { exports } = this; | ||
if (exports.default) { | ||
if (typeof exports.default === "object") { | ||
return exports.default; | ||
} | ||
else if (typeof exports.default === "function") { | ||
return exports.default.prototype; | ||
} | ||
} | ||
return null; | ||
if (typeof exports.default === "object") | ||
return exports.default; | ||
else if (typeof exports.default === "function") | ||
return exports.default.prototype; | ||
else if (typeof exports === "object") | ||
return exports; | ||
else if (typeof exports === "function") | ||
return exports.prototype; | ||
else | ||
return null; | ||
} | ||
get ctor() { | ||
let { exports } = this; | ||
return typeof exports.default === "function" ? exports.default : null; | ||
if (typeof exports.default === "function") | ||
return exports.default; | ||
else if (typeof exports === "function") | ||
return exports; | ||
else | ||
return null; | ||
} | ||
@@ -87,7 +102,7 @@ create(...args) { | ||
let modPath = path.slice(rootPath.length), ext = path_1.extname(modPath); | ||
if (ext === ".js" || ext === ".ts") { | ||
modPath = modPath.slice(0, -3); | ||
if (ext === this.loader.extesion) { | ||
modPath = modPath.slice(0, -this.loader.extesion.length); | ||
} | ||
else if (ext) { | ||
return null; | ||
return; | ||
} | ||
@@ -106,3 +121,3 @@ return this.root.name + "." + modPath.replace(/\\|\//g, "."); | ||
delete this.singletons[name]; | ||
delete require.cache[filename]; | ||
this.loader.remove(filename.slice(0, -this.loader.extesion.length)); | ||
cb && cb(event, filename); | ||
@@ -127,2 +142,5 @@ } | ||
} | ||
setLoader(loader) { | ||
this.loader = loader; | ||
} | ||
__get(prop) { | ||
@@ -136,3 +154,6 @@ if (prop in this) { | ||
else if (typeof prop != "symbol") { | ||
return (this.children[prop] = new ModuleProxy_1((this.name && `${this.name}.`) + String(prop), this.root.path, this.singletons)); | ||
this.children[prop] = new ModuleProxy_1((this.name && `${this.name}.`) + String(prop), this.root.path); | ||
this.children[prop].singletons = this.singletons; | ||
this.children[prop].loader = this.loader; | ||
return this.children[prop]; | ||
} | ||
@@ -139,0 +160,0 @@ } |
{ | ||
"name": "alar", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "Auto-Load And Remote.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -47,6 +47,8 @@ # Alar | ||
In other files, just define and export a default class (Alar only supports the | ||
`default` exports), and merge the type to the namespace `app`, so that another | ||
file can access it directly via namespace. | ||
In other files, just define and export a default class, and merge the type to | ||
the namespace `app`, so that another file can access it directly via namespace. | ||
(NOTE: Alar offers first priority of the `default` export, if a module doesn't | ||
have default export, Alar will try to load the entire exports object instead.) | ||
```typescript | ||
@@ -53,0 +55,0 @@ // src/bootstrap.ts |
@@ -54,5 +54,28 @@ import { resolve, normalize, extname, sep } from "path"; | ||
export interface ModuleLoader { | ||
/** | ||
* Extension name of the module file, by default, it's `.js` (or `.ts` in | ||
* ts-node). | ||
*/ | ||
extesion: string, | ||
/** Loads module from the given `path` (`extension` excluded) or cache. */ | ||
load(path: string): any; | ||
/** Removes module from cache when watcher is running. */ | ||
remove(path: string): void; | ||
} | ||
const isTsNode = process.execArgv.join(" ").includes("ts-node"); | ||
const defaultLoader: ModuleLoader = { | ||
extesion: isTsNode ? ".ts" : ".js", | ||
load: require, | ||
remove(path) { | ||
delete require.cache[path + this.extesion]; | ||
} | ||
} | ||
@applyMagic | ||
export class ModuleProxy { | ||
private root: { name: string, path: string }; | ||
private loader: ModuleLoader = defaultLoader; | ||
private singletons: { [name: string]: any } = {}; | ||
private remoteSingletons: { [dsn: string]: any } = {}; | ||
@@ -64,3 +87,2 @@ private children: { [name: string]: ModuleProxy } = {}; | ||
path: string, | ||
private singletons: { [name: string]: any } = {}, | ||
) { | ||
@@ -78,3 +100,3 @@ this.root = { | ||
get exports(): any { | ||
return require(this.path); | ||
return this.loader.load(this.path); | ||
} | ||
@@ -85,11 +107,12 @@ | ||
if (exports.default) { | ||
if (typeof exports.default === "object") { | ||
return exports.default; | ||
} else if (typeof exports.default === "function") { | ||
return exports.default.prototype; | ||
} | ||
} | ||
return null; | ||
if (typeof exports.default === "object") | ||
return exports.default; | ||
else if (typeof exports.default === "function") | ||
return exports.default.prototype; | ||
else if (typeof exports === "object") | ||
return exports; | ||
else if (typeof exports === "function") | ||
return exports.prototype; | ||
else | ||
return null; | ||
} | ||
@@ -100,3 +123,8 @@ | ||
return typeof exports.default === "function" ? exports.default : null; | ||
if (typeof exports.default === "function") | ||
return exports.default; | ||
else if (typeof exports === "function") | ||
return exports; | ||
else | ||
return null; | ||
} | ||
@@ -156,6 +184,6 @@ | ||
if (ext === ".js" || ext === ".ts") { | ||
modPath = modPath.slice(0, -3); | ||
if (ext === this.loader.extesion) { | ||
modPath = modPath.slice(0, -this.loader.extesion.length); | ||
} else if (ext) { | ||
return null; | ||
return; | ||
} | ||
@@ -177,3 +205,3 @@ | ||
delete this.singletons[name]; | ||
delete require.cache[filename]; | ||
this.loader.remove(filename.slice(0, -this.loader.extesion.length)); | ||
cb && cb(event, filename); | ||
@@ -201,2 +229,7 @@ } | ||
/** Sets a custom loader to resolve the module. */ | ||
setLoader(loader: ModuleLoader) { | ||
this.loader = loader; | ||
} | ||
protected __get(prop: string) { | ||
@@ -208,7 +241,9 @@ if (prop in this) { | ||
} else if (typeof prop != "symbol") { | ||
return (this.children[prop] = new ModuleProxy( | ||
this.children[prop] = new ModuleProxy( | ||
(this.name && `${this.name}.`) + String(prop), | ||
this.root.path, | ||
this.singletons, | ||
)); | ||
this.root.path | ||
); | ||
this.children[prop].singletons = this.singletons; | ||
this.children[prop].loader = this.loader; | ||
return this.children[prop]; | ||
} | ||
@@ -215,0 +250,0 @@ } |
@@ -36,3 +36,2 @@ /* global app */ | ||
assert.strictEqual(app.resolve(app.service.user.path + ".js"), "app.service.user"); | ||
assert.strictEqual(app.resolve(app.service.user.path + ".ts"), "app.service.user"); | ||
}); | ||
@@ -159,2 +158,21 @@ | ||
}); | ||
it("should use a custom loader to load JSON module as expected", () => { | ||
var json = new alar.ModuleProxy("json", __dirname + "/json"); | ||
var cache = {}; | ||
json.setLoader({ | ||
extesion: ".json", | ||
load(path) { | ||
return cache[path] || ( | ||
cache[path] = JSON.parse(fs.readFileSync(path + this.extesion, "utf8")) | ||
); | ||
}, | ||
remove(path) { | ||
cache[path] && (delete cache[path]); | ||
} | ||
}); | ||
assert.deepStrictEqual(json.test.instance(), { name: "JSON", version: "1.0.0" }); | ||
assert.strictEqual(Object.getPrototypeOf(json.test.create()), json.test.instance()); | ||
}); | ||
}); |
@@ -16,2 +16,3 @@ { | ||
"sourceMap": true, | ||
"noImplicitThis": true, | ||
"lib": [ | ||
@@ -18,0 +19,0 @@ "es2015", |
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
76749
20
1280
204