@chromahq/core 1.0.57 → 1.0.61

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.
@@ -535,11 +535,11 @@ function setupEarlyListener(portName = DEFAULT_PORT_NAME$1) {
535
535
  if (portsClaimed && onPortConnectCallback) {
536
536
  onPortConnectCallback(port);
537
537
  } else {
538
- console.log(`[EarlyListener] Captured early port connection: ${port.name}`);
538
+ console.debug(`[EarlyListener] Captured early port connection: ${port.name}`);
539
539
  earlyPorts.push(port);
540
540
  }
541
541
  });
542
- console.log(`[EarlyListener] Early connection listener registered for port: ${portName}`);
542
+ console.debug(`[EarlyListener] Early connection listener registered for port: ${portName}`);
543
543
  }
544
544
  function claimEarlyPorts(onConnect) {
545
545
  if (portsClaimed) {
@@ -551,7 +551,7 @@ function claimEarlyPorts(onConnect) {
551
551
  const captured = [...earlyPorts];
552
552
  earlyPorts.length = 0;
553
553
  if (captured.length > 0) {
554
- console.log(`[EarlyListener] Claimed ${captured.length} early port(s)`);
554
+ console.debug(`[EarlyListener] Claimed ${captured.length} early port(s)`);
555
555
  }
556
556
  return captured;
557
557
  }
@@ -667,7 +667,7 @@ const _BridgeRuntimeManager = class _BridgeRuntimeManager {
667
667
  if (!this.isValidPort(port)) {
668
668
  return;
669
669
  }
670
- this.logger.info(`\u{1F4E1} Port connected: ${port.name}`);
670
+ this.logger.debug(`\u{1F4E1} Port connected: ${port.name}`);
671
671
  this.setupMessageHandler(port);
672
672
  if (chrome.runtime.lastError) {
673
673
  this.logger.warn(`Runtime error during port setup: ${chrome.runtime.lastError.message}`);
@@ -684,7 +684,7 @@ const _BridgeRuntimeManager = class _BridgeRuntimeManager {
684
684
  if (isEarlyListenerSetup()) {
685
685
  const earlyPorts = claimEarlyPorts(handlePort);
686
686
  if (earlyPorts.length > 0) {
687
- this.logger.info(
687
+ this.logger.debug(
688
688
  `\u{1F4E1} Processing ${earlyPorts.length} early port(s) captured during bootstrap`
689
689
  );
690
690
  earlyPorts.forEach(handlePort);
@@ -738,7 +738,7 @@ const _BridgeRuntimeManager = class _BridgeRuntimeManager {
738
738
  });
739
739
  chrome.alarms.onAlarm.addListener(this.handleKeepAliveAlarm);
740
740
  this.keepAliveAlarmRegistered = true;
741
- this.logger.info("Registered keep-alive alarm for background wakeups");
741
+ this.logger.debug("Registered keep-alive alarm for background wakeups");
742
742
  }
743
743
  recordKeepAlivePing(source) {
744
744
  const timestamp = Date.now();
@@ -815,7 +815,7 @@ const _BridgeRuntimeManager = class _BridgeRuntimeManager {
815
815
  void chrome.runtime.lastError;
816
816
  this.diagnostics.lastPortDisconnectError = runtimeErrorMessage;
817
817
  } else {
818
- this.logger.info(`\u{1F4F4} Port disconnected: ${port.name}`);
818
+ this.logger.debug(`\u{1F4F4} Port disconnected: ${port.name}`);
819
819
  }
820
820
  this.diagnostics.portDisconnects++;
821
821
  this.diagnostics.lastPortDisconnectAt = Date.now();
@@ -1073,7 +1073,7 @@ const _BridgeRuntimeManager = class _BridgeRuntimeManager {
1073
1073
  */
1074
1074
  startKeepAlive() {
1075
1075
  if (this.keepAliveTimer) return;
1076
- this.logger.info("Starting keep-alive timer to keep service worker alive");
1076
+ this.logger.debug("Starting keep-alive timer to keep service worker alive");
1077
1077
  this.keepAliveTimer = setInterval(() => {
1078
1078
  chrome.runtime.getPlatformInfo(() => {
1079
1079
  this.recordKeepAlivePing("interval");
@@ -1093,7 +1093,7 @@ const _BridgeRuntimeManager = class _BridgeRuntimeManager {
1093
1093
  if (this.keepAliveTimer) {
1094
1094
  clearInterval(this.keepAliveTimer);
1095
1095
  this.keepAliveTimer = null;
1096
- this.logger.info("Stopped keep-alive timer");
1096
+ this.logger.debug("Stopped keep-alive timer");
1097
1097
  }
1098
1098
  }
1099
1099
  };
@@ -1143,10 +1143,10 @@ const _AlarmAdapter = class _AlarmAdapter {
1143
1143
  /**
1144
1144
  * Initialize the Chrome Alarms listener (once)
1145
1145
  */
1146
- this.initializeAlarmListener = () => {
1146
+ this.initializeAlarmListener = async () => {
1147
1147
  if (this.listenerRegistered) return;
1148
1148
  if (this.isChromeAlarmsAvailable()) {
1149
- this.clearStaleAlarms();
1149
+ await this.clearStaleAlarms();
1150
1150
  chrome.alarms.onAlarm.addListener(this.handleAlarm);
1151
1151
  this.listenerRegistered = true;
1152
1152
  console.log("[AlarmAdapter] \u2705 Chrome Alarms API available and listener registered");
@@ -1157,20 +1157,31 @@ const _AlarmAdapter = class _AlarmAdapter {
1157
1157
  }
1158
1158
  };
1159
1159
  /**
1160
- * Clear any stale chroma alarms from previous SW instances
1160
+ * Clear any stale chroma alarms from previous SW instances.
1161
+ * Returns a promise that resolves once all stale alarms are cleared.
1161
1162
  */
1162
1163
  this.clearStaleAlarms = () => {
1163
- if (!this.isChromeAlarmsAvailable()) return;
1164
- chrome.alarms.getAll((alarms) => {
1165
- const staleAlarms = alarms.filter((a) => a.name.startsWith(_AlarmAdapter.ALARM_PREFIX));
1166
- if (staleAlarms.length > 0) {
1167
- console.log(
1168
- `[AlarmAdapter] \u{1F9F9} Clearing ${staleAlarms.length} stale alarms from previous session`
1169
- );
1170
- staleAlarms.forEach((alarm) => {
1171
- chrome.alarms.clear(alarm.name);
1172
- });
1173
- }
1164
+ if (!this.isChromeAlarmsAvailable()) return Promise.resolve();
1165
+ return new Promise((resolve) => {
1166
+ chrome.alarms.getAll((alarms) => {
1167
+ const staleAlarms = alarms.filter((a) => a.name.startsWith(_AlarmAdapter.ALARM_PREFIX));
1168
+ if (staleAlarms.length > 0) {
1169
+ console.log(
1170
+ `[AlarmAdapter] \u{1F9F9} Clearing ${staleAlarms.length} stale alarms from previous session`
1171
+ );
1172
+ let cleared = 0;
1173
+ staleAlarms.forEach((alarm) => {
1174
+ chrome.alarms.clear(alarm.name, () => {
1175
+ cleared++;
1176
+ if (cleared === staleAlarms.length) {
1177
+ resolve();
1178
+ }
1179
+ });
1180
+ });
1181
+ } else {
1182
+ resolve();
1183
+ }
1184
+ });
1174
1185
  });
1175
1186
  };
1176
1187
  /**
@@ -1275,7 +1286,7 @@ const _AlarmAdapter = class _AlarmAdapter {
1275
1286
  usingChromeApi: this.isChromeAlarmsAvailable()
1276
1287
  };
1277
1288
  };
1278
- this.initializeAlarmListener();
1289
+ this.ready = this.initializeAlarmListener();
1279
1290
  }
1280
1291
  };
1281
1292
  _AlarmAdapter.ALARM_PREFIX = "chroma_job_";
@@ -2084,11 +2095,32 @@ class Scheduler {
2084
2095
  error: console.error,
2085
2096
  debug: console.debug
2086
2097
  };
2087
- this.logger.info("Scheduler initialized");
2098
+ this.logger.debug("Scheduler initialized");
2088
2099
  this.alarm.onTrigger(this.execute.bind(this));
2089
2100
  this.timeout.onTrigger(this.execute.bind(this));
2090
2101
  this.setupPopupVisibilityListener();
2091
2102
  }
2103
+ /**
2104
+ * When `options.schedulerDebug` is true, log at info so diagnostics show without
2105
+ * enabling global debug. Otherwise logs at debug.
2106
+ */
2107
+ logJobDiagnostics(options, message, context) {
2108
+ const ctx = context;
2109
+ if (options?.schedulerDebug) {
2110
+ this.logger.info(message, ctx);
2111
+ } else {
2112
+ this.logger.debug(message, ctx);
2113
+ }
2114
+ }
2115
+ /** Batch summary visible at info if any involved job has `schedulerDebug`. */
2116
+ logBatchIfAnyJobDebug(jobIds, message) {
2117
+ const anyDebug = jobIds.some((jid) => this.registry.meta(jid)?.schedulerDebug);
2118
+ if (anyDebug) {
2119
+ this.logger.info(message);
2120
+ } else {
2121
+ this.logger.debug(message);
2122
+ }
2123
+ }
2092
2124
  /**
2093
2125
  * Setup listener for popup visibility changes.
2094
2126
  * When popup closes, pause all jobs with requiresPopup.
@@ -2096,9 +2128,9 @@ class Scheduler {
2096
2128
  */
2097
2129
  setupPopupVisibilityListener() {
2098
2130
  const visibilityService = PopupVisibilityService.instance;
2099
- this.logger.info("[Scheduler] Setting up popup visibility listener");
2131
+ this.logger.debug("[Scheduler] Setting up popup visibility listener");
2100
2132
  this.popupVisibilityUnsubscribe = visibilityService.onVisibilityChange((isVisible) => {
2101
- this.logger.info(`[Scheduler] Visibility changed: ${isVisible ? "visible" : "hidden"}`);
2133
+ this.logger.debug(`[Scheduler] Visibility changed: ${isVisible ? "visible" : "hidden"}`);
2102
2134
  if (isVisible) {
2103
2135
  this.resumePopupDependentJobs();
2104
2136
  } else {
@@ -2111,13 +2143,14 @@ class Scheduler {
2111
2143
  */
2112
2144
  pausePopupDependentJobs() {
2113
2145
  const jobs = this.registry.listAll();
2114
- this.logger.info(`[Scheduler] pausePopupDependentJobs called, total jobs: ${jobs.length}`);
2146
+ this.logger.debug(`[Scheduler] pausePopupDependentJobs called, total jobs: ${jobs.length}`);
2115
2147
  let pausedCount = 0;
2116
2148
  const pausedJobIds = [];
2117
2149
  for (const job of jobs) {
2118
2150
  const hasRequiresPopup = job.options?.requiresPopup;
2119
2151
  const isPaused = this.registry.getContext(job.id)?.isPaused();
2120
- this.logger.debug(
2152
+ this.logJobDiagnostics(
2153
+ job.options,
2121
2154
  `[Scheduler] Job ${job.id}: requiresPopup=${hasRequiresPopup}, isPaused=${isPaused}`
2122
2155
  );
2123
2156
  if (hasRequiresPopup && !isPaused) {
@@ -2129,11 +2162,12 @@ class Scheduler {
2129
2162
  }
2130
2163
  }
2131
2164
  if (pausedCount > 0) {
2132
- this.logger.info(
2165
+ this.logBatchIfAnyJobDebug(
2166
+ pausedJobIds,
2133
2167
  `[Scheduler] Paused ${pausedCount} popup-dependent jobs (popup closed): ${pausedJobIds.join(", ")}`
2134
2168
  );
2135
2169
  } else {
2136
- this.logger.info(`[Scheduler] No popup-dependent jobs to pause`);
2170
+ this.logger.debug(`[Scheduler] No popup-dependent jobs to pause`);
2137
2171
  }
2138
2172
  }
2139
2173
  /**
@@ -2141,13 +2175,14 @@ class Scheduler {
2141
2175
  */
2142
2176
  resumePopupDependentJobs() {
2143
2177
  const jobs = this.registry.listAll();
2144
- this.logger.info(`[Scheduler] resumePopupDependentJobs called, total jobs: ${jobs.length}`);
2178
+ this.logger.debug(`[Scheduler] resumePopupDependentJobs called, total jobs: ${jobs.length}`);
2145
2179
  let resumedCount = 0;
2146
2180
  const resumedJobIds = [];
2147
2181
  for (const job of jobs) {
2148
2182
  const hasRequiresPopup = job.options?.requiresPopup;
2149
2183
  const isPaused = this.registry.getContext(job.id)?.isPaused();
2150
- this.logger.debug(
2184
+ this.logJobDiagnostics(
2185
+ job.options,
2151
2186
  `[Scheduler] Job ${job.id}: requiresPopup=${hasRequiresPopup}, isPaused=${isPaused}`
2152
2187
  );
2153
2188
  if (hasRequiresPopup && isPaused) {
@@ -2158,11 +2193,12 @@ class Scheduler {
2158
2193
  }
2159
2194
  }
2160
2195
  if (resumedCount > 0) {
2161
- this.logger.info(
2196
+ this.logBatchIfAnyJobDebug(
2197
+ resumedJobIds,
2162
2198
  `[Scheduler] Resumed ${resumedCount} popup-dependent jobs (popup opened): ${resumedJobIds.join(", ")}`
2163
2199
  );
2164
2200
  } else {
2165
- this.logger.info(`[Scheduler] No popup-dependent jobs to resume`);
2201
+ this.logger.debug(`[Scheduler] No popup-dependent jobs to resume`);
2166
2202
  }
2167
2203
  }
2168
2204
  schedule(id, options) {
@@ -2173,7 +2209,8 @@ class Scheduler {
2173
2209
  if (options?.requiresPopup) {
2174
2210
  const isPopupVisible = PopupVisibilityService.instance.isPopupVisible();
2175
2211
  if (!isPopupVisible) {
2176
- this.logger.debug(
2212
+ this.logJobDiagnostics(
2213
+ options,
2177
2214
  `Job ${id} requires popup but popup is not visible, pausing instead of scheduling`
2178
2215
  );
2179
2216
  if (!context.isPaused()) {
@@ -2182,6 +2219,13 @@ class Scheduler {
2182
2219
  return;
2183
2220
  }
2184
2221
  }
2222
+ this.alarm.ready.then(() => this.scheduleInternal(id, options));
2223
+ }
2224
+ scheduleInternal(id, options) {
2225
+ const context = this.registry.getContext(id);
2226
+ if (!context || context.isStopped() || context.isPaused()) {
2227
+ return;
2228
+ }
2185
2229
  const when = this.getScheduleTime(options);
2186
2230
  const now = Date.now();
2187
2231
  if (when <= now) {
@@ -2205,26 +2249,27 @@ class Scheduler {
2205
2249
  if (adapter === this.timeout && timerId) {
2206
2250
  this.registry.setTimeoutId(id, timerId);
2207
2251
  }
2208
- this.logger.info(
2252
+ this.logJobDiagnostics(
2253
+ options,
2209
2254
  `[Scheduler] Job "${id}" scheduled for ${new Date(when).toISOString()} (in ${Math.round(delayMs / 1e3)}s) \u2192 ${adapter === this.alarm ? "\u23F0 AlarmAdapter" : "\u23F1\uFE0F TimeoutAdapter"}`
2210
2255
  );
2211
2256
  }
2212
2257
  pause(id) {
2213
- this.logger.info(`Pausing job ${id}`);
2258
+ this.logJobDiagnostics(this.registry.meta(id), `Pausing job ${id}`);
2214
2259
  this.alarm.cancel(id);
2215
2260
  this.timeout.cancel(id);
2216
2261
  this.registry.pause(id);
2217
2262
  }
2218
2263
  resume(id) {
2219
- this.logger.info(`Resuming job ${id}`);
2220
- this.registry.resume(id);
2221
2264
  const options = this.registry.meta(id);
2265
+ this.logJobDiagnostics(options, `Resuming job ${id}`);
2266
+ this.registry.resume(id);
2222
2267
  if (options) {
2223
2268
  this.schedule(id, options);
2224
2269
  }
2225
2270
  }
2226
2271
  stop(id) {
2227
- this.logger.info(`Stopping job ${id}`);
2272
+ this.logJobDiagnostics(this.registry.meta(id), `Stopping job ${id}`);
2228
2273
  this.alarm.cancel(id);
2229
2274
  this.timeout.cancel(id);
2230
2275
  this.registry.stop(id);
@@ -2234,26 +2279,25 @@ class Scheduler {
2234
2279
  const context = this.registry.getContext(id);
2235
2280
  const options = this.registry.meta(id);
2236
2281
  if (!job || !context) {
2237
- this.logger.debug(`Job ${id} not found or no context`);
2282
+ this.logJobDiagnostics(options, `Job ${id} not found or no context`);
2238
2283
  return;
2239
2284
  }
2240
2285
  if (context.isPaused() || context.isStopped()) {
2241
- this.logger.debug(`Job ${id} is paused or stopped, skipping execution`);
2286
+ this.logJobDiagnostics(options, `Job ${id} is paused or stopped, skipping execution`);
2242
2287
  return;
2243
2288
  }
2244
2289
  if (options?.requiresPopup) {
2245
2290
  const isPopupVisible = PopupVisibilityService.instance.isPopupVisible();
2246
2291
  if (!isPopupVisible) {
2247
- this.logger.debug(`Job ${id} requires popup but popup closed, pausing job`);
2292
+ this.logJobDiagnostics(options, `Job ${id} requires popup but popup closed, pausing job`);
2248
2293
  this.registry.pause(id);
2249
2294
  return;
2250
2295
  }
2251
2296
  }
2252
2297
  try {
2253
2298
  this.registry.updateState(id, JobState.RUNNING);
2254
- this.logger.info(`Executing job ${id}`);
2299
+ this.logJobDiagnostics(options, `Executing job ${id}`);
2255
2300
  const jobInstance = container.get(id);
2256
- this.logger.debug("Job instance:", { jobInstance });
2257
2301
  await jobInstance.handle.bind(jobInstance).call(jobInstance, context);
2258
2302
  if (!context.isStopped() && !context.isPaused()) {
2259
2303
  this.registry.updateState(id, JobState.COMPLETED);
@@ -2266,7 +2310,7 @@ class Scheduler {
2266
2310
  this.logger.error(`Job ${id} execution failed:`, error);
2267
2311
  context.fail(error);
2268
2312
  if (options?.cron || options?.recurring) {
2269
- this.logger.info(`Rescheduling failed recurring job ${id}`);
2313
+ this.logJobDiagnostics(options, `Rescheduling failed recurring job ${id}`);
2270
2314
  this.registry.updateState(id, JobState.SCHEDULED);
2271
2315
  this.schedule(id, options);
2272
2316
  }
@@ -2294,7 +2338,7 @@ class Scheduler {
2294
2338
  * Gracefully shutdown the scheduler, clearing all timers
2295
2339
  */
2296
2340
  shutdown() {
2297
- this.logger.info("Shutting down scheduler...");
2341
+ this.logger.debug("Shutting down scheduler...");
2298
2342
  if (this.popupVisibilityUnsubscribe) {
2299
2343
  this.popupVisibilityUnsubscribe();
2300
2344
  this.popupVisibilityUnsubscribe = void 0;
@@ -2302,7 +2346,7 @@ class Scheduler {
2302
2346
  this.alarm.clear();
2303
2347
  this.timeout.clear();
2304
2348
  this.registry.clear();
2305
- this.logger.info("Scheduler shutdown complete");
2349
+ this.logger.debug("Scheduler shutdown complete");
2306
2350
  }
2307
2351
  /**
2308
2352
  * Get scheduler stats for monitoring
@@ -2797,7 +2841,7 @@ class ApplicationBootstrap {
2797
2841
  if (!container.isBound(JobClass)) {
2798
2842
  container.bind(JobClass).toSelf().inSingletonScope();
2799
2843
  }
2800
- const id = `${jobName.toLowerCase()}:${JobClass.name.toLowerCase()} ${Math.random().toString(36).substring(2, 15)}`;
2844
+ const id = `${jobName.toLowerCase()}:${JobClass.name.toLowerCase()}`;
2801
2845
  container.bind(id).to(JobClass).inSingletonScope();
2802
2846
  const options = Reflect.getMetadata("job:options", JobClass) || {};
2803
2847
  jobEntries.push({ JobClass, jobName, id, options });
@@ -2923,4 +2967,4 @@ class BootstrapBuilder {
2923
2967
  }
2924
2968
 
2925
2969
  export { AppEventBus as A, EventBusToken as E, JobRegistry as J, NonceService as N, PopupVisibilityService as P, Subscribe as S, SUBSCRIBE_METADATA_KEY as a, getNonceService as b, getPopupVisibilityService as c, claimEarlyPorts as d, arePortsClaimed as e, container as f, getSubscribeMetadata as g, create as h, isEarlyListenerSetup as i, bootstrap as j, Scheduler as k, JobState as l, setupEarlyListener as s };
2926
- //# sourceMappingURL=boot-C2Rq9czO.js.map
2970
+ //# sourceMappingURL=boot-yaI0mE0N.js.map