@chromahq/core 1.0.52 → 1.0.54

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/decorators/Service.ts","../src/decorators/Message.ts","../src/scheduler/core/Job.ts","../src/scheduler/decorators/Job.ts","../src/scheduler/decorators/Delay.ts","../src/scheduler/decorators/Every.ts","../src/scheduler/decorators/EverySeconds.ts","../src/services/booteable.ts"],"sourcesContent":["import { inject, injectable } from '@inversifyjs/core';\n\nexport function Service() {\n return injectable();\n}\n\nexport const Use = (id: symbol | string | NewableFunction) => inject(id);\nexport const Store = () => Use(Symbol.for('Store'));\n","import { injectable } from '@inversifyjs/core';\n\nexport abstract class IMessage {\n handle(...args: any[]): Promise<void> | void {\n throw new Error('Method not implemented.');\n }\n}\n\nexport function Message(name: string) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('name', name, constructor);\n return constructor;\n };\n}\n","import { IJob, JobContext } from './IJob';\n\nexport abstract class Job<T = unknown> implements IJob<T> {\n constructor(public readonly data?: T) {}\n\n abstract handle(context?: JobContext): Promise<void> | void;\n\n pause?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} paused`);\n }\n\n resume?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} resumed`);\n }\n\n stop?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} stopped`);\n }\n}\n","import { injectable } from '@inversifyjs/core';\nimport { JobOptions } from '../core/JobOptions';\n\nexport function JobConfig<T extends new (...args: any[]) => any>(options: JobOptions = {}) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('job:options', options, constructor);\n return constructor;\n };\n}\n","import { JobConfig } from './Job';\n\nexport const Delay = (ms: number) => JobConfig({ delay: ms });\n","import { injectable } from '@inversifyjs/core';\n\nexport function Every(cron: string) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('job:options', { cron }, constructor);\n return constructor;\n };\n}\n","import { injectable } from '@inversifyjs/core';\n\n/**\n * Options for the EverySeconds decorator.\n */\nexport interface EverySecondsOptions {\n /** If true, job starts paused and must be resumed manually via Scheduler.resume() */\n startPaused?: boolean;\n /** Explicit job name (survives minification). Required for production builds. */\n name?: string;\n}\n\n/**\n * Decorator for jobs that run at a specific interval in seconds.\n * Unlike cron expressions which have minute-level granularity,\n * this decorator allows for second-level precision.\n *\n * @param seconds - The interval in seconds between job executions\n * @param options - Optional configuration (startPaused, name, etc.)\n *\n * @example\n * ```typescript\n * // Auto-starting job (default)\n * @EverySeconds(5, { name: 'MyJob' })\n * export class MyJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs every 5 seconds');\n * }\n * }\n *\n * // Paused job that must be manually resumed\n * @EverySeconds(2, { startPaused: true, name: 'OnDemandJob' })\n * export class OnDemandJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs when resumed');\n * }\n * }\n * ```\n */\nexport function EverySeconds(seconds: number, options?: EverySecondsOptions) {\n return function (constructor: any) {\n injectable()(constructor);\n // Set explicit name metadata to survive minification\n if (options?.name) {\n Reflect.defineMetadata('name', options.name, constructor);\n }\n\n Reflect.defineMetadata(\n 'job:options',\n {\n delay: seconds * 1000,\n recurring: true,\n startPaused: options?.startPaused ?? false,\n },\n constructor,\n );\n return constructor;\n };\n}\n","export abstract class Booteable {\n /**\n * Boot method to be called when the service is initialized.\n * This method can be used to perform any setup or initialization logic.\n */\n abstract boot(): void;\n /**\n * Optional destroy method to be called when the service is being destroyed.\n * This can be used to clean up resources or perform any necessary teardown logic.\n */\n destroy?(): void {\n // Default implementation does nothing\n }\n}\n\nexport function isBooteable(obj: any): obj is Booteable {\n return typeof obj.boot === 'function';\n}\n\nexport function isDestroyable(obj: any): obj is Booteable {\n return typeof obj.destroy === 'function';\n}\n"],"names":["injectable","inject"],"mappings":";;;;;;AAEO,SAAS,OAAA,GAAU;AACxB,EAAA,OAAOA,eAAA,EAAW;AACpB;AAEO,MAAM,GAAA,GAAM,CAAC,EAAA,KAA0CC,WAAA,CAAO,EAAE;AAChE,MAAM,QAAQ,MAAM,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,OAAO,CAAC;;ACL3C,MAAe,QAAA,CAAS;AAAA,EAC7B,UAAU,IAAA,EAAmC;AAC3C,IAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA;AAE7C;AAEO,SAAS,QAAQ,IAAA,EAAc;AACpC,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAAD,eAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA,CAAe,MAAA,EAAQ,IAAA,EAAM,WAAW,CAAA;AAChD,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;ACZO,MAAe,GAAA,CAAoC;AAAA,EACxD,YAA4B,IAAA,EAAU;AAAV,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA;AAAW,EAIvC,KAAA,GAA+B;AAC7B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA,OAAA,CAAS,CAAA;AAAA;AACnD,EAEA,MAAA,GAAgC;AAC9B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA;AACpD,EAEA,IAAA,GAA8B;AAC5B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA;AAEtD;;ACfO,SAAS,SAAA,CAAiD,OAAA,GAAsB,EAAC,EAAG;AACzF,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAAA,eAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA,CAAe,aAAA,EAAe,OAAA,EAAS,WAAW,CAAA;AAC1D,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;ACPO,MAAM,QAAQ,CAAC,EAAA,KAAe,UAAU,EAAE,KAAA,EAAO,IAAI;;ACArD,SAAS,MAAM,IAAA,EAAc;AAClC,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAAA,eAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA,CAAe,aAAA,EAAe,EAAE,IAAA,IAAQ,WAAW,CAAA;AAC3D,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;AC+BO,SAAS,YAAA,CAAa,SAAiB,OAAA,EAA+B;AAC3E,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAAA,eAAA,GAAa,WAAW,CAAA;AAExB,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAA,CAAQ,cAAA,CAAe,MAAA,EAAQ,OAAA,CAAQ,IAAA,EAAM,WAAW,CAAA;AAAA;AAG1D,IAAA,OAAA,CAAQ,cAAA;AAAA,MACN,aAAA;AAAA,MACA;AAAA,QACE,OAAO,OAAA,GAAU,GAAA;AAAA,QACjB,SAAA,EAAW,IAAA;AAAA,QACX,WAAA,EAAa,SAAS,WAAA,IAAe;AAAA,OACvC;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;AC1DO,MAAe,SAAA,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAU9B,OAAA,GAAiB;AAAA;AAGnB;AAEO,SAAS,YAAY,GAAA,EAA4B;AACtD,EAAA,OAAO,OAAO,IAAI,IAAA,KAAS,UAAA;AAC7B;AAEO,SAAS,cAAc,GAAA,EAA4B;AACxD,EAAA,OAAO,OAAO,IAAI,OAAA,KAAY,UAAA;AAChC;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/decorators/Service.ts","../src/decorators/Message.ts","../src/scheduler/core/Job.ts","../src/scheduler/decorators/Job.ts","../src/scheduler/decorators/Delay.ts","../src/scheduler/decorators/Every.ts","../src/scheduler/decorators/EverySeconds.ts","../src/services/booteable.ts"],"sourcesContent":["import { inject, injectable } from '@inversifyjs/core';\n\nexport function Service() {\n return injectable();\n}\n\nexport const Use = (id: symbol | string | NewableFunction) => inject(id);\nexport const Store = () => Use(Symbol.for('Store'));\n","import { injectable } from '@inversifyjs/core';\n\nexport abstract class IMessage {\n handle(...args: any[]): Promise<void> | void {\n throw new Error('Method not implemented.');\n }\n}\n\nexport function Message(name: string) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('name', name, constructor);\n return constructor;\n };\n}\n","import { IJob, JobContext } from './IJob';\n\nexport abstract class Job<T = unknown> implements IJob<T> {\n constructor(public readonly data?: T) {}\n\n abstract handle(context?: JobContext): Promise<void> | void;\n\n pause?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} paused`);\n }\n\n resume?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} resumed`);\n }\n\n stop?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} stopped`);\n }\n}\n","import { injectable } from '@inversifyjs/core';\nimport { JobOptions } from '../core/JobOptions';\n\nexport function JobConfig<T extends new (...args: any[]) => any>(options: JobOptions = {}) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('job:options', options, constructor);\n return constructor;\n };\n}\n","import { JobConfig } from './Job';\n\nexport const Delay = (ms: number) => JobConfig({ delay: ms });\n","import { injectable } from '@inversifyjs/core';\n\n/**\n * Options for the Every decorator.\n */\nexport interface EveryOptions {\n /**\n * If true, the job will only execute when the popup (or extension view) is visible.\n * This reduces unnecessary background activity when the user isn't looking at the extension.\n */\n requiresPopup?: boolean;\n\n /**\n * Explicit job name (survives minification). Recommended for production builds.\n */\n name?: string;\n\n /**\n * If true, job starts paused and must be resumed manually via Scheduler.resume()\n */\n startPaused?: boolean;\n}\n\n/**\n * Decorator for scheduling jobs using cron expressions.\n *\n * @param cron - Cron expression (e.g., '0 *\\/5 * * * *' for every 5 minutes)\n * @param options - Optional configuration for the job\n *\n * @example\n * ```typescript\n * // Basic usage - runs every 5 minutes\n * @Every('0 *\\/5 * * * *')\n * export class MyJob { ... }\n *\n * // With options - only runs when popup is visible\n * @Every('0 *\\/5 * * * *', { requiresPopup: true, name: 'MyJob' })\n * export class MyJob { ... }\n * ```\n */\nexport function Every(cron: string, options?: EveryOptions) {\n return function (constructor: any) {\n injectable()(constructor);\n\n // Set explicit name metadata to survive minification\n if (options?.name) {\n Reflect.defineMetadata('name', options.name, constructor);\n }\n\n Reflect.defineMetadata(\n 'job:options',\n {\n cron,\n requiresPopup: options?.requiresPopup ?? false,\n startPaused: options?.startPaused ?? false,\n },\n constructor,\n );\n return constructor;\n };\n}\n","import { injectable } from '@inversifyjs/core';\n\n/**\n * Options for the EverySeconds decorator.\n */\nexport interface EverySecondsOptions {\n /** If true, job starts paused and must be resumed manually via Scheduler.resume() */\n startPaused?: boolean;\n\n /** Explicit job name (survives minification). Required for production builds. */\n name?: string;\n\n /**\n * If true, the job will only execute when the popup (or extension view) is visible.\n * This reduces unnecessary background activity when the user isn't looking at the extension.\n */\n requiresPopup?: boolean;\n}\n\n/**\n * Decorator for jobs that run at a specific interval in seconds.\n * Unlike cron expressions which have minute-level granularity,\n * this decorator allows for second-level precision.\n *\n * @param seconds - The interval in seconds between job executions\n * @param options - Optional configuration (startPaused, name, requiresPopup, etc.)\n *\n * @example\n * ```typescript\n * // Auto-starting job (default)\n * @EverySeconds(5, { name: 'MyJob' })\n * export class MyJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs every 5 seconds');\n * }\n * }\n *\n * // Job that only runs when popup is visible\n * @EverySeconds(10, { name: 'UiUpdateJob', requiresPopup: true })\n * export class UiUpdateJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Only runs when user is viewing extension');\n * }\n * }\n *\n * // Paused job that must be manually resumed\n * @EverySeconds(2, { startPaused: true, name: 'OnDemandJob' })\n * export class OnDemandJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs when resumed');\n * }\n * }\n * ```\n */\nexport function EverySeconds(seconds: number, options?: EverySecondsOptions) {\n return function (constructor: any) {\n injectable()(constructor);\n // Set explicit name metadata to survive minification\n if (options?.name) {\n Reflect.defineMetadata('name', options.name, constructor);\n }\n\n Reflect.defineMetadata(\n 'job:options',\n {\n delay: seconds * 1000,\n recurring: true,\n startPaused: options?.startPaused ?? false,\n requiresPopup: options?.requiresPopup ?? false,\n },\n constructor,\n );\n return constructor;\n };\n}\n","export abstract class Booteable {\n /**\n * Boot method to be called when the service is initialized.\n * This method can be used to perform any setup or initialization logic.\n */\n abstract boot(): void;\n /**\n * Optional destroy method to be called when the service is being destroyed.\n * This can be used to clean up resources or perform any necessary teardown logic.\n */\n destroy?(): void {\n // Default implementation does nothing\n }\n}\n\nexport function isBooteable(obj: any): obj is Booteable {\n return typeof obj.boot === 'function';\n}\n\nexport function isDestroyable(obj: any): obj is Booteable {\n return typeof obj.destroy === 'function';\n}\n"],"names":["injectable","inject"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -9,13 +9,39 @@ declare abstract class IMessage {
9
9
  }
