1 | (function (global, factory) {
|
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
3 | typeof define === 'function' && define.amd ? define(factory) :
|
4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.stagnant = factory());
|
5 | }(this, (function () { 'use strict';
|
6 |
|
7 | function defaultConfig(){
|
8 |
|
9 | function onevent(){}
|
10 | function onerror(){}
|
11 | function onsuccess(){}
|
12 | function onflush(){}
|
13 |
|
14 |
|
15 |
|
16 | const ourConsole = {
|
17 | log(){},
|
18 | error(){},
|
19 | warn(){}
|
20 | };
|
21 |
|
22 | function generateId(){
|
23 | return Math.random().toString(15).slice(2,8)
|
24 | }
|
25 |
|
26 | return {
|
27 | onevent, onerror, onsuccess, onflush, console: ourConsole, generateId
|
28 | }
|
29 | }
|
30 |
|
31 | function Main(config={}){
|
32 |
|
33 | config = { ...defaultConfig(), ...config };
|
34 |
|
35 | const { generateId } = config;
|
36 |
|
37 | async function dispatchEvent(event){
|
38 | await config.onevent(event);
|
39 | if( event.error ) {
|
40 | await config.onerror(event);
|
41 | } else {
|
42 | await config.onsuccess(event);
|
43 | }
|
44 | }
|
45 |
|
46 | function Event({
|
47 | parentId, id, startTime, endTime, name, data, error
|
48 | }){
|
49 | return { parentId, id, startTime, endTime, name, data, error }
|
50 | }
|
51 |
|
52 | function RootEvent(){
|
53 | const event = Event({
|
54 | parentId: null
|
55 | ,id: generateId()
|
56 | ,startTime: Date.now()
|
57 | ,endTime: Date.now()
|
58 | ,error: null
|
59 | ,data: {}
|
60 | });
|
61 |
|
62 | event.flush = async function flush(){
|
63 | delete event.flush;
|
64 | event.endTime = Date.now();
|
65 | await dispatchEvent(event);
|
66 | await config.onflush(event);
|
67 | return event
|
68 | };
|
69 |
|
70 | return event
|
71 | }
|
72 |
|
73 | function setupEvent({ parentEvent, name, data, sync }){
|
74 | const event = Event({
|
75 | parentId: parentEvent.id
|
76 | ,id: generateId()
|
77 | ,name
|
78 | ,startTime: null
|
79 | ,endTime: null
|
80 | ,data: { ...parentEvent.data || {}, ...data }
|
81 | ,error: null
|
82 | ,sync: parentEvent.sync || sync
|
83 | });
|
84 | const childP = Instance(event);
|
85 | return { childP, event }
|
86 | }
|
87 |
|
88 |
|
89 | function Instance(parentEvent){
|
90 |
|
91 | function handler(...args){
|
92 | const callbackIndex = args.findIndex( x => typeof x == 'function' );
|
93 | let cb = args[callbackIndex];
|
94 | let rest = callbackIndex > 0 ? args.slice(0,callbackIndex) : args;
|
95 |
|
96 | let [name, data] = rest;
|
97 |
|
98 | if (typeof name != 'string') {
|
99 | data = name;
|
100 | if( cb ) {
|
101 | name = data.name || cb.toString().replace( /\s/g, '' ).replace( /(.)*=>/, '' );
|
102 | }
|
103 | }
|
104 |
|
105 | if ( data == null ) data = {};
|
106 |
|
107 | return { name, data, callback: cb }
|
108 | }
|
109 |
|
110 | function handlerData({ data }){
|
111 | parentEvent.data = { ...parentEvent.data, ...data };
|
112 | return null
|
113 | }
|
114 |
|
115 | async function handlerAsync({ event, childP, callback }){
|
116 | if ( parentEvent.sync ) {
|
117 | throw new Error('Cannot use an async trace within a synchronous trace')
|
118 | }
|
119 |
|
120 | try {
|
121 | event.startTime = Date.now();
|
122 | const out = await callback(childP);
|
123 | event.endTime = Date.now();
|
124 | return out
|
125 | } catch (e) {
|
126 | event.endTime = Date.now();
|
127 | event.error = e;
|
128 | throw e
|
129 | } finally {
|
130 | dispatchEvent(event)
|
131 | .catch( e => config.console.error('Failed to dispatch event', e));
|
132 | }
|
133 |
|
134 | }
|
135 |
|
136 | function handlerSync({ callback, name, event, childP }){
|
137 | try {
|
138 | event.startTime = Date.now();
|
139 | const out = callback(childP);
|
140 | event.endTime = Date.now();
|
141 | if( out != null && 'then' in out ) {
|
142 | config.console.warn(name, 'A call to trace.sync was made but the response was async. This is likely a mistake and should be corrected.');
|
143 | }
|
144 | return out
|
145 | } catch (e) {
|
146 | event.endTime = Date.now();
|
147 | event.error = e;
|
148 | throw e
|
149 | } finally {
|
150 | dispatchEvent(event)
|
151 | .catch( e => config.console.error('Failed to dispatch event', e));
|
152 | }
|
153 | }
|
154 |
|
155 | function routerOptions({ sync }, ...args){
|
156 | const { data, callback, name } = handler(...args);
|
157 |
|
158 | const {event,childP} =
|
159 | callback ? setupEvent({ parentEvent, name, data, sync }) : {};
|
160 |
|
161 | if( callback && sync ) {
|
162 | return handlerSync({ data, callback, childP, name, event })
|
163 | } else if ( callback && !sync ) {
|
164 | return handlerAsync({ data, callback, childP, name, event })
|
165 | } else {
|
166 | return handlerData({ data })
|
167 | }
|
168 | }
|
169 |
|
170 | async function routerAsync(...args){
|
171 | const out = await routerOptions({ sync: false }, ...args);
|
172 | return out
|
173 | }
|
174 |
|
175 | function routerSync(...args){
|
176 | const out = routerOptions({ sync: true }, ...args);
|
177 | return out
|
178 | }
|
179 |
|
180 | routerAsync.sync = routerSync;
|
181 | return routerAsync
|
182 | }
|
183 |
|
184 | let rootEvent = RootEvent();
|
185 | let handlerInstance = Instance(rootEvent);
|
186 | handlerInstance.flush = rootEvent.flush;
|
187 | handlerInstance.config = config;
|
188 | return handlerInstance
|
189 | }
|
190 |
|
191 | |
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 | function call(trace, ...args){
|
202 | const cb = args.find( x => typeof x == 'function' );
|
203 |
|
204 | if ( trace ) {
|
205 | return trace( ...args )
|
206 | } else if ( cb ) {
|
207 | return cb( (...args) => call(null, ...args) )
|
208 | }
|
209 | return null
|
210 | }
|
211 |
|
212 | Main.call = call;
|
213 |
|
214 | |
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 | function ensure(trace){
|
225 | if( trace ) {
|
226 | return trace
|
227 | } else {
|
228 | return (...args) => call(null, ...args)
|
229 | }
|
230 | }
|
231 |
|
232 | Main.ensure = ensure;
|
233 |
|
234 | return Main;
|
235 |
|
236 | })));
|
237 |
|