@tstdl/base 0.93.139 → 0.93.140

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.
Files changed (133) hide show
  1. package/README.md +166 -0
  2. package/ai/genkit/multi-region.plugin.js +5 -3
  3. package/ai/genkit/tests/multi-region.test.d.ts +1 -0
  4. package/ai/genkit/tests/multi-region.test.js +5 -2
  5. package/ai/parser/parser.js +2 -2
  6. package/ai/prompts/build.js +1 -0
  7. package/ai/prompts/instructions-formatter.d.ts +15 -2
  8. package/ai/prompts/instructions-formatter.js +36 -31
  9. package/ai/prompts/prompt-builder.js +5 -5
  10. package/ai/prompts/steering.d.ts +3 -2
  11. package/ai/prompts/steering.js +3 -1
  12. package/ai/tests/instructions-formatter.test.js +1 -0
  13. package/api/README.md +403 -0
  14. package/api/client/client.js +7 -13
  15. package/api/client/tests/api-client.test.js +10 -10
  16. package/api/default-error-handlers.js +1 -1
  17. package/api/response.d.ts +2 -2
  18. package/api/response.js +22 -33
  19. package/api/server/api-controller.d.ts +1 -1
  20. package/api/server/api-controller.js +3 -3
  21. package/api/server/api-request-token.provider.d.ts +1 -0
  22. package/api/server/api-request-token.provider.js +1 -0
  23. package/api/server/middlewares/allowed-methods.middleware.js +2 -1
  24. package/api/server/middlewares/content-type.middleware.js +2 -1
  25. package/api/types.d.ts +3 -2
  26. package/application/README.md +240 -0
  27. package/application/application.js +2 -2
  28. package/audit/README.md +267 -0
  29. package/authentication/README.md +288 -0
  30. package/authentication/client/authentication.service.d.ts +12 -11
  31. package/authentication/client/authentication.service.js +21 -21
  32. package/authentication/client/http-client.middleware.js +2 -2
  33. package/authentication/tests/authentication.client-error-handling.test.js +2 -1
  34. package/authentication/tests/authentication.client-service-refresh.test.js +5 -3
  35. package/browser/README.md +401 -0
  36. package/cancellation/README.md +156 -0
  37. package/cancellation/tests/coverage.test.d.ts +1 -0
  38. package/cancellation/tests/coverage.test.js +49 -0
  39. package/cancellation/tests/leak.test.js +24 -29
  40. package/cancellation/tests/token.test.d.ts +1 -0
  41. package/cancellation/tests/token.test.js +136 -0
  42. package/cancellation/token.d.ts +53 -177
  43. package/cancellation/token.js +132 -208
  44. package/context/README.md +174 -0
  45. package/cookie/README.md +161 -0
  46. package/css/README.md +157 -0
  47. package/data-structures/README.md +320 -0
  48. package/decorators/README.md +140 -0
  49. package/distributed-loop/README.md +231 -0
  50. package/distributed-loop/distributed-loop.js +1 -1
  51. package/document-management/README.md +403 -0
  52. package/document-management/server/services/document-management.service.js +9 -7
  53. package/document-management/tests/document-management-core.test.js +2 -7
  54. package/document-management/tests/document-management.api.test.js +6 -7
  55. package/document-management/tests/document-statistics.service.test.js +11 -12
  56. package/document-management/tests/document.service.test.js +3 -3
  57. package/document-management/tests/enum-helpers.test.js +2 -3
  58. package/dom/README.md +213 -0
  59. package/enumerable/README.md +259 -0
  60. package/enumeration/README.md +121 -0
  61. package/errors/README.md +267 -0
  62. package/file/README.md +191 -0
  63. package/formats/README.md +210 -0
  64. package/function/README.md +144 -0
  65. package/http/README.md +318 -0
  66. package/http/client/adapters/undici.adapter.js +1 -1
  67. package/http/client/http-client-request.d.ts +6 -5
  68. package/http/client/http-client-request.js +8 -9
  69. package/http/server/node/node-http-server.js +1 -2
  70. package/image-service/README.md +137 -0
  71. package/injector/README.md +491 -0
  72. package/intl/README.md +113 -0
  73. package/json-path/README.md +182 -0
  74. package/jsx/README.md +154 -0
  75. package/key-value-store/README.md +191 -0
  76. package/lock/README.md +249 -0
  77. package/lock/web/web-lock.js +119 -47
  78. package/logger/README.md +287 -0
  79. package/mail/README.md +256 -0
  80. package/memory/README.md +144 -0
  81. package/message-bus/README.md +244 -0
  82. package/message-bus/message-bus-base.js +1 -1
  83. package/module/README.md +182 -0
  84. package/module/module.d.ts +1 -1
  85. package/module/module.js +77 -17
  86. package/module/modules/web-server.module.js +1 -1
  87. package/notification/tests/notification-type.service.test.js +24 -15
  88. package/object-storage/README.md +300 -0
  89. package/openid-connect/README.md +274 -0
  90. package/orm/README.md +423 -0
  91. package/package.json +8 -6
  92. package/password/README.md +164 -0
  93. package/pdf/README.md +246 -0
  94. package/polyfills.js +1 -0
  95. package/pool/README.md +198 -0
  96. package/process/README.md +237 -0
  97. package/promise/README.md +252 -0
  98. package/promise/cancelable-promise.js +1 -1
  99. package/random/README.md +193 -0
  100. package/reflection/README.md +305 -0
  101. package/rpc/README.md +386 -0
  102. package/rxjs-utils/README.md +262 -0
  103. package/schema/README.md +342 -0
  104. package/serializer/README.md +342 -0
  105. package/signals/implementation/README.md +134 -0
  106. package/sse/README.md +278 -0
  107. package/task-queue/README.md +300 -0
  108. package/task-queue/postgres/task-queue.d.ts +2 -1
  109. package/task-queue/postgres/task-queue.js +32 -2
  110. package/task-queue/task-context.js +1 -1
  111. package/task-queue/task-queue.d.ts +17 -0
  112. package/task-queue/task-queue.js +103 -45
  113. package/task-queue/tests/complex.test.js +4 -4
  114. package/task-queue/tests/dependencies.test.js +4 -2
  115. package/task-queue/tests/queue.test.js +111 -0
  116. package/task-queue/tests/worker.test.js +21 -13
  117. package/templates/README.md +287 -0
  118. package/testing/README.md +157 -0
  119. package/text/README.md +346 -0
  120. package/threading/README.md +238 -0
  121. package/types/README.md +311 -0
  122. package/utils/README.md +322 -0
  123. package/utils/async-iterable-helpers/observable-iterable.d.ts +1 -1
  124. package/utils/async-iterable-helpers/observable-iterable.js +4 -8
  125. package/utils/async-iterable-helpers/take-until.js +4 -4
  126. package/utils/backoff.js +89 -30
  127. package/utils/retry-with-backoff.js +1 -1
  128. package/utils/timer.d.ts +1 -1
  129. package/utils/timer.js +5 -7
  130. package/utils/timing.d.ts +1 -1
  131. package/utils/timing.js +2 -4
  132. package/utils/z-base32.d.ts +1 -0
  133. package/utils/z-base32.js +1 -0
