Socket
Socket
Sign inDemoInstall

pdi

Package Overview
Dependencies
4
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.0 to 4.0.1

17

package.json
{
"name": "pdi",
"version": "3.0.0",
"version": "4.0.1",
"description": "Minimal Promise based dependency injection framework",
"repository": "https://github.com/davidgtonge/pdi",
"main": "src/index.js",

@@ -14,12 +15,12 @@ "scripts": {

"dependencies": {
"bluebird": "^3.5.1",
"debug": "^3.1.0",
"ramda": "^0.25.0"
"bluebird": "^3.7.2",
"debug": "^4.2.0",
"ramda": "^0.27.1"
},
"devDependencies": {
"@mft/eslint-config-momentumft": "^3.1.5",
"eslint": "^4.18.1",
"mocha": "^5.0.1",
"sinon": "^4.4.2"
"@mft/eslint-config-momentumft": "^4.0.0",
"eslint": "^7.9.0",
"mocha": "^8.1.3",
"sinon": "^9.0.3"
}
}

@@ -74,5 +74,14 @@ # PDI - Minimal Promise based Dependency Injection framework

### `strict`
If this function is called before activation, then there are checks made when calling the factory fucntion, the following will cause an error to be thrown
* If the factory tries to access a property that hasn't been depended on
* If a property is not accessed even though it has been depended on
### `create`
This function is useful for where the DI container will be used to perform a particular operation, rather then for system start-up. It returns a DI container with the `add`, `start` and `clear` methods.
This function is useful for where the DI container will be used to perform a particular operation, rather then for system start-up. It returns a DI container with the `add`, `start`, `strict` and `clear` methods.

@@ -79,0 +88,0 @@ While being small this library is powerful enough to be used for async flow

@@ -42,3 +42,3 @@ const Promise = require("bluebird")

function move(subset, from, to) {
forEach(item => {
forEach((item) => {
const fromPos = from.indexOf(item)

@@ -67,13 +67,37 @@ from.splice(fromPos, 1)

function activationReducer(memo, items) {
const activationReducer = (strictMode) => (memo, items) => {
const names = pluck("name", items)
debug(`Initialising ${names.join(", ")}`)
return Promise.map(items, item => {
const opts = pick(item.deps, memo)
return Promise.resolve(item.fn(opts))
return Promise.map(items, (item) => {
const _opts = pick(item.deps, memo)
if (!strictMode) {
return Promise.resolve(item.fn(_opts))
}
const accessed = []
const opts = new Proxy(_opts, {
get(target, prop) {
if (target[prop]) {
accessed.push(prop)
return target[prop]
}
throw new Error(`Invalid property access: ${prop}`)
},
})
const result = item.fn(opts)
const notAccessed = difference(item.deps, accessed)
if (notAccessed.length) {
throw new Error(
`Depended on property not accessed: ${notAccessed.join(",")}`,
)
}
return Promise.resolve(result)
}).then(compose(merge(memo), zipObj(names)))
}
function startActivation(array) {
return Promise.reduce(array, activationReducer, {})
function startActivation(array, strictMode) {
return Promise.reduce(array, activationReducer(strictMode), {})
}

@@ -88,3 +112,3 @@

named arugments using destructing. It therefore doesn't accept functions with
a length of more than 1`
a length of more than 1`,
)

@@ -100,9 +124,17 @@ }

let nameIdx = 0
let strictMode = false
const startTime = Date.now()
let firstAdd
const strict = () => {
if (activated) {
throw new Error("Can't set strict mode after activation")
}
strictMode = true
}
function add(name, deps, fn) {
if (!firstAdd) firstAdd = Date.now()
if (activated) {
throw new Error(`DI already activated - can't register: ${name} `)
throw new Error(`DI already activated - can't register: ${name}`)
}

@@ -132,3 +164,3 @@ // (array, fn) = side effect function

const sorted = checkAndSortDependencies(registry)
return startActivation(sorted).then(_modules => {
return startActivation(sorted, strictMode).then((_modules) => {
debug("Activation complete", Date.now() - startTime)

@@ -142,2 +174,3 @@ modules = _modules

activated = false
strictMode = false
registry = {}

@@ -159,3 +192,3 @@ modules = {}

return {add, start, clear, __test}
return {add, start, clear, strict, __test}
}

@@ -162,0 +195,0 @@

/* eslint max-nested-callbacks: 0 */
const {ok, equal, deepEqual, throws} = require("assert")
const {ok, strictEqual, deepStrictEqual, throws, rejects} = require("assert")
const pdi = require("../src/index")

@@ -19,5 +19,5 @@ const sinon = require("sinon")

const registry = pdi.__test.getRegistry()
equal(registry[name].name, name)
equal(registry[name].fn, fn)
equal(registry[name].deps, deps)
strictEqual(registry[name].name, name)
strictEqual(registry[name].fn, fn)
strictEqual(registry[name].deps, deps)
})

@@ -30,5 +30,5 @@

const registry = pdi.__test.getRegistry()
equal(registry[name].name, name)
equal(registry[name].fn, fn)
deepEqual(registry[name].deps, [])
strictEqual(registry[name].name, name)
strictEqual(registry[name].fn, fn)
deepStrictEqual(registry[name].deps, [])
})

@@ -40,5 +40,8 @@

pdi.add(name, fn)
throws(() => {
pdi.add(name, fn)
})
throws(
() => {
pdi.add(name, fn)
},
{message: "Attempted to register module: NAME multiple times"},
)
})

@@ -51,5 +54,8 @@

return pdi.start().then(() => {
throws(() => {
pdi.add("something", fn)
})
throws(
() => {
pdi.add("something", fn)
},
{message: "DI already activated - can't register: something"},
)
})

@@ -65,4 +71,4 @@ })

const sorted = pdi.__test.checkAndSortDependencies(registry)
equal(sorted[0][0].name, "2")
equal(sorted[1][0].name, "1")
strictEqual(sorted[0][0].name, "2")
strictEqual(sorted[1][0].name, "1")
})

@@ -97,4 +103,4 @@

const names = compose(pluck("name"), flatten)(sorted)
equal(sorted.length, 4)
deepEqual(names, ["1", "2", "4", "5", "3"])
strictEqual(sorted.length, 4)
deepStrictEqual(names, ["1", "2", "4", "5", "3"])
})

