@chromahq/core 1.0.45 → 1.0.47
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-PA1aK9w-.js → boot-CgF0JVQl.js} +403 -18
- package/dist/boot-CgF0JVQl.js.map +1 -0
- package/dist/{boot-PbJQqgzX.js → boot-uR3rw2A8.js} +398 -19
- package/dist/boot-uR3rw2A8.js.map +1 -0
- package/dist/boot.cjs.js +4 -1
- package/dist/boot.cjs.js.map +1 -1
- package/dist/boot.d.ts +56 -1
- package/dist/boot.es.js +1 -1
- package/dist/index.cjs.js +7 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +219 -2
- package/dist/index.es.js +1 -1
- package/package.json +1 -1
- package/dist/boot-PA1aK9w-.js.map +0 -1
- package/dist/boot-PbJQqgzX.js.map +0 -1
package/dist/index.cjs.js.map
CHANGED
|
@@ -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 * 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 *\n * @example\n * ```typescript\n * @EverySeconds(5)\n * export class MyJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs every 5 seconds');\n * }\n * }\n * ```\n */\nexport function EverySeconds(seconds: number) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata(\n 'job:options',\n {\n delay: seconds * 1000,\n recurring: true,\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;;ACWO,SAAS,aAAa,OAAA,EAAiB;AAC5C,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAAA,eAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA;AAAA,MACN,aAAA;AAAA,MACA;AAAA,QACE,OAAO,OAAA,GAAU,GAAA;AAAA,QACjB,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;AChCO,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\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 * 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 *\n * @example\n * ```typescript\n * @EverySeconds(5)\n * export class MyJob implements IJob {\n * async handle(context: JobContext) {\n * console.log('Runs every 5 seconds');\n * }\n * }\n * ```\n */\nexport function EverySeconds(seconds: number) {\n return function (constructor: any) {\n injectable()(constructor);\n Reflect.defineMetadata(\n 'job:options',\n {\n delay: seconds * 1000,\n recurring: true,\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;;ACWO,SAAS,aAAa,OAAA,EAAiB;AAC5C,EAAA,OAAO,SAAU,WAAA,EAAkB;AACjC,IAAAA,eAAA,GAAa,WAAW,CAAA;AACxB,IAAA,OAAA,CAAQ,cAAA;AAAA,MACN,aAAA;AAAA,MACA;AAAA,QACE,OAAO,OAAA,GAAU,GAAA;AAAA,QACjB,SAAA,EAAW;AAAA,OACb;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,WAAA;AAAA,GACT;AACF;;AChCO,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;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -115,6 +115,223 @@ declare abstract class Booteable {
|
|
|
115
115
|
declare function isBooteable(obj: any): obj is Booteable;
|
|
116
116
|
declare function isDestroyable(obj: any): obj is Booteable;
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* @fileoverview NonceService - Idempotency service for critical operations.
|
|
120
|
+
*
|
|
121
|
+
* Ensures that critical operations (transfers, signing, staking, etc.) are not
|
|
122
|
+
* executed multiple times if the same request is retried. Uses nonces to track
|
|
123
|
+
* operation state and caches results for duplicate detection.
|
|
124
|
+
*
|
|
125
|
+
* Key features:
|
|
126
|
+
* - Nonce-based idempotency for critical operations
|
|
127
|
+
* - Automatic TTL expiration for nonce entries
|
|
128
|
+
* - Persistence to chrome.storage.local for SW restart recovery
|
|
129
|
+
* - Memory limits to prevent unbounded growth
|
|
130
|
+
* - Status tracking: pending → completed/failed
|
|
131
|
+
*
|
|
132
|
+
* @module @chromahq/core/services/NonceService
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // In a message handler
|
|
137
|
+
* @Message('transfer')
|
|
138
|
+
* class TransferHandler {
|
|
139
|
+
* constructor(@Use(NonceService) private nonceService: NonceService) {}
|
|
140
|
+
*
|
|
141
|
+
* async handle(payload: CriticalPayload) {
|
|
142
|
+
* // Check for duplicate (returns cached result if exists)
|
|
143
|
+
* const cached = await this.nonceService.checkNonce(payload.__nonce__);
|
|
144
|
+
* if (cached.exists) return cached.result;
|
|
145
|
+
*
|
|
146
|
+
* // Mark as pending to prevent duplicate processing
|
|
147
|
+
* await this.nonceService.markPending(payload.__nonce__, payload.__timestamp__);
|
|
148
|
+
*
|
|
149
|
+
* try {
|
|
150
|
+
* const result = await this.doTransfer(payload.data);
|
|
151
|
+
* await this.nonceService.storeResult(payload.__nonce__, result);
|
|
152
|
+
* return result;
|
|
153
|
+
* } catch (error) {
|
|
154
|
+
* await this.nonceService.storeError(payload.__nonce__, error.message);
|
|
155
|
+
* throw error;
|
|
156
|
+
* }
|
|
157
|
+
* }
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
/**
|
|
162
|
+
* Payload wrapper for critical operations.
|
|
163
|
+
* Sent by BridgeProvider.sendCritical/sendWithNonce methods.
|
|
164
|
+
*
|
|
165
|
+
* @template T - The type of the wrapped data payload
|
|
166
|
+
*/
|
|
167
|
+
interface CriticalPayload<T = unknown> {
|
|
168
|
+
/** Marker indicating this is a critical operation */
|
|
169
|
+
__critical__: true;
|
|
170
|
+
/** Unique nonce for idempotency tracking */
|
|
171
|
+
__nonce__: string;
|
|
172
|
+
/** Unix timestamp when the request was created */
|
|
173
|
+
__timestamp__: number;
|
|
174
|
+
/** The actual operation payload */
|
|
175
|
+
data: T;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Result returned by checkNonce.
|
|
179
|
+
* Contains cached operation state if the nonce was previously processed.
|
|
180
|
+
*/
|
|
181
|
+
interface NonceCheckResult {
|
|
182
|
+
/** Whether this nonce has been seen before */
|
|
183
|
+
exists: boolean;
|
|
184
|
+
/** Status of the operation (if exists) */
|
|
185
|
+
status?: 'pending' | 'completed' | 'failed';
|
|
186
|
+
/** Cached result (if completed) */
|
|
187
|
+
result?: unknown;
|
|
188
|
+
/** Error message (if failed) */
|
|
189
|
+
error?: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Service for tracking nonces to ensure idempotent critical operations.
|
|
193
|
+
*
|
|
194
|
+
* Maintains an in-memory map of nonces with persistence to chrome.storage.local
|
|
195
|
+
* for recovery after service worker restarts.
|
|
196
|
+
*/
|
|
197
|
+
declare class NonceService {
|
|
198
|
+
/** In-memory nonce store */
|
|
199
|
+
private readonly nonceStore;
|
|
200
|
+
/** Default TTL for completed/failed entries (24 hours) */
|
|
201
|
+
private readonly DEFAULT_TTL_MS;
|
|
202
|
+
/** TTL for pending entries (5 minutes) */
|
|
203
|
+
private readonly PENDING_TTL_MS;
|
|
204
|
+
/** Maximum entries to prevent unbounded growth */
|
|
205
|
+
private readonly MAX_ENTRIES;
|
|
206
|
+
/** Interval handle for periodic cleanup */
|
|
207
|
+
private cleanupInterval;
|
|
208
|
+
/** Whether store has been loaded from persistence */
|
|
209
|
+
private loaded;
|
|
210
|
+
/** Promise for initial load operation */
|
|
211
|
+
private loadPromise;
|
|
212
|
+
/** Debounce timer for persistence */
|
|
213
|
+
private persistTimer;
|
|
214
|
+
/** In-flight persistence promise */
|
|
215
|
+
private persistInFlight;
|
|
216
|
+
constructor();
|
|
217
|
+
/**
|
|
218
|
+
* Ensure nonce store has been loaded from storage.
|
|
219
|
+
* Safe to call multiple times.
|
|
220
|
+
*/
|
|
221
|
+
ensureLoaded(): Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* Check if a nonce has already been processed
|
|
224
|
+
* @returns NonceCheckResult with cached data if exists
|
|
225
|
+
*/
|
|
226
|
+
checkNonce(nonce: string): Promise<NonceCheckResult>;
|
|
227
|
+
/**
|
|
228
|
+
* Mark a nonce as pending (operation started but not completed)
|
|
229
|
+
* This prevents duplicate submissions while operation is in progress
|
|
230
|
+
*/
|
|
231
|
+
markPending(nonce: string, timestamp: number): Promise<void>;
|
|
232
|
+
/**
|
|
233
|
+
* Store the result of a completed operation
|
|
234
|
+
*/
|
|
235
|
+
storeResult(nonce: string, result: unknown, ttlMs?: number): Promise<void>;
|
|
236
|
+
/**
|
|
237
|
+
* Store an error result (operation failed)
|
|
238
|
+
* We store failures too so retries get the same error
|
|
239
|
+
*/
|
|
240
|
+
storeError(nonce: string, error: string, ttlMs?: number): Promise<void>;
|
|
241
|
+
/**
|
|
242
|
+
* Remove a nonce (e.g., if operation was cancelled before starting)
|
|
243
|
+
*/
|
|
244
|
+
removeNonce(nonce: string): Promise<void>;
|
|
245
|
+
/**
|
|
246
|
+
* Check if a payload is a critical operation
|
|
247
|
+
*/
|
|
248
|
+
isCriticalPayload(payload: unknown): payload is CriticalPayload;
|
|
249
|
+
/**
|
|
250
|
+
* Get statistics about the nonce store (for debugging)
|
|
251
|
+
*/
|
|
252
|
+
getStats(): {
|
|
253
|
+
total: number;
|
|
254
|
+
pending: number;
|
|
255
|
+
completed: number;
|
|
256
|
+
failed: number;
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Start periodic cleanup of expired nonces
|
|
260
|
+
*/
|
|
261
|
+
private startCleanup;
|
|
262
|
+
/**
|
|
263
|
+
* Remove expired nonces
|
|
264
|
+
*/
|
|
265
|
+
private cleanup;
|
|
266
|
+
/**
|
|
267
|
+
* Destroy the service (stop cleanup interval)
|
|
268
|
+
*/
|
|
269
|
+
destroy(): void;
|
|
270
|
+
private enforceLimits;
|
|
271
|
+
private schedulePersist;
|
|
272
|
+
private persist;
|
|
273
|
+
}
|
|
274
|
+
declare function getNonceService(): NonceService;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* @fileoverview Early Connection Listener for Chrome Extension Service Workers.
|
|
278
|
+
*
|
|
279
|
+
* This module captures port connections as early as possible during service worker
|
|
280
|
+
* bootstrap, before the full BridgeRuntime is initialized. This prevents lost
|
|
281
|
+
* connections when the popup opens before the SW has finished bootstrapping.
|
|
282
|
+
*
|
|
283
|
+
* Usage:
|
|
284
|
+
* 1. Import and call `setupEarlyListener()` at the very top of your SW entry point
|
|
285
|
+
* 2. Call `getEarlyPorts()` when BridgeRuntime initializes to wire up captured ports
|
|
286
|
+
*
|
|
287
|
+
* @module @chromahq/core/runtime/EarlyListener
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* Sets up an early connection listener to capture ports before BridgeRuntime is ready.
|
|
291
|
+
*
|
|
292
|
+
* Call this at the very top of your service worker entry point, before any async work.
|
|
293
|
+
* This ensures connections aren't lost during bootstrap.
|
|
294
|
+
*
|
|
295
|
+
* @param portName - The port name to listen for (defaults to 'chroma-bridge')
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```typescript
|
|
299
|
+
* // At the top of your service worker (before any await):
|
|
300
|
+
* import { setupEarlyListener } from '@chromahq/core';
|
|
301
|
+
*
|
|
302
|
+
* setupEarlyListener('chroma-bridge');
|
|
303
|
+
*
|
|
304
|
+
* // Later, during bootstrap:
|
|
305
|
+
* const runtime = bootstrap({ ... });
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
declare function setupEarlyListener(portName?: string): void;
|
|
309
|
+
/**
|
|
310
|
+
* Gets all ports captured before BridgeRuntime was ready.
|
|
311
|
+
*
|
|
312
|
+
* Call this once when BridgeRuntime initializes. After calling, new connections
|
|
313
|
+
* will go directly to the provided callback.
|
|
314
|
+
*
|
|
315
|
+
* @param onConnect - Callback to invoke for future port connections
|
|
316
|
+
* @returns Array of ports captured during bootstrap
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* // In BridgeRuntime.initialize():
|
|
321
|
+
* const earlyPorts = claimEarlyPorts((port) => this.setupMessageHandler(port));
|
|
322
|
+
* earlyPorts.forEach((port) => this.setupMessageHandler(port));
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
declare function claimEarlyPorts(onConnect: (port: chrome.runtime.Port) => void): chrome.runtime.Port[];
|
|
326
|
+
/**
|
|
327
|
+
* Check if the early listener has been set up.
|
|
328
|
+
*/
|
|
329
|
+
declare function isEarlyListenerSetup(): boolean;
|
|
330
|
+
/**
|
|
331
|
+
* Check if early ports have been claimed by BridgeRuntime.
|
|
332
|
+
*/
|
|
333
|
+
declare function arePortsClaimed(): boolean;
|
|
334
|
+
|
|
118
335
|
declare const container: Container;
|
|
119
336
|
|
|
120
337
|
declare function create({ keepPortAlive, portName, enableLogs, disableBootMethods, }?: {
|
|
@@ -145,5 +362,5 @@ declare class BootstrapBuilder {
|
|
|
145
362
|
}): Promise<void>;
|
|
146
363
|
}
|
|
147
364
|
|
|
148
|
-
export { Booteable, Delay, Every, EverySeconds, IMessage, Job, JobState, Message, Service, Store, Use, bootstrap, container, create, isBooteable, isDestroyable };
|
|
149
|
-
export type { IJob, JobContext };
|
|
365
|
+
export { Booteable, Delay, Every, EverySeconds, IMessage, Job, JobState, Message, NonceService, Service, Store, Use, arePortsClaimed, bootstrap, claimEarlyPorts, container, create, getNonceService, isBooteable, isDestroyable, isEarlyListenerSetup, setupEarlyListener };
|
|
366
|
+
export type { CriticalPayload, 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 JobState,
|
|
2
|
+
export { J as JobState, N as NonceService, 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-uR3rw2A8.js';
|
|
3
3
|
import '@inversifyjs/container';
|
|
4
4
|
|
|
5
5
|
function Service() {
|