package/lock/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # Lock Module
2
+
3
+ A robust, provider-based resource locking mechanism designed to prevent race conditions in both distributed server-side environments and client-side browser contexts.
4
+
5
+ ## Table of Contents
6
+
7
+ - [✨ Features](#-features)
8
+ - [Core Concepts](#core-concepts)
9
+ - [Lock](#lock)
10
+ - [LockProvider](#lockprovider)
11
+ - [Backends](#backends)
12
+ - [🚀 Basic Usage](#-basic-usage)
13
+ - [🔧 Advanced Topics](#-advanced-topics)
14
+ - [Manual Acquisition](#manual-acquisition)
15
+ - [Non-Throwing Attempts](#non-throwing-attempts)
16
+ - [Scoped Providers (Prefixing)](#scoped-providers-prefixing)
17
+ - [Checking Lock Existence](#checking-lock-existence)
18
+ - [PostgreSQL Backend Configuration](#postgresql-backend-configuration)
19
+ - [Web Locks Backend Configuration](#web-locks-backend-configuration)
20
+ - [📚 API](#-api)
21
+
22
+ ## ✨ Features
23
+
24
+ - **Pluggable Backends**: Seamlessly switch between distributed server-side locking (PostgreSQL) and client-side locking (Web Locks API).
25
+ - **Automatic Renewal**: The PostgreSQL backend automatically renews locks (heartbeat) to prevent expiration during long-running tasks while ensuring deadlocks are cleared if a process crashes.
26
+ - **Safe Execution**: The `use` pattern guarantees locks are released even if the critical section throws an error.
27
+ - **Timeout Support**: Configurable timeouts for acquiring locks.
28
+ - **Scoped Providers**: Easily namespace locks using prefixes to prevent collisions between different modules.
29
+ - **Cancellation Support**: Integrated with `@tstdl/base/cancellation` for aborting lock acquisition.
30
+
31
+ ## Core Concepts
32
+
33
+ ### Lock
34
+
35
+ A `Lock` instance represents a mutual exclusion lock for a specific resource string. It provides methods to acquire the lock, execute code within the lock, and release it. Many methods support a `timeout` parameter:
36
+ - `undefined` or `<= 0`: Tries to acquire the lock once and returns/throws immediately if unsuccessful.
37
+ - `> 0`: Retries to acquire the lock for the specified duration in milliseconds.
38
+ - `Infinity`: Retries indefinitely until the lock is acquired or the operation is canceled.
39
+
40
+ ### LockProvider
41
+
42
+ The `LockProvider` is an injectable factory service. It creates `Lock` instances for specific resources. It is the primary entry point for consuming the module in your services.
43
+
44
+ ### Backends
45
+
46
+ 1. **PostgresLock**: Designed for distributed backend systems. It uses a database table to coordinate locks between multiple server instances. It features an automatic "heartbeat" mechanism to keep the lock alive while the process is running.
47
+ 2. **WebLock**: Designed for browser environments. It wraps the native [Web Locks API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API), allowing coordination between tabs, windows, and workers on the same origin.
48
+
49
+ ## 🚀 Basic Usage
50
+
51
+ The recommended way to use a lock is via the `use` method. It handles acquisition, error propagation, and ensures the lock is released automatically.
52
+
53
+ ```typescript
54
+ import { inject } from '@tstdl/base/injector';
55
+ import { LockProvider } from '@tstdl/base/lock';
56
+
57
+ export class UserService {
58
+ readonly #lockProvider = inject(LockProvider);
59
+
60
+ async updateUserBalance(userId: string, amount: number): Promise<void> {
61
+ const lock = this.#lockProvider.get(`user-balance:${userId}`);
62
+
63
+ // Try to acquire the lock for up to 5000ms.
64
+ // If acquired, runs the function and automatically releases the lock afterwards.
65
+ // If timeout is reached, it throws an Error.
66
+ await lock.use(5000, async (controller) => {
67
+ // Critical section: only one process can be here for this resource string
68
+
69
+ // Optional: Check if lock was lost (e.g. network partition or renewal failure)
70
+ if (controller.lost) {
71
+ throw new Error('Lock lost during operation');
72
+ }
73
+
74
+ console.log(`Updating balance for ${userId}...`);
75
+ // await database.update(...)
76
+ });
77
+ }
78
+ }
79
+ ```
80
+
81
+ ## 🔧 Advanced Topics
82
+
83
+ ### Dependency Injection
84
+
85
+ You can inject `LockProvider` or even specific `Lock` instances directly using the `inject` function or decorators.
86
+
87
+ ```typescript
88
+ import { inject } from '@tstdl/base/injector';
89
+ import { Lock, LockProvider } from '@tstdl/base/lock';
90
+
91
+ // 1. Injecting a prefixed provider
92
+ const billingLocks = inject(LockProvider, 'billing');
93
+ const lock1 = billingLocks.get('user:123'); // resource: "billing:user:123"
94
+
95
+ // 2. Injecting a specific lock directly
96
+ const userLock = inject(Lock, 'user:123');
97
+ const prefixedUserLock = inject(Lock, { prefix: 'billing', resource: 'user:123' });
98
+ ```
99
+
100
+ ### Manual Acquisition
101
+
102
+ For scenarios where the `use` block structure doesn't fit (e.g., lock spans across multiple function calls), you can manually acquire and release the lock.
103
+
104
+ ```typescript
105
+ import { inject } from '@tstdl/base/injector';
106
+ import { LockProvider } from '@tstdl/base/lock';
107
+
108
+ class JobProcessor {
109
+ readonly #lockProvider = inject(LockProvider);
110
+
111
+ async processJob(jobId: string) {
112
+ const lock = this.#lockProvider.get(`job:${jobId}`);
113
+
114
+ // Acquire lock, waiting for up to 10 seconds.
115
+ // Throws if acquisition fails within the timeout.
116
+ const controller = await lock.acquire(10000);
117
+
118
+ try {
119
+ console.log('Lock acquired');
120
+ // Do work...
121
+ } finally {
122
+ // Always release in finally block
123
+ await controller.release();
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ### Non-Throwing Attempts
130
+
131
+ If you want to attempt to acquire a lock but simply return `false` or a failure result instead of throwing an error upon timeout/failure, use `tryAcquire` or `tryUse`.
132
+
133
+ ```typescript
134
+ const lock = lockProvider.get('daily-report');
135
+
136
+ // Try to acquire for 100ms
137
+ const result = await lock.tryUse(100, async () => {
138
+ return 'Report Generated';
139
+ });
140
+
141
+ if (result.success) {
142
+ console.log(result.result);
143
+ } else {
144
+ console.log('Could not acquire lock, skipping report generation.');
145
+ }
146
+ ```
147
+
148
+ ### Scoped Providers (Prefixing)
149
+
150
+ To avoid naming collisions between different parts of your application (e.g., "user:123" in the billing module vs "user:123" in the notification module), use `prefix()`.
151
+
152
+ ```typescript
153
+ import { inject } from '@tstdl/base/injector';
154
+ import { LockProvider } from '@tstdl/base/lock';
155
+
156
+ const rootProvider = inject(LockProvider);
157
+
158
+ // Creates a provider that prefixes all keys with "billing:"
159
+ const billingLocks = rootProvider.prefix('billing');
160
+ const lock1 = billingLocks.get('user:123'); // Actual resource: "billing:user:123"
161
+
162
+ // Creates a provider that prefixes all keys with "notifications:"
163
+ const notificationLocks = rootProvider.prefix('notifications');
164
+ const lock2 = notificationLocks.get('user:123'); // Actual resource: "notifications:user:123"
165
+ ```
166
+
167
+ ### Checking Lock Existence
168
+
169
+ You can check if a resource is currently locked without trying to acquire it.
170
+
171
+ ```typescript
172
+ const lock = lockProvider.get('maintenance-mode');
173
+
174
+ if (await lock.exists()) {
175
+ console.log('System is currently in maintenance mode (locked).');
176
+ }
177
+ ```
178
+
179
+ ### PostgreSQL Backend Configuration
180
+
181
+ To use the PostgreSQL backend, ensure the ORM module is configured, then configure the lock module in your application bootstrap.
182
+
183
+ ```typescript
184
+ import { configurePostgresLock, migratePostgresLockSchema } from '@tstdl/base/lock/postgres';
185
+ import { configureOrm } from '@tstdl/base/orm/server';
186
+ import { runInInjectionContext, inject, Injector } from '@tstdl/base/injector';
187
+
188
+ async function bootstrap() {
189
+ // 1. Configure ORM
190
+ configureOrm({
191
+ /* ... default connection details ... */
192
+ });
193
+
194
+ // 2. Configure Lock Module.
195
+ // Optionally provide a different database configuration for locks.
196
+ configurePostgresLock({
197
+ // database: { connection: { ... } }
198
+ });
199
+
200
+ // 3. Run Migrations (creates the 'lock' schema and table)
201
+ const injector = inject(Injector);
202
+ await runInInjectionContext(injector, migratePostgresLockSchema);
203
+ }
204
+ ```
205
+
206
+ ### Web Locks Backend Configuration
207
+
208
+ For browser environments, use the Web Lock configuration.
209
+
210
+ ```typescript
211
+ import { configureWebLock } from '@tstdl/base/lock/web';
212
+
213
+ function bootstrap() {
214
+ configureWebLock();
215
+ }
216
+ ```
217
+
218
+ ## 📚 API
219
+
220
+ ### `LockProvider`
221
+
222
+ | Method | Signature | Description |
223
+ | :------- | :------------------------------------- | :-------------------------------------------------------------------------- |
224
+ | `get` | `get(resource: string): Lock` | Creates a `Lock` instance for the specified resource. |
225
+ | `prefix` | `prefix(prefix: string): LockProvider` | Returns a new `LockProvider` that automatically prefixes all resource keys. |
226
+
227
+ ### `Lock`
228
+
229
+ | Method | Signature | Description |
230
+ | :----------- | :----------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------ |
231
+ | `acquire` | `acquire(timeout?: number): Promise<LockController>` | Acquires the lock. Throws if the lock cannot be acquired within the timeout. |
232
+ | `tryAcquire` | `tryAcquire(timeout?: number): Promise<LockController \| false>` | Tries to acquire the lock. Returns `false` if it fails/times out. |
233
+ | `use` | `use<R>(timeout: number \| undefined, func: LockedFunction<R>): Promise<R>` | Acquires lock, runs function, releases lock. Throws on acquisition failure. |
234
+ | `tryUse` | `tryUse<R>(timeout: number \| undefined, func: LockedFunction<R>): Promise<LockTryUseResult<R>>` | Tries to acquire lock and run function. Returns a result object indicating success/failure. |
235
+ | `exists` | `exists(): Promise<boolean>` | Checks if the lock is currently held by any process. |
236
+
237
+ ### `LockController`
238
+
239
+ | Property/Method | Type | Description |
240
+ | :-------------- | :-------------------- | :----------------------------------------------------------------------------------- |
241
+ | `lost` | `boolean` | Indicates if the lock has been lost (e.g., due to failed renewal or network issues). |
242
+ | `release` | `() => Promise<void>` | Manually releases the lock. |
243
+
244
+ ### `LockTryUseResult<R>`
245
+
246
+ | Property | Type | Description |
247
+ | :-------- | :--------------- | :------------------------------------------------------- |
248
+ | `success` | `boolean` | `true` if lock was acquired and function executed. |
249
+ | `result` | `R \| undefined` | The return value of the function (if `success` is true). |
@@ -4,6 +4,58 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
8
+ if (value !== null && value !== void 0) {
9
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
10
+ var dispose, inner;
11
+ if (async) {
12
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
13
+ dispose = value[Symbol.asyncDispose];
14
+ }
15
+ if (dispose === void 0) {
16
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
17
+ dispose = value[Symbol.dispose];
18
+ if (async) inner = dispose;
19
+ }
20
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
21
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
22
+ env.stack.push({ value: value, dispose: dispose, async: async });
23
+ }
24
+ else if (async) {
25
+ env.stack.push({ async: true });
26
+ }
27
+ return value;
28
+ };
29
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
30
+ return function (env) {
31
+ function fail(e) {
32
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
33
+ env.hasError = true;
34
+ }
35
+ var r, s = 0;
36
+ function next() {
37
+ while (r = env.stack.pop()) {
38
+ try {
39
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
40
+ if (r.dispose) {
41
+ var result = r.dispose.call(r.value);
42
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
43
+ }
44
+ else s |= 1;
45
+ }
46
+ catch (e) {
47
+ fail(e);
48
+ }
49
+ }
50
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
51
+ if (env.hasError) throw env.error;
52
+ }
53
+ return next();
54
+ };
55
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
56
+ var e = new Error(message);
57
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
58
+ });
7
59
  import { Injectable } from '../../injector/index.js';
8
60
  import { DeferredPromise } from '../../promise/deferred-promise.js';
9
61
  import { assertStringPass, isNull, isObject, isUndefined } from '../../utils/type-guards.js';
@@ -14,58 +66,78 @@ let WebLock = class WebLock extends Lock {
14
66
  return await this.tryAcquire(0);
15
67
  }
16
68
  async tryAcquire(timeout) {
17
- const controllerPromise = new DeferredPromise();
18
- const releasePromise = new DeferredPromise();
19
- const ifAvailable = isUndefined(timeout) || (timeout <= 0);
20
- const signal = ifAvailable ? undefined : AbortSignal.any([AbortSignal.timeout(timeout), this.cancellationSignal.asAbortSignal()]);
21
- await navigator.locks
22
- .request(this.resource, { signal, ifAvailable }, async (lock) => {
23
- if (isNull(lock)) {
24
- throw new Error('Failed to acquire lock.');
25
- }
26
- let lost = false;
27
- controllerPromise.resolve({
28
- get lost() {
29
- return lost;
30
- },
31
- async release() {
32
- releasePromise.resolve();
33
- },
34
- });
35
- await releasePromise;
36
- lost = true;
37
- })
38
- .catch(() => controllerPromise.resolve(false));
39
- return await controllerPromise;
40
- }
41
- async tryUse(timeout, func) {
42
- const ifAvailable = isUndefined(timeout) || (timeout <= 0);
43
- const signal = ifAvailable ? undefined : AbortSignal.any([AbortSignal.timeout(timeout), this.cancellationSignal.asAbortSignal()]);
44
- let result;
69
+ const env_1 = { stack: [], error: void 0, hasError: false };
45
70
  try {
46
- result = await navigator.locks.request(this.resource, { signal, ifAvailable }, async (lock) => {
71
+ const controllerPromise = new DeferredPromise();
72
+ const releasePromise = new DeferredPromise();
73
+ const ifAvailable = isUndefined(timeout) || (timeout <= 0);
74
+ const signal = __addDisposableResource(env_1, ifAvailable ? undefined : this.cancellationSignal.withTimeout(timeout), false);
75
+ await navigator.locks
76
+ .request(this.resource, { signal: signal?.abortSignal, ifAvailable }, async (lock) => {
47
77
  if (isNull(lock)) {
48
- return { type: 'already-locked' };
49
- }
50
- try {
51
- const returnValue = await func({ lost: false });
52
- return { type: 'result', value: returnValue };
53
- }
54
- catch (error) {
55
- return { type: 'error', error };
78
+ throw new Error('Failed to acquire lock.');
56
79
  }
57
- });
80
+ let lost = false;
81
+ controllerPromise.resolve({
82
+ get lost() {
83
+ return lost;
84
+ },
85
+ async release() {
86
+ releasePromise.resolve();
87
+ },
88
+ });
89
+ await releasePromise;
90
+ lost = true;
91
+ })
92
+ .catch(() => controllerPromise.resolve(false));
93
+ return await controllerPromise;
94
+ }
95
+ catch (e_1) {
96
+ env_1.error = e_1;
97
+ env_1.hasError = true;
98
+ }
99
+ finally {
100
+ __disposeResources(env_1);
101
+ }
102
+ }
103
+ async tryUse(timeout, func) {
104
+ const env_2 = { stack: [], error: void 0, hasError: false };
105
+ try {
106
+ const ifAvailable = isUndefined(timeout) || (timeout <= 0);
107
+ const signal = __addDisposableResource(env_2, ifAvailable ? undefined : this.cancellationSignal.withTimeout(timeout), false);
108
+ let result;
109
+ try {
110
+ result = await navigator.locks.request(this.resource, { signal: signal?.abortSignal, ifAvailable }, async (lock) => {
111
+ if (isNull(lock)) {
112
+ return { type: 'already-locked' };
113
+ }
114
+ try {
115
+ const returnValue = await func({ lost: false });
116
+ return { type: 'result', value: returnValue };
117
+ }
118
+ catch (error) {
119
+ return { type: 'error', error };
120
+ }
121
+ });
122
+ }
123
+ catch {
124
+ return { success: false }; // navigator.locks.request throws a DOMException on timeout
125
+ }
126
+ switch (result.type) {
127
+ case 'result':
128
+ return { success: true, result: result.value };
129
+ case 'already-locked':
130
+ return { success: false };
131
+ case 'error':
132
+ throw result.error;
133
+ }
58
134
  }
59
- catch {
60
- return { success: false }; // navigator.locks.request throws a DOMException on timeout
135
+ catch (e_2) {
136
+ env_2.error = e_2;
137
+ env_2.hasError = true;
61
138
  }
62
- switch (result.type) {
63
- case 'result':
64
- return { success: true, result: result.value };
65
- case 'already-locked':
66
- return { success: false };
67
- case 'error':
68
- throw result.error;
139
+ finally {
140
+ __disposeResources(env_2);
69
141
  }
70
142
  }
71
143
  async exists() {