@@ -124,4 +130,4 @@

return pdi.start().then(() => {
equal(fn1.callCount, 1)
equal(fn2.callCount, 1)
strictEqual(fn1.callCount, 1)
strictEqual(fn2.callCount, 1)
})

@@ -135,5 +141,5 @@ })

pdi.add("2", fn2)
return pdi.start().then(result => {
equal(result["1"], "foo")
equal(result["2"], "bar")
return pdi.start().then((result) => {
strictEqual(result["1"], "foo")
strictEqual(result["2"], "bar")
})

@@ -149,6 +155,3 @@ })

pdi.add("2", fn2)
return pdi.start().catch(err => {
ok(err)
equal(err.message, "error in dep")
})
return rejects(() => pdi.start(), {message: "error in dep"})
})

@@ -161,6 +164,3 @@

pdi.add("2", fn2)
return pdi.start().catch(err => {
ok(err)
equal(err.message, "error in dep")
})
return rejects(() => pdi.start(), {message: "error in dep"})
})

@@ -175,3 +175,3 @@

return pdi.start().then(() => {
ok(fn1.calledWith({"2": foo}))
ok(fn1.calledWith({2: foo}))
})

@@ -190,6 +190,61 @@ })

return pdi.start().then(() => {
ok(fn1.calledWith({"2": foo, "3": foo2}))
ok(fn1.calledWith({2: foo, 3: foo2}))
})
})
})
describe("strict mode", () => {
it("throws if a property is accessed that has not been depended on", () => {
pdi.strict()
const foo = Math.random()
const foo2 = Math.random()
const fn1 = ({b, c, d}) => [b, c, d]
const fn2 = sinon.stub().returns(foo)
const fn3 = sinon.stub().returns(foo2)
pdi.add("a", ["b", "c"], fn1)
pdi.add("b", fn2)
pdi.add("c", fn3)
return rejects(() => pdi.start(), {message: "Invalid property access: d"})
})
it("throws if a property is depended on but not accessed", () => {
pdi.strict()
const foo = Math.random()
const foo2 = Math.random()
const fn1 = ({b}) => [b]
const fn2 = sinon.stub().returns(foo)
const fn3 = sinon.stub().returns(foo2)
pdi.add("a", ["b", "c"], fn1)
pdi.add("b", fn2)
pdi.add("c", fn3)
return rejects(() => pdi.start(), {
message: "Depended on property not accessed: c",
})
})
it("throws if a property is depended on but not accessed in an async fn", () => {
pdi.strict()
const foo = Math.random()
const foo2 = Math.random()
const fn1 = async ({b}) => Promise.resolve([b])
const fn2 = sinon.stub().returns(foo)
const fn3 = sinon.stub().returns(foo2)
pdi.add("a", ["b", "c"], fn1)
pdi.add("b", fn2)
pdi.add("c", fn3)
return rejects(() => pdi.start(), {
message: "Depended on property not accessed: c",
})
})
})
})
/*
Create a proxy and throw if invalid property is accessed
Log if property is not accessed.
Also consider how it can handle things like ids
e.g. whenever log gets injected
*/

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc