@@ -346,6 +346,166 @@ It is recommended to set a default `user-agent` header for Node.js
346346applications. The default for the default Node.js document loader is
347347` jsonld.js ` .
348348
349+ ### Events
350+
351+ ** WARNING** : This feature is ** experimental** and the API, events, codes,
352+ levels, and messages may change.
353+
354+ Various events may occur during processing. The event handler system allows
355+ callers to handle events as appropriate. Use cases can be as simple as logging
356+ warnings, to displaying helpful UI hints, to failing on specific conditions.
357+
358+ ** Note** : By default no event handler is used. This is due to general
359+ performance considerations and the impossibility of providing a default handler
360+ that would work for all use cases. Event construction and the handling system
361+ are avoided by default providing the best performance for use cases where data
362+ quality is known events are unnecessary.
363+
364+ #### Event Structure
365+
366+ Events are basic JSON objects with the following properties:
367+
368+ - ** ` code ` ** : A basic string code, similar to existing JSON-LD error codes.
369+ - ** ` level ` ** : The severity level. Currently only ` warning ` is emitted.
370+ - ** ` tags ` ** : Optional hints for the type of event. Currently defined:
371+ - ** ` unsafe ` ** : Event is considered unsafe.
372+ - ** ` lossy ` ** : Event is related to potential data loss.
373+ - ** ` empty ` ** : Event is related to empty data structures.
374+ - ** ` message ` ** : A human readable message describing the event.
375+ - ** ` details ` ** : A JSON object with event specific details.
376+
377+ #### Event Handlers
378+
379+ Event handlers are chainable functions, arrays of handlers, objects mapping
380+ codes to handlers, or any mix of these structures. Each function is passed an
381+ object with two properties:
382+
383+ - ** ` event ` ** : The event data.
384+ - ** ` next ` ** : A function to call to an ` event ` and a ` next ` .
385+
386+ The event handling system will process the handler structure, calling all
387+ handlers, and continuing onto the next handler if ` next() ` is called. To stop
388+ processing, throw an error, or return without calling ` next() ` .
389+
390+ This design allows for composable handler structures, for instance to handle
391+ some conditions with a custom handler, and default to generic "unknown event"
392+ or logging handler.
393+
394+ ** Note** : Handlers are currently synchronous due to possible performance
395+ issues. This may change to an ` async ` /` await ` design in the future.
396+
397+ ``` js
398+ // expand a document with a logging event handler
399+ const expanded = await jsonld .expand (data, {
400+ // simple logging handler
401+ eventHandler : function ({event , next}) {
402+ console .log (' event' , {event });
403+ }
404+ });
405+ ```
406+
407+ ``` js
408+ function logEventHandler ({event , next}) {
409+ console .log (' event' , {event });
410+ next ();
411+ }
412+
413+ function noWarningsEventHandler ({event , next}) {
414+ if (event .level === ' warning' ) {
415+ throw new Error (' No warnings!' , {event });
416+ }
417+ next ();
418+ }
419+
420+ function unknownEventHandler ({event , next}) {
421+ throw new Error (' Unknown event' , {event });
422+ }
423+
424+ // expand a document with an array of event handlers
425+ const expanded = await jsonld .expand (data, {
426+ // array of handlers
427+ eventHandler: [
428+ logEventHandler,
429+ noWarningsEventHandler,
430+ unknownEventHandler
431+ ]}
432+ });
433+ ```
434+
435+ ``` js
436+ const handler = {
437+ ' a mild event code ' : function ({event }) {
438+ console .log (' the thing happened' , {event });
439+ },
440+ ' a serious event code ' : function ({event }) {
441+ throw new Error (' the specific thing happened' , {event });
442+ }
443+ };
444+ // expand a document with a code map event handler
445+ const expanded = await jsonld .expand (data, {eventHandler});
446+ ```
447+
448+ #### Safe Mode
449+
450+ A common use case is to avoid JSON-LD constructs that will result in lossy
451+ behavior. The JSON-LD specifications have notes about when data is dropped.
452+ This can be especially important when calling [ ` canonize ` ] [ ] in order to
453+ digitally sign data. The event system can be used to detect and avoid these
454+ situations. A special "safe mode" is available that will inject an initial
455+ event handler that fails on conditions that would result in data loss. More
456+ benign events may fall back to the passed event handler, if any.
457+
458+ ** Note** : This mode is designed to be the common way that digital signing and
459+ similar applications use this library.
460+
461+ The ` safe ` options flag set to ` true ` enables this behavior:
462+
463+ ``` js
464+ // expand a document in safe mode
465+ const expanded = await jsonld .expand (data, {safe: true });
466+ ```
467+
468+ ``` js
469+ // expand a document in safe mode, with fallback handler
470+ const expanded = await jsonld .expand (data, {
471+ safe: true
472+ eventHandler : function ({event }) { /* ... */ }
473+ });
474+ ```
475+
476+ #### Available Handlers
477+
478+ Some predefined event handlers are available to use alone or as part of a more
479+ complex handler:
480+
481+ - ** safeModeEventHandler** : The handler used when ` safe ` is ` true ` .
482+ - ** strictModeEventHandler** : A handler that is more strict than the ` safe `
483+ handler and also fails on other detectable events related to poor input
484+ structure.
485+ - ** logEventHandler** : A debugging handler that outputs to the console.
486+ - ** logWarningHandler** : A debugging handler that outputs ` warning ` level
487+ events to the console.
488+ - ** unhandledEventHandler** : Throws on all events not yet handled.
489+
490+ #### Default Event Handler
491+
492+ A default event handler can be set. It will be the only handler when not in
493+ safe mode, and the second handler when in safe mode.
494+
495+ ``` js
496+ // fail on unknown events
497+ jsonld .setDefaultEventHandler (jsonld .unhandledEventHandler );
498+ // will use safe mode handler, like `{safe: true}`
499+ const expanded = await jsonld .expand (data);
500+ ```
501+
502+ ``` js
503+ // always use safe mode event handler, ignore other events
504+ jsonld .setDefaultEventHandler (jsonld .safeModeEventHandler );
505+ // will use safe mode handler, like `{safe: true}`
506+ const expanded = await jsonld .expand (data);
507+ ```
508+
349509Related Modules
350510---------------
351511
0 commit comments