10
10
  declare function Message(name: string): (constructor: any) => any;
11
11
 
12
+ /**
13
+ * Configuration options for scheduled jobs.
14
+ */
12
15
  interface JobOptions {
16
+ /** Unique identifier for the job */
13
17
  id?: string;
18
+ /** Delay in milliseconds before first execution (for delay-based jobs) */
14
19
  delay?: number;
20
+ /** Cron expression for scheduling (e.g., '0 *​/5 * * * *' for every 5 minutes) */
15
21
  cron?: string;
22
+ /** Whether the job should persist across service worker restarts */
16
23
  persistent?: boolean;
24
+ /** Whether the job should repeat after each execution (for delay-based jobs) */
17
25
  recurring?: boolean;
26
+ /** If true, job starts paused and must be resumed manually via Scheduler.resume() */
18
27
  startPaused?: boolean;
28
+ /**
29
+ * If true, the job will only execute when the popup (or extension view) is visible.
30
+ * This reduces unnecessary background activity when the user isn't looking at the extension.
31
+ *
32
+ * When the popup is closed:
33
+ * - The job will be skipped silently
34
+ * - It will be rescheduled for its next occurrence
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * @Every('0 *\/5 * * * *', { requiresPopup: true })
39
+ * export class AllocationFetchJob {
40
+ * // Only runs when popup is open
41
+ * }
42
+ * ```
43
+ */
44
+ requiresPopup?: boolean;
19
45
  }
