Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
NebulaServices
GitHub Repository: NebulaServices/Nebula
Path: blob/main/public/workerware/workerware.js
976 views
1
importScripts("/workerware/WWError.js");
2
const dbg = console.log.bind(console, "[WorkerWare]");
3
const time = console.time.bind(console, "[WorkerWare]");
4
const timeEnd = console.timeEnd.bind(console, "[WorkerWare]");
5
6
/*
7
OPTS:
8
debug - Enables debug logging.
9
randomNames - Generate random names for middlewares.
10
timing - Logs timing for each middleware.
11
*/
12
13
const defaultOpt = {
14
debug: false,
15
randomNames: false,
16
timing: false
17
};
18
19
const validEvents = [
20
"abortpayment",
21
"activate",
22
"backgroundfetchabort",
23
"backgroundfetchclick",
24
"backgroundfetchfail",
25
"backgroundfetchsuccess",
26
"canmakepayment",
27
"contentdelete",
28
"cookiechange",
29
"fetch",
30
"install",
31
"message",
32
"messageerror",
33
"notificationclick",
34
"notificationclose",
35
"paymentrequest",
36
"periodicsync",
37
"push",
38
"pushsubscriptionchange",
39
"sync"
40
];
41
42
class WorkerWare {
43
constructor(opt) {
44
this._opt = Object.assign({}, defaultOpt, opt);
45
this._middlewares = [];
46
}
47
info() {
48
return {
49
version: "0.1.0",
50
middlewares: this._middlewares,
51
options: this._opt
52
};
53
}
54
use(middleware) {
55
let validateMW = this.validateMiddleware(middleware);
56
if (validateMW.error) throw new WWError(validateMW.error);
57
// This means the middleware is an anonymous function, or the user is silly and named their function "function"
58
if (middleware.function.name == "function") middleware.name = crypto.randomUUID();
59
if (!middleware.name) middleware.name = middleware.function.name;
60
if (this._opt.randomNames) middleware.name = crypto.randomUUID();
61
if (this._opt.debug) dbg("Adding middleware:", middleware.name);
62
this._middlewares.push(middleware);
63
}
64
// Run all middlewares for the event type passed in.
65
run(event) {
66
const middlewares = this._middlewares;
67
const returnList = [];
68
let fn = async () => {
69
for (let i = 0; i < middlewares.length; i++) {
70
if (middlewares[i].events.includes(event.type)) {
71
if (this._opt.timing) console.time(middlewares[i].name);
72
// Add the configuration to the event object.
73
event.workerware = {
74
config: middlewares[i].configuration || {}
75
};
76
if (!middlewares[i].explicitCall) {
77
let res = await middlewares[i].function(event);
78
if (this._opt.timing) console.timeEnd(middlewares[i].name);
79
returnList.push(res);
80
}
81
}
82
}
83
return returnList;
84
};
85
return fn;
86
}
87
deleteByName(middlewareID) {
88
if (this._opt.debug) dbg("Deleting middleware:", middlewareID);
89
this._middlewares = this._middlewares.filter((mw) => mw.name !== middlewareID);
90
}
91
deleteByEvent(middlewareEvent) {
92
if (this._opt.debug) dbg("Deleting middleware by event:", middlewareEvent);
93
this._middlewares = this._middlewares.filter((mw) => !mw.events.includes(middlewareEvent));
94
}
95
get() {
96
return this._middlewares;
97
}
98
/*
99
Run a single middleware by ID.
100
This assumes that the user knows what they're doing, and is running the middleware on an event that it's supposed to run on.
101
*/
102
runMW(name, event) {
103
const middlewares = this._middlewares;
104
if (this._opt.debug) dbg("Running middleware:", name);
105
// if (middlewares.includes(name)) {
106
// return middlewares[name](event);
107
// } else {
108
// throw new WWError("Middleware not found!");
109
// }
110
let didCall = false;
111
for (let i = 0; i < middlewares.length; i++) {
112
if (middlewares[i].name == name) {
113
didCall = true;
114
event.workerware = {
115
config: middlewares[i].configuration || {}
116
};
117
if (this._opt.timing) console.time(middlewares[i].name);
118
let call = middlewares[i].function(event);
119
if (this._opt.timing) console.timeEnd(middlewares[i].name);
120
return call;
121
}
122
}
123
if (!didCall) {
124
throw new WWError("Middleware not found!");
125
}
126
}
127
// type middlewareManifest = {
128
// function: Function,
129
// name?: string,
130
// events: string[], // Should be a union of validEvents.
131
// configuration?: Object // Optional configuration for the middleware.
132
// }
133
validateMiddleware(middleware) {
134
if (!middleware.function)
135
return {
136
error: "middleware.function is required"
137
};
138
if (typeof middleware.function !== "function")
139
return {
140
error: "middleware.function must be typeof function"
141
};
142
if (
143
typeof middleware.configuration !== "object" &&
144
middleware.configuration !== undefined
145
) {
146
return {
147
error: "middleware.configuration must be typeof object"
148
};
149
}
150
if (!middleware.events)
151
return {
152
error: "middleware.events is required"
153
};
154
if (!Array.isArray(middleware.events))
155
return {
156
error: "middleware.events must be an array"
157
};
158
if (middleware.events.some((ev) => !validEvents.includes(ev)))
159
return {
160
error: "Invalid event type! Must be one of the following: " + validEvents.join(", ")
161
};
162
if (middleware.explicitCall && typeof middleware.explicitCall !== "boolean") {
163
return {
164
error: "middleware.explicitCall must be typeof boolean"
165
};
166
}
167
return {
168
error: undefined
169
};
170
}
171
}
172
173