@chromahq/core 1.0.56 → 1.0.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{boot-CUFlC4bu.js → boot--zb14Gg3.js} +219 -17
- package/dist/boot--zb14Gg3.js.map +1 -0
- package/dist/{boot-c2gJZWBc.js → boot-DPtu_qKj.js} +216 -18
- package/dist/boot-DPtu_qKj.js.map +1 -0
- package/dist/boot.cjs.js +2 -1
- package/dist/boot.cjs.js.map +1 -1
- package/dist/boot.es.js +2 -1
- package/dist/boot.es.js.map +1 -1
- package/dist/index.cjs.js +11 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +153 -2
- package/dist/index.es.js +3 -2
- package/dist/index.es.js.map +1 -1
- package/package.json +1 -1
- package/dist/boot-CUFlC4bu.js.map +0 -1
- package/dist/boot-c2gJZWBc.js.map +0 -1
|
@@ -1,6 +1,126 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var container$1 = require('@inversifyjs/container');
|
|
4
|
+
var core = require('@inversifyjs/core');
|
|
5
|
+
|
|
6
|
+
const SUBSCRIBE_METADATA_KEY = "chroma:subscribe";
|
|
7
|
+
function Subscribe(eventName) {
|
|
8
|
+
return function(target, propertyKey, _descriptor) {
|
|
9
|
+
const key = "chroma:subscribe";
|
|
10
|
+
const constructor = target.constructor;
|
|
11
|
+
const existing = Reflect.getMetadata(key, constructor) || [];
|
|
12
|
+
existing.push({ eventName, methodName: propertyKey });
|
|
13
|
+
Reflect.defineMetadata(key, existing, constructor);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function getSubscribeMetadata(constructor) {
|
|
17
|
+
return Reflect.getMetadata("chroma:subscribe", constructor) || [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
21
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
22
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
23
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
24
|
+
if (decorator = decorators[i])
|
|
25
|
+
result = (decorator(result)) || result;
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
const EventBusToken = /* @__PURE__ */ Symbol.for("EventBus");
|
|
29
|
+
exports.AppEventBus = class AppEventBus {
|
|
30
|
+
constructor() {
|
|
31
|
+
/** Registry of all active subscriptions */
|
|
32
|
+
this.subscriptions = [];
|
|
33
|
+
/** Auto-incrementing ID counter */
|
|
34
|
+
this.nextId = 0;
|
|
35
|
+
}
|
|
36
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
37
|
+
// Subscribe
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* Subscribe to a named event.
|
|
41
|
+
*
|
|
42
|
+
* @param eventName - the event to listen for
|
|
43
|
+
* @param handler - callback invoked with the event payload
|
|
44
|
+
* @param handlerName - human-readable name for logging
|
|
45
|
+
* @returns an unsubscribe function
|
|
46
|
+
*/
|
|
47
|
+
on(eventName, handler, handlerName) {
|
|
48
|
+
const id = ++this.nextId;
|
|
49
|
+
this.subscriptions.push({
|
|
50
|
+
id,
|
|
51
|
+
eventName,
|
|
52
|
+
handler,
|
|
53
|
+
handlerName
|
|
54
|
+
});
|
|
55
|
+
return () => {
|
|
56
|
+
this.subscriptions = this.subscriptions.filter((s) => s.id !== id);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
60
|
+
// Emit
|
|
61
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Emit a named event to all matching subscribers.
|
|
64
|
+
*
|
|
65
|
+
* Handlers execute in parallel. Individual handler failures are caught
|
|
66
|
+
* and logged — they do not propagate or block other handlers.
|
|
67
|
+
*
|
|
68
|
+
* @param eventName - the event to emit
|
|
69
|
+
* @param payload - optional data passed to every handler
|
|
70
|
+
*/
|
|
71
|
+
async emit(eventName, payload) {
|
|
72
|
+
const matching = this.subscriptions.filter((s) => s.eventName === eventName);
|
|
73
|
+
if (matching.length === 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const results = await Promise.allSettled(
|
|
77
|
+
matching.map(async (sub) => {
|
|
78
|
+
try {
|
|
79
|
+
await sub.handler(payload);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(
|
|
82
|
+
`[AppEventBus] Handler "${sub.handlerName}" failed for event "${eventName}":`,
|
|
83
|
+
error
|
|
84
|
+
);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
const failed = results.filter((r) => r.status === "rejected").length;
|
|
90
|
+
if (failed > 0) {
|
|
91
|
+
console.warn(
|
|
92
|
+
`[AppEventBus] ${failed}/${matching.length} handler(s) failed for event "${eventName}"`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
97
|
+
// Utilities
|
|
98
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
99
|
+
/**
|
|
100
|
+
* Get the total number of active subscriptions.
|
|
101
|
+
* Useful for debugging and testing.
|
|
102
|
+
*/
|
|
103
|
+
getSubscriptionCount() {
|
|
104
|
+
return this.subscriptions.length;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the number of subscriptions for a specific event.
|
|
108
|
+
*
|
|
109
|
+
* @param eventName - the event to count subscriptions for
|
|
110
|
+
*/
|
|
111
|
+
getSubscriptionCountForEvent(eventName) {
|
|
112
|
+
return this.subscriptions.filter((s) => s.eventName === eventName).length;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Remove all subscriptions. Primarily for testing.
|
|
116
|
+
*/
|
|
117
|
+
clearAllSubscriptions() {
|
|
118
|
+
this.subscriptions = [];
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
exports.AppEventBus = __decorateClass([
|
|
122
|
+
core.injectable()
|
|
123
|
+
], exports.AppEventBus);
|
|
4
124
|
|
|
5
125
|
const NONCE_STORE_STORAGE_KEY = "__CHROMA_NONCE_STORE__";
|
|
6
126
|
class NonceService {
|
|
@@ -1025,10 +1145,10 @@ const _AlarmAdapter = class _AlarmAdapter {
|
|
|
1025
1145
|
/**
|
|
1026
1146
|
* Initialize the Chrome Alarms listener (once)
|
|
1027
1147
|
*/
|
|
1028
|
-
this.initializeAlarmListener = () => {
|
|
1148
|
+
this.initializeAlarmListener = async () => {
|
|
1029
1149
|
if (this.listenerRegistered) return;
|
|
1030
1150
|
if (this.isChromeAlarmsAvailable()) {
|
|
1031
|
-
this.clearStaleAlarms();
|
|
1151
|
+
await this.clearStaleAlarms();
|
|
1032
1152
|
chrome.alarms.onAlarm.addListener(this.handleAlarm);
|
|
1033
1153
|
this.listenerRegistered = true;
|
|
1034
1154
|
console.log("[AlarmAdapter] \u2705 Chrome Alarms API available and listener registered");
|
|
@@ -1039,20 +1159,31 @@ const _AlarmAdapter = class _AlarmAdapter {
|
|
|
1039
1159
|
}
|
|
1040
1160
|
};
|
|
1041
1161
|
/**
|
|
1042
|
-
* Clear any stale chroma alarms from previous SW instances
|
|
1162
|
+
* Clear any stale chroma alarms from previous SW instances.
|
|
1163
|
+
* Returns a promise that resolves once all stale alarms are cleared.
|
|
1043
1164
|
*/
|
|
1044
1165
|
this.clearStaleAlarms = () => {
|
|
1045
|
-
if (!this.isChromeAlarmsAvailable()) return;
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1166
|
+
if (!this.isChromeAlarmsAvailable()) return Promise.resolve();
|
|
1167
|
+
return new Promise((resolve) => {
|
|
1168
|
+
chrome.alarms.getAll((alarms) => {
|
|
1169
|
+
const staleAlarms = alarms.filter((a) => a.name.startsWith(_AlarmAdapter.ALARM_PREFIX));
|
|
1170
|
+
if (staleAlarms.length > 0) {
|
|
1171
|
+
console.log(
|
|
1172
|
+
`[AlarmAdapter] \u{1F9F9} Clearing ${staleAlarms.length} stale alarms from previous session`
|
|
1173
|
+
);
|
|
1174
|
+
let cleared = 0;
|
|
1175
|
+
staleAlarms.forEach((alarm) => {
|
|
1176
|
+
chrome.alarms.clear(alarm.name, () => {
|
|
1177
|
+
cleared++;
|
|
1178
|
+
if (cleared === staleAlarms.length) {
|
|
1179
|
+
resolve();
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
});
|
|
1183
|
+
} else {
|
|
1184
|
+
resolve();
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1056
1187
|
});
|
|
1057
1188
|
};
|
|
1058
1189
|
/**
|
|
@@ -1157,7 +1288,7 @@ const _AlarmAdapter = class _AlarmAdapter {
|
|
|
1157
1288
|
usingChromeApi: this.isChromeAlarmsAvailable()
|
|
1158
1289
|
};
|
|
1159
1290
|
};
|
|
1160
|
-
this.initializeAlarmListener();
|
|
1291
|
+
this.ready = this.initializeAlarmListener();
|
|
1161
1292
|
}
|
|
1162
1293
|
};
|
|
1163
1294
|
_AlarmAdapter.ALARM_PREFIX = "chroma_job_";
|
|
@@ -2064,6 +2195,13 @@ class Scheduler {
|
|
|
2064
2195
|
return;
|
|
2065
2196
|
}
|
|
2066
2197
|
}
|
|
2198
|
+
this.alarm.ready.then(() => this.scheduleInternal(id, options));
|
|
2199
|
+
}
|
|
2200
|
+
scheduleInternal(id, options) {
|
|
2201
|
+
const context = this.registry.getContext(id);
|
|
2202
|
+
if (!context || context.isStopped() || context.isPaused()) {
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2067
2205
|
const when = this.getScheduleTime(options);
|
|
2068
2206
|
const now = Date.now();
|
|
2069
2207
|
if (when <= now) {
|
|
@@ -2202,6 +2340,7 @@ class ApplicationBootstrap {
|
|
|
2202
2340
|
constructor() {
|
|
2203
2341
|
this.serviceDependencies = /* @__PURE__ */ new Map();
|
|
2204
2342
|
this.serviceRegistry = /* @__PURE__ */ new Map();
|
|
2343
|
+
this.jobRegistry = /* @__PURE__ */ new Map();
|
|
2205
2344
|
this.logger = new BootstrapLogger();
|
|
2206
2345
|
this.storeDefinitions = [];
|
|
2207
2346
|
}
|
|
@@ -2233,6 +2372,7 @@ class ApplicationBootstrap {
|
|
|
2233
2372
|
try {
|
|
2234
2373
|
this.logger = new BootstrapLogger(enableLogs);
|
|
2235
2374
|
this.logger.info("Starting Chroma application bootstrap...");
|
|
2375
|
+
this.initializeEventBus();
|
|
2236
2376
|
await this.discoverAndInitializeStores();
|
|
2237
2377
|
await this.discoverServices();
|
|
2238
2378
|
const store = this.storeDefinitions[0].store;
|
|
@@ -2252,6 +2392,7 @@ class ApplicationBootstrap {
|
|
|
2252
2392
|
if (!disableBootMethods) {
|
|
2253
2393
|
await this.bootMessages();
|
|
2254
2394
|
await this.bootServices();
|
|
2395
|
+
this.wireEventSubscriptions();
|
|
2255
2396
|
}
|
|
2256
2397
|
this.logger.success("Chroma application initialization complete");
|
|
2257
2398
|
} catch (error) {
|
|
@@ -2282,6 +2423,62 @@ class ApplicationBootstrap {
|
|
|
2282
2423
|
);
|
|
2283
2424
|
await Promise.all(bootPromises);
|
|
2284
2425
|
}
|
|
2426
|
+
/**
|
|
2427
|
+
* Create and bind the global AppEventBus singleton to the DI container.
|
|
2428
|
+
* Called early in bootstrap so any service can inject it.
|
|
2429
|
+
*/
|
|
2430
|
+
initializeEventBus() {
|
|
2431
|
+
if (!container.isBound(exports.AppEventBus)) {
|
|
2432
|
+
container.bind(exports.AppEventBus).toSelf().inSingletonScope();
|
|
2433
|
+
}
|
|
2434
|
+
if (!container.isBound(EventBusToken)) {
|
|
2435
|
+
container.bind(EventBusToken).toDynamicValue(() => container.get(exports.AppEventBus)).inSingletonScope();
|
|
2436
|
+
}
|
|
2437
|
+
this.logger.debug("AppEventBus bound to DI container");
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Scan all registered services and jobs for @Subscribe metadata and
|
|
2441
|
+
* wire the decorated methods to the AppEventBus.
|
|
2442
|
+
*
|
|
2443
|
+
* This runs after bootServices so every singleton is already instantiated.
|
|
2444
|
+
*/
|
|
2445
|
+
wireEventSubscriptions() {
|
|
2446
|
+
this.logger.info("Wiring @Subscribe event subscriptions...");
|
|
2447
|
+
const bus = container.get(exports.AppEventBus);
|
|
2448
|
+
let wiredCount = 0;
|
|
2449
|
+
const scan = (name, Constructor) => {
|
|
2450
|
+
const metadata = getSubscribeMetadata(Constructor);
|
|
2451
|
+
if (metadata.length === 0) {
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
let instance;
|
|
2455
|
+
try {
|
|
2456
|
+
instance = container.get(Constructor);
|
|
2457
|
+
} catch {
|
|
2458
|
+
this.logger.warn(`Could not resolve instance for ${name}, skipping @Subscribe wiring`);
|
|
2459
|
+
return;
|
|
2460
|
+
}
|
|
2461
|
+
for (const { eventName, methodName } of metadata) {
|
|
2462
|
+
const method = instance[methodName];
|
|
2463
|
+
if (typeof method !== "function") {
|
|
2464
|
+
this.logger.warn(
|
|
2465
|
+
`@Subscribe('${eventName}') on ${name}.${methodName} is not a function, skipping`
|
|
2466
|
+
);
|
|
2467
|
+
continue;
|
|
2468
|
+
}
|
|
2469
|
+
bus.on(eventName, method.bind(instance), `${name}.${methodName}`);
|
|
2470
|
+
wiredCount++;
|
|
2471
|
+
this.logger.debug(`Wired @Subscribe('${eventName}') \u2192 ${name}.${methodName}`);
|
|
2472
|
+
}
|
|
2473
|
+
};
|
|
2474
|
+
for (const [name, Constructor] of this.serviceRegistry) {
|
|
2475
|
+
scan(name, Constructor);
|
|
2476
|
+
}
|
|
2477
|
+
for (const [name, Constructor] of this.jobRegistry) {
|
|
2478
|
+
scan(name, Constructor);
|
|
2479
|
+
}
|
|
2480
|
+
this.logger.success(`Wired ${wiredCount} @Subscribe handler(s) to AppEventBus`);
|
|
2481
|
+
}
|
|
2285
2482
|
/**
|
|
2286
2483
|
* Discover all services in the application directory
|
|
2287
2484
|
*/
|
|
@@ -2620,10 +2817,11 @@ class ApplicationBootstrap {
|
|
|
2620
2817
|
if (!container.isBound(JobClass)) {
|
|
2621
2818
|
container.bind(JobClass).toSelf().inSingletonScope();
|
|
2622
2819
|
}
|
|
2623
|
-
const id = `${jobName.toLowerCase()}:${JobClass.name.toLowerCase()}
|
|
2820
|
+
const id = `${jobName.toLowerCase()}:${JobClass.name.toLowerCase()}`;
|
|
2624
2821
|
container.bind(id).to(JobClass).inSingletonScope();
|
|
2625
2822
|
const options = Reflect.getMetadata("job:options", JobClass) || {};
|
|
2626
2823
|
jobEntries.push({ JobClass, jobName, id, options });
|
|
2824
|
+
this.jobRegistry.set(jobName, JobClass);
|
|
2627
2825
|
this.logger.debug(`Bound job: ${jobName}`);
|
|
2628
2826
|
} catch (error) {
|
|
2629
2827
|
this.logger.error(`Failed to bind job ${JobClass.name}:`, error);
|
|
@@ -2744,11 +2942,14 @@ class BootstrapBuilder {
|
|
|
2744
2942
|
}
|
|
2745
2943
|
}
|
|
2746
2944
|
|
|
2945
|
+
exports.EventBusToken = EventBusToken;
|
|
2747
2946
|
exports.JobRegistry = JobRegistry;
|
|
2748
2947
|
exports.JobState = JobState;
|
|
2749
2948
|
exports.NonceService = NonceService;
|
|
2750
2949
|
exports.PopupVisibilityService = PopupVisibilityService;
|
|
2950
|
+
exports.SUBSCRIBE_METADATA_KEY = SUBSCRIBE_METADATA_KEY;
|
|
2751
2951
|
exports.Scheduler = Scheduler;
|
|
2952
|
+
exports.Subscribe = Subscribe;
|
|
2752
2953
|
exports.arePortsClaimed = arePortsClaimed;
|
|
2753
2954
|
exports.bootstrap = bootstrap;
|
|
2754
2955
|
exports.claimEarlyPorts = claimEarlyPorts;
|
|
@@ -2756,6 +2957,7 @@ exports.container = container;
|
|
|
2756
2957
|
exports.create = create;
|
|
2757
2958
|
exports.getNonceService = getNonceService;
|
|
2758
2959
|
exports.getPopupVisibilityService = getPopupVisibilityService;
|
|
2960
|
+
exports.getSubscribeMetadata = getSubscribeMetadata;
|
|
2759
2961
|
exports.isEarlyListenerSetup = isEarlyListenerSetup;
|
|
2760
2962
|
exports.setupEarlyListener = setupEarlyListener;
|
|
2761
|
-
//# sourceMappingURL=boot
|
|
2963
|
+
//# sourceMappingURL=boot--zb14Gg3.js.map
|