20
46
 
21
47
  interface IJob<T = unknown> {
@@ -80,7 +106,42 @@ declare abstract class Job<T = unknown> implements IJob<T> {
80
106
 
81
107
  declare const Delay: (ms: number) => (constructor: any) => any;
82
108
 
83
- declare function Every(cron: string): (constructor: any) => any;
109
+ /**
110
+ * Options for the Every decorator.
111
+ */
112
+ interface EveryOptions {
113
+ /**
114
+ * If true, the job will only execute when the popup (or extension view) is visible.
115
+ * This reduces unnecessary background activity when the user isn't looking at the extension.
116
+ */
117
+ requiresPopup?: boolean;
118
+ /**
119
+ * Explicit job name (survives minification). Recommended for production builds.
120
+ */
121
+ name?: string;
122
+ /**
123
+ * If true, job starts paused and must be resumed manually via Scheduler.resume()
124
+ */
125
+ startPaused?: boolean;
126
+ }
127
+ /**
128
+ * Decorator for scheduling jobs using cron expressions.
129
+ *
130
+ * @param cron - Cron expression (e.g., '0 *\/5 * * * *' for every 5 minutes)
131
+ * @param options - Optional configuration for the job
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * // Basic usage - runs every 5 minutes
136
+ * @Every('0 *\/5 * * * *')
137
+ * export class MyJob { ... }
138
+ *
139
+ * // With options - only runs when popup is visible
140
+ * @Every('0 *\/5 * * * *', { requiresPopup: true, name: 'MyJob' })
141
+ * export class MyJob { ... }
142
+ * ```
143
+ */
144
+ declare function Every(cron: string, options?: EveryOptions): (constructor: any) => any;
84
145
 
85
146
  /**
86
147
  * Options for the EverySeconds decorator.
@@ -90,6 +151,11 @@ interface EverySecondsOptions {
90
151
  startPaused?: boolean;
91
152
  /** Explicit job name (survives minification). Required for production builds. */
92
153
  name?: string;
154
+ /**
155
+ * If true, the job will only execute when the popup (or extension view) is visible.
156
+ * This reduces unnecessary background activity when the user isn't looking at the extension.
157
+ */
158
+ requiresPopup?: boolean;
93
159
  }
94
160
  /**
95
161
  * Decorator for jobs that run at a specific interval in seconds.
@@ -97,7 +163,7 @@ interface EverySecondsOptions {
97
163
  * this decorator allows for second-level precision.
98
164
  *
99
165
  * @param seconds - The interval in seconds between job executions
100
- * @param options - Optional configuration (startPaused, name, etc.)
166
+ * @param options - Optional configuration (startPaused, name, requiresPopup, etc.)
101
167
  *
102
168
  * @example
103
169
  * ```typescript
@@ -109,6 +175,14 @@ interface EverySecondsOptions {
109
175
  * }
110
176
  * }
111
177
  *
178
+ * // Job that only runs when popup is visible
179
+ * @EverySeconds(10, { name: 'UiUpdateJob', requiresPopup: true })
180
+ * export class UiUpdateJob implements IJob {
181
+ * async handle(context: JobContext) {
182
+ * console.log('Only runs when user is viewing extension');
183
+ * }
184
+ * }
185
+ *
112
186
  * // Paused job that must be manually resumed
113
187
  * @EverySeconds(2, { startPaused: true, name: 'OnDemandJob' })
114
188
  * export class OnDemandJob implements IJob {
@@ -293,6 +367,111 @@ declare class NonceService {
293
367
  }
294
368
  declare function getNonceService(): NonceService;
295
369
 
370
+ /**
371
+ * @fileoverview Popup Visibility Service for Chrome Extensions.
372
+ *
373
+ * Tracks whether the extension popup (or any extension view) is currently visible
374
+ * by monitoring connected ports. This allows jobs to conditionally run only when
375
+ * a user is actively viewing the extension, reducing unnecessary background activity.
376
+ *
377
+ * @module services/PopupVisibilityService
378
+ *
379
+ * @example
380
+ * ```typescript
381
+ * import { PopupVisibilityService } from '@chromahq/core';
382
+ *
383
+ * // Check if popup is visible
384
+ * if (PopupVisibilityService.instance.isPopupVisible()) {
385
+ * // Run UI-related tasks
386
+ * }
387
+ *
388
+ * // Listen for visibility changes
389
+ * PopupVisibilityService.instance.onVisibilityChange((isVisible) => {
390
+ * console.log('Popup visibility changed:', isVisible);
391
+ * });
392
+ * ```
393
+ */
394
+ /** Callback type for visibility change events */
395
+ type VisibilityChangeCallback = (isVisible: boolean) => void;
396
+ /**
397
+ * Service that tracks popup/extension view visibility.
398
+ *
399
+ * Uses a singleton pattern to ensure consistent state across the application.
400
+ * The service is updated by the BridgeRuntime when ports connect/disconnect.
401
+ */
402
+ declare class PopupVisibilityService {
403
+ private static _instance;
404
+ /** Number of currently connected ports (popup views) */
405
+ private connectedPortCount;
406
+ /** Listeners for visibility changes */
407
+ private listeners;
408
+ /** Timestamp of last visibility change */
409
+ private lastVisibilityChangeAt;
410
+ /**
411
+ * Private constructor - use PopupVisibilityService.instance instead.
412
+ */
413
+ private constructor();
414
+ /**
415
+ * Get the singleton instance of the service.
416
+ */
417
+ static get instance(): PopupVisibilityService;
418
+ /**
419
+ * Reset the singleton instance (primarily for testing).
420
+ * @internal
421
+ */
422
+ static resetInstance(): void;
423
+ /**
424
+ * Check if the popup (or any extension view) is currently visible.
425
+ *
426
+ * @returns true if at least one port is connected (popup is open)
427
+ */
428
+ isPopupVisible(): boolean;
429
+ /**
430
+ * Get the number of connected ports.
431
+ *
432
+ * @returns The current count of connected extension views
433
+ */
434
+ getConnectedPortCount(): number;
435
+ /**
436
+ * Get the timestamp of the last visibility change.
437
+ *
438
+ * @returns Unix timestamp in milliseconds, or 0 if never changed
439
+ */
440
+ getLastVisibilityChangeAt(): number;
441
+ /**
442
+ * Register a callback to be notified when visibility changes.
443
+ *
444
+ * @param callback - Function to call when visibility changes
445
+ * @returns Unsubscribe function to remove the listener
446
+ */
447
+ onVisibilityChange(callback: VisibilityChangeCallback): () => void;
448
+ /**
449
+ * Called when a port connects (popup opens).
450
+ * @internal
451
+ */
452
+ onPortConnected(): void;
453
+ /**
454
+ * Called when a port disconnects (popup closes).
455
+ * @internal
456
+ */
457
+ onPortDisconnected(): void;
458
+ /**
459
+ * Sync the port count with the actual connected ports set.
460
+ * Called by BridgeRuntime to ensure consistency.
461
+ * @internal
462
+ */
463
+ syncPortCount(count: number): void;
464
+ /**
465
+ * Notify all registered listeners of a visibility change.
466
+ */
467
+ private notifyListeners;
468
+ }
469
+ /**
470
+ * Get the PopupVisibilityService singleton instance.
471
+ * Convenience function for cleaner imports.
472
+ */
473
+ declare function getPopupVisibilityService(): PopupVisibilityService;
474
+
296
475
  /**
297
476
  * @fileoverview Early Connection Listener for Chrome Extension Service Workers.
298
477
  *
@@ -399,7 +578,22 @@ declare class Scheduler {
399
578
  private readonly alarm;
400
579
  private readonly timeout;
401
580
  private readonly logger;
581
+ private popupVisibilityUnsubscribe?;
402
582
  constructor(logger?: Logger);
583
+ /**
584
+ * Setup listener for popup visibility changes.
585
+ * When popup closes, pause all jobs with requiresPopup.
586
+ * When popup opens, resume those jobs.
587
+ */
588
+ private setupPopupVisibilityListener;
589
+ /**
590
+ * Pause all jobs that have requiresPopup: true
591
+ */
592
+ private pausePopupDependentJobs;
593
+ /**
594
+ * Resume all jobs that have requiresPopup: true
595
+ */
596
+ private resumePopupDependentJobs;
403
597
  schedule(id: string, options: JobOptions): void;
404
598
  pause(id: string): void;
405
599
  resume(id: string): void;
@@ -468,5 +662,5 @@ declare class JobRegistry {
468
662
  private createJobContext;
469
663
  }
470
664
 
471
- export { Booteable, Delay, Every, EverySeconds, IMessage, Job, JobRegistry, JobState, Message, NonceService, Scheduler, Service, Store, Use, arePortsClaimed, bootstrap, claimEarlyPorts, container, create, getNonceService, isBooteable, isDestroyable, isEarlyListenerSetup, setupEarlyListener };
472
- export type { CriticalPayload, EverySecondsOptions, IJob, JobContext, NonceCheckResult };
665
+ export { Booteable, Delay, Every, EverySeconds, IMessage, Job, JobRegistry, JobState, Message, NonceService, PopupVisibilityService, Scheduler, Service, Store, Use, arePortsClaimed, bootstrap, claimEarlyPorts, container, create, getNonceService, getPopupVisibilityService, isBooteable, isDestroyable, isEarlyListenerSetup, setupEarlyListener };
666
+ export type { CriticalPayload, EveryOptions, EverySecondsOptions, IJob, JobContext, NonceCheckResult };
package/dist/index.es.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { inject, injectable } from '@inversifyjs/core';
2
- export { J as JobRegistry, f as JobState, N as NonceService, S as Scheduler, a as arePortsClaimed, e as bootstrap, c as claimEarlyPorts, b as container, d as create, g as getNonceService, i as isEarlyListenerSetup, s as setupEarlyListener } from './boot-DmW_OC5R.js';
2
+ export { J as JobRegistry, h as JobState, N as NonceService, P as PopupVisibilityService, S as Scheduler, b as arePortsClaimed, f as bootstrap, c as claimEarlyPorts, d as container, e as create, g as getNonceService, a as getPopupVisibilityService, i as isEarlyListenerSetup, s as setupEarlyListener } from './boot-DRsz4LpW.js';
3
3
  import '@inversifyjs/container';
4
4
 
5
5
  function Service() {
@@ -46,10 +46,21 @@ function JobConfig(options = {}) {
46
46
 
47
47
  const Delay = (ms) => JobConfig({ delay: ms });
48
48
 
49
- function Every(cron) {
49
+ function Every(cron, options) {
50
50
  return function(constructor) {
51
51
  injectable()(constructor);
52
- Reflect.defineMetadata("job:options", { cron }, constructor);
52
+ if (options?.name) {
53
+ Reflect.defineMetadata("name", options.name, constructor);
54
+ }
55
+ Reflect.defineMetadata(
56
+ "job:options",
57
+ {
58
+ cron,
59
+ requiresPopup: options?.requiresPopup ?? false,
60
+ startPaused: options?.startPaused ?? false
61
+ },
62
+ constructor
63
+ );
53
64
  return constructor;
54
65
  };
55
66
  }
@@ -65,7 +76,8 @@ function EverySeconds(seconds, options) {
65
76
  {
66
77
  delay: seconds * 1e3,
67
78
  recurring: true,
68
- startPaused: options?.startPaused ?? false
79
+ startPaused: options?.startPaused ?? false,
80
+ requiresPopup: options?.requiresPopup ?? false
69
81
  },
70
82
  constructor
71
83
  );
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/decorators/Service.ts","../src/decorators/Message.ts","../src/scheduler/core/Job.ts","../src/scheduler/decorators/Job.ts","../src/scheduler/decorators/Delay.ts","../src/scheduler/decorators/Every.ts","../src/scheduler/decorators/EverySeconds.ts","../src/services/booteable.ts"],"sourcesContent":["import { inject, injectable } from '@inversifyjs/core';\n\nexport function Service() {\n return injectable();\n}\n\nexport const Use = (id: symbol | string | NewableFunction) => inject(id);\nexport const Store = () => Use(Symbol.for('Store'));\n","import { injectable } from '@inversifyjs/core';\n\nexport abstract class IMessage {\n handle(...args: any[]): Promise<void> | void {\n throw new Error('Method not implemented.');\n }\n}\n\nexport function Message(name: string) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('name', name, constructor);\n return constructor;\n };\n}\n","import { IJob, JobContext } from './IJob';\n\nexport abstract class Job<T = unknown> implements IJob<T> {\n constructor(public readonly data?: T) {}\n\n abstract handle(context?: JobContext): Promise<void> | void;\n\n pause?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} paused`);\n }\n\n resume?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} resumed`);\n }\n\n stop?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} stopped`);\n }\n}\n","import { injectable } from '@inversifyjs/core';\nimport { JobOptions } from '../core/JobOptions';\n\nexport function JobConfig<T extends new (...args: any[]) => any>(options: JobOptions = {}) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('job:options', options, constructor);\n return constructor;\n };\n}\n","import { JobConfig } from './Job';\n\nexport const Delay = (ms: number) => JobConfig({ delay: ms });\n","import { injectable } from '@inversifyjs/core';\n\nexport function Every(cron: string) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('job:options', { cron }, constructor);\n return constructor;\n };\n}\n","import { injectable } from '@inversifyjs/core';\n\n/**\n * Options for the EverySeconds decorator.\n */\nexport interface EverySecondsOptions {\n /** If true, job starts paused and must be resumed manually via Scheduler.resume() */\n startPaused?: boolean;\n /** Explicit job name (survives minification). Required for production builds. */\n name?: string;\n}\n\n/**\n * Decorator for jobs that run at a specific interval in seconds.\n * Unlike cron expressions which have minute-level granularity,\n * this decorator allows for second-level precision.\n *\n * @param seconds - The interval in seconds between job executions\n * @param options - Optional configuration (startPaused, name, etc.)\n *\n * @example\n * ```typescript\n * // Auto-starting job (default)\n * @EverySeconds(5, { name: 'MyJob' })\n * export class MyJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs every 5 seconds');\n * }\n * }\n *\n * // Paused job that must be manually resumed\n * @EverySeconds(2, { startPaused: true, name: 'OnDemandJob' })\n * export class OnDemandJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs when resumed');\n * }\n * }\n * ```\n */\nexport function EverySeconds(seconds: number, options?: EverySecondsOptions) {\n return function (constructor: any) {\n injectable()(constructor);\n // Set explicit name metadata to survive minification\n if (options?.name) {\n Reflect.defineMetadata('name', options.name, constructor);\n }\n\n Reflect.defineMetadata(\n 'job:options',\n {\n delay: seconds * 1000,\n recurring: true,\n startPaused: options?.startPaused ?? false,\n },\n constructor,\n );\n return constructor;\n };\n}\n","export abstract class Booteable {\n /**\n * Boot method to be called when the service is initialized.\n * This method can be used to perform any setup or initialization logic.\n */\n abstract boot(): void;\n /**\n * Optional destroy method to be called when the service is being destroyed.\n * This can be used to clean up resources or perform any necessary teardown logic.\n */\n destroy?(): void {\n // Default implementation does nothing\n }\n}\n\nexport function isBooteable(obj: any): obj is Booteable {\n return typeof obj.boot === 'function';\n}\n\nexport function isDestroyable(obj: any): obj is Booteable {\n return typeof obj.destroy === 'function';\n}\n"],"names":[],"mappings":";;;;AAEO,SAAS,OAAA,GAAU;AACxB,EAAA,OAAO,UAAA,EAAW;AACpB;AAEO,MAAM,GAAA,GAAM,CAAC,EAAA,KAA0C,MAAA,CAAO,EAAE;AAChE,MAAM,QAAQ,MAAM,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,OAAO,CAAC;;ACL3C,MAAe,QAAA,CAAS;AAAA,EAC7B,UAAU,IAAA,EAAmC;AAC3C,IAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA;AAE7C;AAEO,SAAS,QAAQ,IAAA,EAAc;AACpC,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAA,UAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA,CAAe,MAAA,EAAQ,IAAA,EAAM,WAAW,CAAA;AAChD,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;ACZO,MAAe,GAAA,CAAoC;AAAA,EACxD,YAA4B,IAAA,EAAU;AAAV,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA;AAAW,EAIvC,KAAA,GAA+B;AAC7B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA,OAAA,CAAS,CAAA;AAAA;AACnD,EAEA,MAAA,GAAgC;AAC9B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA;AACpD,EAEA,IAAA,GAA8B;AAC5B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA;AAEtD;;ACfO,SAAS,SAAA,CAAiD,OAAA,GAAsB,EAAC,EAAG;AACzF,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAA,UAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA,CAAe,aAAA,EAAe,OAAA,EAAS,WAAW,CAAA;AAC1D,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;ACPO,MAAM,QAAQ,CAAC,EAAA,KAAe,UAAU,EAAE,KAAA,EAAO,IAAI;;ACArD,SAAS,MAAM,IAAA,EAAc;AAClC,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAA,UAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA,CAAe,aAAA,EAAe,EAAE,IAAA,IAAQ,WAAW,CAAA;AAC3D,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;AC+BO,SAAS,YAAA,CAAa,SAAiB,OAAA,EAA+B;AAC3E,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAA,UAAA,GAAa,WAAW,CAAA;AAExB,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAA,CAAQ,cAAA,CAAe,MAAA,EAAQ,OAAA,CAAQ,IAAA,EAAM,WAAW,CAAA;AAAA;AAG1D,IAAA,OAAA,CAAQ,cAAA;AAAA,MACN,aAAA;AAAA,MACA;AAAA,QACE,OAAO,OAAA,GAAU,GAAA;AAAA,QACjB,SAAA,EAAW,IAAA;AAAA,QACX,WAAA,EAAa,SAAS,WAAA,IAAe;AAAA,OACvC;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;AC1DO,MAAe,SAAA,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAU9B,OAAA,GAAiB;AAAA;AAGnB;AAEO,SAAS,YAAY,GAAA,EAA4B;AACtD,EAAA,OAAO,OAAO,IAAI,IAAA,KAAS,UAAA;AAC7B;AAEO,SAAS,cAAc,GAAA,EAA4B;AACxD,EAAA,OAAO,OAAO,IAAI,OAAA,KAAY,UAAA;AAChC;;;;"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/decorators/Service.ts","../src/decorators/Message.ts","../src/scheduler/core/Job.ts","../src/scheduler/decorators/Job.ts","../src/scheduler/decorators/Delay.ts","../src/scheduler/decorators/Every.ts","../src/scheduler/decorators/EverySeconds.ts","../src/services/booteable.ts"],"sourcesContent":["import { inject, injectable } from '@inversifyjs/core';\n\nexport function Service() {\n return injectable();\n}\n\nexport const Use = (id: symbol | string | NewableFunction) => inject(id);\nexport const Store = () => Use(Symbol.for('Store'));\n","import { injectable } from '@inversifyjs/core';\n\nexport abstract class IMessage {\n handle(...args: any[]): Promise<void> | void {\n throw new Error('Method not implemented.');\n }\n}\n\nexport function Message(name: string) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('name', name, constructor);\n return constructor;\n };\n}\n","import { IJob, JobContext } from './IJob';\n\nexport abstract class Job<T = unknown> implements IJob<T> {\n constructor(public readonly data?: T) {}\n\n abstract handle(context?: JobContext): Promise<void> | void;\n\n pause?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} paused`);\n }\n\n resume?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} resumed`);\n }\n\n stop?(): Promise<void> | void {\n console.log(`Job ${this.constructor.name} stopped`);\n }\n}\n","import { injectable } from '@inversifyjs/core';\nimport { JobOptions } from '../core/JobOptions';\n\nexport function JobConfig<T extends new (...args: any[]) => any>(options: JobOptions = {}) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata('job:options', options, constructor);\n return constructor;\n };\n}\n","import { JobConfig } from './Job';\n\nexport const Delay = (ms: number) => JobConfig({ delay: ms });\n","import { injectable } from '@inversifyjs/core';\n\n/**\n * Options for the Every decorator.\n */\nexport interface EveryOptions {\n /**\n * If true, the job will only execute when the popup (or extension view) is visible.\n * This reduces unnecessary background activity when the user isn't looking at the extension.\n */\n requiresPopup?: boolean;\n\n /**\n * Explicit job name (survives minification). Recommended for production builds.\n */\n name?: string;\n\n /**\n * If true, job starts paused and must be resumed manually via Scheduler.resume()\n */\n startPaused?: boolean;\n}\n\n/**\n * Decorator for scheduling jobs using cron expressions.\n *\n * @param cron - Cron expression (e.g., '0 *\\/5 * * * *' for every 5 minutes)\n * @param options - Optional configuration for the job\n *\n * @example\n * ```typescript\n * // Basic usage - runs every 5 minutes\n * @Every('0 *\\/5 * * * *')\n * export class MyJob { ... }\n *\n * // With options - only runs when popup is visible\n * @Every('0 *\\/5 * * * *', { requiresPopup: true, name: 'MyJob' })\n * export class MyJob { ... }\n * ```\n */\nexport function Every(cron: string, options?: EveryOptions) {\n return function (constructor: any) {\n injectable()(constructor);\n\n // Set explicit name metadata to survive minification\n if (options?.name) {\n Reflect.defineMetadata('name', options.name, constructor);\n }\n\n Reflect.defineMetadata(\n 'job:options',\n {\n cron,\n requiresPopup: options?.requiresPopup ?? false,\n startPaused: options?.startPaused ?? false,\n },\n constructor,\n );\n return constructor;\n };\n}\n","import { injectable } from '@inversifyjs/core';\n\n/**\n * Options for the EverySeconds decorator.\n */\nexport interface EverySecondsOptions {\n /** If true, job starts paused and must be resumed manually via Scheduler.resume() */\n startPaused?: boolean;\n\n /** Explicit job name (survives minification). Required for production builds. */\n name?: string;\n\n /**\n * If true, the job will only execute when the popup (or extension view) is visible.\n * This reduces unnecessary background activity when the user isn't looking at the extension.\n */\n requiresPopup?: boolean;\n}\n\n/**\n * Decorator for jobs that run at a specific interval in seconds.\n * Unlike cron expressions which have minute-level granularity,\n * this decorator allows for second-level precision.\n *\n * @param seconds - The interval in seconds between job executions\n * @param options - Optional configuration (startPaused, name, requiresPopup, etc.)\n *\n * @example\n * ```typescript\n * // Auto-starting job (default)\n * @EverySeconds(5, { name: 'MyJob' })\n * export class MyJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs every 5 seconds');\n * }\n * }\n *\n * // Job that only runs when popup is visible\n * @EverySeconds(10, { name: 'UiUpdateJob', requiresPopup: true })\n * export class UiUpdateJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Only runs when user is viewing extension');\n * }\n * }\n *\n * // Paused job that must be manually resumed\n * @EverySeconds(2, { startPaused: true, name: 'OnDemandJob' })\n * export class OnDemandJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs when resumed');\n * }\n * }\n * ```\n */\nexport function EverySeconds(seconds: number, options?: EverySecondsOptions) {\n return function (constructor: any) {\n injectable()(constructor);\n // Set explicit name metadata to survive minification\n if (options?.name) {\n Reflect.defineMetadata('name', options.name, constructor);\n }\n\n Reflect.defineMetadata(\n 'job:options',\n {\n delay: seconds * 1000,\n recurring: true,\n startPaused: options?.startPaused ?? false,\n requiresPopup: options?.requiresPopup ?? false,\n },\n constructor,\n );\n return constructor;\n };\n}\n","export abstract class Booteable {\n /**\n * Boot method to be called when the service is initialized.\n * This method can be used to perform any setup or initialization logic.\n */\n abstract boot(): void;\n /**\n * Optional destroy method to be called when the service is being destroyed.\n * This can be used to clean up resources or perform any necessary teardown logic.\n */\n destroy?(): void {\n // Default implementation does nothing\n }\n}\n\nexport function isBooteable(obj: any): obj is Booteable {\n return typeof obj.boot === 'function';\n}\n\nexport function isDestroyable(obj: any): obj is Booteable {\n return typeof obj.destroy === 'function';\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chromahq/core",
3
- "version": "1.0.52",
3
+ "version": "1.0.54",
4
4
  "description": "Core library for building Chrome extensions with Chroma framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",