Comparing version 1.0.6 to 1.1.0
@@ -14,2 +14,4 @@ # ModuleProxy | ||
- `path: string` The path (without extension) of the module. | ||
- `exports: any` The very exports object of the module. | ||
- `proto: object` The very prototype of the module. | ||
- `ctor: ModuleConstructor<T>` The very class constructor of the module. | ||
@@ -16,0 +18,0 @@ - `create()` Creates a new instance of the module. |
@@ -29,19 +29,32 @@ "use strict"; | ||
} | ||
get ctor() { | ||
let { path } = this; | ||
let mod = require.cache[path + ".ts"] || require.cache[path + ".js"]; | ||
if (!mod) { | ||
mod = require(path); | ||
if (!mod.default || typeof mod.default !== "function") { | ||
throw new TypeError(`Module ${this.name} is not a constructor.`); | ||
get exports() { | ||
return require(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; | ||
} | ||
get ctor() { | ||
let { exports } = this; | ||
return typeof exports.default === "function" ? exports.default : null; | ||
} | ||
create(...args) { | ||
if (this.ctor) { | ||
return new this.ctor(...args); | ||
} | ||
else if (this.proto) { | ||
return Object.create(this.proto); | ||
} | ||
else { | ||
mod = mod.exports; | ||
throw new TypeError(`${this.name} is not a valid module.`); | ||
} | ||
return mod.default; | ||
} | ||
create(...args) { | ||
return new this.ctor(...args); | ||
} | ||
instance(ins) { | ||
@@ -48,0 +61,0 @@ if (ins) { |
@@ -30,12 +30,8 @@ "use strict"; | ||
let ins; | ||
if (typeof mod.ctor.getInstance === "function") { | ||
ins = mod.ctor.getInstance(); | ||
let { ctor } = mod; | ||
if (ctor && typeof ctor.getInstance === "function") { | ||
ins = ctor.getInstance(); | ||
} | ||
else { | ||
try { | ||
ins = mod.create(); | ||
} | ||
catch (err) { | ||
ins = Object.create(mod.ctor.prototype); | ||
} | ||
else if ((ins = mod.proto) === null) { | ||
ins = mod.create(); | ||
} | ||
@@ -42,0 +38,0 @@ return ins; |
{ | ||
"name": "alar", | ||
"version": "1.0.6", | ||
"version": "1.1.0", | ||
"description": "Auto-Load And Remote.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -48,4 +48,4 @@ # Alar | ||
In other files, just define and export a default class (Alar only supports the | ||
`default class` exported), and merge the type to the namespace `app`, so that | ||
another file can access it directly via namespace. | ||
`default` exports), and merge the type to the namespace `app`, so that another | ||
file can access it directly via namespace. | ||
@@ -101,2 +101,26 @@ ```typescript | ||
### Prototype Module | ||
Any module that exports an object as default will be considered as a prototype | ||
module, when calling `create()` of that module, the object will be used as a | ||
prototype, however when calling `instance()` of that module, the object itself | ||
will be used as the singleton. | ||
```typescript | ||
// src/config.ts | ||
declare global { | ||
namespace app { | ||
const config: ModuleProxy<Config>; | ||
} | ||
} | ||
export interface Config { | ||
// ... | ||
} | ||
export default <Config>{ | ||
// ... | ||
} | ||
``` | ||
## Remote Service | ||
@@ -103,0 +127,0 @@ |
@@ -25,2 +25,6 @@ import { resolve, normalize, extname, sep } from "path"; | ||
readonly path: string; | ||
/** The very exports object of the module. */ | ||
readonly exports: any; | ||
/** The very prototype of the module. */ | ||
readonly proto: object; | ||
/** The very class constructor of the module. */ | ||
@@ -72,22 +76,35 @@ readonly ctor: ModuleConstructor<T>; | ||
get ctor(): ModuleConstructor<any> { | ||
let { path } = this; | ||
let mod = require.cache[path + ".ts"] || require.cache[path + ".js"]; | ||
get exports(): any { | ||
return require(this.path); | ||
} | ||
if (!mod) { | ||
mod = require(path); | ||
get proto(): object { | ||
let { exports } = this; | ||
if (!mod.default || typeof mod.default !== "function") { | ||
throw new TypeError(`Module ${this.name} is not a constructor.`); | ||
if (exports.default) { | ||
if (typeof exports.default === "object") { | ||
return exports.default; | ||
} else if (typeof exports.default === "function") { | ||
return exports.default.prototype; | ||
} | ||
} else { | ||
mod = mod.exports; | ||
} | ||
return mod.default; | ||
return null; | ||
} | ||
get ctor(): ModuleConstructor<any> { | ||
let { exports } = this; | ||
return typeof exports.default === "function" ? exports.default : null; | ||
} | ||
/** Creates a new instance of the module. */ | ||
create(...args: any[]) { | ||
return new this.ctor(...args); | ||
if (this.ctor) { | ||
return new this.ctor(...args); | ||
} else if (this.proto) { | ||
return Object.create(this.proto); | ||
} else { | ||
throw new TypeError(`${this.name} is not a valid module.`); | ||
} | ||
} | ||
@@ -94,0 +111,0 @@ |
@@ -34,11 +34,8 @@ import * as os from "os"; | ||
let ins: T; | ||
let { ctor } = mod; | ||
if (typeof mod.ctor.getInstance === "function") { | ||
ins = mod.ctor.getInstance(); | ||
} else { | ||
try { | ||
ins = mod.create(); | ||
} catch (err) { | ||
ins = Object.create(mod.ctor.prototype); | ||
} | ||
if (ctor && typeof ctor.getInstance === "function") { | ||
ins = ctor.getInstance(); | ||
} else if ((ins = <any>mod.proto) === null) { | ||
ins = mod.create(); | ||
} | ||
@@ -45,0 +42,0 @@ |
@@ -72,2 +72,22 @@ /* global app */ | ||
it("should access to a prototype module as expected", () => { | ||
assert.strictEqual(app.config.name, "app.config"); | ||
assert.strictEqual(app.config.path, path.normalize(__dirname + "/app/config")); | ||
assert.deepStrictEqual(app.config.proto, require(__dirname + "/app/config").default); | ||
}); | ||
it("should create instance from a prototype module as expected", () => { | ||
let ins = app.config.create(); | ||
let mod = require(__dirname + "/app/config").default; | ||
assert.strictEqual(Object.getPrototypeOf(ins), mod); | ||
assert.strictEqual(ins.name, mod.name); | ||
assert.strictEqual(ins.version, mod.version); | ||
}); | ||
it("should use the prototype module as singleton as expected", () => { | ||
let ins = app.config.instance(); | ||
let mod = require(__dirname + "/app/config").default; | ||
assert.strictEqual(ins, mod); | ||
}); | ||
// it("should watch file change and reload module as expected", (done) => { | ||
@@ -74,0 +94,0 @@ // awaiter(null, null, null, function* () { |
Sorry, the diff of this file is not supported yet
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
71907
19
1192
202
6