Security News
Node.js EOL Versions CVE Dubbed the "Worst CVE of the Year" by Security Experts
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
@produck/duck
Advanced tools
Duck is an extensible, lightweight, flexible, progressive software development frameworks for building software product.
Duck is an extensible, lightweight, flexible, progressive software development frameworks for building software product. It uses dependency injection and control inversion just a little like "Java Spring". It help developers to create, use, manage various runtime objects to inject to whereever required. Everyone can extend framework directly in low cost.
In the past, we often have to face to inflexible, confused project directory problems in development in Node.js. Everyone could disgust require modules from parent directory like require('../../')
. Because it represent some coupling out of control. Duck resolve the problems above and provide a programming models to help developer avoid incorrect design.
Duck does not impose any restrictions on your coding style. But it will still provide the necessary guidance to advance the right design. Be brave enough to use your imagination to solve your problems.
On the one hand Duck is a useful framework & pattern for architect or tech leader to take apart development tasks. Developers working at the top will feel comfortable with structuring their work. Duck hopes every developer does NOT need to learn any framework practices. Duck respects, supports and maintains the development team's own practices. What does it mean?
The DUCK knows first when the river becomes warm in SPRING.
Duck is used to build product!
npm install @produck/duck
To build a very simple product,
const Duck = require('@produck/duck');
const meta = require('./package.json');
// To create the product factory named Simple.
function Simple() {
const simple = {};
Duck({
id: 'com.orchange.duck.demo',
name: 'Simple Product',
version: meta.version
}, ({ product }) => {
// There will be 2 methods on a Simple product instance.
simple.getMeta = function getMeta() {
return product.meta;
};
simple.getComponents = function getComponents() {
return product.components;
}
});
return simple;
}
// To create a Simple product instance then use it.
const simple = Simple();
console.log(simple.getMeta());
// => {name: "Simple Product", namespace: "", version: "0.0.0", description: "Default product descrition"}
console.log(simple.getComponents());
// => []
// Because there is no component in the product.
A duck instance is just an EventEmitter
instance without any preset event. Everyone can emit necessary event by injection.product
.
[RECOMMANDED] Avoid using classes or constructors if there are no special requirements. For a framework for assembly resources like duck, class
& constructor
cause too much programming burden and are not flexible enough. There is almost no such need for inctanceof
. "Duck typing" always be useful.
options
is an object. callback
is a function. Return a product instance. The product instance is extended from EventEmitter
.
Property | Type | Default value | Description |
---|---|---|---|
id | String | Product id | |
name | String | 'Default Product Name' | Product name |
namespace | String | '' | Namespace component may use |
version | String | '0.0.0' | Current version |
description | String | 'No descrition' | What am I? |
installed | Object | () => {} | Invoking after components |
injection | Object | {} | Initial dependences |
components | Array | [] | Product components list |
[RECOMMANDED] Some dependencies just for current product can be injected into by options.injection
to avoid defining components (see components). Because dependencies from components is universal and reusable across products.
[RECOMMANDED] In hook options.installed
, some direct dependencies using component dependencies could be created and injected into injection. In other words, injection could still be changed here and then to be non-extensible.
Only one formal parameter could be accessed is injection
. [RECOMMANDED] Using object destructuring assignment syntax to access dependencies of injection can make the code more clear. There is no meaningful context here (this === null
). Arrow function is also accepted here if you like.
Injection is very IMPORTANT to be careful for using. Avoid to change injection outside of the Duck instance lifecycle. Because incorrect state may cause fatal runtime errors. This will not help reduce R&D costs.
[RECOMMANDED] Accessing injection & dependencies in callback and providing external accessing by indirect way.
Best practice example,
const Duck = require('@produck/duck');
const http = require('http');
function MyProduct() {
const product = {};
Duck({
id: 'com.xxx.yyy.zzz',
component: [
Duck.Web()
]
}, function callback({ Web }) {
// Access all dependences safely here.
// Be careful and responsible for providing external indirect access to injected dependencies.
product.start = function startServer() {
return http.createServer(Web.Application.Default()).listen(8080);
};
});
return product;
}
// External access.
const myProduct = MyProduct();
myProduct.start(); // Use injected dependence 'Web' indirectly.
// Use arrow callback function
function MyProductB() {
Duck({
id: 'com.xxx.yyy.zzz',
component: [
Duck.Web()
]
}, ({ Web }) => {
// There is no meaningful context here. (this === null)
// Arrow function is also accepted here if you like will make the code more clear.
console.log(Web);
});
}
options.injection
Mixin
options.injection
Invoking
options.installed(injection)
Invoking
callback(injection)
A product
dependence will be injected into injection after components have been installed. The project
provides meta
, components
and duck
getters to reflect the final abstract of the duck instance.
Use project dependence,
const Duck = require('../');
Duck({
id: 'com.xxx.yy.zz',
}, ({ project }) => {
console.log(project.meta);
console.log(project.components);
console.log(project.duck);
});
project.meta
returns a new plain object every time. Pproperties,
Property | Type | Example Value | Description |
---|---|---|---|
id | String | 'com.xx.yy.zz' | options.id |
name | String | 'Default Product Name' | options.name |
namespace | String | '' | options.namespace |
version | String | '0.0.0' | options.version |
description | String | 'No descrition' | options.description |
project.components
returns a new array about used components. Each element properties,
Property | Type | Example Value | Description |
---|---|---|---|
id | String | 'com.xx.yy.zz' | component.id |
name | String | 'Component Name' | component.name |
description | String | 'No descrition' | component.description |
details | any | null | component.getDetails() |
project.duck
returns a new plain object about duck. Properties,
Property | Type | Example Value | Description |
---|---|---|---|
version | String | '0.0.0' | duck version |
peerDependencies | object | {} | duck peerDependencies |
Component
is use to append some runtime dependencies into injection. Each component instance MUST include 3 items to describe the features & meta of itself. They are id
, name
, install
.
In addition, component.description
is a string for describing what the component is. component.created
a hook function will be called after the duck has been created.
[RECOMMENDED] Appending dependence only in component.install
. Accessing dependence only after duck instance created, like in component.created
and Duck(options[, callback
]).
[NOTICE] Defining a component means that there are some widespread jobs need to be decoupled. Just use options.injection
if there is no special need for flexibility.
Althought accessing when component.install
is ok, it means "Component_A depends Component_B" that cause coulping between components. Developers can still handle these problems with care and "Put Component_A before Component_B" to ensure Component_B can use Component_A in install.
Properties Table
Property | Type | Default value | Description |
---|---|---|---|
id | String | Unique component id | |
name | String | Component name for display | |
install | Function | Installer | |
description | String | 'No description' | Description |
created | Function | () => {} | Calling after duck created |
getDetails | Function | () => null | Custom Details Snapshot |
Create a component directly,
const Duck = require('@produck/duck');
Duck({
id: 'com.orchange.duck.demo',
components: [
{
id: 'com.example.duck.literal',
name: 'DirectSample',
install(injection) {
// Append a dependence named 'foo'
injection.foo = function () {
return 'bar';
}
},
}
]
}, ({ foo }) => {
console.log(foo());
// => 'bar'
});
The example is just want to tell developers that create a component by literal is be allowed. There is NO magic about component. Everyone can do everything in this pattern. [RECOMMANDED] Defining a factory to build a component instance like a provider can make the code clear and maintainable. Many native components have been defined in @produck/duck
. Enjoy them!
Simple web application example,
const http = require('http');
const Duck = require('@produck/duck');
Duck({
id: 'com.orchange.duck.demo',
components: [
Duck.Web()
]
}, ({ Web }) => {
// Access Web.Application.Default to get the default application factory.
// Call the factory then return the request listener instance of application.
// The "Default" Application is provided by Web Component default options.
http.createServer(Web.Application.Default()).listen(8080);
});
// Now, open your browser and navigate to http://localhost:8080
/**
{
"meta": {
"name": "Default Product Name",
"namespace": "",
"version": "0.0.0",
"description": "No descrition"
},
"components": [
{
"id": "com.oc.duck.web",
"name": "WebApplication",
"description": "Used to guide developer to create a web application.",
"details": null
}
]
}
*/
Injection is the core function to manage dependencies regularly. Dependencies could be in any form. After product dependence
injection will be freezed (see lifecycle). Setting new dependence will become invalid.
An injection is use to set, get, transmit and manage dependencies to everywhere in a product. Each duck instance will create only one injection for itself.
About injection, some facts MUST be known,
injection.injection
reference itself for convenience.FAQs
An extensible, lightweight, flexible, progressive software development framework for product.
The npm package @produck/duck receives a total of 6 weekly downloads. As such, @produck/duck popularity was classified as not popular.
We found that @produck/duck demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
Security News
Bun 1.2 enhances its JavaScript runtime with 90% Node.js compatibility, built-in S3 and Postgres support, HTML Imports, and faster, cloud-first performance.