@blokjs/runner 0.4.0 → 0.6.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/dist/Blok.js +32 -3
- package/dist/Blok.js.map +1 -1
- package/dist/Configuration.d.ts +41 -5
- package/dist/Configuration.js +215 -92
- package/dist/Configuration.js.map +1 -1
- package/dist/ForEachNode.d.ts +59 -0
- package/dist/ForEachNode.js +522 -0
- package/dist/ForEachNode.js.map +1 -0
- package/dist/LoopMaxIterationsError.d.ts +11 -0
- package/dist/LoopMaxIterationsError.js +18 -0
- package/dist/LoopMaxIterationsError.js.map +1 -0
- package/dist/LoopNode.d.ts +36 -0
- package/dist/LoopNode.js +182 -0
- package/dist/LoopNode.js.map +1 -0
- package/dist/Runner.d.ts +11 -1
- package/dist/Runner.js +9 -2
- package/dist/Runner.js.map +1 -1
- package/dist/RunnerSteps.js +419 -112
- package/dist/RunnerSteps.js.map +1 -1
- package/dist/RuntimeAdapterNode.d.ts +2 -1
- package/dist/RuntimeAdapterNode.js +2 -2
- package/dist/RuntimeAdapterNode.js.map +1 -1
- package/dist/RuntimeRegistry.d.ts +23 -2
- package/dist/RuntimeRegistry.js +31 -2
- package/dist/RuntimeRegistry.js.map +1 -1
- package/dist/SubworkflowNode.d.ts +106 -0
- package/dist/SubworkflowNode.js +261 -3
- package/dist/SubworkflowNode.js.map +1 -1
- package/dist/SwitchNode.d.ts +37 -0
- package/dist/SwitchNode.js +153 -0
- package/dist/SwitchNode.js.map +1 -0
- package/dist/TriggerBase.d.ts +50 -0
- package/dist/TriggerBase.js +262 -4
- package/dist/TriggerBase.js.map +1 -1
- package/dist/TryCatchNode.d.ts +32 -0
- package/dist/TryCatchNode.js +207 -0
- package/dist/TryCatchNode.js.map +1 -0
- package/dist/adapters/grpc/GrpcCodec.js +2 -2
- package/dist/adapters/grpc/GrpcRuntimeAdapter.d.ts +6 -4
- package/dist/adapters/grpc/GrpcRuntimeAdapter.js +6 -4
- package/dist/adapters/grpc/GrpcRuntimeAdapter.js.map +1 -1
- package/dist/adapters/grpc/types.d.ts +7 -5
- package/dist/adapters/grpc/types.js.map +1 -1
- package/dist/adapters/transport.d.ts +12 -41
- package/dist/adapters/transport.js +21 -70
- package/dist/adapters/transport.js.map +1 -1
- package/dist/cache/NodeResultCache.js +7 -0
- package/dist/cache/NodeResultCache.js.map +1 -1
- package/dist/concurrency/NatsKvConcurrencyBackend.js +18 -5
- package/dist/concurrency/NatsKvConcurrencyBackend.js.map +1 -1
- package/dist/concurrency/RedisConcurrencyBackend.d.ts +64 -0
- package/dist/concurrency/RedisConcurrencyBackend.js +374 -0
- package/dist/concurrency/RedisConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/createConcurrencyBackend.d.ts +1 -0
- package/dist/concurrency/createConcurrencyBackend.js +5 -1
- package/dist/concurrency/createConcurrencyBackend.js.map +1 -1
- package/dist/defineNode.d.ts +8 -0
- package/dist/defineNode.js +25 -5
- package/dist/defineNode.js.map +1 -1
- package/dist/graphql/GraphQLSchemaGenerator.js +1 -1
- package/dist/graphql/GraphQLSchemaGenerator.js.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.js +13 -9
- package/dist/index.js.map +1 -1
- package/dist/marketplace/RuntimeCatalog.d.ts +6 -0
- package/dist/marketplace/RuntimeCatalog.js.map +1 -1
- package/dist/marketplace/RuntimeDiscovery.d.ts +2 -2
- package/dist/marketplace/RuntimeDiscovery.js +18 -6
- package/dist/marketplace/RuntimeDiscovery.js.map +1 -1
- package/dist/monitoring/ConcurrencyMetrics.d.ts +26 -0
- package/dist/monitoring/ConcurrencyMetrics.js +36 -4
- package/dist/monitoring/ConcurrencyMetrics.js.map +1 -1
- package/dist/monitoring/ForEachWaitMetrics.d.ts +22 -0
- package/dist/monitoring/ForEachWaitMetrics.js +36 -0
- package/dist/monitoring/ForEachWaitMetrics.js.map +1 -0
- package/dist/openapi/OpenAPIGenerator.js +7 -2
- package/dist/openapi/OpenAPIGenerator.js.map +1 -1
- package/dist/runtime/PrimitiveStack.d.ts +64 -0
- package/dist/runtime/PrimitiveStack.js +92 -0
- package/dist/runtime/PrimitiveStack.js.map +1 -0
- package/dist/scheduling/DebounceBackend.d.ts +108 -0
- package/dist/scheduling/DebounceBackend.js +23 -0
- package/dist/scheduling/DebounceBackend.js.map +1 -0
- package/dist/scheduling/DebounceCoordinator.d.ts +65 -12
- package/dist/scheduling/DebounceCoordinator.js +234 -13
- package/dist/scheduling/DebounceCoordinator.js.map +1 -1
- package/dist/scheduling/DeferredRunScheduler.d.ts +28 -0
- package/dist/scheduling/DeferredRunScheduler.js +105 -3
- package/dist/scheduling/DeferredRunScheduler.js.map +1 -1
- package/dist/scheduling/NatsKvDebounceBackend.d.ts +53 -0
- package/dist/scheduling/NatsKvDebounceBackend.js +334 -0
- package/dist/scheduling/NatsKvDebounceBackend.js.map +1 -0
- package/dist/scheduling/RedisDebounceBackend.d.ts +49 -0
- package/dist/scheduling/RedisDebounceBackend.js +356 -0
- package/dist/scheduling/RedisDebounceBackend.js.map +1 -0
- package/dist/scheduling/createDebounceBackend.d.ts +25 -0
- package/dist/scheduling/createDebounceBackend.js +39 -0
- package/dist/scheduling/createDebounceBackend.js.map +1 -0
- package/dist/security/AuditLogger.js +1 -1
- package/dist/security/AuditLogger.js.map +1 -1
- package/dist/security/AuthMiddleware.d.ts +19 -20
- package/dist/security/AuthMiddleware.js +35 -20
- package/dist/security/AuthMiddleware.js.map +1 -1
- package/dist/security/OAuthProvider.js +2 -2
- package/dist/security/OAuthProvider.js.map +1 -1
- package/dist/security/SecretManager.js +14 -13
- package/dist/security/SecretManager.js.map +1 -1
- package/dist/security/index.d.ts +3 -1
- package/dist/security/index.js +3 -1
- package/dist/security/index.js.map +1 -1
- package/dist/testing/TestHarness.d.ts +27 -12
- package/dist/testing/TestHarness.js +19 -3
- package/dist/testing/TestHarness.js.map +1 -1
- package/dist/testing/WorkflowTestRunner.js +0 -7
- package/dist/testing/WorkflowTestRunner.js.map +1 -1
- package/dist/tracing/InMemoryRunStore.d.ts +14 -1
- package/dist/tracing/InMemoryRunStore.js +95 -6
- package/dist/tracing/InMemoryRunStore.js.map +1 -1
- package/dist/tracing/PostgresRunStore.d.ts +28 -2
- package/dist/tracing/PostgresRunStore.js +276 -3
- package/dist/tracing/PostgresRunStore.js.map +1 -1
- package/dist/tracing/RoutingDiagnostics.d.ts +55 -0
- package/dist/tracing/RoutingDiagnostics.js +50 -0
- package/dist/tracing/RoutingDiagnostics.js.map +1 -0
- package/dist/tracing/RunStore.d.ts +82 -1
- package/dist/tracing/RunTracker.d.ts +7 -1
- package/dist/tracing/RunTracker.js +23 -0
- package/dist/tracing/RunTracker.js.map +1 -1
- package/dist/tracing/SqliteRunStore.d.ts +57 -2
- package/dist/tracing/SqliteRunStore.js +408 -48
- package/dist/tracing/SqliteRunStore.js.map +1 -1
- package/dist/tracing/TraceRouter.js +380 -18
- package/dist/tracing/TraceRouter.js.map +1 -1
- package/dist/tracing/createStore.js +14 -3
- package/dist/tracing/createStore.js.map +1 -1
- package/dist/tracing/metadataFilter.d.ts +63 -0
- package/dist/tracing/metadataFilter.js +224 -0
- package/dist/tracing/metadataFilter.js.map +1 -0
- package/dist/tracing/types.d.ts +331 -7
- package/dist/utils/envAllowlist.d.ts +35 -0
- package/dist/utils/envAllowlist.js +113 -0
- package/dist/utils/envAllowlist.js.map +1 -0
- package/dist/version/RuntimeVersionValidator.d.ts +38 -0
- package/dist/version/RuntimeVersionValidator.js +121 -0
- package/dist/version/RuntimeVersionValidator.js.map +1 -0
- package/dist/visualization/WorkflowVisualizer.js +4 -4
- package/dist/visualization/WorkflowVisualizer.js.map +1 -1
- package/dist/workflow/PersistenceHelper.d.ts +18 -10
- package/dist/workflow/PersistenceHelper.js +35 -9
- package/dist/workflow/PersistenceHelper.js.map +1 -1
- package/dist/workflow/WorkflowNormalizer.d.ts +19 -1
- package/dist/workflow/WorkflowNormalizer.js +469 -19
- package/dist/workflow/WorkflowNormalizer.js.map +1 -1
- package/dist/workflow/WorkflowRegistry.d.ts +122 -0
- package/dist/workflow/WorkflowRegistry.js +121 -0
- package/dist/workflow/WorkflowRegistry.js.map +1 -1
- package/dist/workflow/sampleBody.d.ts +54 -0
- package/dist/workflow/sampleBody.js +320 -0
- package/dist/workflow/sampleBody.js.map +1 -0
- package/package.json +3 -8
- package/dist/adapters/HttpRuntimeAdapter.d.ts +0 -79
- package/dist/adapters/HttpRuntimeAdapter.js +0 -233
- package/dist/adapters/HttpRuntimeAdapter.js.map +0 -1
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier C #1 · Redis-backed debounce backend.
|
|
3
|
+
*
|
|
4
|
+
* Coordinates per-(workflow, debounceKey) window state across processes
|
|
5
|
+
* via a single Redis string key per bucket. Atomicity comes from
|
|
6
|
+
* server-side **Lua scripts** — `registerPing` / `finalize` /
|
|
7
|
+
* `cancel` / `purgeExpired` each run as a single `EVAL` with no OCC
|
|
8
|
+
* retry loop (Lua runs single-threaded against the keyspace).
|
|
9
|
+
*
|
|
10
|
+
* Storage shape: one JSON document per `(workflowName, debounceKey)`
|
|
11
|
+
* bucket. Owner identity is encoded in the doc itself as
|
|
12
|
+
* `(activeRunId, ownerProcessId, ownerLeaseExpiresAt)`; lease handoff
|
|
13
|
+
* happens atomically when a ping arrives after the lease expired.
|
|
14
|
+
*
|
|
15
|
+
* **Owner-local payload**: this backend tracks `pingCount`,
|
|
16
|
+
* `lastPingAt`, and `scheduledAt` only — payloads do NOT travel across
|
|
17
|
+
* processes. The owning process's local `onFire` closure fires when
|
|
18
|
+
* its timer elapses.
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_KEY_PREFIX = "blok-debounce";
|
|
21
|
+
/**
|
|
22
|
+
* Atomic registerPing. Reads the current doc (if any), decides
|
|
23
|
+
* ownership, writes back the next state, and returns
|
|
24
|
+
* `{outcome, activeRunId, scheduledAt, pingCount}`.
|
|
25
|
+
*
|
|
26
|
+
* KEYS[1] = bucket key
|
|
27
|
+
* ARGV[1] = mode ("leading" | "trailing")
|
|
28
|
+
* ARGV[2] = delayMs
|
|
29
|
+
* ARGV[3] = maxDelayMs ("-1" when unset)
|
|
30
|
+
* ARGV[4] = runId
|
|
31
|
+
* ARGV[5] = processId
|
|
32
|
+
* ARGV[6] = ownerLeaseMs
|
|
33
|
+
* ARGV[7] = now
|
|
34
|
+
*
|
|
35
|
+
* Returns: { outcome ("owner-new" | "owner-extend" | "coalesce"),
|
|
36
|
+
* activeRunId, scheduledAt, pingCount }
|
|
37
|
+
*/
|
|
38
|
+
const REGISTER_PING_LUA = `
|
|
39
|
+
local raw = redis.call('GET', KEYS[1])
|
|
40
|
+
local existing = nil
|
|
41
|
+
if raw and raw ~= '' then
|
|
42
|
+
local ok, parsed = pcall(cjson.decode, raw)
|
|
43
|
+
if ok and type(parsed) == 'table' then
|
|
44
|
+
existing = parsed
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
local mode = ARGV[1]
|
|
49
|
+
local delayMs = tonumber(ARGV[2])
|
|
50
|
+
local maxDelayMsRaw = tonumber(ARGV[3])
|
|
51
|
+
local maxDelayMs
|
|
52
|
+
if maxDelayMsRaw and maxDelayMsRaw >= 0 then maxDelayMs = maxDelayMsRaw end
|
|
53
|
+
local runId = ARGV[4]
|
|
54
|
+
local processId = ARGV[5]
|
|
55
|
+
local ownerLeaseMs = tonumber(ARGV[6])
|
|
56
|
+
local now = tonumber(ARGV[7])
|
|
57
|
+
|
|
58
|
+
local function compute_scheduled_at(existing_doc, now_)
|
|
59
|
+
local naive = now_ + delayMs
|
|
60
|
+
local deadline
|
|
61
|
+
if existing_doc and existing_doc.maxDelayDeadline then
|
|
62
|
+
deadline = tonumber(existing_doc.maxDelayDeadline)
|
|
63
|
+
elseif maxDelayMs then
|
|
64
|
+
deadline = now_ + maxDelayMs
|
|
65
|
+
end
|
|
66
|
+
if deadline and deadline < naive then return deadline end
|
|
67
|
+
return naive
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
local ownerActive = existing ~= nil and tonumber(existing.ownerLeaseExpiresAt) and tonumber(existing.ownerLeaseExpiresAt) > now
|
|
71
|
+
|
|
72
|
+
if not existing or not ownerActive then
|
|
73
|
+
local first_ping_at = (existing and existing.firstPingAt) and tonumber(existing.firstPingAt) or now
|
|
74
|
+
local max_delay_deadline
|
|
75
|
+
if existing and existing.maxDelayDeadline then
|
|
76
|
+
max_delay_deadline = tonumber(existing.maxDelayDeadline)
|
|
77
|
+
elseif maxDelayMs then
|
|
78
|
+
max_delay_deadline = now + maxDelayMs
|
|
79
|
+
end
|
|
80
|
+
local prev_count = (existing and existing.pingCount) and tonumber(existing.pingCount) or 0
|
|
81
|
+
local doc = {
|
|
82
|
+
mode = mode,
|
|
83
|
+
delayMs = delayMs,
|
|
84
|
+
maxDelayMs = maxDelayMs,
|
|
85
|
+
maxDelayDeadline = max_delay_deadline,
|
|
86
|
+
firstPingAt = first_ping_at,
|
|
87
|
+
lastPingAt = now,
|
|
88
|
+
pingCount = prev_count + 1,
|
|
89
|
+
activeRunId = runId,
|
|
90
|
+
ownerProcessId = processId,
|
|
91
|
+
ownerLeaseExpiresAt = now + ownerLeaseMs,
|
|
92
|
+
scheduledAt = compute_scheduled_at(existing, now),
|
|
93
|
+
}
|
|
94
|
+
redis.call('SET', KEYS[1], cjson.encode(doc))
|
|
95
|
+
return { "owner-new", doc.activeRunId, tostring(doc.scheduledAt), tostring(doc.pingCount) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if tostring(existing.ownerProcessId) == processId then
|
|
99
|
+
-- We still own — extend window.
|
|
100
|
+
existing.lastPingAt = now
|
|
101
|
+
existing.pingCount = (tonumber(existing.pingCount) or 0) + 1
|
|
102
|
+
existing.ownerLeaseExpiresAt = now + ownerLeaseMs
|
|
103
|
+
existing.scheduledAt = compute_scheduled_at(existing, now)
|
|
104
|
+
redis.call('SET', KEYS[1], cjson.encode(existing))
|
|
105
|
+
return { "owner-extend", tostring(existing.activeRunId), tostring(existing.scheduledAt), tostring(existing.pingCount) }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
-- Different process owns — coalesce.
|
|
109
|
+
existing.lastPingAt = now
|
|
110
|
+
existing.pingCount = (tonumber(existing.pingCount) or 0) + 1
|
|
111
|
+
existing.scheduledAt = compute_scheduled_at(existing, now)
|
|
112
|
+
redis.call('SET', KEYS[1], cjson.encode(existing))
|
|
113
|
+
return { "coalesce", tostring(existing.activeRunId), tostring(existing.scheduledAt), tostring(existing.pingCount) }
|
|
114
|
+
`;
|
|
115
|
+
/**
|
|
116
|
+
* Atomic finalize. The owning process calls this on local timer fire.
|
|
117
|
+
*
|
|
118
|
+
* KEYS[1] = bucket key
|
|
119
|
+
* ARGV[1] = runId (the OWNING runId from the caller's perspective)
|
|
120
|
+
* ARGV[2] = now
|
|
121
|
+
*
|
|
122
|
+
* Returns:
|
|
123
|
+
* { "fire" } — caller still owns AND silence elapsed; DELETE done.
|
|
124
|
+
* { "reschedule", "<scheduledAt>" } — coalesce pings pushed scheduledAt forward.
|
|
125
|
+
* { "abandoned" } — caller no longer owns OR bucket gone.
|
|
126
|
+
*/
|
|
127
|
+
const FINALIZE_LUA = `
|
|
128
|
+
local raw = redis.call('GET', KEYS[1])
|
|
129
|
+
if not raw or raw == '' then return { "abandoned" } end
|
|
130
|
+
|
|
131
|
+
local ok, doc = pcall(cjson.decode, raw)
|
|
132
|
+
if not ok or type(doc) ~= 'table' then return { "abandoned" } end
|
|
133
|
+
|
|
134
|
+
if tostring(doc.activeRunId) ~= ARGV[1] then return { "abandoned" } end
|
|
135
|
+
|
|
136
|
+
local now = tonumber(ARGV[2])
|
|
137
|
+
local scheduled = tonumber(doc.scheduledAt) or 0
|
|
138
|
+
if now < scheduled then
|
|
139
|
+
return { "reschedule", tostring(scheduled) }
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
redis.call('DEL', KEYS[1])
|
|
143
|
+
return { "fire" }
|
|
144
|
+
`;
|
|
145
|
+
export function readRedisDebounceConfigFromEnv() {
|
|
146
|
+
const url = process.env.BLOK_DEBOUNCE_REDIS_URL?.trim() || undefined;
|
|
147
|
+
const host = process.env.BLOK_DEBOUNCE_REDIS_HOST?.trim() || undefined;
|
|
148
|
+
const portRaw = process.env.BLOK_DEBOUNCE_REDIS_PORT?.trim();
|
|
149
|
+
const port = portRaw && /^\d+$/.test(portRaw) ? Number(portRaw) : undefined;
|
|
150
|
+
const dbRaw = process.env.BLOK_DEBOUNCE_REDIS_DB?.trim();
|
|
151
|
+
const db = dbRaw && /^\d+$/.test(dbRaw) ? Number(dbRaw) : undefined;
|
|
152
|
+
const tls = process.env.BLOK_DEBOUNCE_REDIS_TLS === "1" || process.env.BLOK_DEBOUNCE_REDIS_TLS === "true";
|
|
153
|
+
return {
|
|
154
|
+
url,
|
|
155
|
+
host,
|
|
156
|
+
port,
|
|
157
|
+
password: process.env.BLOK_DEBOUNCE_REDIS_PASSWORD,
|
|
158
|
+
username: process.env.BLOK_DEBOUNCE_REDIS_USERNAME,
|
|
159
|
+
db,
|
|
160
|
+
tls,
|
|
161
|
+
keyPrefix: process.env.BLOK_DEBOUNCE_REDIS_KEY_PREFIX?.trim() || DEFAULT_KEY_PREFIX,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
export class RedisDebounceBackend {
|
|
165
|
+
name = "redis";
|
|
166
|
+
client = null;
|
|
167
|
+
config;
|
|
168
|
+
connected = false;
|
|
169
|
+
constructor(config) {
|
|
170
|
+
const env = readRedisDebounceConfigFromEnv();
|
|
171
|
+
this.config = {
|
|
172
|
+
url: config?.url ?? env.url,
|
|
173
|
+
host: config?.host ?? env.host,
|
|
174
|
+
port: config?.port ?? env.port,
|
|
175
|
+
password: config?.password ?? env.password,
|
|
176
|
+
username: config?.username ?? env.username,
|
|
177
|
+
db: config?.db ?? env.db,
|
|
178
|
+
tls: config?.tls ?? env.tls,
|
|
179
|
+
keyPrefix: config?.keyPrefix ?? env.keyPrefix,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async connect() {
|
|
183
|
+
if (this.connected)
|
|
184
|
+
return;
|
|
185
|
+
const blokEnv = process.env.BLOK_ENV;
|
|
186
|
+
const nodeEnv = process.env.NODE_ENV;
|
|
187
|
+
const isProd = blokEnv === "production" || nodeEnv === "production";
|
|
188
|
+
if (isProd && this.config.keyPrefix === DEFAULT_KEY_PREFIX) {
|
|
189
|
+
throw new Error(`[blok] Redis debounce backend refuses to start in production with the default key prefix ('${DEFAULT_KEY_PREFIX}'). Set BLOK_DEBOUNCE_REDIS_KEY_PREFIX to a deployment-unique value (e.g. 'blok-debounce-acme-prod') to prevent cross-deployment collision on a shared Redis instance.`);
|
|
190
|
+
}
|
|
191
|
+
let ioredisModule;
|
|
192
|
+
try {
|
|
193
|
+
ioredisModule = (await import("ioredis"));
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw new Error(`RedisDebounceBackend requires the 'ioredis' package. Install it: \`bun add ioredis\` or \`npm install ioredis\`. Underlying error: ${err instanceof Error ? err.message : String(err)}`);
|
|
197
|
+
}
|
|
198
|
+
const IORedisCtor = ioredisModule.default ?? ioredisModule.Redis;
|
|
199
|
+
if (!IORedisCtor) {
|
|
200
|
+
throw new Error("RedisDebounceBackend could not locate the ioredis constructor on the imported module. Reinstall ioredis or report this issue.");
|
|
201
|
+
}
|
|
202
|
+
// Same fail-fast posture as RedisConcurrencyBackend.
|
|
203
|
+
const failFastDefaults = {
|
|
204
|
+
connectTimeout: 5_000,
|
|
205
|
+
maxRetriesPerRequest: 0,
|
|
206
|
+
enableOfflineQueue: false,
|
|
207
|
+
lazyConnect: true,
|
|
208
|
+
};
|
|
209
|
+
if (this.config.url) {
|
|
210
|
+
this.client = new IORedisCtor(this.config.url);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
const opts = { ...failFastDefaults };
|
|
214
|
+
if (this.config.host)
|
|
215
|
+
opts.host = this.config.host;
|
|
216
|
+
if (this.config.port)
|
|
217
|
+
opts.port = this.config.port;
|
|
218
|
+
if (this.config.username)
|
|
219
|
+
opts.username = this.config.username;
|
|
220
|
+
if (this.config.password)
|
|
221
|
+
opts.password = this.config.password;
|
|
222
|
+
if (typeof this.config.db === "number")
|
|
223
|
+
opts.db = this.config.db;
|
|
224
|
+
if (this.config.tls)
|
|
225
|
+
opts.tls = {};
|
|
226
|
+
this.client = new IORedisCtor(opts);
|
|
227
|
+
}
|
|
228
|
+
this.client.on("error", (err) => {
|
|
229
|
+
console.warn(`[blok][debounce][redis] client error: ${err.message}`);
|
|
230
|
+
});
|
|
231
|
+
await this.client.ping();
|
|
232
|
+
this.connected = true;
|
|
233
|
+
}
|
|
234
|
+
async disconnect() {
|
|
235
|
+
if (!this.connected)
|
|
236
|
+
return;
|
|
237
|
+
try {
|
|
238
|
+
await this.client?.quit();
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
// best-effort
|
|
242
|
+
}
|
|
243
|
+
finally {
|
|
244
|
+
this.client = null;
|
|
245
|
+
this.connected = false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
bucketKey(workflowName, debounceKey) {
|
|
249
|
+
return `${this.config.keyPrefix}:${this.encodeSegment(workflowName)}__${this.encodeSegment(debounceKey)}`;
|
|
250
|
+
}
|
|
251
|
+
encodeSegment(s) {
|
|
252
|
+
return s.replace(/[^-_=.a-zA-Z0-9]/g, (ch) => `_${ch.codePointAt(0)?.toString(16)}_`);
|
|
253
|
+
}
|
|
254
|
+
requireClient() {
|
|
255
|
+
if (!this.client) {
|
|
256
|
+
throw new Error("RedisDebounceBackend not connected — call connect() first.");
|
|
257
|
+
}
|
|
258
|
+
return this.client;
|
|
259
|
+
}
|
|
260
|
+
async registerPing(opts) {
|
|
261
|
+
const client = this.requireClient();
|
|
262
|
+
const key = this.bucketKey(opts.workflowName, opts.debounceKey);
|
|
263
|
+
const raw = await client.eval(REGISTER_PING_LUA, 1, key, opts.mode, String(opts.delayMs), opts.maxDelayMs !== undefined ? String(opts.maxDelayMs) : "-1", opts.runId, opts.processId, String(opts.ownerLeaseMs), String(opts.now));
|
|
264
|
+
return this.parseRegisterResult(raw);
|
|
265
|
+
}
|
|
266
|
+
async finalize(workflowName, debounceKey, runId, now) {
|
|
267
|
+
const client = this.requireClient();
|
|
268
|
+
const key = this.bucketKey(workflowName, debounceKey);
|
|
269
|
+
const raw = await client.eval(FINALIZE_LUA, 1, key, runId, String(now));
|
|
270
|
+
return this.parseFinalizeResult(raw);
|
|
271
|
+
}
|
|
272
|
+
async cancel(workflowName, debounceKey) {
|
|
273
|
+
const client = this.requireClient();
|
|
274
|
+
const key = this.bucketKey(workflowName, debounceKey);
|
|
275
|
+
const deleted = await client.del(key);
|
|
276
|
+
return deleted > 0;
|
|
277
|
+
}
|
|
278
|
+
async purgeExpired(now) {
|
|
279
|
+
const client = this.requireClient();
|
|
280
|
+
const pattern = `${this.config.keyPrefix}:*`;
|
|
281
|
+
let cursor = "0";
|
|
282
|
+
let purged = 0;
|
|
283
|
+
do {
|
|
284
|
+
let res;
|
|
285
|
+
try {
|
|
286
|
+
res = await client.scan(cursor, "MATCH", pattern, "COUNT", 100);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
return purged;
|
|
290
|
+
}
|
|
291
|
+
const [nextCursor, keys] = res;
|
|
292
|
+
cursor = nextCursor;
|
|
293
|
+
for (const key of keys) {
|
|
294
|
+
try {
|
|
295
|
+
const raw = await client.eval(PURGE_EXPIRED_BUCKET_LUA, 1, key, String(now));
|
|
296
|
+
const count = typeof raw === "number" ? raw : Number(raw);
|
|
297
|
+
if (!Number.isNaN(count))
|
|
298
|
+
purged += count;
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
// best-effort
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
} while (cursor !== "0");
|
|
305
|
+
return purged;
|
|
306
|
+
}
|
|
307
|
+
parseRegisterResult(raw) {
|
|
308
|
+
if (!Array.isArray(raw) || raw.length < 4) {
|
|
309
|
+
throw new Error(`Unexpected Lua result shape for registerPing: ${JSON.stringify(raw)}`);
|
|
310
|
+
}
|
|
311
|
+
const outcome = String(raw[0]);
|
|
312
|
+
if (outcome !== "owner-new" && outcome !== "owner-extend" && outcome !== "coalesce") {
|
|
313
|
+
throw new Error(`Unexpected outcome in Lua result: ${outcome}`);
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
outcome,
|
|
317
|
+
activeRunId: String(raw[1]),
|
|
318
|
+
scheduledAt: Number(raw[2]),
|
|
319
|
+
pingCount: Number(raw[3]),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
parseFinalizeResult(raw) {
|
|
323
|
+
if (!Array.isArray(raw) || raw.length < 1)
|
|
324
|
+
return { finalize: "abandoned" };
|
|
325
|
+
const tag = String(raw[0]);
|
|
326
|
+
if (tag === "fire")
|
|
327
|
+
return { finalize: "fire" };
|
|
328
|
+
if (tag === "reschedule")
|
|
329
|
+
return { finalize: "reschedule", scheduledAt: Number(raw[1]) };
|
|
330
|
+
return { finalize: "abandoned" };
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Per-bucket purge. Deletes the bucket iff the owner-lease has expired
|
|
335
|
+
* AND scheduledAt has elapsed (no active owner with a pending fire).
|
|
336
|
+
*
|
|
337
|
+
* KEYS[1] = bucket key
|
|
338
|
+
* ARGV[1] = now
|
|
339
|
+
*
|
|
340
|
+
* Returns: 1 if deleted, 0 otherwise.
|
|
341
|
+
*/
|
|
342
|
+
const PURGE_EXPIRED_BUCKET_LUA = `
|
|
343
|
+
local raw = redis.call('GET', KEYS[1])
|
|
344
|
+
if not raw or raw == '' then return 0 end
|
|
345
|
+
local ok, doc = pcall(cjson.decode, raw)
|
|
346
|
+
if not ok or type(doc) ~= 'table' then return 0 end
|
|
347
|
+
local now = tonumber(ARGV[1])
|
|
348
|
+
local lease = tonumber(doc.ownerLeaseExpiresAt) or 0
|
|
349
|
+
local sched = tonumber(doc.scheduledAt) or 0
|
|
350
|
+
if lease <= now and sched <= now then
|
|
351
|
+
redis.call('DEL', KEYS[1])
|
|
352
|
+
return 1
|
|
353
|
+
end
|
|
354
|
+
return 0
|
|
355
|
+
`;
|
|
356
|
+
//# sourceMappingURL=RedisDebounceBackend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RedisDebounceBackend.js","sourceRoot":"","sources":["../../src/scheduling/RedisDebounceBackend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier C #1 · Debounce backend factory.
|
|
3
|
+
*
|
|
4
|
+
* Reads `BLOK_DEBOUNCE_BACKEND` and returns the matching backend
|
|
5
|
+
* instance, or `null` when the operator wants the default in-process
|
|
6
|
+
* coordinator (no cross-process coordination).
|
|
7
|
+
*
|
|
8
|
+
* Trigger packages call this in `listen()` and pass the result to
|
|
9
|
+
* `DebounceCoordinator.getInstance().setBackend(backend)`.
|
|
10
|
+
*/
|
|
11
|
+
import type { DebounceBackend } from "./DebounceBackend";
|
|
12
|
+
/**
|
|
13
|
+
* Returns a configured `DebounceBackend` based on
|
|
14
|
+
* `BLOK_DEBOUNCE_BACKEND`, or `null` for the default in-memory coordinator.
|
|
15
|
+
*
|
|
16
|
+
* Recognized values:
|
|
17
|
+
* - unset / `""` / `"memory"` / `"in-process"` — null (use default in-memory)
|
|
18
|
+
* - `"nats-kv"` — NATS KV backend (requires `nats` package + reachable NATS server)
|
|
19
|
+
* - `"redis"` — Redis backend (requires `ioredis` package + reachable Redis server)
|
|
20
|
+
*
|
|
21
|
+
* Unknown values throw at startup with a clear error message — silently
|
|
22
|
+
* falling back would be dangerous (operator thinks they configured
|
|
23
|
+
* cross-process debounce but they didn't).
|
|
24
|
+
*/
|
|
25
|
+
export declare function createDebounceBackend(): DebounceBackend | null;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier C #1 · Debounce backend factory.
|
|
3
|
+
*
|
|
4
|
+
* Reads `BLOK_DEBOUNCE_BACKEND` and returns the matching backend
|
|
5
|
+
* instance, or `null` when the operator wants the default in-process
|
|
6
|
+
* coordinator (no cross-process coordination).
|
|
7
|
+
*
|
|
8
|
+
* Trigger packages call this in `listen()` and pass the result to
|
|
9
|
+
* `DebounceCoordinator.getInstance().setBackend(backend)`.
|
|
10
|
+
*/
|
|
11
|
+
import { NatsKvDebounceBackend } from "./NatsKvDebounceBackend";
|
|
12
|
+
import { RedisDebounceBackend } from "./RedisDebounceBackend";
|
|
13
|
+
/**
|
|
14
|
+
* Returns a configured `DebounceBackend` based on
|
|
15
|
+
* `BLOK_DEBOUNCE_BACKEND`, or `null` for the default in-memory coordinator.
|
|
16
|
+
*
|
|
17
|
+
* Recognized values:
|
|
18
|
+
* - unset / `""` / `"memory"` / `"in-process"` — null (use default in-memory)
|
|
19
|
+
* - `"nats-kv"` — NATS KV backend (requires `nats` package + reachable NATS server)
|
|
20
|
+
* - `"redis"` — Redis backend (requires `ioredis` package + reachable Redis server)
|
|
21
|
+
*
|
|
22
|
+
* Unknown values throw at startup with a clear error message — silently
|
|
23
|
+
* falling back would be dangerous (operator thinks they configured
|
|
24
|
+
* cross-process debounce but they didn't).
|
|
25
|
+
*/
|
|
26
|
+
export function createDebounceBackend() {
|
|
27
|
+
const kind = (process.env.BLOK_DEBOUNCE_BACKEND ?? "").trim().toLowerCase();
|
|
28
|
+
if (!kind || kind === "memory" || kind === "in-process")
|
|
29
|
+
return null;
|
|
30
|
+
switch (kind) {
|
|
31
|
+
case "nats-kv":
|
|
32
|
+
return new NatsKvDebounceBackend();
|
|
33
|
+
case "redis":
|
|
34
|
+
return new RedisDebounceBackend();
|
|
35
|
+
default:
|
|
36
|
+
throw new Error(`Unknown BLOK_DEBOUNCE_BACKEND='${kind}'. Expected one of: 'memory' (default), 'nats-kv', 'redis'.`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=createDebounceBackend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDebounceBackend.js","sourceRoot":"","sources":["../../src/scheduling/createDebounceBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB;IACpC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5E,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IAErE,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,SAAS;YACb,OAAO,IAAI,qBAAqB,EAAE,CAAC;QACpC,KAAK,OAAO;YACX,OAAO,IAAI,oBAAoB,EAAE,CAAC;QACnC;YACC,MAAM,IAAI,KAAK,CACd,kCAAkC,IAAI,6DAA6D,CACnG,CAAC;IACJ,CAAC;AACF,CAAC"}
|
|
@@ -264,7 +264,7 @@ export class FileAuditSink {
|
|
|
264
264
|
await mkdir(dirname(this.filePath), { recursive: true });
|
|
265
265
|
this.initialized = true;
|
|
266
266
|
}
|
|
267
|
-
const data = this.buffer.join("\n")
|
|
267
|
+
const data = `${this.buffer.join("\n")}\n`;
|
|
268
268
|
this.buffer = [];
|
|
269
269
|
await appendFile(this.filePath, data, "utf-8");
|
|
270
270
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditLogger.js","sourceRoot":"","sources":["../../src/security/AuditLogger.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"AuditLogger.js","sourceRoot":"","sources":["../../src/security/AuditLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Authentication Middleware for Blok Triggers
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* - API
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* @deprecated Since v0.4.1. Will be removed in v0.5. This class ships as
|
|
5
|
+
* example-grade code (HS256-only JWT verification, no JWKS, no key
|
|
6
|
+
* rotation, non-constant-time API-key lookup) and is not wired into any
|
|
7
|
+
* trigger. Production deployments should compose auth from a hardened
|
|
8
|
+
* library (`jose`, `hono/jwt`, `node-jsonwebtoken`) at the trigger or
|
|
9
|
+
* workflow layer instead. See `docs/d/security/cookbook.mdx` for the
|
|
10
|
+
* recommended patterns.
|
|
10
11
|
*
|
|
11
12
|
* @example
|
|
12
13
|
* ```typescript
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* new APIKeyAuthProvider({
|
|
17
|
-
* keys: new Map([["my-api-key", { name: "service-a", roles: ["admin"] }]]),
|
|
18
|
-
* }),
|
|
19
|
-
* ],
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
* // In Express middleware
|
|
23
|
-
* app.use(auth.expressMiddleware());
|
|
24
|
-
*
|
|
25
|
-
* // Or manually
|
|
26
|
-
* const identity = await auth.authenticate(request);
|
|
14
|
+
* // Recommended (jose):
|
|
15
|
+
* import { jwtVerify } from "jose";
|
|
16
|
+
* const { payload } = await jwtVerify(token, secret, { issuer, audience });
|
|
27
17
|
* ```
|
|
28
18
|
*/
|
|
29
19
|
export interface AuthIdentity {
|
|
@@ -75,6 +65,9 @@ export interface AuthMiddlewareConfig {
|
|
|
75
65
|
/** Custom error handler */
|
|
76
66
|
onAuthFailure?: (result: AuthResult, request: AuthRequest) => void;
|
|
77
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Since v0.4.1. See file-level JSDoc; will be removed in v0.5.
|
|
70
|
+
*/
|
|
78
71
|
export declare class AuthMiddleware {
|
|
79
72
|
private config;
|
|
80
73
|
constructor(config: AuthMiddlewareConfig);
|
|
@@ -119,6 +112,9 @@ export interface JWTAuthProviderConfig {
|
|
|
119
112
|
/** Map JWT claims to roles (claim name → role mapping function) */
|
|
120
113
|
rolesClaim?: string;
|
|
121
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* @deprecated Since v0.4.1. See file-level JSDoc; will be removed in v0.5.
|
|
117
|
+
*/
|
|
122
118
|
export declare class JWTAuthProvider implements AuthProvider {
|
|
123
119
|
readonly name = "jwt";
|
|
124
120
|
private config;
|
|
@@ -154,6 +150,9 @@ export interface APIKeyAuthProviderConfig {
|
|
|
154
150
|
/** Custom key validation function (e.g., for database lookups) */
|
|
155
151
|
validate?: (key: string) => Promise<APIKeyInfo | null>;
|
|
156
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* @deprecated Since v0.4.1. See file-level JSDoc; will be removed in v0.5.
|
|
155
|
+
*/
|
|
157
156
|
export declare class APIKeyAuthProvider implements AuthProvider {
|
|
158
157
|
readonly name = "api-key";
|
|
159
158
|
private config;
|
|
@@ -1,32 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Authentication Middleware for Blok Triggers
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* - API
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* @deprecated Since v0.4.1. Will be removed in v0.5. This class ships as
|
|
5
|
+
* example-grade code (HS256-only JWT verification, no JWKS, no key
|
|
6
|
+
* rotation, non-constant-time API-key lookup) and is not wired into any
|
|
7
|
+
* trigger. Production deployments should compose auth from a hardened
|
|
8
|
+
* library (`jose`, `hono/jwt`, `node-jsonwebtoken`) at the trigger or
|
|
9
|
+
* workflow layer instead. See `docs/d/security/cookbook.mdx` for the
|
|
10
|
+
* recommended patterns.
|
|
10
11
|
*
|
|
11
12
|
* @example
|
|
12
13
|
* ```typescript
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* new APIKeyAuthProvider({
|
|
17
|
-
* keys: new Map([["my-api-key", { name: "service-a", roles: ["admin"] }]]),
|
|
18
|
-
* }),
|
|
19
|
-
* ],
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
* // In Express middleware
|
|
23
|
-
* app.use(auth.expressMiddleware());
|
|
24
|
-
*
|
|
25
|
-
* // Or manually
|
|
26
|
-
* const identity = await auth.authenticate(request);
|
|
14
|
+
* // Recommended (jose):
|
|
15
|
+
* import { jwtVerify } from "jose";
|
|
16
|
+
* const { payload } = await jwtVerify(token, secret, { issuer, audience });
|
|
27
17
|
* ```
|
|
28
18
|
*/
|
|
29
19
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
20
|
+
let authMiddlewareWarningEmitted = false;
|
|
21
|
+
function emitAuthMiddlewareDeprecationWarning() {
|
|
22
|
+
if (authMiddlewareWarningEmitted)
|
|
23
|
+
return;
|
|
24
|
+
authMiddlewareWarningEmitted = true;
|
|
25
|
+
if (process.env.BLOK_SUPPRESS_AUTHMIDDLEWARE_WARNING === "1")
|
|
26
|
+
return;
|
|
27
|
+
console.warn("[blok] AuthMiddleware (and JWTAuthProvider, APIKeyAuthProvider) is deprecated and will be removed in v0.5. " +
|
|
28
|
+
"It ships as example-grade code, not production auth. " +
|
|
29
|
+
"Use `jose`, `hono/jwt`, or `node-jsonwebtoken` at the trigger or workflow layer instead. " +
|
|
30
|
+
"See docs/d/security/cookbook.mdx. " +
|
|
31
|
+
"Set BLOK_SUPPRESS_AUTHMIDDLEWARE_WARNING=1 to silence.");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated Since v0.4.1. See file-level JSDoc; will be removed in v0.5.
|
|
35
|
+
*/
|
|
30
36
|
export class AuthMiddleware {
|
|
31
37
|
config;
|
|
32
38
|
constructor(config) {
|
|
@@ -35,6 +41,7 @@ export class AuthMiddleware {
|
|
|
35
41
|
required: true,
|
|
36
42
|
...config,
|
|
37
43
|
};
|
|
44
|
+
emitAuthMiddlewareDeprecationWarning();
|
|
38
45
|
}
|
|
39
46
|
/**
|
|
40
47
|
* Authenticate a request against all registered providers.
|
|
@@ -108,6 +115,9 @@ export class AuthMiddleware {
|
|
|
108
115
|
return (this.config.excludePaths || []).some((excluded) => path === excluded || path.startsWith(`${excluded}/`));
|
|
109
116
|
}
|
|
110
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* @deprecated Since v0.4.1. See file-level JSDoc; will be removed in v0.5.
|
|
120
|
+
*/
|
|
111
121
|
export class JWTAuthProvider {
|
|
112
122
|
name = "jwt";
|
|
113
123
|
config;
|
|
@@ -118,6 +128,7 @@ export class JWTAuthProvider {
|
|
|
118
128
|
rolesClaim: "roles",
|
|
119
129
|
...config,
|
|
120
130
|
};
|
|
131
|
+
emitAuthMiddlewareDeprecationWarning();
|
|
121
132
|
}
|
|
122
133
|
async authenticate(request) {
|
|
123
134
|
const headerValue = request.headers[this.config.headerName || "authorization"];
|
|
@@ -213,6 +224,9 @@ export class JWTAuthProvider {
|
|
|
213
224
|
}
|
|
214
225
|
}
|
|
215
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* @deprecated Since v0.4.1. See file-level JSDoc; will be removed in v0.5.
|
|
229
|
+
*/
|
|
216
230
|
export class APIKeyAuthProvider {
|
|
217
231
|
name = "api-key";
|
|
218
232
|
config;
|
|
@@ -222,6 +236,7 @@ export class APIKeyAuthProvider {
|
|
|
222
236
|
queryParam: "api_key",
|
|
223
237
|
...config,
|
|
224
238
|
};
|
|
239
|
+
emitAuthMiddlewareDeprecationWarning();
|
|
225
240
|
}
|
|
226
241
|
async authenticate(request) {
|
|
227
242
|
// Try header first
|