@asaidimu/utils-sync 1.1.0 → 1.1.1

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/index.d.mts CHANGED
@@ -92,6 +92,15 @@ declare class Once<T = void> {
92
92
  * @param timeout - Max wait time in ms (includes lock wait + execution time).
93
93
  */
94
94
  do(fn: () => Promise<T> | T, timeout?: number): Promise<OnceResult<T>>;
95
+ /**
96
+ * Executes the function synchronously if it hasn't been executed yet.
97
+ * If an async operation is pending or the lock is contended, it will fail immediately.
98
+ * The failure is returned as an error state, OR thrown if `throws: true` is configured.
99
+ *
100
+ * @param fn - The synchronous function to execute.
101
+ * @returns The result of the execution.
102
+ */
103
+ doSync(fn: () => T): OnceResult<T>;
95
104
  /**
96
105
  * Returns true if the operation has completed (success or non-retryable failure)
97
106
  * and is not currently executing.
package/index.d.ts CHANGED
@@ -92,6 +92,15 @@ declare class Once<T = void> {
92
92
  * @param timeout - Max wait time in ms (includes lock wait + execution time).
93
93
  */
94
94
  do(fn: () => Promise<T> | T, timeout?: number): Promise<OnceResult<T>>;
95
+ /**
96
+ * Executes the function synchronously if it hasn't been executed yet.
97
+ * If an async operation is pending or the lock is contended, it will fail immediately.
98
+ * The failure is returned as an error state, OR thrown if `throws: true` is configured.
99
+ *
100
+ * @param fn - The synchronous function to execute.
101
+ * @returns The result of the execution.
102
+ */
103
+ doSync(fn: () => T): OnceResult<T>;
95
104
  /**
96
105
  * Returns true if the operation has completed (success or non-retryable failure)
97
106
  * and is not currently executing.
package/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var t=class t extends Error{constructor(e,r){super(e,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,t.prototype)}},e=class extends t{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`)}},r=class extends t{constructor(t){super("[Serializer] The serializer has been marked as done!",t)}},i=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(t){this._capacity=t?.capacity??1/0,this._yieldMode=t?.yieldMode??"macrotask"}async lock(t){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let r;const i=new Promise((t=>r=t));this.waiters.push(r),null!=t?await Promise.race([i,new Promise(((i,s)=>setTimeout((()=>{const t=this.waiters.indexOf(r);-1!==t&&this.waiters.splice(t,1),s(new e("Mutex lock timed out"))}),t)))]):await i}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const t=this.waiters.shift();t?"microtask"===this._yieldMode?queueMicrotask(t):setTimeout(t,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}};exports.Mutex=i,exports.Once=class{mutex=new i({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:t,throws:e}={}){this.retry=Boolean(t),this.throws=Boolean(e)}async do(t,e){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,e,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")):(this.promise=(async()=>{try{const e=await t();this._value=e,this._done=!0}catch(t){if(this._error=t,this.retry||(this._done=!0),this.throws)throw t}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")))}isReady(){return this._done&&null===this.promise}running(){return null!==this.promise&&!this._done}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){this._done=!1,this.promise=null,this._value=null,this._error=void 0}resolved(){return this.promise}done(){return this._done}_awaitWithTimeout(t,r,i="Operation timed out"){return null==r?t:Promise.race([t,new Promise(((t,s)=>setTimeout((()=>s(new e(i))),r)))])}},exports.Serializer=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;constructor(t){this.mutex=new i({capacity:t?.capacity??1e3,yieldMode:t?.yieldMode??"macrotask"})}async do(t,e){if(this._done)return{value:null,error:new r};try{await this.mutex.lock(e)}catch(t){return{value:null,error:t}}let i,s=null;try{if(this._done)throw new r;s=await t(),this._lastValue=s,this._lastError=void 0}catch(t){i=t,this._lastError=t}finally{this.mutex.unlock()}return{value:s,error:i}}peek(){return{value:this._lastValue,error:this._lastError}}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}};
1
+ "use strict";var t=class t extends Error{constructor(e,r){super(e,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,t.prototype)}},e=class extends t{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`)}},r=class extends t{constructor(t){super("[Serializer] The serializer has been marked as done!",t)}},i=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(t){this._capacity=t?.capacity??1/0,this._yieldMode=t?.yieldMode??"macrotask"}async lock(t){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let r;const i=new Promise((t=>r=t));this.waiters.push(r),null!=t?await Promise.race([i,new Promise(((i,s)=>setTimeout((()=>{const t=this.waiters.indexOf(r);-1!==t&&this.waiters.splice(t,1),s(new e("Mutex lock timed out"))}),t)))]):await i}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const t=this.waiters.shift();t?"microtask"===this._yieldMode?queueMicrotask(t):setTimeout(t,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}};exports.Mutex=i,exports.Once=class{mutex=new i({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:t,throws:e}={}){this.retry=Boolean(t),this.throws=Boolean(e)}async do(t,e){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,e,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")):(this.promise=(async()=>{try{const e=await t();this._value=e,this._done=!0}catch(t){if(this._error=t,this.retry||(this._done=!0),this.throws)throw t}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")))}doSync(t){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const t=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw t;return{value:null,error:t}}if(!this.mutex.tryLock()){const t=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw t;return{value:null,error:t}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const t=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw t;return{value:null,error:t}}try{const e=t();this._value=e,this._done=!0}catch(t){if(this._error=t,this.retry||(this._done=!0),this.throws)throw t}finally{this.mutex.unlock()}return this.peek()}isReady(){return this._done&&null===this.promise}running(){return null!==this.promise&&!this._done}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){this._done=!1,this.promise=null,this._value=null,this._error=void 0}resolved(){return this.promise}done(){return this._done}_awaitWithTimeout(t,r,i="Operation timed out"){return null==r?t:Promise.race([t,new Promise(((t,s)=>setTimeout((()=>s(new e(i))),r)))])}},exports.Serializer=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;constructor(t){this.mutex=new i({capacity:t?.capacity??1e3,yieldMode:t?.yieldMode??"macrotask"})}async do(t,e){if(this._done)return{value:null,error:new r};try{await this.mutex.lock(e)}catch(t){return{value:null,error:t}}let i,s=null;try{if(this._done)throw new r;s=await t(),this._lastValue=s,this._lastError=void 0}catch(t){i=t,this._lastError=t}finally{this.mutex.unlock()}return{value:s,error:i}}peek(){return{value:this._lastValue,error:this._lastError}}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}};
package/index.mjs CHANGED
@@ -1 +1 @@
1
- var t=class t extends Error{constructor(e,r){super(e,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,t.prototype)}},e=class extends t{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`)}},r=class extends t{constructor(t){super("[Serializer] The serializer has been marked as done!",t)}},i=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(t){this._capacity=t?.capacity??1/0,this._yieldMode=t?.yieldMode??"macrotask"}async lock(t){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let r;const i=new Promise((t=>r=t));this.waiters.push(r),null!=t?await Promise.race([i,new Promise(((i,s)=>setTimeout((()=>{const t=this.waiters.indexOf(r);-1!==t&&this.waiters.splice(t,1),s(new e("Mutex lock timed out"))}),t)))]):await i}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const t=this.waiters.shift();t?"microtask"===this._yieldMode?queueMicrotask(t):setTimeout(t,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},s=class{mutex=new i({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:t,throws:e}={}){this.retry=Boolean(t),this.throws=Boolean(e)}async do(t,e){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,e,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")):(this.promise=(async()=>{try{const e=await t();this._value=e,this._done=!0}catch(t){if(this._error=t,this.retry||(this._done=!0),this.throws)throw t}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")))}isReady(){return this._done&&null===this.promise}running(){return null!==this.promise&&!this._done}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){this._done=!1,this.promise=null,this._value=null,this._error=void 0}resolved(){return this.promise}done(){return this._done}_awaitWithTimeout(t,r,i="Operation timed out"){return null==r?t:Promise.race([t,new Promise(((t,s)=>setTimeout((()=>s(new e(i))),r)))])}},o=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;constructor(t){this.mutex=new i({capacity:t?.capacity??1e3,yieldMode:t?.yieldMode??"macrotask"})}async do(t,e){if(this._done)return{value:null,error:new r};try{await this.mutex.lock(e)}catch(t){return{value:null,error:t}}let i,s=null;try{if(this._done)throw new r;s=await t(),this._lastValue=s,this._lastError=void 0}catch(t){i=t,this._lastError=t}finally{this.mutex.unlock()}return{value:s,error:i}}peek(){return{value:this._lastValue,error:this._lastError}}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}};export{i as Mutex,s as Once,o as Serializer};
1
+ var t=class t extends Error{constructor(e,r){super(e,{cause:r}),this.name="SyncError",Object.setPrototypeOf(this,t.prototype)}},e=class extends t{constructor(t){super(`[ArtifactContainer] Operation timed out: ${t}`)}},r=class extends t{constructor(t){super("[Serializer] The serializer has been marked as done!",t)}},i=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(t){this._capacity=t?.capacity??1/0,this._yieldMode=t?.yieldMode??"macrotask"}async lock(t){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let r;const i=new Promise((t=>r=t));this.waiters.push(r),null!=t?await Promise.race([i,new Promise(((i,s)=>setTimeout((()=>{const t=this.waiters.indexOf(r);-1!==t&&this.waiters.splice(t,1),s(new e("Mutex lock timed out"))}),t)))]):await i}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const t=this.waiters.shift();t?"microtask"===this._yieldMode?queueMicrotask(t):setTimeout(t,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},s=class{mutex=new i({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:t,throws:e}={}){this.retry=Boolean(t),this.throws=Boolean(e)}async do(t,e){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,e,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")):(this.promise=(async()=>{try{const e=await t();this._value=e,this._done=!0}catch(t){if(this._error=t,this.retry||(this._done=!0),this.throws)throw t}finally{this.promise=null}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,e,"Once do() timed out")))}doSync(t){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const t=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw t;return{value:null,error:t}}if(!this.mutex.tryLock()){const t=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw t;return{value:null,error:t}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const t=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw t;return{value:null,error:t}}try{const e=t();this._value=e,this._done=!0}catch(t){if(this._error=t,this.retry||(this._done=!0),this.throws)throw t}finally{this.mutex.unlock()}return this.peek()}isReady(){return this._done&&null===this.promise}running(){return null!==this.promise&&!this._done}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){this._done=!1,this.promise=null,this._value=null,this._error=void 0}resolved(){return this.promise}done(){return this._done}_awaitWithTimeout(t,r,i="Operation timed out"){return null==r?t:Promise.race([t,new Promise(((t,s)=>setTimeout((()=>s(new e(i))),r)))])}},o=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;constructor(t){this.mutex=new i({capacity:t?.capacity??1e3,yieldMode:t?.yieldMode??"macrotask"})}async do(t,e){if(this._done)return{value:null,error:new r};try{await this.mutex.lock(e)}catch(t){return{value:null,error:t}}let i,s=null;try{if(this._done)throw new r;s=await t(),this._lastValue=s,this._lastError=void 0}catch(t){i=t,this._lastError=t}finally{this.mutex.unlock()}return{value:s,error:i}}peek(){return{value:this._lastValue,error:this._lastError}}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}};export{i as Mutex,s as Once,o as Serializer};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-sync",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "A collection of sync utilities.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",