### Install Data Store Plugins Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Install required database driver modules via npm. ```bash npm install seneca-mongo-store ``` -------------------------------- ### Execute plugin module code Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Example output from running the module loading script. ```bash $ node module.js null { color: 'pink' } ``` -------------------------------- ### Install and use an npm plugin Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Plugins can be installed via npm and loaded by name. The 'seneca-' prefix can be omitted in the use method. ```bash $ npm install seneca-echo ``` ```javascript // echo.js var seneca = require('seneca')() seneca.use( 'seneca-echo' ) seneca.act( {role:'echo', foo:'bar'}, console.log ) ``` ```bash $ node echo.js null { foo: 'bar' } ``` ```javascript seneca.use( 'echo' ) ``` -------------------------------- ### Execute tagged plugin code Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Expected output when running the tagged plugin example. ```bash $ node tags.js null { color: 'red', tag: 'AAA' } null { color: 'green', tag: 'BBB' } ``` -------------------------------- ### Initialize Seneca entity plugin Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Setup the Seneca instance and load the entity plugin to enable data persistence features. ```javascript var seneca = require('seneca')() var entities = require('seneca-entity') seneca.use(entities) ``` -------------------------------- ### Create entities with zone, base, and name Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html The `make` method optionally accepts up to three string arguments: zone, base, and name, in that order. This example shows creating entities with different combinations. ```javascript var foo = seneca.make('foo') var bar_foo = seneca.make('bar','foo') var zen_bar_foo = seneca.make('zen','bar','foo') ``` -------------------------------- ### Filter action logs via CLI Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Example command to run the application and filter logs by action type. ```bash $ node sales-tax-log.js --seneca.log=type:act [-isodate-] DEBUG act in uk74hd {cmd=salestax,country=IE,net=100} [-isodate-] DEBUG act out uk74hd {total=123} [-isodate-] DEBUG act in qv5sts {cmd=salestax,country=UK,net=200} [-isodate-] DEBUG act out qv5sts {total=240} [-isodate-] DEBUG act in 7j9q4a {cmd=salestax,country=UK,net=300} [-isodate-] DEBUG act out 7j9q4a {total=360} ``` -------------------------------- ### Filter plugin logs via CLI Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Example command to run the application and filter logs by plugin name. ```bash $ node sales-tax-log.js --seneca.log=plugin:shop [-isodate-] DEBUG plugin sales-tax IE annv4h net: 100 total: 123 tax: {hits=1,rate=0.23,country=IE} [-isodate-] DEBUG plugin sales-tax UK 3rkaa2 net: 200 total: 240 tax: {hits=1,rate=0.2,country=UK} [-isodate-] DEBUG plugin sales-tax UK cwxcts net: 300 total: 360 tax: {hits=2,rate=0.2,country=UK} ``` -------------------------------- ### Basic Seneca Unit Test Setup Source: https://senecajs.org/docs/tutorials/unit-testing.html Sets up the necessary modules and basic structure for a Seneca unit test using the 'lab' testing framework. Requires 'lab', 'code', and 'seneca' modules. ```javascript // file: test/color-test.js var Lab = require('lab') var Code = require('code') var Seneca = require('seneca') var lab = exports.lab = Lab.script() var describe = lab.describe var it = lab.it var expect = Code.expect describe('color', function () { it('to-hex', function (fin) { var seneca = test_seneca(fin) fin() }) }) ``` -------------------------------- ### Initialize entity data during creation Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html You can initialize an entity's fields by passing an object as the last argument to the `make` method. This example creates a 'foo' entity with initial 'price' and 'color' properties. ```javascript var foo = seneca.make('foo', {price:1.99,color:'red'}) console.log('price is '+foo.price+' and color is '+foo.color) ``` -------------------------------- ### Create 'sys' base entities for user and login Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html When plugins share related functions, they often use the same 'base' to avoid entity name collisions. This example shows creating 'user' and 'login' entities within the 'sys' base. ```javascript var sys_user = seneca.make('sys','user') var sys_login = seneca.make('sys','login') ``` -------------------------------- ### Advanced Promise Usage Source: https://senecajs.org/docs/tutorials/seneca-with-promises.html Example of using Promise.all to execute multiple Seneca actions in parallel. ```javascript var Promise = require('bluebird'); var seneca = require('seneca')(); // Promisify the .act() method var act = Promise.promisify(seneca.act, seneca); // Add a conversion command seneca.add({cmd: 'dollars-to-euros'}, function(args, done) { var exchangeRate = 0.88; var euros = args.product.price * exchangeRate; // Return the product with euros set done(null, { name: args.product.name, price: args.product.price, euros: euros }); }); var products = [ {name: 'Product A', price: 9.99}, {name: 'Product B', price: 23.99}, {name: 'Product C', price: 10.00}, {name: 'Product D', price: 100.99}, {name: 'Product E', price: 0.99} ]; // Build an array of promisified commands var cmds = []; products.forEach(function (product) { var command = act({cmd: 'dollars-to-euros', product: product}); cmds.push(command); }); Promise.all(cmds) .then(function (results) { // results is now an array of each of the resolved promises // {name: 'Product A', price: 9.99, euros: 8.81} // {name: 'Product B', price: 23.99, euros: 21.15} // {name: 'Product C', price: 10.00, euros: 8.82} // {name: 'Product D', price: 100.99, euros: 89.05} // {name: 'Product E', price: 0.99, euros: 0.87} results.forEach(function (result) { console.log(result); }); }) .catch(function (err) { console.error(err); }); ``` -------------------------------- ### Create a 'foo' entity with an alias Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html The `make` method can be aliased as `make$` for convenience. This example demonstrates creating a 'foo' entity using this alias. ```javascript var foo = seneca.make('foo') ``` -------------------------------- ### Example of Simplified Test Log Output Source: https://senecajs.org/docs/tutorials/unit-testing.html Illustrates the tab-separated, plain-text log output generated by Seneca in test mode when '.test(fin, 'print')' is enabled. Useful for tracing message flow. ```text 238/7p plugin/init color 244/7p add/ADD role:color,to:hex 244/7p options/SET 246/7p plugin/install color 250/7p act/DEFAULT ce/81 {init:'color',tag:undefined} 251/7p act/OUT ce/81 {} 251/7p plugin/ready color 252/7p act/OUT c7/m6 name:color,plugin:define,role:seneca,seq:2,tag:undefined {role:'seneca',plugin:'define',name:'color',tag:undefined,seq:2} 255/7p act/IN gn/mc role:color,to:hex {role:'color',to:'hex',color:'red'} 256/7p act/OUT gn/mc role:color,to:hex {hex:'FF0000'} 259/7p act/IN lf/9e role:color,to:hex {role:'color',to:'hex',color:'not-a-color'} 260/7p act/OUT lf/9e role:color,to:hex {hex:'000000'} ``` -------------------------------- ### Promisify Seneca .act() Source: https://senecajs.org/docs/tutorials/seneca-with-promises.html Basic setup to promisify the Seneca act method for use with Bluebird. ```javascript var Promise = require('bluebird'); var seneca = require('seneca')(); // Promisify the .act() method; to learn more about this technique see: // http://bluebirdjs.com/docs/features.html#promisification-on-steroids var act = Promise.promisify(seneca.act, seneca); // Return no error and a success message to illustrate a resolved promise seneca.add({cmd: 'resolve'}, function (args, done) { done(null, {message: "Yay, I've been resolved!"}); }); // Return an error to force a rejected promise seneca.add({cmd: 'reject'}, function (args, done) { done(new Error("D'oh! I've been rejected.")); }); // Use the new promisified act() with no callback act({cmd: 'resolve'}) .then(function (result) { // result will be {message: "Yay, I've been resolved!"} since // its guaranteed to resolve }) .catch(function (err) { // Catch any error as usual if it was rejected }); act({cmd: 'reject'}) .then(function (result) { // Never reaches here since we throw an error on purpose }) .catch(function (err) { // err will be set with message "D'oh! I've been rejected." }); ``` ```javascript var act = Promise.promisify(seneca.act, seneca); ``` ```javascript var act = Promise.promisify(seneca.act, {context: seneca}); ``` -------------------------------- ### Sequence Seneca Actions with gate() Source: https://senecajs.org/docs/tutorials/unit-testing.html Use `seneca.gate()` to create a new Seneca instance where actions execute sequentially. Callbacks must complete before the next action starts. Useful for plugin initialization and unit testing. ```javascript // file: test/color-test.js it('to-hex', function (fin) { var seneca = test_seneca(fin) seneca .gate() .act({ role: 'color', to: 'hex', color: 'red' }, function (ignore, result) { expect(result.hex).to.equal('FF0000') }) .act({ role: 'color', to: 'hex', color: 'not-a-color' }, function (ignore, result) { expect(result.hex).to.equal('000000') }) .ready(fin) }) ``` -------------------------------- ### AND Filter Entities Source: https://senecajs.org/docs/tutorials/understanding-query-syntax.html Apply multiple constraints to filter entries by including additional matching fields in the query object for `list$`. This example filters by both 'name' and 'surname'. ```javascript list$({name:'William', surname:'McDonald'}, function (err, res) { if (err) console.error(err) _.each(res, function (entry) { console.log(entry) }) }) ``` -------------------------------- ### Filter Entities by Name Source: https://senecajs.org/docs/tutorials/understanding-query-syntax.html Select a subset of entries by providing field-value pairs in the query object to `list$`. This example filters by the 'name' field. ```javascript list$({name:'William'}, function (err, res) { if (err) console.error(err) _.each(res, function (entry) { console.log(entry) }) }) ``` -------------------------------- ### Add Dynamic Log Route in Seneca Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Adds a new log route at runtime using `seneca.logroute`. This example adds a handler to print logs to the console for all levels. Omitting the handler removes the route. ```javascript seneca.logroute( {level:'all', handler:seneca.handler.print} ) ``` -------------------------------- ### Initialize a plugin with an action pattern Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Plugins can perform asynchronous initialization by defining an 'init' action pattern that matches the plugin name. ```javascript // init.js var plugin = function( options ) { seneca.add( {init:'pluginName'}, function( args, done ) { // do stuff, e.g. console.log('connecting to db...') setTimeout(function(){ console.log('connected!') done() }, 1000) }) this.add( {foo:'bar'}, function( args, done ) { done( null, {color: options.color} ) }) return 'pluginName' } ``` -------------------------------- ### Register plugin instances with tags Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Demonstrates two methods for tagging plugin instances: using a description object or suffixing the module reference with a dollar sign. ```javascript // tags.js var seneca = require('seneca')() seneca.use( {name:'./bar.js',tag:'AAA'}, {zed:1,color:'red'} ) seneca.use( './bar.js$BBB', {zed:2,color:'green'} ) seneca.act( {foo:'bar',zed:1}, console.log ) seneca.act( {foo:'bar',zed:2}, console.log ) ``` -------------------------------- ### Register a Data Store Plugin Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Configure a database plugin by passing connection details as options during registration. ```javascript var seneca = require('seneca')() seneca.use('mongo-store',{ name:'dbname', host:'127.0.0.1', port:27017 }) ``` -------------------------------- ### Initialize Seneca web application Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Configure a Node.js server with the Seneca web plugin and admin interface. ```javascript var connect = require('connect') var connect_query = require('connect-query') var body_parser = require('body-parser') var seneca = require('seneca')() seneca.use('sales-tax-plugin', {country: 'IE', rate: 0.23}) seneca.use('sales-tax-plugin', {country: 'UK', rate: 0.20}) seneca.use('sales-tax-plugin', {country: '*', rate: 0.25}) var app = connect() app.use(connect_query()) app.use(body_parser.json()) app.use(seneca.export('web')) app.listen(3000) seneca.use('data-editor') seneca.use('admin', {server: app, local: true}) ``` -------------------------------- ### Get entity properties using canon$ Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html The `canon$` method on an entity can be used to retrieve its zone, base, and name properties in different formats (string, object, array). ```javascript var apple = seneca.make('market','fruit'); // Get the properties apple.canon$(); // -> '-/market/fruit' apple.canon$({object: true}); // -> {zone: undefined, base: 'market', name: 'fruit'} apple.canon$({array: true}); // -> [undefined, 'market', 'fruit'] ``` -------------------------------- ### Enable verbose logging Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Print all available logging information for debugging purposes. ```bash node sales-tax.js --seneca.log.print [-isodate-] INFO init start ... lots of init stuff ... [-isodate-] INFO init end [-isodate-] INFO add {cmd=salestax} [-isodate-] DEBUG act in 90xkee {cmd=salestax,net=100} [-isodate-] DEBUG act out 90xkee {total=123} 123 ``` -------------------------------- ### Command Line Options for Plugin Configuration Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Specify plugin options directly on the command line using `--seneca.options`. Use dot notation for nested options and provide multiple options separated by spaces. Command-line options have the highest priority. ```bash $ node zed-dev.js --seneca.options.zed.red=10 --seneca.options.zed.blue=200 ``` -------------------------------- ### Creating Entities Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Demonstrates how to create Seneca entities using the `make` method with different namespace configurations. ```APIDOC ## Creating Entities The `make` method is used to create entity instances. It can be called on the main Seneca object or on an existing entity object (using `make$`). ### Basic Entity Creation ```javascript // Create an entity with only a name var foo_entity = seneca.make('foo'); ``` ### Creating Entities with Base and Name ```javascript // Create an entity with base and name var sys_user = seneca.make('sys', 'user'); var sys_login = seneca.make('sys', 'login'); ``` ### Creating Entities with Zone, Base, and Name ```javascript // Create an entity with zone, base, and name var zen_bar_foo = seneca.make('zen', 'bar', 'foo'); ``` ### Creating a New Instance of an Existing Entity Type ```javascript var foo = seneca.make('foo'); // Create a new, empty entity of the same type var morefoo = foo.make$(); ``` ### Initializing Entity Data on Creation ```javascript // Create an entity and initialize its data fields var foo = seneca.make('foo', {price: 1.99, color: 'red'}); console.log('price is ' + foo.price + ' and color is ' + foo.color); // Output: price is 1.99 and color is red ``` ``` -------------------------------- ### Create and Save Sample Entities Source: https://senecajs.org/docs/tutorials/understanding-query-syntax.html Use `make$` and `save$` to create and store sample entities in the Seneca store. Ensure `make$` is called for each instance to maintain uniqueness. ```javascript var person = seneca.make$('person') person .make$().save$({name:'John', surname:'Smith', city:'Dublin', address:'Street 4'}) .make$().save$({name:'John', surname:'Smith', city:'Dublin', address:'Street 5'}) .make$().save$({name:'John', surname:'Smith', city:'Dublin', address:'Street 6'}) .make$().save$({name:'John', surname:'Smith', city:'Dublin', address:'Street 1'}) .make$().save$({name:'John', surname:'Smith', city:'Dublin', address:'Street 2'}) .make$().save$({name:'John', surname:'Smith', city:'Dublin', address:'Street 3'}) .make$().save$({name:'William', surname:'Smith', city:'Dublin', address:'Street 7'}) .make$().save$({name:'William', surname:'Smith', city:'Dublin', address:'Street 8'}) .make$().save$({name:'William', surname:'McDonald', city:'Dublin', address:'Street 9'}, function (err, res) { if (err) console.error(err) // all entities saved }) ``` -------------------------------- ### Use and Act with a Seneca Plugin Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Load a plugin into Seneca using `seneca.use` with optional configuration, then trigger its actions using `seneca.act`. The output demonstrates the result of the action. ```javascript // simple.js var seneca = require('seneca')() var plugin = function( options ) { ... } // as above seneca.use( plugin, {color:'pink'} ) seneca.act( {foo:'bar'}, console.log ) ``` -------------------------------- ### Save Entity Data with ready Callback Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Ensure the database connection is established before performing operations using the ready function. ```javascript seneca.ready(function(err){ var apple = seneca.make$('fruit') apple.name = 'Pink Lady' apple.price = 1.99 apple.save$(function(err,apple){ if( err ) return console.log(err); console.log( "apple = "+apple ) }) }) ``` -------------------------------- ### Manage tagged plugin instances and options Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Use the $suffix convention to provide specific options to tagged plugin instances, which inherit base defaults from the main plugin configuration. ```javascript // zed-tag.js function zed( options ) { console.log( this.context.name, this.context.tag, options ) } var seneca = require('seneca')() seneca.use( zed ) seneca.use( {init:zed, name:'zed', tag:'tag0'} ) ``` ```bash $ node zed-tag.js zed undefined { red: 50, green: 100, blue: 150 } zed tag0 { red: 55, green: 100, blue: 150 } ``` -------------------------------- ### Run sales-tax.js Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Successful execution output of the defined sales tax action. ```bash $ node sales-tax.js [-isodate-] INFO init start [-isodate-] INFO init end 123 ``` -------------------------------- ### List All Entities Source: https://senecajs.org/docs/tutorials/understanding-query-syntax.html Retrieve all entries from the store by passing an empty query object to `list$`. The empty object can also be omitted. ```javascript person.list$({}, function (err, res) { if (err) console.error(err) _.each(res, function (entry) { console.log(entry) }) }) ``` ```javascript person.list$(function (err, res) { if (err) console.error(err) _.each(res, function (entry) { console.log(entry) }) }) ``` -------------------------------- ### Loading Custom Options and Using Plugin Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html This script demonstrates loading custom options from a file (`./dev.options.js`) and then using a Seneca plugin. The options defined in the file will override default options. ```javascript function zed( options ) { console.log( this.context.name, this.context.tag, options ) } var seneca = require('seneca')() seneca.options('./dev.options.js') seneca.use( zed ) ``` -------------------------------- ### Configure global and plugin options via seneca.options.js Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Create a seneca.options.js file to export a JSON object containing global or plugin-specific configuration. ```javascript // seneca.options.js module.exports = { zed: { red: 50, green: 100, blue: 150, }, 'zed$tag0': { red: 55, } } ``` -------------------------------- ### Expose plugin via service Source: https://senecajs.org/docs/tutorials/unit-testing.html A service script that loads the color plugin and listens for network requests. ```javascript // file: color-service.js // run with: node color-service.js require('seneca')() .use('color') .listen(9000) ``` -------------------------------- ### Create a test instance Source: https://senecajs.org/docs/tutorials/unit-testing.html Helper function to initialize a Seneca instance in test mode with the plugin loaded. ```javascript // file: test/color-test.js function test_seneca (fin) { return Seneca({log: 'test'}) // activate unit test mode. Errors provide additional stack tracing context. // The fin callback is called when an error occurs anywhere. .test(fin) // Load the microservice business logic .use(require('../color')) } ``` -------------------------------- ### List entities with a query Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Retrieve a list of entities matching specific property criteria. ```javascript var foo_entity = seneca.make('foo') foo_entity.list$( {price:1.99}, function(err,list){ list.forEach(function( foo ){ console.log(foo) }) }) ``` -------------------------------- ### Create and populate a data entity Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Instantiate a new entity and assign data fields as standard object properties. ```javascript var foo = seneca.make('foo') foo.name = 'Apple' foo.price = 1.99 ``` -------------------------------- ### Chain .act() Commands Source: https://senecajs.org/docs/tutorials/seneca-with-promises.html Shows how to chain multiple promisified Seneca actions sequentially. ```javascript act({cmd: 'fetchOrderProducts', id: 'order-12345'}) .then(function (products) { return act({cmd: 'adjustInventory', products: products}); }) .then(function (inventoryUpdates) { return act({cmd: 'generateInventoryReport', updates: inventoryUpdates}) }) .catch(function (err) { console.error(err); }); ``` -------------------------------- ### Load a local plugin file Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Use the seneca.use method with a relative file path to load a plugin module. ```javascript // module.js var seneca = require('seneca')() seneca.use( './foo.js', {color:'pink'} ) seneca.act( {foo:'bar'}, console.log ) ``` -------------------------------- ### Configure Seneca admin plugins Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Enable the data-editor and admin interface with local access. ```javascript seneca.use('data-editor') seneca.use('admin', {server: app, local: true}) ``` -------------------------------- ### Create a new entity instance from an existing entity Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Calling `make$` on an existing entity object creates a new, empty instance of the same entity type (same zone, base, and name). Use `clone$` to copy data. ```javascript var bar = foo.make$('bar') ``` -------------------------------- ### Configure LogEntries.com Handler in Seneca Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Integrates Seneca logging with the LogEntries.com cloud logging service. Requires the 'node-logentries' module and a valid LogEntries token. Custom log levels are mapped to match Seneca's. ```javascript var logentries = require('node-logentries') var log = logentries.logger({ token: 'YOUR_TOKEN', // redefine log levels to match the ones seneca uses levels: {debug: 0, info: 1, warn: 2, error: 3, fatal: 4} }) var seneca = require('seneca')({ log: { map: [ {level: 'all', handler: function () { log.log(arguments[1], Array.prototype.join.call(arguments, '\t')) }} ] } }) seneca.use('sales-tax-plugin', {rate: 0.23}) seneca.ready(function (err) { if (err) return process.exit(!console.error(err)) seneca.act({role: 'shop', cmd: 'salestax', net: 100}) seneca.act({role: 'shop', cmd: 'salestax', net: 200}) seneca.act({role: 'shop', cmd: 'salestax', net: 300}) }) ``` -------------------------------- ### Plugin Naming with Module Reference Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html When a plugin is loaded as a module, its module reference is used as the initial name. This can be overridden by returning a specific name from the plugin definition. ```bash $ node module.js --seneca.log=plugin:./foo.js ``` -------------------------------- ### Sales tax plugin implementation Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Defines the plugin logic, including action registration and debug logging. ```javascript module.exports = function (options) { var seneca = this var plugin = 'shop' var country = options.country || 'IE' var rate = options.rate || 0.23 var calc = function (net) { return net * (1 + rate) } seneca.add({ role: plugin, cmd: 'salestax', country: country }, function (args, callback) { var total = calc(parseFloat(args.net, 10)) seneca.log.debug('apply-tax', args.net, total, rate, country) callback(null, { total: total }) }) seneca.add({ role: plugin, cmd: 'salestax' }, function (args, callback) { var total = calc(parseFloat(args.net, 10)) seneca.log.debug('apply-tax', args.net, total, rate, country) callback(null, { total: total }) }) seneca.act({ role: 'web', use: { prefix: 'shop/', pin: { role: 'shop', cmd: '*' }, map: { salestax: { GET: true } } }}) return { name: plugin } } ``` -------------------------------- ### Access plugin options in a plugin Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Define a plugin that receives options and logs them, demonstrating how Seneca automatically maps options from the configuration file. ```javascript // zed.js function zed( options ) { console.log( this.context.name, this.context.tag, options ) } var seneca = require('seneca')() seneca.use( zed ) ``` ```bash $ node zed.js zed undefined { red: 50, green: 100, blue: 150 } ``` -------------------------------- ### Run Seneca application with logging Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Execute the application while applying specific log filters. ```bash $ node sales-tax-app.js --seneca.log=plugin:shop ``` -------------------------------- ### Map Entities to Specific Data Stores Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Use the map option to route specific entity patterns to different storage backends. ```javascript seneca.use('mem-store',{ map:{ '-/-/tmp':'*' }}) ``` ```javascript seneca.use('jsonfile-store',{ folder:'json-data', map:{'-/json/-':'*'} }) seneca.use('level-store',{ folder:'level-data', map:{'-/level/-':'*'} }) ``` -------------------------------- ### Action Pattern Convention: Role and Command Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Use the `role:plugin-name` convention for action patterns to namespace functionality and avoid conflicts. The `cmd` property is often used for the main public commands. ```javascript var plugin = function trinity( options ) { this.add( {role:'trinity', cmd:'detonate'}, function( args, done ) { // ... compress plutonium, etc }) } ``` -------------------------------- ### Entity Representation and Canonization Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Explains how entities are represented as strings and how to use the `canon$` method for property extraction and testing. ```APIDOC ## Entity Representation and Canonization ### Entity String Representation Calling `toString` on an entity shows its zone, base, and name, prefixed to the entity data. * **Syntax**: `zone/base/name:{id=...;prop=val,...}` * **Placeholder**: If a namespace element is undefined, a hyphen `-` is used (e.g., `$-/-/name:{...}`). ### Entity Type Pattern Shorthand The `zone/base/name` syntax can also be used as a shorthand for entity type patterns (e.g., `-/bar/-` matches any entity with the base `bar`). ### `entity.canon$([options])` Method The `canon$` method extracts or tests the `zone/base/name` properties of an entity. #### Getting Canon Properties ```javascript var apple = seneca.make('market', 'fruit'); // Get properties as a string apple.canon$(); // -> '-/market/fruit' // Get properties as an object apple.canon$({object: true}); // -> {zone: undefined, base: 'market', name: 'fruit'} // Get properties as an array apple.canon$({array: true}); // -> [undefined, 'market', 'fruit'] ``` #### Testing Canon Properties (`isa`) ```javascript var apple = seneca.make('market', 'fruit'); // Test if the entity matches a specific canon pattern apple.canon$({isa: '-/market/fruit'}); // -> true apple.canon$({isa: {base: 'market', name: 'fruit'}}); // -> true apple.canon$({isa: '-/market/vegetable'}); // -> false ``` ``` -------------------------------- ### Trace data store actions Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Use the --seneca.log=type:act filter to view IN and OUT markers for entity save actions. ```bash $ node main.js --seneca.log=type:act ... 2013-04-18T10:05:45.818Z DEBUG act jsonfile-store BCL wa8xc5 In {cmd=save,role=entity,ent=$-/json/foo:{id=;propA=val1;propB=val2},name=foo,base=json} gx38qi 2013-04-18T10:05:45.821Z DEBUG act jsonfile-store BCL wa8xc5 OUT [$-/json/foo:{id=ulw8ew;propA=val1;propB=val2}] gx38qi ... 2013-04-18T10:05:45.822Z DEBUG act level-store GPN 8dnjyt IN {cmd=save,role=entity,ent=$-/level/bar:{id=;propA=val3;propB=val4},name=bar,base=level} 8ml1p7 2013-04-18T10:05:45.826Z DEBUG act level-store GPN 8dnjyt OUT [$-/level/bar:{id=7de92fc0-f402-411d-80ea-59e435a8c398;propA=val3;propB=val4}] 8ml1p7 ... ``` -------------------------------- ### Basic Plugin Usage Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html This snippet shows the basic usage of a Seneca plugin. Ensure the plugin is correctly imported and used with `seneca.use()`. ```javascript seneca.use( zed ) ``` -------------------------------- ### Create a basic 'foo' entity Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Use the `make` method on the Seneca object to create a basic entity without specifying zone or base. ```javascript var foo_entity = seneca.make('foo') ``` -------------------------------- ### Configure File and Console Log Handlers in Seneca Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Sets up Seneca to log messages to both the console and a file using a mapping configuration. The 'shop' plugin logs to the console, while all other messages are directed to 'shop.log'. ```javascript var seneca = require('seneca') // need this to get a reference to seneca.loghandler seneca = seneca({ log: { map: [ {plugin: 'shop', handler: 'print'}, {level: 'all', handler: seneca.loghandler.file('shop.log')} ] } }) seneca.use('sales-tax-plugin', {rate: 0.23}) seneca.ready(function (err) { if (err) return process.exit(!console.error(err)) seneca.act({role: 'shop', cmd: 'salestax', net: 100}) seneca.act({role: 'shop', cmd: 'salestax', net: 200}) seneca.act({role: 'shop', cmd: 'salestax', net: 300}) }) ``` -------------------------------- ### Debug plugin instances with logs Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Use the --seneca.log flag to track specific plugin instances in the debug output. ```bash $ node tags.js --seneca.log=plugin:./bar.js ... DEBUG plugin ./bar.js AAA add ./bar.js AAA {foo=bar,zed=1} ... ... DEBUG plugin ./bar.js BBB add ./bar.js BBB {foo=bar,zed=2} ... ... DEBUG act ./bar.js AAA pamds7vlteyv IN {foo=bar,zed=1} ... ... DEBUG act ./bar.js BBB 4uxz90gcczn5 IN {foo=bar,zed=2} ... ... DEBUG act ./bar.js AAA pamds7vlteyv OUT {color=red,tag=AAA} ... null { color: 'red', tag: 'AAA' } ... DEBUG act ./bar.js BBB 4uxz90gcczn5 OUT {color=green,tag=BBB} ... null { color: 'green', tag: 'BBB' } ``` -------------------------------- ### Client code for sales tax plugin Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Initializes the Seneca instance and registers the sales tax plugin with specific configuration options. ```javascript var seneca = require('seneca')() seneca.use('sales-tax-plugin', {country: 'IE', rate: 0.23}) seneca.use('sales-tax-plugin', {country: 'UK', rate: 0.20}) seneca.ready(function (err) { if (err) return process.exit(!console.error(err)) seneca.act({role: 'shop', cmd: 'salestax', country: 'IE', net: 100}) seneca.act({role: 'shop', cmd: 'salestax', country: 'UK', net: 200}) seneca.act({role: 'shop', cmd: 'salestax', country: 'UK', net: 300}) }) ``` -------------------------------- ### Define Plugin Name by Function Name Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Name the plugin definition function directly to set the plugin's name. This is an alternative to returning the name from the function. ```javascript // name1.js var plugin = function name1( options ) { this.add( {foo:'bar'}, function( args, done ) { done( null, {color: options.color} ) }) } ``` ```javascript var seneca = require('seneca')() seneca.use( plugin, {color:'pink'} ) seneca.act( {foo:'bar'}, console.log ) ``` -------------------------------- ### Define default plugin options Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Implement default options within a plugin module using deepextend to merge them with user-provided values. ```javascript // foo-defopts.js module.exports = function( options ) { // Default options options = this.util.deepextend({ color: 'red', box: { width: 100, height: 200 } },options) this.add( {foo:'bar'}, function( args, done ){ done( null, { color: options.color, box_width: options.box.width, box_height: options.box.height }) }) return {name:'foo'} } ``` -------------------------------- ### Test entity properties using canon$ Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Use the `canon$` method with the `isa` option to test if an entity matches a specific zone, base, and name pattern. ```javascript var apple = seneca.make('market','fruit'); // Test the properties by 'is a' apple.canon$({isa: '-/market/fruit'}); // -> true apple.canon$({isa: {base: 'market', name: 'fruit'}}); // -> true apple.canon$({isa: '-/market/vegetable'}); // -> false ``` -------------------------------- ### Define a basic color conversion plugin Source: https://senecajs.org/docs/tutorials/understanding-prior-actions.html Creates a Seneca plugin that maps color names to hex codes using a pattern-based action. ```javascript var seneca = require('seneca')() seneca.use( function color() { var map_name_hex = { black: '000000', red: 'FF0000', green: '00FF00', blue: '0000FF', white: 'FFFFFF' } this .add('role:color,cmd:convert', function (msg, respond) { var out = { hex: map_name_hex[msg.name] } respond( null, out ) }) }) // prints { hex: 'FF0000' } seneca.act('role:color,cmd:convert,name:red', console.log) // prints { hex: undefined } as yellow not recognized seneca.act('role:color,cmd:convert,name:yellow', console.log) ``` -------------------------------- ### Define a plugin with tag-dependent action patterns Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html The plugin uses the context tag to differentiate action patterns based on provided options. ```javascript // bar.js module.exports = function( options ) { var tag = this.context.tag this.add( {foo:'bar', zed:options.zed}, function( args, done ) { done( null, {color: options.color, tag:tag} ) }) } ``` -------------------------------- ### Override patterns using this.prior Source: https://senecajs.org/docs/tutorials/understanding-prior-actions.html Uses this.prior to intercept an action, execute the original logic, and provide fallback behavior if the original result is empty. ```javascript var more_name_hex = { cyan: '00FFFF', fuchsia: 'FF00FF' } seneca.add('role:color,cmd:convert', function (msg, respond) { this.prior(msg, function (err, out) { if (err) return respond(err) if (!out.hex) { out.hex = more_name_hex[msg.name] } respond(null, out) }) }) // prints { hex: 'FFFF00' }, from override seneca.act('role:color,cmd:convert,name:cyan', console.log) // prints { hex: '00FFFF' }, from more specific custom pattern seneca.act('role:color,cmd:convert,name:yellow', console.log) // prints { hex: 'FF0000' }, from color plugin seneca.act('role:color,cmd:convert,name:red', console.log) ``` -------------------------------- ### Define Seneca Action Patterns with Priors Source: https://senecajs.org/docs/tutorials/understanding-prior-actions.html A sample script defining nested action patterns that utilize the prior function to build a response chain. ```javascript // filename: prior-debug.js var seneca = require('seneca')() seneca .add('a:1', function( msg, respond ) { respond( null, { a:1 }) }) .add('a:1,b:2', function( msg, respond ) { this.prior( msg, function( err, out ) { out.b = 2 respond( err, out ) }) }) .add('a:1,b:2,c:3', function( msg, respond ) { this.prior( msg, function( err, out ) { out.c = 3 respond( err, out ) }) }) .act( 'a:1,b:2,c:3', console.log ) ``` -------------------------------- ### Monitor plugin activity Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Use the --seneca.log=type:plugin filter to see specific save/insert operations performed by data store plugins. ```bash $ node main.js --seneca.log=type:plugin 2013-04-18T10:39:54.961Z DEBUG plugin jsonfile-store QSG cop6lx save/insert $-/json/foo:{id=nt7usm;propA=val1;propB=val2} jsonfile-store~QSG~-/json/- 2013-04-18T10:40:19.802Z DEBUG plugin level-store JNG save/insert $-/level/bar:{id=7166037e-112d-448c-9afa-84e69d84aa25;propA=val3;propB=val4} level-store~JNG~-/level/- ``` -------------------------------- ### Custom Plugin Options File Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Configure plugin options using a custom JavaScript file. This file should export an object containing the desired option values. Seneca will load this file if provided as an argument to `seneca.options()`. ```javascript // dev.options.js module.exports = { zed: { green: 110, } } ``` -------------------------------- ### Handle Gate Executor Timeouts Source: https://senecajs.org/docs/tutorials/seneca-with-promises.html Demonstrates how promise rejection handles Seneca gate executor timeouts. ```javascript var Promise = require('bluebird'); var seneca = require('seneca')({ timeout: 500 }); var act = Promise.promisify(seneca.act, seneca); // Add a command that takes a longer time than the seneca's timeout period seneca.add({cmd: 'timeout'}, function (args, done) { setTimeout(function () { done(null, {message: 'resolve'}); }, 1000); }); act({cmd: 'timeout'}) .then(function (result) { // Never reaches here since the gate executer times out }) .catch(function (err) { // err will be set with a timeout error thrown by the gate executer }); ``` -------------------------------- ### Override plugin options during usage Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Supply custom options when loading a plugin to override the defined defaults. ```javascript // module-defopts.js var seneca = require('seneca')() seneca.use( './foo-defopts.js', { color:'pink', box:{ width:50 } }) seneca.act( {foo:'bar'}, console.log ) ``` ```bash $ node module-defopts.js null { color: 'pink', box_width: 50, box_height: 200 } ``` -------------------------------- ### Initialize Seneca test mode Source: https://senecajs.org/docs/tutorials/unit-testing.html Basic structure for enabling unit test mode in a test runner. ```javascript test('name-of-test', function (callback) { var seneca = Seneca().test(callback) ... }) ``` -------------------------------- ### Run sales-tax-error.js Source: https://senecajs.org/docs/tutorials/logging-with-seneca.html Execution output showing the error when an action pattern is not found. ```bash $ node sales-tax-error.js [-isodate-] INFO init start [-isodate-] INFO init end [-isodate-] ERROR fail seneca/act_not_found Seneca: act(args,cb): action not found for args = {"cmd":"salestax","net":100} { [Error: ...] } ``` -------------------------------- ### Extend plugin with a special case Source: https://senecajs.org/docs/tutorials/understanding-prior-actions.html Adds a specific pattern match to handle a color not covered by the original plugin definition. ```javascript seneca.add('role:color,cmd:convert,name:yellow', function( msg, respond ) { respond( null, { hex: 'FFFF00' }) }) // prints { hex: 'FFFF00' } seneca.act('role:color,cmd:convert,name:yellow', console.log ) ``` -------------------------------- ### Export a plugin as a Node.js module Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Plugins can be exported using module.exports to allow loading via file path or npm package name. ```javascript // foo.js module.exports = function( options ) { this.add( {foo:'bar'}, function( args, done ) { done( null, {color: options.color} ) }) } ``` -------------------------------- ### Load a data entity Source: https://senecajs.org/docs/tutorials/understanding-data-entities.html Retrieve an existing entity from the data store by its unique ID. ```javascript var id = '...' var foo_entity = seneca.make('foo') foo_entity.load$( id, function(err,foo){ console.log(foo) }) ``` -------------------------------- ### Define Plugin Name by Return Value Source: https://senecajs.org/docs/tutorials/how-to-write-a-plugin.html Return a string from the plugin definition function to set its name. This name is used in Seneca logs for tracking plugin activity. ```javascript // name0.js var plugin = function( options ) { this.add( {foo:'bar'}, function( args, done ) { done( null, {color: options.color} ) }) return 'name0' } var seneca = require('seneca')() seneca.use( plugin, {color:'pink'} ) seneca.act( {foo:'bar'}, console.log ) ```