@zerotal/core 1.0.0
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/CHANGELOG.md +79 -0
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/package.json +72 -0
- package/src/application/Application.ts +1671 -0
- package/src/application/BootDoctor.ts +108 -0
- package/src/application/DevErrorPage.ts +567 -0
- package/src/application/ExceptionHandler.ts +183 -0
- package/src/application/currentApp.ts +73 -0
- package/src/assets/assets.ts +79 -0
- package/src/assets/index.ts +16 -0
- package/src/auth/AuthenticatedUser.ts +18 -0
- package/src/build/PackageLinter.ts +146 -0
- package/src/build/PackageScaffold.ts +127 -0
- package/src/build/codemod.ts +64 -0
- package/src/build/index.ts +12 -0
- package/src/command/Command.ts +254 -0
- package/src/command/CommandRunner.ts +593 -0
- package/src/command/OutputWriter.ts +61 -0
- package/src/command/builtin/CompileCommand.ts +46 -0
- package/src/command/builtin/CssBuildCommand.ts +71 -0
- package/src/command/builtin/KeyGenerateCommand.ts +58 -0
- package/src/command/builtin/LintPackagesCommand.ts +72 -0
- package/src/command/builtin/MakeCommandCommand.ts +85 -0
- package/src/command/builtin/MakeControllerCommand.ts +95 -0
- package/src/command/builtin/MakeEventCommand.ts +85 -0
- package/src/command/builtin/MakeJobCommand.ts +53 -0
- package/src/command/builtin/MakeListenerCommand.ts +35 -0
- package/src/command/builtin/MakeMiddlewareCommand.ts +63 -0
- package/src/command/builtin/MakeNotificationCommand.ts +48 -0
- package/src/command/builtin/MakeObserverCommand.ts +78 -0
- package/src/command/builtin/MakePackageCommand.ts +45 -0
- package/src/command/builtin/MakePolicyCommand.ts +66 -0
- package/src/command/builtin/MakeProviderCommand.ts +75 -0
- package/src/command/builtin/MakeRequestCommand.ts +47 -0
- package/src/command/builtin/MakeResourceCommand.ts +61 -0
- package/src/command/builtin/MakeTestCommand.ts +120 -0
- package/src/command/builtin/ReloadCommand.ts +52 -0
- package/src/command/builtin/ReplCommand.ts +174 -0
- package/src/command/builtin/RouteListCommand.ts +188 -0
- package/src/command/builtin/ServeCommand.ts +321 -0
- package/src/command/builtin/StartCommand.ts +3 -0
- package/src/command/builtin/StatusCommand.ts +71 -0
- package/src/command/builtin/TestCommand.ts +172 -0
- package/src/command/builtin/WorkerCommand.ts +27 -0
- package/src/command/builtin/index.ts +53 -0
- package/src/command/scaffold/worker.ts.txt +12 -0
- package/src/command/scaffold/zerotal.ts.txt +26 -0
- package/src/command/startZerotal.ts +55 -0
- package/src/config/AppConfig.ts +253 -0
- package/src/config/ConfigLoader.ts +117 -0
- package/src/config/ConfigManager.ts +169 -0
- package/src/config/index.ts +46 -0
- package/src/config/registry.ts +59 -0
- package/src/config/validation.ts +117 -0
- package/src/container/Container.ts +606 -0
- package/src/container/ContextualBindingBuilder.ts +57 -0
- package/src/container/ScopedResolver.ts +117 -0
- package/src/container/index.ts +32 -0
- package/src/container/inject.ts +55 -0
- package/src/container/types.ts +71 -0
- package/src/context/RequestContext.ts +91 -0
- package/src/contracts/auth.ts +24 -0
- package/src/contracts/index.ts +23 -0
- package/src/contracts/session.ts +70 -0
- package/src/contracts/transaction.ts +26 -0
- package/src/conventions/ConventionLoader.ts +128 -0
- package/src/conventions/builtinConcerns.ts +131 -0
- package/src/crypt/Crypt.ts +141 -0
- package/src/crypt/URLSigner.ts +96 -0
- package/src/datetime/Carbon.ts +1396 -0
- package/src/datetime/CarbonInterval.ts +421 -0
- package/src/datetime/clock.ts +28 -0
- package/src/datetime/index.ts +23 -0
- package/src/datetime/temporal-shim.ts +1 -0
- package/src/dev/BuildOutput.ts +131 -0
- package/src/dev/CssPlugins.ts +184 -0
- package/src/dev/DevBuildHook.ts +74 -0
- package/src/dev/DevOrchestrator.ts +213 -0
- package/src/dev/DevReloadMiddleware.ts +101 -0
- package/src/dev/DevReloadServer.ts +85 -0
- package/src/dev/DevWsServer.ts +45 -0
- package/src/dev/index.ts +19 -0
- package/src/dev/reloadClient.ts +39 -0
- package/src/env/Def.ts +232 -0
- package/src/env/EnvSchema.ts +105 -0
- package/src/env/index.ts +34 -0
- package/src/env/t.ts +128 -0
- package/src/errors/ConfigError.ts +12 -0
- package/src/errors/ContainerErrors.ts +143 -0
- package/src/errors/HttpError.ts +127 -0
- package/src/errors/ValidationError.ts +19 -0
- package/src/errors/ZerotalError.ts +25 -0
- package/src/errors/index.ts +46 -0
- package/src/events/CallQueuedListener.ts +66 -0
- package/src/events/Emitter.ts +280 -0
- package/src/events/EventFake.ts +160 -0
- package/src/events/FrameworkEvents.ts +252 -0
- package/src/facade/Facade.ts +101 -0
- package/src/facade/facades/App.ts +155 -0
- package/src/facade/facades/Artisan.ts +63 -0
- package/src/facade/facades/Config.ts +21 -0
- package/src/facade/facades/Events.ts +19 -0
- package/src/facade/facades/index.ts +28 -0
- package/src/global.d.ts +9 -0
- package/src/hash/Hash.ts +60 -0
- package/src/health/Health.ts +221 -0
- package/src/health/index.ts +27 -0
- package/src/helpers/Collection.ts +435 -0
- package/src/helpers/config.ts +59 -0
- package/src/helpers/fluent.ts +52 -0
- package/src/helpers/html.ts +11 -0
- package/src/helpers/index.ts +266 -0
- package/src/helpers/make.ts +35 -0
- package/src/helpers/markdown.ts +73 -0
- package/src/helpers/pageElements.ts +27 -0
- package/src/helpers/request.ts +62 -0
- package/src/helpers/response.ts +411 -0
- package/src/helpers/str.ts +208 -0
- package/src/http/Http.ts +298 -0
- package/src/http/HttpClient.ts +289 -0
- package/src/http/Resource.ts +171 -0
- package/src/http/UploadedFile.ts +204 -0
- package/src/http/Uri.ts +490 -0
- package/src/http/index.ts +46 -0
- package/src/http/negotiate.ts +213 -0
- package/src/http/originGuard.ts +76 -0
- package/src/http/sniffContentType.ts +105 -0
- package/src/http/url.ts +204 -0
- package/src/http/withHeaders.ts +24 -0
- package/src/index.ts +250 -0
- package/src/lock/LockManager.ts +228 -0
- package/src/lock/config.ts +49 -0
- package/src/lock/drivers/LockDriver.ts +32 -0
- package/src/lock/drivers/MemoryLockDriver.ts +52 -0
- package/src/lock/drivers/RedisLockDriver.ts +58 -0
- package/src/lock/drivers/SqliteLockDriver.ts +85 -0
- package/src/lock/errors.ts +20 -0
- package/src/lock/facades/Lock.ts +114 -0
- package/src/lock/index.ts +53 -0
- package/src/logger/Log.ts +35 -0
- package/src/logger/LogManager.ts +430 -0
- package/src/logger/LoggerMiddleware.ts +125 -0
- package/src/logger/channels/ConsoleChannel.ts +139 -0
- package/src/logger/channels/DailyChannel.ts +74 -0
- package/src/logger/channels/NullChannel.ts +17 -0
- package/src/logger/channels/SingleChannel.ts +34 -0
- package/src/logger/channels/StackChannel.ts +29 -0
- package/src/logger/config.ts +90 -0
- package/src/logger/format.ts +96 -0
- package/src/logger/frameworkLog.ts +93 -0
- package/src/logger/index.ts +68 -0
- package/src/logger/renderTable.ts +111 -0
- package/src/logger/types.ts +212 -0
- package/src/macros/config.macro.ts +50 -0
- package/src/metrics/HttpMetrics.ts +114 -0
- package/src/metrics/index.ts +18 -0
- package/src/middleware/BaseMiddleware.ts +72 -0
- package/src/middleware/CorsMiddleware.ts +152 -0
- package/src/middleware/RateLimiter.ts +255 -0
- package/src/middleware/SecureHeadersMiddleware.ts +127 -0
- package/src/middleware/ThrottleMiddleware.ts +252 -0
- package/src/middleware/WebhookMiddleware.ts +204 -0
- package/src/pipeline/ContextRegistry.ts +42 -0
- package/src/pipeline/HttpContext.ts +865 -0
- package/src/pipeline/Pipeline.ts +150 -0
- package/src/pipeline/currentPage.ts +46 -0
- package/src/pipeline/types.ts +80 -0
- package/src/provider/LockProvider.ts +64 -0
- package/src/provider/LogProvider.ts +137 -0
- package/src/provider/ServiceProvider.ts +84 -0
- package/src/provider/StorageProvider.ts +45 -0
- package/src/router/FileRouter.ts +526 -0
- package/src/router/Route.ts +76 -0
- package/src/router/RouteHandler.ts +335 -0
- package/src/router/Router.ts +1247 -0
- package/src/router/domain.ts +65 -0
- package/src/security/index.ts +22 -0
- package/src/storage/FakeDisk.ts +233 -0
- package/src/storage/StorageFilesMiddleware.ts +150 -0
- package/src/storage/StorageManager.ts +173 -0
- package/src/storage/config.ts +47 -0
- package/src/storage/drivers/LocalDriver.ts +138 -0
- package/src/storage/drivers/S3Driver.ts +169 -0
- package/src/storage/errors.ts +135 -0
- package/src/storage/facades/Storage.ts +3 -0
- package/src/storage/global.d.ts +7 -0
- package/src/storage/index.ts +22 -0
- package/src/storage/root.ts +59 -0
- package/src/storage/types.ts +104 -0
- package/src/support/appKey.ts +38 -0
- package/src/support/cookie.ts +72 -0
- package/src/support/crypto.ts +52 -0
- package/src/support/deepMerge.ts +117 -0
- package/src/support/env.ts +71 -0
- package/src/support/network.ts +79 -0
- package/src/support/port.ts +197 -0
- package/src/support/str.ts +122 -0
- package/src/view/FileRouteResolver.ts +59 -0
- package/src/view/index.ts +144 -0
- package/src/view/jsx-runtime.ts +233 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import type { LockDriver } from "./LockDriver.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SQLite-backed lock driver.
|
|
6
|
+
*
|
|
7
|
+
* Suitable for single-server deployments that need locks to survive process
|
|
8
|
+
* restarts. Backed by `bun:sqlite` — fully synchronous under the hood so
|
|
9
|
+
* every acquire/release is a single atomic statement.
|
|
10
|
+
*
|
|
11
|
+
* Use `:memory:` as the path for in-process persistence across tests
|
|
12
|
+
* without touching the filesystem.
|
|
13
|
+
*
|
|
14
|
+
* @category Configuration
|
|
15
|
+
*/
|
|
16
|
+
export class SqliteLockDriver implements LockDriver {
|
|
17
|
+
private readonly _db: Database;
|
|
18
|
+
|
|
19
|
+
constructor(path = ":memory:") {
|
|
20
|
+
this._db = new Database(path);
|
|
21
|
+
this._db.exec(`
|
|
22
|
+
CREATE TABLE IF NOT EXISTS zerotal_locks (
|
|
23
|
+
key TEXT PRIMARY KEY,
|
|
24
|
+
owner TEXT NOT NULL,
|
|
25
|
+
expires_at INTEGER NOT NULL
|
|
26
|
+
)
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async acquire(key: string, owner: string, ttlSeconds: number): Promise<boolean> {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const expiresAt = now + ttlSeconds * 1000;
|
|
33
|
+
|
|
34
|
+
// Purge any expired record for this key so INSERT can succeed
|
|
35
|
+
this._db.prepare("DELETE FROM zerotal_locks WHERE key = ? AND expires_at <= ?").run(key, now);
|
|
36
|
+
|
|
37
|
+
// If the lock is already held by this owner, refresh the TTL
|
|
38
|
+
const existing = this._db
|
|
39
|
+
.prepare<{ owner: string }, string>("SELECT owner FROM zerotal_locks WHERE key = ?")
|
|
40
|
+
.get(key);
|
|
41
|
+
|
|
42
|
+
if (existing) {
|
|
43
|
+
if (existing.owner === owner) {
|
|
44
|
+
this._db
|
|
45
|
+
.prepare("UPDATE zerotal_locks SET expires_at = ? WHERE key = ?")
|
|
46
|
+
.run(expiresAt, key);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false; // held by another owner
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
this._db
|
|
54
|
+
.prepare("INSERT INTO zerotal_locks (key, owner, expires_at) VALUES (?, ?, ?)")
|
|
55
|
+
.run(key, owner, expiresAt);
|
|
56
|
+
return true;
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async release(key: string, owner: string): Promise<boolean> {
|
|
63
|
+
const result = this._db
|
|
64
|
+
.prepare("DELETE FROM zerotal_locks WHERE key = ? AND owner = ?")
|
|
65
|
+
.run(key, owner);
|
|
66
|
+
return result.changes > 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async forceRelease(key: string): Promise<void> {
|
|
70
|
+
this._db.prepare("DELETE FROM zerotal_locks WHERE key = ?").run(key);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async exists(key: string): Promise<boolean> {
|
|
74
|
+
const row = this._db
|
|
75
|
+
.prepare<{ 1: number }, [string, number]>(
|
|
76
|
+
"SELECT 1 FROM zerotal_locks WHERE key = ? AND expires_at > ?",
|
|
77
|
+
)
|
|
78
|
+
.get(key, Date.now());
|
|
79
|
+
return row !== null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
dispose(): void {
|
|
83
|
+
this._db.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ZerotalError } from "../errors/index.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Thrown when a lock cannot be acquired: immediately by
|
|
5
|
+
* {@link LockManager.try | try}/{@link Lock.try | Lock.try} when the key is
|
|
6
|
+
* busy, or by {@link LockManager.block | block}/{@link Lock.block | Lock.block}
|
|
7
|
+
* when the wait timeout elapses. Carries the contended {@link key} and maps to
|
|
8
|
+
* HTTP 409 (code `E_LOCK_NOT_ACQUIRED`).
|
|
9
|
+
*
|
|
10
|
+
* @category Acquiring
|
|
11
|
+
*/
|
|
12
|
+
export class LockNotAcquiredError extends ZerotalError {
|
|
13
|
+
/** The lock key that could not be acquired. */
|
|
14
|
+
readonly key: string;
|
|
15
|
+
|
|
16
|
+
constructor(key: string) {
|
|
17
|
+
super(`[Zerotal Lock] Could not acquire lock for key: "${key}"`, "E_LOCK_NOT_ACQUIRED", 409);
|
|
18
|
+
this.key = key;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { currentApp } from "../../application/currentApp.ts";
|
|
2
|
+
import { ZerotalError } from "../../errors/index.ts";
|
|
3
|
+
import type { LockManager, ManagedLock, BlockOptions } from "../LockManager.ts";
|
|
4
|
+
import { LockNotAcquiredError } from "../errors.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the live LockManager from the application container on every call.
|
|
8
|
+
* The container is the single source of truth — the facade caches nothing and
|
|
9
|
+
* holds no module-level state.
|
|
10
|
+
*/
|
|
11
|
+
function _manager(): LockManager {
|
|
12
|
+
try {
|
|
13
|
+
return currentApp().container.makeSync("lock");
|
|
14
|
+
} catch {
|
|
15
|
+
throw new ZerotalError(
|
|
16
|
+
"[Zerotal Lock] Lock facade unavailable — register LockProvider in your application.",
|
|
17
|
+
"E_LOCK_FACADE_UNAVAILABLE",
|
|
18
|
+
500,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Static facade over the container-bound {@link LockManager}.
|
|
25
|
+
*
|
|
26
|
+
* Resolves the live `lock` singleton on every call and forwards to the
|
|
27
|
+
* manager, so it exposes the same three usage styles: {@link Lock.try | try}
|
|
28
|
+
* (fail fast), {@link Lock.block | block} (wait for the lock), and
|
|
29
|
+
* {@link Lock.make | make} (a manual {@link ManagedLock} handle). Requires
|
|
30
|
+
* {@link LockProvider} to be registered.
|
|
31
|
+
*
|
|
32
|
+
* @category Acquiring
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* // Fail-fast — throws immediately if the lock is busy
|
|
37
|
+
* await Lock.try('invoice:123', 10, async () => {
|
|
38
|
+
* await processInvoice(123);
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* // Blocking — waits up to 30s for the lock
|
|
42
|
+
* await Lock.block('invoice:123', 10, async () => {
|
|
43
|
+
* await processInvoice(123);
|
|
44
|
+
* }, { timeout: 30 });
|
|
45
|
+
*
|
|
46
|
+
* // Manual handle for complex flows
|
|
47
|
+
* const handle = Lock.make('payment:456', 15);
|
|
48
|
+
* if (await handle.acquire()) {
|
|
49
|
+
* try {
|
|
50
|
+
* await capturePayment(456);
|
|
51
|
+
* } finally {
|
|
52
|
+
* await handle.release();
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export class Lock {
|
|
58
|
+
/**
|
|
59
|
+
* Create a named lock handle for manual acquire/release flows.
|
|
60
|
+
* Does NOT acquire the lock — call `.acquire()` or `.block()` explicitly.
|
|
61
|
+
*
|
|
62
|
+
* @param key - Logical lock name.
|
|
63
|
+
* @param ttlSeconds - Lock time-to-live in seconds.
|
|
64
|
+
* @throws {ZerotalError} (code `E_LOCK_FACADE_UNAVAILABLE`) if {@link LockProvider} is not registered.
|
|
65
|
+
* @category Acquiring
|
|
66
|
+
*/
|
|
67
|
+
static make(key: string, ttlSeconds: number): ManagedLock {
|
|
68
|
+
return _manager().lock(key, ttlSeconds);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Acquire the lock exactly once, run `callback`, then release — always,
|
|
73
|
+
* even if `callback` throws.
|
|
74
|
+
*
|
|
75
|
+
* @param key - Logical lock name.
|
|
76
|
+
* @param ttlSeconds - Lock time-to-live in seconds.
|
|
77
|
+
* @param callback - Critical section to run while the lock is held.
|
|
78
|
+
* @returns The value returned by `callback`.
|
|
79
|
+
* @throws {LockNotAcquiredError} Immediately, if the lock is busy.
|
|
80
|
+
* @category Acquiring
|
|
81
|
+
*/
|
|
82
|
+
static async try<T>(key: string, ttlSeconds: number, callback: () => Promise<T> | T): Promise<T> {
|
|
83
|
+
return _manager().try(key, ttlSeconds, callback);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Wait until the lock is free (up to `options.timeout` seconds), run
|
|
88
|
+
* `callback`, then release — always, even if `callback` throws.
|
|
89
|
+
*
|
|
90
|
+
* @param key - Logical lock name.
|
|
91
|
+
* @param ttlSeconds - Lock time-to-live in seconds.
|
|
92
|
+
* @param callback - Critical section to run while the lock is held.
|
|
93
|
+
* @param options - Wait {@link BlockOptions.timeout | timeout} and poll interval.
|
|
94
|
+
* @returns The value returned by `callback`.
|
|
95
|
+
* @throws {LockNotAcquiredError} If the timeout elapses before the lock is acquired.
|
|
96
|
+
* @category Acquiring
|
|
97
|
+
*/
|
|
98
|
+
static async block<T>(
|
|
99
|
+
key: string,
|
|
100
|
+
ttlSeconds: number,
|
|
101
|
+
callback: () => Promise<T> | T,
|
|
102
|
+
options?: BlockOptions,
|
|
103
|
+
): Promise<T> {
|
|
104
|
+
return _manager().block(key, ttlSeconds, callback, options);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The {@link LockNotAcquiredError} class, re-exported for convenience in
|
|
109
|
+
* `catch` blocks (`err instanceof Lock.NotAcquired`).
|
|
110
|
+
*
|
|
111
|
+
* @category Acquiring
|
|
112
|
+
*/
|
|
113
|
+
static readonly NotAcquired = LockNotAcquiredError;
|
|
114
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distributed mutual-exclusion locks for Zerotal applications.
|
|
3
|
+
*
|
|
4
|
+
* A named lock guarantees that at most one holder runs a critical section at a
|
|
5
|
+
* time — across processes and servers when backed by the Redis or SQLite
|
|
6
|
+
* driver, or in-process with the default memory driver. Every lock carries a
|
|
7
|
+
* TTL so a crashed holder cannot deadlock the key, and release is owner-guarded
|
|
8
|
+
* so a holder whose lock already expired can never release a newer holder's
|
|
9
|
+
* lock. Reach the container-bound manager through the {@link Lock} facade;
|
|
10
|
+
* configure the backend with {@link LockConfig}.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { Lock } from "@zerotal/core/lock";
|
|
15
|
+
*
|
|
16
|
+
* // Fail fast: throw LockNotAcquiredError immediately if the key is busy.
|
|
17
|
+
* await Lock.try("invoice:123", 10, async () => {
|
|
18
|
+
* await processInvoice(123);
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Blocking: wait up to 30s for the key to free, holding it for 10s (TTL).
|
|
22
|
+
* await Lock.block("invoice:123", 10, async () => {
|
|
23
|
+
* await processInvoice(123);
|
|
24
|
+
* }, { timeout: 30 });
|
|
25
|
+
*
|
|
26
|
+
* // Manual handle for flows that span multiple steps.
|
|
27
|
+
* const handle = Lock.make("payment:456", 15);
|
|
28
|
+
* if (await handle.acquire()) {
|
|
29
|
+
* try {
|
|
30
|
+
* await capturePayment(456);
|
|
31
|
+
* } finally {
|
|
32
|
+
* await handle.release();
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @packageDocumentation
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export { LockManager, ManagedLock } from "./LockManager.ts";
|
|
41
|
+
export type { BlockOptions } from "./LockManager.ts";
|
|
42
|
+
|
|
43
|
+
export { Lock } from "./facades/Lock.ts";
|
|
44
|
+
export { LockProvider } from "../provider/LockProvider.ts";
|
|
45
|
+
export { LockConfig } from "./config.ts";
|
|
46
|
+
export type { LockConfigShape } from "./config.ts";
|
|
47
|
+
export { LockNotAcquiredError } from "./errors.ts";
|
|
48
|
+
|
|
49
|
+
// Drivers — exported for custom driver registration and direct instantiation
|
|
50
|
+
export type { LockDriver } from "./drivers/LockDriver.ts";
|
|
51
|
+
export { MemoryLockDriver } from "./drivers/MemoryLockDriver.ts";
|
|
52
|
+
export { SqliteLockDriver } from "./drivers/SqliteLockDriver.ts";
|
|
53
|
+
export { RedisLockDriver } from "./drivers/RedisLockDriver.ts";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createFacade } from "../facade/Facade.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Static facade over the container-bound {@link LogManager}.
|
|
5
|
+
*
|
|
6
|
+
* Every access resolves the live `log` singleton, so `Log` exposes the full
|
|
7
|
+
* {@link LogManager} surface: the five level methods
|
|
8
|
+
* ({@link LogManager.debug | debug}/{@link LogManager.info | info}/
|
|
9
|
+
* {@link LogManager.warn | warn}/{@link LogManager.error | error}/
|
|
10
|
+
* {@link LogManager.fatal | fatal}) on the default channel, plus
|
|
11
|
+
* {@link LogManager.channel | channel} and
|
|
12
|
+
* {@link LogManager.withContext | withContext}. Available after the application
|
|
13
|
+
* has booted (the facade throws if accessed at module scope before boot).
|
|
14
|
+
*
|
|
15
|
+
* @category Logging
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { Log } from "@zerotal/core/logger";
|
|
20
|
+
*
|
|
21
|
+
* // Level + structured context.
|
|
22
|
+
* Log.info("Order placed", { orderId: 99, total: 42.5 });
|
|
23
|
+
*
|
|
24
|
+
* // Attach an error — its message and stack are captured onto the entry.
|
|
25
|
+
* Log.error("Charge failed", { orderId: 99 }, err);
|
|
26
|
+
*
|
|
27
|
+
* // Contextual logging: shared fields merged into every subsequent entry.
|
|
28
|
+
* const scoped = Log.withContext({ tenant: "acme" });
|
|
29
|
+
* scoped.warn("Quota nearly exhausted", { pct: 92 });
|
|
30
|
+
*
|
|
31
|
+
* // Target a specific configured channel.
|
|
32
|
+
* Log.channel("daily").info("Persisted to today's rotating file");
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const Log = createFacade("log");
|