@deslop/stash 0.1.0 → 0.1.1018

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/cli.js CHANGED
@@ -1,6 +1,669 @@
1
1
  #!/usr/bin/env -S node --max-old-space-size=16384 --heapsnapshot-near-heap-limit=3 --report-on-fatalerror
2
- import { Cc as getOrElse, Ci as fail, Cl as identity, Co as provideMerge, Ct as TrueLiterals, D as Stdio, Ea as void_, Ec as isNone, El as pipeArguments, Et as Union, Fc as some, Fi as gen, Gc as withFiber, Gi as map$3, Gs as isReadonlyArrayNonEmpty, Is as findFirst, Ji as match$2, Js as match, Jt as optional$2, Ka as round, Kc as assignProperty, Li as interrupt, Ls as findFirstIndex, Mc as match$1, Ms as empty, Nc as none, Oc as isSome, Oi as fnUntraced, Os as Prototype, Pt as decodeUnknownEffect, Qt as toCodecStringTree, Rs as findLast, Sc as fromUndefinedOr, St as TaggedError, Tc as getOrUndefined, Ti as flatMap$1, Tl as pipe, Ts as make$2, Vt as is, Wr as take, Xo as ConsoleRef, Xs as reduce, Yt as optionalKey, Zc as format, _a as sync$1, _s as Reference, a as LogToStderr, aa as provideContext, bo as merge, bs as empty$1, bt as String$6, c as runMain, ca as result, cl as hasProperty, d as layer, ds as taggedEnum, f as QuitError, fa as scoped, fi as catchFilter, ft as Literal, ga as suspend, gi as catchTags, h as layer$1, hc as succeed$2, hi as catchTag, ia as provide, ic as fail$1, ir as FileSystem, it as BooleanLiterals, jc as map$5, l as errorExitCode, lt as FalseLiterals, m as isQuitError, ma as succeed$1, mn as value, na as orDie, nt as ArraySchema, oa as provideService, ot as Defect, p as Terminal, pn as make$1, qi as mapError, qs as map$4, ri as andThen, rr as Path$2, rs as sync, sa as raceFirst, t as Media, u as errorReported, ul as isNotUndefined, vc as exists, vs as Service, xi as ensuring, xl as dual, zi as isEffect, zo as MinimumLogLevel } from "./service-D6Z3eq9Z.mjs";
3
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/Console.js
2
+ import { $ as Socket, $l as dual, $o as MinimumLogLevel, Ao as effect, Ar as take, At as TaggedError, B as constPing, Ci as fnUntraced, Cl as assignProperty, Cr as failCause, Ct as Literal, D as option, Di as forkIn, Do as squash, Ea as timeoutOrElse, Er as offerAll, F as layerJson, Fa as whileLoop, Fi as interruptible, Fs as Reference, Gc as succeed$2, Gn as fromQueue, Gt as tag, Ha as exponential, Hc as isSuccess, Hl as hasProperty, Ho as Scope, Hs as getUnsafe, Ht as is, Ia as withFiber, Ic as fail$2, Ii as isEffect, Ir as makeUnsafe, Is as Service, It as decodeSync, J as spanAttributes, Jc as exists, Ji as matchCauseEffect, K as getStreamSchemas, Ki as mapError, Ks as Prototype, L as RequestId, Lo as provide$1, Lr as getCurrent, Ls as add, Lt as decodeUnknownEffect, Mi as ignore, N as withRunClient, Na as useSpan, Ni as ignoreCause, Nt as Union, Oi as forkScoped, Ot as String$6, P as RpcSerialization, Pa as void_, Pi as interrupt$1, Ps as toMillis, Qi as onError, Qs as empty$2, Rr as interrupt$2, Rs as empty$1, Rt as encodeEffect, Sa as tapCause, Sc as reduce, Sl as withFiber$1, So as interruptors, Sr as end, Ss as sync, Ti as forever, Tt as NonEmptyArray, U as exitSchema, Ua as min, Ui as makeSpanScoped, Ul as isNotUndefined, Uo as addFinalizer, Us as make$3, Ut as optional$2, Vi as logInfo, Vs as getOrUndefinedUnsafe, Wa as spaced, Wi as map$3, Wo as addFinalizerExit, Wt as optionalKey, X as Collector, Xa as isEmpty, Xr as andThen, Y as spanName, Z as makeCollectorUnsafe, Za as isNonEmpty, Zl as constVoid, Zr as annotateLogs, _ as QuitError, _a as serviceOption, _o as findError, _t as BooleanLiterals, aa as provide, al as isSome, ar as runHead, at as layerWebSocket, ba as suspend, bc as match, bi as flatMap$1, bo as hasInterrupts, br as bounded, c as NotesError, ca as raceFirst, cl as map$4, dt as HttpClientErrorSchema, el as fromUndefinedOr, et as SocketError, fa as runForkWith, fi as context, fl as some, g as layer, gc as join, gi as ensuring, gt as ArraySchema, h as errorReported, ha as scoped, hc as isReadonlyArrayNonEmpty, hn as value, ic as findLast, ii as catchCauseIf, il as isNone, is as interrupt, j as Stdio, ja as uninterruptibleMask, ji as gen, jl as format, js as taggedEnum, jt as TrueLiterals, kr as shutdownUnsafe, la as result, li as catchTag, ll as match$1, lo as round, m as errorExitCode, mi as delay, mn as make$2, ms as ConsoleRef, na as orDie, nc as findFirst, ni as callback, ns as fail, nu as pipe, oa as provideContext, oi as catchFilter, on as empty, os as isFailure, ot as layerWebSocketConstructorGlobal, p as runMain, pr as unwrap, q as isStreamSchema, qi as match$2, qt as toCodecStringTree, rc as findFirstIndex, ri as catchCause, rl as getOrUndefined, rs as failCause$1, rt as SocketReadError, ru as pipeArguments, sa as provideService, sn as fromInput, t as RpcContracts, ta as onInterrupt, tc as filter$1, tl as getOrElse, to as replace, ts as die, tt as SocketErrorReason, tu as identity, u as LogToStderr, ua as retryOrElse, ui as catchTags, ul as none, un as merge, uo as Clock, v as Terminal, va as succeed$1, vi as fail$1, vt as Defect, w as String$7, wa as timeout, wc as some$1, wi as forEach, x as Crypto, xa as sync$1, xt as FalseLiterals, y as isQuitError, yc as map$5, yt as Error$1, za as withParentSpan, zi as logError, zn as filter, zs as get } from "./contracts-Cy_AB8uR.mjs";
3
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/workers/WorkerError.js
4
+ /**
5
+ * Worker error reason for failures while spawning or setting up a worker.
6
+ *
7
+ * @stability unstable
8
+ * @category errors
9
+ * @since 4.0.0
10
+ */
11
+ var WorkerSpawnError = class extends (/*#__PURE__*/ Error$1("effect/workers/WorkerError/WorkerSpawnError")({
12
+ _tag: /*#__PURE__*/ tag("WorkerSpawnError"),
13
+ message: String$6,
14
+ cause: /*#__PURE__*/ optional$2(/*#__PURE__*/ Defect())
15
+ })) {};
16
+ /**
17
+ * Worker error reason for failures while sending a message to a worker.
18
+ *
19
+ * @stability unstable
20
+ * @category errors
21
+ * @since 4.0.0
22
+ */
23
+ var WorkerSendError = class extends (/*#__PURE__*/ Error$1("effect/workers/WorkerError/WorkerSendError")({
24
+ _tag: /*#__PURE__*/ tag("WorkerSendError"),
25
+ message: String$6,
26
+ cause: /*#__PURE__*/ optional$2(/*#__PURE__*/ Defect())
27
+ })) {};
28
+ /**
29
+ * Worker error reason for failures while receiving or handling a message from a
30
+ * worker.
31
+ *
32
+ * @stability unstable
33
+ * @category errors
34
+ * @since 4.0.0
35
+ */
36
+ var WorkerReceiveError = class extends (/*#__PURE__*/ Error$1("effect/workers/WorkerError/WorkerReceiveError")({
37
+ _tag: /*#__PURE__*/ tag("WorkerReceiveError"),
38
+ message: String$6,
39
+ cause: /*#__PURE__*/ optional$2(/*#__PURE__*/ Defect())
40
+ })) {};
41
+ /**
42
+ * Worker error reason for an unclassified worker failure.
43
+ *
44
+ * @stability unstable
45
+ * @category errors
46
+ * @since 4.0.0
47
+ */
48
+ var WorkerUnknownError = class extends (/*#__PURE__*/ Error$1("effect/workers/WorkerError/WorkerUnknownError")({
49
+ _tag: /*#__PURE__*/ tag("WorkerUnknownError"),
50
+ message: String$6,
51
+ cause: /*#__PURE__*/ optional$2(/*#__PURE__*/ Defect())
52
+ })) {};
53
+ /**
54
+ * Schema for decoding and encoding all supported worker error reason variants.
55
+ *
56
+ * @stability unstable
57
+ * @category schemas
58
+ * @since 4.0.0
59
+ */
60
+ const WorkerErrorReason = /*#__PURE__*/ Union([
61
+ WorkerSpawnError,
62
+ WorkerSendError,
63
+ WorkerReceiveError,
64
+ WorkerUnknownError
65
+ ]);
66
+ //#endregion
67
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/rpc/RpcClientError.js
68
+ /**
69
+ * Client-side protocol failures reported by unstable RPC transports.
70
+ *
71
+ * `RpcClientError` is the error type generated clients use when a call fails
72
+ * before a remote handler can return its declared typed error. Its `reason`
73
+ * covers built-in transport failures from HTTP, sockets, and workers, plus
74
+ * `RpcClientDefect` values for malformed or incompatible protocol data.
75
+ *
76
+ * @stability unstable
77
+ * @since 4.0.0
78
+ */
79
+ const TypeId$4 = "~effect/rpc/RpcClientError";
80
+ /**
81
+ * Represents a client-side RPC defect, such as a protocol violation or
82
+ * decoding failure, with a message and original cause.
83
+ *
84
+ * @stability unstable
85
+ * @category errors
86
+ * @since 4.0.0
87
+ */
88
+ var RpcClientDefect = class extends (/*#__PURE__*/ Error$1("effect/rpc/RpcClientError/RpcClientDefect")({
89
+ _tag: /*#__PURE__*/ tag("RpcClientDefect"),
90
+ message: String$6,
91
+ cause: /*#__PURE__*/ Defect()
92
+ })) {};
93
+ /**
94
+ * Error wrapper for RPC client failures, including worker, socket, HTTP client,
95
+ * and client protocol defect failures.
96
+ *
97
+ * @stability unstable
98
+ * @category errors
99
+ * @since 4.0.0
100
+ */
101
+ var RpcClientError = class extends (/*#__PURE__*/ Error$1(TypeId$4)({
102
+ _tag: /*#__PURE__*/ tag("RpcClientError"),
103
+ reason: /*#__PURE__*/ Union([
104
+ WorkerErrorReason,
105
+ SocketErrorReason,
106
+ HttpClientErrorSchema,
107
+ RpcClientDefect
108
+ ])
109
+ })) {
110
+ /**
111
+ * Marks this value as an RPC client error for runtime guards.
112
+ *
113
+ * @stability unstable
114
+ * @since 4.0.0
115
+ */
116
+ [TypeId$4] = TypeId$4;
117
+ get message() {
118
+ return `${this.reason._tag}: ${this.reason.message}`;
119
+ }
120
+ };
121
+ //#endregion
122
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/rpc/RpcClient.js
123
+ let requestIdCounter = 0;
124
+ /**
125
+ * Creates an RPC client for an already-decoded message channel, returning the
126
+ * client API together with a `write` function for delivering server messages
127
+ * back to the client.
128
+ *
129
+ * @stability unstable
130
+ * @category constructors
131
+ * @since 4.0.0
132
+ */
133
+ const makeNoSerialization = /*#__PURE__*/ fnUntraced(function* (group, options) {
134
+ const spanPrefix = options.spanPrefix;
135
+ const supportsAck = options?.supportsAck ?? true;
136
+ const disableTracing = options?.disableTracing ?? false;
137
+ const generateRequestId = options?.generateRequestId ?? (() => requestIdCounter++);
138
+ const services = yield* context();
139
+ const scope = get(services, Scope);
140
+ const entries = /* @__PURE__ */ new Map();
141
+ let isShutdown = false;
142
+ yield* addFinalizer(scope, withFiber((parent) => {
143
+ isShutdown = true;
144
+ return clearEntries(interrupt(parent.id));
145
+ }));
146
+ const clearEntries = fnUntraced(function* (exit) {
147
+ for (const [id, entry] of entries) {
148
+ entries.delete(id);
149
+ if (entry._tag === "Queue") yield* exit._tag === "Success" ? end(entry.queue) : failCause(entry.queue, exit.cause);
150
+ else entry.resume(exit);
151
+ }
152
+ });
153
+ const onRequest = (rpc) => {
154
+ const isStream = isStreamSchema(rpc.successSchema);
155
+ const middleware = getRpcClientMiddleware(rpc);
156
+ return (payload, opts) => {
157
+ const headers = opts?.headers ? fromInput(opts.headers) : empty;
158
+ const context = opts?.context ?? empty$1();
159
+ if (!isStream) {
160
+ const onRequest = (span) => onEffectRequest(rpc, middleware, span, rpc.payloadSchema.make(payload), headers, context, opts?.discard ?? false);
161
+ return disableTracing ? onRequest(void 0) : useSpan(spanName(spanPrefix, rpc._tag), {
162
+ kind: "client",
163
+ attributes: spanAttributes(rpc._tag, options.spanAttributes)
164
+ }, onRequest);
165
+ }
166
+ const queue = onStreamRequest(rpc, middleware, rpc.payloadSchema.make(payload), headers, opts?.streamBufferSize ?? 16, context);
167
+ if (opts?.asQueue) return queue;
168
+ return unwrap(map$3(queue, fromQueue));
169
+ };
170
+ };
171
+ const onEffectRequest = (rpc, middleware, span, payload, headers, context, discard) => withFiber((parentFiber) => {
172
+ if (isShutdown) return interrupt$1;
173
+ const id = generateRequestId();
174
+ const send = middleware((message) => options.onFromClient({
175
+ message,
176
+ context,
177
+ discard
178
+ }), {
179
+ _tag: "Request",
180
+ id,
181
+ tag: rpc._tag,
182
+ payload,
183
+ ...span ? {
184
+ traceId: span.traceId,
185
+ spanId: span.spanId,
186
+ sampled: span.sampled
187
+ } : {},
188
+ headers: merge(parentFiber.getRef(CurrentHeaders), headers)
189
+ });
190
+ if (discard) return send;
191
+ let fiber;
192
+ return onInterrupt(callback((resume) => {
193
+ const entry = {
194
+ _tag: "Effect",
195
+ rpc,
196
+ context,
197
+ resume(exit) {
198
+ resume(exit);
199
+ if (fiber && !fiber.pollUnsafe()) parentFiber.currentDispatcher.scheduleTask(() => {
200
+ fiber.interruptUnsafe(parentFiber.id);
201
+ }, 0);
202
+ }
203
+ };
204
+ entries.set(id, entry);
205
+ fiber = send.pipe(span ? withParentSpan(span, { captureStackTrace: false }) : identity, runForkWith(parentFiber.context));
206
+ fiber.addObserver((exit) => {
207
+ if (exit._tag === "Failure") return resume(exit);
208
+ });
209
+ }), (interruptors) => {
210
+ entries.delete(id);
211
+ return andThen(interrupt$2(fiber), sendInterrupt(id, Array.from(interruptors), context));
212
+ });
213
+ });
214
+ const onStreamRequest = fnUntraced(function* (rpc, middleware, payload, headers, streamBufferSize, context) {
215
+ if (isShutdown) return yield* interrupt$1;
216
+ const span = disableTracing ? void 0 : yield* makeSpanScoped(spanName(spanPrefix, rpc._tag), {
217
+ kind: "client",
218
+ attributes: spanAttributes(rpc._tag, options.spanAttributes)
219
+ });
220
+ const fiber = getCurrent();
221
+ const id = generateRequestId();
222
+ const scope = getUnsafe(fiber.context, Scope);
223
+ const queue = yield* bounded(streamBufferSize);
224
+ yield* addFinalizerExit(scope, (exit) => {
225
+ shutdownUnsafe(queue);
226
+ if (!entries.has(id)) return void_;
227
+ entries.delete(id);
228
+ return sendInterrupt(id, isFailure(exit) ? Array.from(interruptors(exit.cause)) : [], context);
229
+ });
230
+ entries.set(id, {
231
+ _tag: "Queue",
232
+ rpc,
233
+ queue,
234
+ scope,
235
+ context
236
+ });
237
+ yield* middleware((message) => options.onFromClient({
238
+ message,
239
+ context,
240
+ discard: false
241
+ }), {
242
+ _tag: "Request",
243
+ id,
244
+ tag: rpc._tag,
245
+ payload,
246
+ ...span ? {
247
+ traceId: span.traceId,
248
+ spanId: span.spanId,
249
+ sampled: span.sampled
250
+ } : {},
251
+ headers: merge(fiber.getRef(CurrentHeaders), headers)
252
+ }).pipe(span ? withParentSpan(span, { captureStackTrace: false }) : identity, onError((cause) => failCause(queue, cause)), interruptible, forkIn(scope, { startImmediately: true }));
253
+ return queue;
254
+ });
255
+ const getRpcClientMiddleware = (rpc) => {
256
+ const middlewares = [];
257
+ for (const tag of rpc.middlewares.values()) {
258
+ const middleware = getOrUndefinedUnsafe(services, `${tag.key}/Client`);
259
+ if (!middleware) continue;
260
+ middlewares.push(middleware);
261
+ }
262
+ if (middlewares.length === 0) return (send, request) => send(request);
263
+ return function loop(send, request, index = middlewares.length - 1) {
264
+ if (index === -1) return send(request);
265
+ return middlewares[index]({
266
+ rpc,
267
+ request,
268
+ next(request) {
269
+ return loop(send, request, index - 1);
270
+ }
271
+ });
272
+ };
273
+ };
274
+ const sendInterrupt = (requestId, interruptors, context) => callback((resume) => {
275
+ const parentFiber = getCurrent();
276
+ options.onFromClient({
277
+ message: {
278
+ _tag: "Interrupt",
279
+ requestId,
280
+ interruptors
281
+ },
282
+ context,
283
+ discard: false
284
+ }).pipe(timeout(1e3), runForkWith(parentFiber.context)).addObserver(() => {
285
+ resume(void_);
286
+ });
287
+ });
288
+ const write = (message) => {
289
+ switch (message._tag) {
290
+ case "Chunk": {
291
+ const requestId = message.requestId;
292
+ const entry = entries.get(requestId);
293
+ if (!entry || entry._tag !== "Queue") return void_;
294
+ return offerAll(entry.queue, message.values).pipe(supportsAck ? flatMap$1(() => options.onFromClient({
295
+ message: {
296
+ _tag: "Ack",
297
+ requestId: message.requestId
298
+ },
299
+ context: entry.context,
300
+ discard: false
301
+ })) : identity, catchCause((cause) => failCause(entry.queue, cause)));
302
+ }
303
+ case "Exit": {
304
+ const requestId = message.requestId;
305
+ const entry = entries.get(requestId);
306
+ if (!entry) return void_;
307
+ entries.delete(requestId);
308
+ if (entry._tag === "Effect") {
309
+ entry.resume(message.exit);
310
+ return void_;
311
+ }
312
+ return message.exit._tag === "Success" ? end(entry.queue) : failCause(entry.queue, message.exit.cause);
313
+ }
314
+ case "Defect": return clearEntries(die(message.defect));
315
+ case "ClientEnd": return void_;
316
+ }
317
+ };
318
+ let client;
319
+ if (options.flatten) {
320
+ const fns = /* @__PURE__ */ new Map();
321
+ client = function client(tag, payload, options) {
322
+ let fn = fns.get(tag);
323
+ if (!fn) {
324
+ fn = onRequest(group.requests.get(tag));
325
+ fns.set(tag, fn);
326
+ }
327
+ return fn(payload, options);
328
+ };
329
+ } else {
330
+ client = {};
331
+ group.requests.forEach((rpc) => {
332
+ assignProperty(client, rpc._tag, onRequest(rpc));
333
+ });
334
+ }
335
+ return {
336
+ client,
337
+ write
338
+ };
339
+ });
340
+ let clientIdCounter = 0;
341
+ /**
342
+ * Creates a schema-aware RPC client for a group using the current client
343
+ * `Protocol`, encoding requests and decoding server responses.
344
+ *
345
+ * @stability unstable
346
+ * @category constructors
347
+ * @since 4.0.0
348
+ */
349
+ const make$1 = /*#__PURE__*/ fnUntraced(function* (group, options) {
350
+ const clientId = clientIdCounter++;
351
+ const { codecFor, run, send, supportsAck, supportsTransferables } = yield* Protocol;
352
+ const rpcSchemas = makeRpcSchemas(codecFor);
353
+ const decodeDefect = decodeSync(codecFor(Defect()));
354
+ const entries = /* @__PURE__ */ new Map();
355
+ const interruptRequest = (requestId) => {
356
+ if (!entries.has(requestId)) return void_;
357
+ entries.delete(requestId);
358
+ return send(clientId, {
359
+ _tag: "Interrupt",
360
+ requestId
361
+ });
362
+ };
363
+ const { client, write } = yield* makeNoSerialization(group, {
364
+ ...options,
365
+ supportsAck,
366
+ onFromClient({ message }) {
367
+ switch (message._tag) {
368
+ case "Request": {
369
+ const rpc = group.requests.get(message.tag);
370
+ const collector = supportsTransferables ? makeCollectorUnsafe() : void 0;
371
+ const fiber = getCurrent();
372
+ const entry = {
373
+ rpc,
374
+ context: collector ? add(fiber.context, Collector, collector) : fiber.context,
375
+ schemas: rpcSchemas(rpc)
376
+ };
377
+ entries.set(message.id, entry);
378
+ return entry.schemas.encodePayload(message.payload).pipe(provideContext(entry.context), orDie, flatMap$1((payload) => send(clientId, {
379
+ ...message,
380
+ id: message.id,
381
+ payload,
382
+ headers: Object.entries(message.headers)
383
+ }, collector && collector.readUnsafe())));
384
+ }
385
+ case "Ack":
386
+ if (!entries.get(message.requestId)) return void_;
387
+ return send(clientId, {
388
+ _tag: "Ack",
389
+ requestId: message.requestId
390
+ });
391
+ case "Interrupt": return interruptRequest(message.requestId);
392
+ case "Eof": return void_;
393
+ }
394
+ }
395
+ });
396
+ yield* run(clientId, (message) => {
397
+ switch (message._tag) {
398
+ case "Chunk": {
399
+ const requestId = RequestId(message.requestId);
400
+ const entry = entries.get(requestId);
401
+ if (!entry || isNone(entry.schemas.decodeChunk)) return void_;
402
+ const decodeChunk = entry.schemas.decodeChunk.value;
403
+ return uninterruptibleMask((restore) => restore(decodeChunk(message.values).pipe(provideContext(entry.context), orDie, flatMap$1((chunk) => write({
404
+ _tag: "Chunk",
405
+ clientId: 0,
406
+ requestId,
407
+ values: chunk
408
+ })))).pipe(onError((cause) => write({
409
+ _tag: "Exit",
410
+ clientId: 0,
411
+ requestId,
412
+ exit: failCause$1(cause)
413
+ }).pipe(andThen(hasInterrupts(cause) ? void_ : ignore(interruptRequest(requestId))))), catchCauseIf((cause) => !hasInterrupts(cause), () => void_)));
414
+ }
415
+ case "Exit": {
416
+ const requestId = RequestId(message.requestId);
417
+ const entry = entries.get(requestId);
418
+ if (!entry) return void_;
419
+ entries.delete(requestId);
420
+ return entry.schemas.decodeExit(message.exit).pipe(provideContext(entry.context), orDie, matchCauseEffect({
421
+ onSuccess: (exit) => write({
422
+ _tag: "Exit",
423
+ clientId: 0,
424
+ requestId,
425
+ exit
426
+ }),
427
+ onFailure: (cause) => write({
428
+ _tag: "Exit",
429
+ clientId: 0,
430
+ requestId,
431
+ exit: failCause$1(cause)
432
+ })
433
+ }));
434
+ }
435
+ case "Defect": return write({
436
+ _tag: "Defect",
437
+ clientId: 0,
438
+ defect: decodeDefect(message.defect)
439
+ });
440
+ case "ClientProtocolError": {
441
+ const exit = fail(message.error);
442
+ return forEach(Array.from(entries.keys()), (requestId) => write({
443
+ _tag: "Exit",
444
+ clientId: 0,
445
+ requestId,
446
+ exit
447
+ }));
448
+ }
449
+ default: return void_;
450
+ }
451
+ }).pipe(catchCause(logError), interruptible, forkScoped);
452
+ return client;
453
+ });
454
+ const makeRpcSchemas = (codecFor) => {
455
+ const cache = /* @__PURE__ */ new WeakMap();
456
+ return (rpc) => {
457
+ let entry = cache.get(rpc);
458
+ if (entry !== void 0) return entry;
459
+ const streamSchemas = getStreamSchemas(rpc.successSchema);
460
+ entry = {
461
+ decodeChunk: map$4(streamSchemas, (streamSchemas) => decodeUnknownEffect(codecFor(NonEmptyArray(streamSchemas.success)))),
462
+ encodePayload: encodeEffect(codecFor(rpc.payloadSchema)),
463
+ decodeExit: decodeUnknownEffect(codecFor(exitSchema(rpc)))
464
+ };
465
+ cache.set(rpc, entry);
466
+ return entry;
467
+ };
468
+ };
469
+ /**
470
+ * Fiber reference containing headers that are merged into outgoing RPC
471
+ * client requests.
472
+ *
473
+ * **When to use**
474
+ *
475
+ * Use to set request headers that should be automatically merged into outgoing
476
+ * RPC client messages.
477
+ *
478
+ * @stability unstable
479
+ * @category services
480
+ * @since 4.0.0
481
+ */
482
+ const CurrentHeaders = /*#__PURE__*/ Reference("effect/rpc/RpcClient/CurrentHeaders", { defaultValue: () => empty });
483
+ /**
484
+ * Defines the service interface for an RPC client transport, responsible for running the
485
+ * receive loop and sending encoded client messages.
486
+ *
487
+ * **When to use**
488
+ *
489
+ * Use to provide the transport boundary for RPC clients over HTTP, WebSocket,
490
+ * workers, sockets, or custom protocols.
491
+ *
492
+ * @stability unstable
493
+ * @category services
494
+ * @since 4.0.0
495
+ */
496
+ var Protocol = class extends (/*#__PURE__*/ Service()("effect/rpc/RpcClient/Protocol")) {
497
+ /**
498
+ * Creates a client protocol service from the supplied RPC request runner.
499
+ *
500
+ * @stability unstable
501
+ * @since 4.0.0
502
+ */
503
+ static make = withRunClient;
504
+ };
505
+ /**
506
+ * Creates a client `Protocol` over the current `Socket`, using the current
507
+ * `RpcSerialization`, connection hooks, ping timeouts, and the configured retry
508
+ * policy.
509
+ *
510
+ * **Details**
511
+ *
512
+ * `pingInterval` defaults to 5 seconds. `pingTimeout` defaults to the interval
513
+ * and measures time since the last decoded server frame, not the last pong.
514
+ * The timeout is checked on each ping tick; any decoded frame counts as liveness.
515
+ *
516
+ * @stability unstable
517
+ * @category protocols
518
+ * @since 4.0.0
519
+ */
520
+ const makeProtocolSocket = (options) => Protocol.make(fnUntraced(function* (writeResponse, clientIds) {
521
+ const socket = yield* Socket;
522
+ const serialization = yield* RpcSerialization;
523
+ const hooks = yield* serviceOption(ConnectionHooks);
524
+ const requestClientMap = /* @__PURE__ */ new Map();
525
+ const writer = yield* socket.writer;
526
+ let parser = serialization.makeUnsafe();
527
+ const pinger = yield* makePinger(suspend(() => writer.write(parser.encode(constPing))), options);
528
+ let currentError;
529
+ const broadcast = (response) => forEach(clientIds, (clientId) => writeResponse(clientId, response));
530
+ const broadcastError = (error) => {
531
+ currentError = error;
532
+ return broadcast({
533
+ _tag: "ClientProtocolError",
534
+ error
535
+ });
536
+ };
537
+ const processData = (data) => {
538
+ try {
539
+ const responses = parser.decode(data);
540
+ if (responses.length === 0) return void_;
541
+ pinger.onFrame();
542
+ let i = 0;
543
+ return whileLoop({
544
+ while: () => i < responses.length,
545
+ body: () => {
546
+ const response = responses[i++];
547
+ if (response._tag === "Pong") return void_;
548
+ if (Object.hasOwn(response, "requestId")) {
549
+ const requestId = response.requestId;
550
+ const clientId = requestClientMap.get(requestId);
551
+ if (clientId !== void 0) {
552
+ if (response._tag === "Exit") requestClientMap.delete(requestId);
553
+ return writeResponse(clientId, response);
554
+ }
555
+ }
556
+ return broadcast(response);
557
+ },
558
+ step: constVoid
559
+ });
560
+ } catch (defect) {
561
+ return broadcast({
562
+ _tag: "ClientProtocolError",
563
+ error: new RpcClientError({ reason: new RpcClientDefect({
564
+ message: "Error decoding message",
565
+ cause: defect
566
+ }) })
567
+ });
568
+ }
569
+ };
570
+ yield* suspend(() => {
571
+ parser = serialization.makeUnsafe();
572
+ pinger.reset();
573
+ return gen(function* () {
574
+ const { pull } = yield* socket.reader;
575
+ currentError = void 0;
576
+ if (isSome(hooks)) yield* hooks.value.onConnect;
577
+ while (true) {
578
+ const frames = yield* pull;
579
+ for (let i = 0; i < frames.length; i++) yield* processData(frames[i]);
580
+ }
581
+ }).pipe(scoped, raceFirst(flatMap$1(pinger.timeout, () => fail$1(new SocketError({ reason: new SocketReadError({ cause: /* @__PURE__ */ new Error("ping timeout") }) })))));
582
+ }).pipe(isSome(hooks) ? ensuring(hooks.value.onDisconnect) : identity, tapCause((cause) => {
583
+ const error = findError(cause);
584
+ const hasError = isSuccess(error);
585
+ const rpcError = new RpcClientError({ reason: hasError ? error.success.reason : new RpcClientDefect({
586
+ message: "Unknown socket error",
587
+ cause: squash(cause)
588
+ }) });
589
+ if (options?.retryTransientErrors && hasError && error.success.reason._tag === "SocketOpenError") return (options.onTransientError?.(rpcError) ?? void_).pipe(ignoreCause({
590
+ log: true,
591
+ message: "RpcClient onTransientError hook failed"
592
+ }));
593
+ return broadcastError(rpcError);
594
+ }), retryOrElse(options?.retryPolicy ?? defaultRetryPolicy, (error) => broadcastError(new RpcClientError({ reason: error.reason }))), annotateLogs({
595
+ module: "RpcClient",
596
+ method: "makeProtocolSocket"
597
+ }), forkScoped);
598
+ return {
599
+ send(clientId, request) {
600
+ if (currentError) return fail$1(currentError);
601
+ if (request._tag === "Request") requestClientMap.set(request.id, clientId);
602
+ const encoded = parser.encode(request);
603
+ if (encoded === void 0) return void_;
604
+ return orDie(writer.write(encoded));
605
+ },
606
+ supportsAck: true,
607
+ supportsTransferables: false,
608
+ codecFor: serialization.codecFor
609
+ };
610
+ }));
611
+ const defaultRetryPolicy = /*#__PURE__*/ min([/*#__PURE__*/ exponential(500, 1.5), /*#__PURE__*/ spaced(5e3)]);
612
+ const makePinger = /*#__PURE__*/ fnUntraced(function* (writePing, options) {
613
+ const clock = yield* Clock;
614
+ const interval = options?.pingInterval ?? "5 seconds";
615
+ const timeoutMillis = toMillis(options?.pingTimeout ?? interval);
616
+ let lastSeen = clock.currentTimeMillisUnsafe();
617
+ const latch = makeUnsafe();
618
+ const onFrame = () => {
619
+ lastSeen = clock.currentTimeMillisUnsafe();
620
+ };
621
+ const reset = () => {
622
+ onFrame();
623
+ latch.closeUnsafe();
624
+ };
625
+ yield* suspend(() => {
626
+ if (clock.currentTimeMillisUnsafe() - lastSeen > timeoutMillis) return latch.open;
627
+ return writePing;
628
+ }).pipe(delay(interval), ignore, forever, interruptible, forkScoped);
629
+ return {
630
+ timeout: latch.await,
631
+ reset,
632
+ onFrame
633
+ };
634
+ });
635
+ /**
636
+ * Provides a client `Protocol` backed by the current `Socket` and
637
+ * `RpcSerialization` services.
638
+ *
639
+ * **Details**
640
+ *
641
+ * `pingInterval` defaults to 5 seconds. `pingTimeout` defaults to the interval
642
+ * and measures time since the last decoded server frame, not the last pong.
643
+ * The timeout is checked on each ping tick; any decoded frame counts as liveness.
644
+ * `retryPolicy` configures retries after socket errors.
645
+ *
646
+ * @stability unstable
647
+ * @category layers
648
+ * @since 4.0.0
649
+ */
650
+ const layerProtocolSocket = (options) => effect(Protocol)(makeProtocolSocket(options));
651
+ /**
652
+ * Represents optional client protocol hooks that run when a transport connects
653
+ * and disconnects.
654
+ *
655
+ * **When to use**
656
+ *
657
+ * Use to run setup or cleanup effects when an RPC client transport opens or
658
+ * closes.
659
+ *
660
+ * @stability unstable
661
+ * @category services
662
+ * @since 4.0.0
663
+ */
664
+ var ConnectionHooks = class extends (/*#__PURE__*/ Service()("effect/rpc/RpcClient/ConnectionHooks")) {};
665
+ //#endregion
666
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/Console.js
4
667
  /**
5
668
  * Context reference for the current console service in the Effect system, allowing access to the active console implementation from within the Effect context.
6
669
  *
@@ -34,6 +697,7 @@ import { Cc as getOrElse, Ci as fail, Cl as identity, Co as provideMerge, Ct as
34
697
  *
35
698
  * @see {@link consoleWith} for using the current console service inside an effect
36
699
  *
700
+ * @stability stable
37
701
  * @category services
38
702
  * @since 2.0.0
39
703
  */
@@ -62,10 +726,11 @@ const Console = ConsoleRef;
62
726
  * messages // => ["Hello, world!", "This is an error message"]
63
727
  * ```
64
728
  *
729
+ * @stability stable
65
730
  * @category constructors
66
731
  * @since 2.0.0
67
732
  */
68
- const consoleWith = (f) => withFiber((fiber) => f(fiber.getRef(Console)));
733
+ const consoleWith = (f) => withFiber$1((fiber) => f(fiber.getRef(Console)));
69
734
  /**
70
735
  * Writes an error-level message to the console, typically displayed with error
71
736
  * styling by the active console implementation.
@@ -95,6 +760,7 @@ const consoleWith = (f) => withFiber((fiber) => f(fiber.getRef(Console)));
95
760
  * messages // => expected
96
761
  * ```
97
762
  *
763
+ * @stability stable
98
764
  * @category accessors
99
765
  * @since 2.0.0
100
766
  */
@@ -128,6 +794,7 @@ const error = (...args) => consoleWith((console) => sync(() => {
128
794
  * messages // => expected
129
795
  * ```
130
796
  *
797
+ * @stability stable
131
798
  * @category accessors
132
799
  * @since 2.0.0
133
800
  */
@@ -135,7 +802,7 @@ const log = (...args) => consoleWith((console) => sync(() => {
135
802
  console.log(...args);
136
803
  }));
137
804
  //#endregion
138
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/CliError.js
805
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/CliError.js
139
806
  /**
140
807
  * Defines structured errors for the unstable CLI parser and runner.
141
808
  *
@@ -665,7 +1332,7 @@ var ShowHelp = class extends (/*#__PURE__*/ TaggedError(`${TypeId$3}/ShowHelp`)(
665
1332
  }
666
1333
  };
667
1334
  //#endregion
668
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Primitive.js
1335
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Primitive.js
669
1336
  /**
670
1337
  * Parses raw command-line strings into typed values.
671
1338
  *
@@ -843,70 +1510,11 @@ const Choice = (choices) => {
843
1510
  const validChoices = choices.map(([key]) => format(key)).join(" | ");
844
1511
  const primitive = makePrimitive("Choice", (value) => {
845
1512
  if (choiceMap.has(value)) return succeed$1(choiceMap.get(value));
846
- return fail(validChoices);
1513
+ return fail$1(validChoices);
847
1514
  });
848
1515
  return Object.assign(primitive, { choiceKeys: choices.map(([key]) => key) });
849
1516
  };
850
1517
  /**
851
- * Creates a primitive that validates and resolves file system paths.
852
- *
853
- * **Example** (Parsing file system paths)
854
- *
855
- * ```ts import.meta.vitest
856
- * import { Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect"
857
- * import { Primitive } from "effect/cli"
858
- * import { ChildProcessSpawner } from "effect/process"
859
- *
860
- * const services = Layer.mergeAll(
861
- * Path.layer,
862
- * FileSystem.layerNoop({
863
- * exists: () => Effect.succeed(true),
864
- * stat: () => Effect.succeed({ type: "File" } as FileSystem.File.Info)
865
- * }),
866
- * Stdio.layerTest({}),
867
- * Layer.succeed(Terminal.Terminal, Terminal.make({
868
- * columns: Effect.succeed(80),
869
- * rows: Effect.succeed(24),
870
- * readInput: Effect.die("unused"),
871
- * readLine: Effect.die("unused"),
872
- * display: () => Effect.void
873
- * })),
874
- * Layer.succeed(
875
- * ChildProcessSpawner.ChildProcessSpawner,
876
- * ChildProcessSpawner.make(() => Effect.die("unused"))
877
- * )
878
- * )
879
- *
880
- * const program = Effect.gen(function*() {
881
- * const filePrimitive = Primitive.Path("file", true)
882
- * const filePath = yield* filePrimitive.parse("./package.json")
883
- * return filePath.endsWith("/package.json")
884
- * }).pipe(Effect.provide(services))
885
- *
886
- * await Effect.runPromise(program) // => true
887
- * ```
888
- *
889
- * @stability unstable
890
- * @category constructors
891
- * @since 4.0.0
892
- */
893
- const Path$1 = (pathType, mustExist) => {
894
- const primitive = makePrimitive("Path", fnUntraced(function* (value) {
895
- const fs = yield* FileSystem;
896
- const path = yield* Path$2;
897
- const absolutePath = path.isAbsolute(value) ? value : path.resolve(value);
898
- const exists = yield* mapError(fs.exists(absolutePath), (error) => `Failed to check path existence: ${error.message}`);
899
- if (mustExist === true && !exists) return yield* fail(`Path does not exist: ${absolutePath}`);
900
- if (exists && pathType !== "either") {
901
- const stat = yield* mapError(fs.stat(absolutePath), (error) => `Failed to stat path: ${error.message}`);
902
- if (pathType === "file" && stat.type !== "File") return yield* fail(`Path is not a file: ${absolutePath}`);
903
- if (pathType === "directory" && stat.type !== "Directory") return yield* fail(`Path is not a directory: ${absolutePath}`);
904
- }
905
- return absolutePath;
906
- }));
907
- return Object.assign(primitive, { pathType });
908
- };
909
- /**
910
1518
  * Gets a human-readable type name for a primitive.
911
1519
  *
912
1520
  * **When to use**
@@ -963,7 +1571,7 @@ const getChoiceKeys = (primitive) => primitive._tag === "Choice" ? primitive.cho
963
1571
  */
964
1572
  const getPathType = (primitive) => primitive._tag === "Path" ? primitive.pathType : void 0;
965
1573
  //#endregion
966
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/ansi.js
1574
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/ansi.js
967
1575
  /**
968
1576
  * Internal ANSI escape sequence helpers used by the unstable CLI rendering
969
1577
  * implementation. This module centralizes the control codes for text styling,
@@ -1085,7 +1693,7 @@ const eraseLines = (rows) => {
1085
1693
  return command;
1086
1694
  };
1087
1695
  //#endregion
1088
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Prompt.js
1696
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Prompt.js
1089
1697
  /**
1090
1698
  * Builds interactive terminal prompts for CLI applications.
1091
1699
  *
@@ -1323,8 +1931,8 @@ const Number$1 = (options) => {
1323
1931
  decrementBy: 1,
1324
1932
  precision: 2,
1325
1933
  validate: (n) => {
1326
- if (n < opts.min) return fail(`${n} must be greater than or equal to ${opts.min}`);
1327
- if (n > opts.max) return fail(`${n} must be less than or equal to ${opts.max}`);
1934
+ if (n < opts.min) return fail$1(`${n} must be greater than or equal to ${opts.min}`);
1935
+ if (n > opts.max) return fail$1(`${n} must be less than or equal to ${opts.max}`);
1328
1936
  return succeed$1(n);
1329
1937
  },
1330
1938
  ...options
@@ -1361,8 +1969,8 @@ const Int = (options) => {
1361
1969
  incrementBy: 1,
1362
1970
  decrementBy: 1,
1363
1971
  validate: (n) => {
1364
- if (n < opts.min) return fail(`${n} must be greater than or equal to ${opts.min}`);
1365
- if (n > opts.max) return fail(`${n} must be less than or equal to ${opts.max}`);
1972
+ if (n < opts.min) return fail$1(`${n} must be greater than or equal to ${opts.min}`);
1973
+ if (n > opts.max) return fail$1(`${n} must be less than or equal to ${opts.max}`);
1366
1974
  return succeed$1(n);
1367
1975
  },
1368
1976
  ...options
@@ -1395,7 +2003,7 @@ const map$2 = /*#__PURE__*/ dual(2, (self, f) => flatMap(self, (a) => succeed(f(
1395
2003
  * @category constructors
1396
2004
  * @since 4.0.0
1397
2005
  */
1398
- const Password = (options) => basePrompt(options, "password").pipe(map$2(make$1));
2006
+ const Password = (options) => basePrompt(options, "password").pipe(map$2(make$2));
1399
2007
  /**
1400
2008
  * Runs a prompt by reading terminal input and rendering prompt frames until the
1401
2009
  * prompt submits a value.
@@ -1563,7 +2171,7 @@ const eraseText = (text, columns) => {
1563
2171
  };
1564
2172
  const lines = (prompt, columns) => {
1565
2173
  const lines = prompt.split(NEWLINE_REGEXP);
1566
- return columns === 0 ? lines.length : pipe(map$4(lines, (line) => Math.ceil(line.length / columns)), reduce(0, (left, right) => left + right));
2174
+ return columns === 0 ? lines.length : pipe(map$5(lines, (line) => Math.ceil(line.length / columns)), reduce(0, (left, right) => left + right));
1567
2175
  };
1568
2176
  const clearOutputWithError = (outputText, columns, errorText) => {
1569
2177
  if (errorText !== void 0 && errorText.length > 0) return cursorDown(lines(errorText, columns)) + eraseText(`\n${errorText}`, columns) + eraseText(outputText, columns);
@@ -1634,7 +2242,7 @@ const renderDateError = (state, pointer, theme) => {
1634
2242
  const errorLines = state.error.value.split(NEWLINE_REGEXP);
1635
2243
  if (isReadonlyArrayNonEmpty(errorLines)) {
1636
2244
  const prefix = annotateSymbol(pointer, theme.errorColor);
1637
- const lines = map$4(errorLines, (str) => annotateErrorLine(str, theme.errorColor));
2245
+ const lines = map$5(errorLines, (str) => annotateErrorLine(str, theme.errorColor));
1638
2246
  return cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + cursorRestorePosition;
1639
2247
  }
1640
2248
  }
@@ -1842,7 +2450,7 @@ const makeDateParts = (dateMask, date, locales) => {
1842
2450
  if (element.isToken() && lastElement !== void 0 && lastElement.isToken()) lastElement.setValue(element.token);
1843
2451
  else array.push(element);
1844
2452
  return array;
1845
- }, empty());
2453
+ }, empty$2());
1846
2454
  parts.splice(0, parts.length, ...orderedParts);
1847
2455
  return parts;
1848
2456
  };
@@ -2048,7 +2656,7 @@ const renderPrompt = (confirm, message, leadingSymbol, trailingSymbol, options)
2048
2656
  return match(message.split(NEWLINE_REGEXP), {
2049
2657
  onEmpty: () => renderLine(""),
2050
2658
  onNonEmpty: (promptLines) => {
2051
- const lines = map$4(promptLines, (line) => annotate(line));
2659
+ const lines = map$5(promptLines, (line) => annotate(line));
2052
2660
  return renderLine(lines.join("\n"));
2053
2661
  }
2054
2662
  });
@@ -2082,7 +2690,7 @@ const renderNumberError = (state, pointer, theme, renderOptions) => {
2082
2690
  onNonEmpty: (errorLines) => {
2083
2691
  if (renderOptions?.plain === true) return separateSymbol(pointer, errorLines.join("\n"));
2084
2692
  const prefix = annotateSymbol(pointer, theme.errorColor);
2085
- const lines = map$4(errorLines, (str) => annotateErrorLine(str, theme.errorColor));
2693
+ const lines = map$5(errorLines, (str) => annotateErrorLine(str, theme.errorColor));
2086
2694
  return cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + cursorRestorePosition;
2087
2695
  }
2088
2696
  });
@@ -2359,7 +2967,7 @@ const renderTextError = (nextState, pointer, theme, renderOptions) => {
2359
2967
  onNonEmpty: (errorLines) => {
2360
2968
  if (renderOptions?.plain === true) return separateSymbol(pointer, errorLines.join("\n"));
2361
2969
  const prefix = annotateSymbol(pointer, theme.errorColor);
2362
- const lines = map$4(errorLines, (str) => annotateErrorLine(str, theme.errorColor));
2970
+ const lines = map$5(errorLines, (str) => annotateErrorLine(str, theme.errorColor));
2363
2971
  return cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + cursorRestorePosition;
2364
2972
  }
2365
2973
  });
@@ -2587,7 +3195,20 @@ const entriesToDisplay = (cursor, total, maxVisible) => {
2587
3195
  };
2588
3196
  };
2589
3197
  //#endregion
2590
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Param.js
3198
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Param.js
3199
+ /**
3200
+ * Defines the shared parameter model for CLI arguments and flags.
3201
+ *
3202
+ * A `Param<Kind, A>` describes how to consume parsed command-line input and
3203
+ * return a typed value. The `Kind` decides whether the parameter reads
3204
+ * positional arguments or named flags. `Argument` and `Flag` build on this
3205
+ * module to share parsing structure, primitive constructors, help metadata,
3206
+ * aliases, defaults, prompts, configuration fallbacks, validation, schema
3207
+ * decoding, fallback parameters, and traversal helpers.
3208
+ *
3209
+ * @stability unstable
3210
+ * @since 4.0.0
3211
+ */
2591
3212
  const TypeId$1 = "~effect/cli/Param";
2592
3213
  /**
2593
3214
  * Defines the kind discriminator for positional argument parameters.
@@ -2791,71 +3412,6 @@ const Literals$1 = (kind, name, choices) => {
2791
3412
  const mappedChoices = choices.map((value) => [value, value]);
2792
3413
  return ChoiceWithValue$1(kind, name, mappedChoices);
2793
3414
  };
2794
- /**
2795
- * Creates a path parameter that accepts file or directory paths.
2796
- *
2797
- * **Example** (Creating path parameters)
2798
- *
2799
- * ```ts import.meta.vitest
2800
- * import { Param } from "effect/cli"
2801
- *
2802
- * // Basic path parameter
2803
- * const outputPath = Param.Path(Param.flagKind, "output")
2804
- *
2805
- * // Path that must exist
2806
- * const inputPath = Param.Path(Param.flagKind, "input", { mustExist: true })
2807
- *
2808
- * // File-only path
2809
- * const configFile = Param.Path(Param.flagKind, "config", {
2810
- * pathType: "file",
2811
- * mustExist: true,
2812
- * typeName: "config-file"
2813
- * })
2814
- * const kinds = [outputPath.kind, inputPath.kind, configFile.kind] // => ["flag", "flag", "flag"]
2815
- * ```
2816
- *
2817
- * @stability unstable
2818
- * @category constructors
2819
- * @since 4.0.0
2820
- */
2821
- const Path = (kind, name, options) => makeSingle({
2822
- name,
2823
- kind,
2824
- primitiveType: Path$1(options?.pathType ?? "either", options?.mustExist),
2825
- typeName: options?.typeName
2826
- });
2827
- /**
2828
- * Creates a directory path parameter.
2829
- *
2830
- * **Details**
2831
- *
2832
- * This is a convenience function that creates a path parameter with the
2833
- * `pathType` set to `"directory"` and a default type name of `"directory"`.
2834
- *
2835
- * **Example** (Creating directory parameters)
2836
- *
2837
- * ```ts import.meta.vitest
2838
- * import { Param } from "effect/cli"
2839
- *
2840
- * // Basic directory parameter
2841
- * const outputDir = Param.Directory(Param.flagKind, "output-dir")
2842
- *
2843
- * // Directory that must exist
2844
- * const sourceDir = Param.Directory(Param.flagKind, "source", { mustExist: true })
2845
- *
2846
- * // Usage: --output-dir /path/to/dir --source /existing/dir
2847
- * const kinds = [outputDir.kind, sourceDir.kind] // => ["flag", "flag"]
2848
- * ```
2849
- *
2850
- * @stability unstable
2851
- * @category constructors
2852
- * @since 4.0.0
2853
- */
2854
- const Directory$1 = (kind, name, options) => Path(kind, name, {
2855
- pathType: "directory",
2856
- typeName: "directory",
2857
- mustExist: options?.mustExist
2858
- });
2859
3415
  const FLAG_DASH_REGEXP = /^-+/;
2860
3416
  /**
2861
3417
  * Adds an alias to an option.
@@ -3091,7 +3647,7 @@ const optional$1 = (param) => {
3091
3647
  * @category combinators
3092
3648
  * @since 4.0.0
3093
3649
  */
3094
- const withDefault$2 = /*#__PURE__*/ dual(2, (self, defaultValue) => {
3650
+ const withDefault$1 = /*#__PURE__*/ dual(2, (self, defaultValue) => {
3095
3651
  if (!isEffect(defaultValue)) return map$1(optional$1(self), getOrElse(() => defaultValue));
3096
3652
  return mapEffect(optional$1(self), match$1({
3097
3653
  onNone: () => defaultValue,
@@ -3099,6 +3655,44 @@ const withDefault$2 = /*#__PURE__*/ dual(2, (self, defaultValue) => {
3099
3655
  }));
3100
3656
  });
3101
3657
  /**
3658
+ * Adds a fallback config that is loaded when a required parameter is missing.
3659
+ *
3660
+ * **When to use**
3661
+ *
3662
+ * Use when you need config to provide a fallback source for required flags or
3663
+ * arguments that are absent from CLI input.
3664
+ *
3665
+ * **Details**
3666
+ *
3667
+ * Provided CLI values win. Config is loaded only after a missing option or
3668
+ * missing argument error.
3669
+ *
3670
+ * **Gotchas**
3671
+ *
3672
+ * Missing config preserves the original missing-parameter error. Config parse
3673
+ * failure becomes `CliError.InvalidValue`.
3674
+ *
3675
+ * @see {@link withDefault} for a pure default value
3676
+ * @see {@link withFallbackPrompt} for prompting interactively when input is missing
3677
+ *
3678
+ * @stability unstable
3679
+ * @category combinators
3680
+ * @since 4.0.0
3681
+ */
3682
+ const withFallbackConfig$1 = /*#__PURE__*/ dual(2, (self, config) => {
3683
+ const toInvalidValue = (error, configError) => new InvalidValue({
3684
+ option: error._tag === "MissingOption" ? error.option : error.argument,
3685
+ value: "config",
3686
+ expected: configError.message,
3687
+ kind: error._tag === "MissingOption" ? "flag" : "argument"
3688
+ });
3689
+ const runConfig = (error, args) => option(config).pipe(mapError((configError) => toInvalidValue(error, configError)), flatMap$1(match$1({
3690
+ onNone: () => fail$1(error),
3691
+ onSome: (value) => succeed$1([args.arguments, value])
3692
+ })));
3693
+ return transform(self, (parse) => (args) => parse(args).pipe(catchTag(["MissingOption", "MissingArgument"], (error) => runConfig(error, args))));
3694
+ });
3695
+ /**
3102
3696
  * Creates a variadic parameter that can be specified multiple times.
3103
3697
  *
3104
3698
  * **Details**
@@ -3336,7 +3930,7 @@ const getParamMetadata = (param) => {
3336
3930
  });
3337
3931
  };
3338
3932
  //#endregion
3339
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Argument.js
3933
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Argument.js
3340
3934
  /**
3341
3935
  * Creates a positional string argument.
3342
3936
  *
@@ -3355,23 +3949,6 @@ const getParamMetadata = (param) => {
3355
3949
  */
3356
3950
  const String$2 = (name) => String$3(argumentKind, name);
3357
3951
  /**
3358
- * Creates a positional directory path argument.
3359
- *
3360
- * **Example** (Creating a directory path argument)
3361
- *
3362
- * ```ts import.meta.vitest
3363
- * import { Argument } from "effect/cli"
3364
- *
3365
- * const workspace = Argument.Directory("workspace", { mustExist: true }) // Must exist
3366
- * workspace.kind // => "argument"
3367
- * ```
3368
- *
3369
- * @stability unstable
3370
- * @category constructors
3371
- * @since 4.0.0
3372
- */
3373
- const Directory = (name, options) => Directory$1(argumentKind, name, options);
3374
- /**
3375
3952
  * Adds a description to a positional argument.
3376
3953
  *
3377
3954
  * **Example** (Adding an argument description)
@@ -3390,25 +3967,8 @@ const Directory = (name, options) => Directory$1(argumentKind, name, options);
3390
3967
  * @since 4.0.0
3391
3968
  */
3392
3969
  const withDescription$2 = /*#__PURE__*/ dual(2, (self, description) => withDescription$3(self, description));
3393
- /**
3394
- * Provides a default value for a positional argument.
3395
- *
3396
- * **Example** (Providing a default value)
3397
- *
3398
- * ```ts import.meta.vitest
3399
- * import { Argument } from "effect/cli"
3400
- *
3401
- * const port = Argument.Int("port").pipe(Argument.withDefault(8080))
3402
- * port.kind // => "argument"
3403
- * ```
3404
- *
3405
- * @stability unstable
3406
- * @category combinators
3407
- * @since 4.0.0
3408
- */
3409
- const withDefault$1 = withDefault$2;
3410
3970
  //#endregion
3411
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/CliOutput.js
3971
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/CliOutput.js
3412
3972
  /**
3413
3973
  * Formats CLI help and errors as text.
3414
3974
  *
@@ -3676,7 +4236,7 @@ const formatHelpDocImpl = (doc, colors) => {
3676
4236
  return sections.join("\n");
3677
4237
  };
3678
4238
  //#endregion
3679
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/completions/bash.js
4239
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/completions/bash.js
3680
4240
  const escapeForBash = (s) => s.replace(/'/g, "'\\''");
3681
4241
  const sanitizeFunctionName = (s) => s.replace(/[^a-zA-Z0-9_]/g, "_");
3682
4242
  const flagNamesForWordlist = (flag) => {
@@ -3946,7 +4506,7 @@ const generate$3 = (executableName, descriptor) => {
3946
4506
  return lines.join("\n");
3947
4507
  };
3948
4508
  //#endregion
3949
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/completions/fish.js
4509
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/completions/fish.js
3950
4510
  const escapeFishString = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
3951
4511
  /** Escape choices for Fish's second expansion of `complete -a`. */
3952
4512
  const escapeFishChoice = (s) => escapeFishString(s.replace(/[^A-Za-z0-9_.,/@%+-]/gu, "\\$&"));
@@ -4096,7 +4656,7 @@ const generate$2 = (executableName, descriptor) => {
4096
4656
  return lines.join("\n");
4097
4657
  };
4098
4658
  //#endregion
4099
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/completions/zsh.js
4659
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/completions/zsh.js
4100
4660
  const escapeZsh = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/:/g, "\\:");
4101
4661
  /** Escape choices for the second parse of a Zsh `_arguments` action. */
4102
4662
  const escapeZshChoice = (s) => s.replace(/[^A-Za-z0-9_.,/@%+-]/gu, "\\$&").replace(/'/g, "'\\''");
@@ -4243,7 +4803,7 @@ const generate$1 = (executableName, descriptor) => {
4243
4803
  return lines.join("\n");
4244
4804
  };
4245
4805
  //#endregion
4246
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Completions.js
4806
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Completions.js
4247
4807
  /**
4248
4808
  * The `Completions` module turns a plain description of an Effect CLI command
4249
4809
  * tree into shell completion scripts for Bash, Zsh, and Fish. It is the
@@ -4281,7 +4841,7 @@ const generate = (executableName, shell, descriptor) => {
4281
4841
  }
4282
4842
  };
4283
4843
  //#endregion
4284
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Flag.js
4844
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Flag.js
4285
4845
  /**
4286
4846
  * Creates a string flag that accepts text input.
4287
4847
  *
@@ -4504,7 +5064,27 @@ const optional = (param) => optional$1(param);
4504
5064
  * @category optionality
4505
5065
  * @since 4.0.0
4506
5066
  */
4507
- const withDefault = withDefault$2;
5067
+ const withDefault = withDefault$1;
5068
+ /**
5069
+ * Adds a fallback config that is loaded when a required flag is missing.
5070
+ *
5071
+ * **Example** (Falling back to config)
5072
+ *
5073
+ * ```ts import.meta.vitest
5074
+ * import { Config } from "effect"
5075
+ * import { Flag } from "effect/cli"
5076
+ *
5077
+ * const verbose = Flag.Boolean("verbose").pipe(
5078
+ * Flag.withFallbackConfig(Config.Boolean("VERBOSE"))
5079
+ * )
5080
+ * verbose.kind // => "flag"
5081
+ * ```
5082
+ *
5083
+ * @stability unstable
5084
+ * @category combinators
5085
+ * @since 4.0.0
5086
+ */
5087
+ const withFallbackConfig = /*#__PURE__*/ dual(2, (self, config) => withFallbackConfig$1(self, config));
4508
5088
  /**
4509
5089
  * Transforms the parsed value of a flag using a mapping function.
4510
5090
  *
@@ -4531,7 +5111,7 @@ const withDefault = withDefault$2;
4531
5111
  */
4532
5112
  const map = /*#__PURE__*/ dual(2, (self, f) => map$1(self, f));
4533
5113
  //#endregion
4534
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/config.js
5114
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/config.js
4535
5115
  /**
4536
5116
  * Config Internal
4537
5117
  * ================
@@ -4652,7 +5232,7 @@ const reconstructTree = (tree, results) => {
4652
5232
  }
4653
5233
  };
4654
5234
  //#endregion
4655
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/command.js
5235
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/command.js
4656
5236
  /**
4657
5237
  * Command Implementation
4658
5238
  * ======================
@@ -4682,7 +5262,7 @@ const makeCommand = (options) => {
4682
5262
  const annotations = options.annotations ?? empty$1();
4683
5263
  const globalFlags = options.globalFlags ?? [];
4684
5264
  const subcommands = options.subcommands ?? [];
4685
- const handle = (input, commandPath) => isNotUndefined(options.handle) ? options.handle(input, commandPath) : fail(new ShowHelp({
5265
+ const handle = (input, commandPath) => isNotUndefined(options.handle) ? options.handle(input, commandPath) : fail$1(new ShowHelp({
4686
5266
  commandPath,
4687
5267
  errors: []
4688
5268
  }));
@@ -4723,7 +5303,7 @@ const makeCommand = (options) => {
4723
5303
  if (visible.length === 0) continue;
4724
5304
  subcommandDocs.push({
4725
5305
  group: group.group,
4726
- commands: map$4(visible, (subcommand) => ({
5306
+ commands: map$5(visible, (subcommand) => ({
4727
5307
  name: subcommand.name,
4728
5308
  alias: subcommand.alias,
4729
5309
  shortDescription: subcommand.shortDescription,
@@ -4846,7 +5426,7 @@ const checkForDuplicateFlags = (parent, subcommands, options) => {
4846
5426
  }
4847
5427
  };
4848
5428
  //#endregion
4849
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/completions/descriptor.js
5429
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/completions/descriptor.js
4850
5430
  /**
4851
5431
  * CommandDescriptor — pure-data representation of a command tree for
4852
5432
  * shell completion generation.
@@ -4956,7 +5536,7 @@ const fromCommand = (cmd, inheritedFlags = []) => {
4956
5536
  };
4957
5537
  };
4958
5538
  //#endregion
4959
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/help.js
5539
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/help.js
4960
5540
  /**
4961
5541
  * Help Documentation
4962
5542
  * ================
@@ -5066,7 +5646,7 @@ const getHelpForCommandPath = (command, commandPath, builtIns) => gen(function*
5066
5646
  };
5067
5647
  });
5068
5648
  //#endregion
5069
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/GlobalFlag.js
5649
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/GlobalFlag.js
5070
5650
  /**
5071
5651
  * Global flags for Effect CLI command trees. Global flags are parsed outside a
5072
5652
  * single command's local flags and can apply to a command and its descendants.
@@ -5181,7 +5761,7 @@ const Completions = /*#__PURE__*/ Action({
5181
5761
  "zsh",
5182
5762
  "fish",
5183
5763
  "sh"
5184
- ]).pipe(optional, /*#__PURE__*/ map((v) => map$5(v, (s) => s === "sh" ? "bash" : s)), /*#__PURE__*/ withMetavar("<bash|zsh|fish|sh>"), /*#__PURE__*/ withDescription$1("Print shell completion script")),
5764
+ ]).pipe(optional, /*#__PURE__*/ map((v) => map$4(v, (s) => s === "sh" ? "bash" : s)), /*#__PURE__*/ withMetavar("<bash|zsh|fish|sh>"), /*#__PURE__*/ withDescription$1("Print shell completion script")),
5185
5765
  run: /*#__PURE__*/ fnUntraced(function* (shell, { command }) {
5186
5766
  if (isNone(shell)) return;
5187
5767
  const descriptor = fromCommand(command);
@@ -5247,7 +5827,7 @@ const BuiltIns = [
5247
5827
  LogLevel
5248
5828
  ];
5249
5829
  //#endregion
5250
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/CliConfig.js
5830
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/CliConfig.js
5251
5831
  /**
5252
5832
  * Configuration for Effect CLI command execution.
5253
5833
  *
@@ -5277,7 +5857,7 @@ var CliConfig = class extends (/*#__PURE__*/ Reference("effect/cli/CliConfig", {
5277
5857
  */
5278
5858
  const defaults = { builtIns: BuiltIns };
5279
5859
  //#endregion
5280
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/lexer.js
5860
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/lexer.js
5281
5861
  /**
5282
5862
  * @internal
5283
5863
  */
@@ -5339,7 +5919,7 @@ const lexTokens = (args) => {
5339
5919
  return tokens;
5340
5920
  };
5341
5921
  //#endregion
5342
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/auto-suggest.js
5922
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/auto-suggest.js
5343
5923
  /**
5344
5924
  * Simple Levenshtein distance implementation (small N, no perf worries)
5345
5925
  */
@@ -5367,7 +5947,7 @@ const suggest = (input, candidates) => {
5367
5947
  return distances.filter(([d]) => d === minDistance).map(([, c]) => c);
5368
5948
  };
5369
5949
  //#endregion
5370
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/parser.js
5950
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/parser.js
5371
5951
  /**
5372
5952
  * Parsing Pipeline for CLI Commands
5373
5953
  * ==================================
@@ -5899,7 +6479,7 @@ const scanCommandLevel = (tokens, context) => {
5899
6479
  return toLeafResult(state);
5900
6480
  };
5901
6481
  //#endregion
5902
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/internal/wizard.js
6482
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/internal/wizard.js
5903
6483
  const run$1 = /*#__PURE__*/ fnUntraced(function* (command, options) {
5904
6484
  const commandPath = options?.commandPath ?? [command.name];
5905
6485
  const selected = getCommandAtPath(command, commandPath);
@@ -6069,7 +6649,7 @@ const wrapCommand = (commandLine) => {
6069
6649
  };
6070
6650
  const formatShellArg = (arg) => /^[A-Za-z0-9_./:@%+=,-]+$/.test(arg) ? arg : `'${arg.replaceAll("'", `'"'"'`)}'`;
6071
6651
  //#endregion
6072
- //#region ../../node_modules/.pnpm/effect@4.0.0/node_modules/effect/dist/cli/Command.js
6652
+ //#region ../../node_modules/.pnpm/effect@4.0.2/node_modules/effect/dist/cli/Command.js
6073
6653
  /**
6074
6654
  * Returns `true` if the provided value is a `Command`.
6075
6655
  *
@@ -6668,44 +7248,56 @@ const runWith = (command, config) => {
6668
7248
  }
6669
7249
  const services = match$1(logLevel, {
6670
7250
  onNone: () => empty$1(),
6671
- onSome: (level) => make$2(MinimumLogLevel, level)
7251
+ onSome: (level) => make$3(MinimumLogLevel, level)
6672
7252
  });
6673
7253
  yield* provideContext(program, services);
6674
- }, catchFilter((error) => isCliError(error) && error._tag === "ShowHelp" ? succeed$2(error) : fail$1(error), (error) => andThen(showHelp(command, error, config.renderErrors !== false), fail(error))), catchFilter((error) => config.renderErrors !== false && isCliError(error) && error._tag === "UserError" ? succeed$2(error) : fail$1(error), (error) => andThen(showUserError(error), fail(error))), catchFilter((e) => isQuitError(e) ? succeed$2(e) : fail$1(e), (_) => interrupt));
7254
+ }, catchFilter((error) => isCliError(error) && error._tag === "ShowHelp" ? succeed$2(error) : fail$2(error), (error) => andThen(showHelp(command, error, config.renderErrors !== false), fail$1(error))), catchFilter((error) => config.renderErrors !== false && isCliError(error) && error._tag === "UserError" ? succeed$2(error) : fail$2(error), (error) => andThen(showUserError(error), fail$1(error))), catchFilter((e) => isQuitError(e) ? succeed$2(e) : fail$2(e), (_) => interrupt$1));
6675
7255
  };
6676
7256
  //#endregion
6677
7257
  //#region package.json
6678
- var version = "0.1.0";
7258
+ var version = "0.1.1018";
6679
7259
  //#endregion
6680
7260
  //#region src/main.cli.ts
6681
- const media = pipe(make("media", {
6682
- language: pipe(String$1("language"), withDescription$1("Spoken language code, such as it; defaults to the original caption language, then the declared language, then English"), optional),
6683
- link: pipe(String$2("url"), withDescription$2("Video or post URL")),
6684
- output: pipe(Directory("output", { mustExist: false }), withDescription$2("Directory for info.md and transcript.txt"), withDefault$1("/tmp/media"))
7261
+ function section(title, text) {
7262
+ return isEmpty(text) ? "" : `## ${title}\n\n${text}`;
7263
+ }
7264
+ const save = pipe(make("save", {
7265
+ entry: pipe(String$2("text"), withDescription$2("A link, or the text of a note")),
7266
+ server: pipe(String$1("server"), withDescription$1("Stash server; defaults to STASH_SERVER, then the tailnet address on dev"), withFallbackConfig(String$7("STASH_SERVER")), withDefault("https://dev.tailnet-8c4c.ts.net:8443"))
6685
7267
  }, fnUntraced(function* (input) {
6686
- const fs = yield* FileSystem;
6687
- const path = yield* Path$2;
6688
- const output = path.resolve(input.output);
6689
- const info = path.join(output, "info.md");
6690
- const transcript = path.join(output, "transcript.txt");
6691
- yield* fs.makeDirectory(output, { recursive: true });
6692
- yield* fs.remove(info, { force: true });
6693
- yield* fs.remove(transcript, { force: true });
6694
- const report = yield* (yield* Media).read({
6695
- language: input.language,
6696
- link: input.link,
6697
- maxWhisperSeconds: none()
6698
- });
6699
- yield* fs.writeFileString(info, report.info);
6700
- yield* log(`Wrote ${info}`);
6701
- yield* match$1(yield* report.transcript, {
6702
- onNone: () => void_,
6703
- onSome: (text) => andThen(fs.writeFileString(transcript, text.text), log(`Wrote ${transcript} from ${text.source === "captions" ? "published captions" : "local Whisper"}`))
6704
- });
6705
- })), withDescription("Write info.md (title, author, date, description, chapters and X post text) and transcript.txt with [mm:ss] timestamps for a video or social post URL. Uses published captions when they exist, otherwise downloads the audio and transcribes it locally with Whisper. Needs ffmpeg on PATH; caches yt-dlp and the model in $XDG_CACHE_HOME/deslop/media, ~/.cache by default."), withExamples([{
6706
- command: "vpx @deslop/stash@latest media https://x.com/poteto/status/2102050467505430555 /tmp/media/poteto",
6707
- description: "Transcribe the talk attached to an X post."
7268
+ const note = yield* pipe(gen(function* () {
7269
+ const client = yield* make$1(RpcContracts);
7270
+ const saved = yield* client["notes.capture"]({
7271
+ id: yield* (yield* Crypto).randomUUIDv4,
7272
+ text: input.entry
7273
+ });
7274
+ yield* logInfo("Saved; the server is reading and tagging it, which takes minutes for a long video");
7275
+ yield* pipe(client["notes.watch"](void 0), filter((event) => some$1(event.upserted, (item) => item.id === saved.id && item.status !== "organizing")), runHead, timeoutOrElse({
7276
+ duration: "2 hours",
7277
+ orElse: () => fail$1(NotesError.make({ message: "The server did not finish the note within two hours." }))
7278
+ }));
7279
+ return yield* client["notes.get"]({ id: saved.id });
7280
+ }), scoped, provide(pipe(layerProtocolSocket(), provide$1(layerWebSocket(pipe(new URL("/api/rpc", input.server).href, replace(/^http/u, "ws")))), provide$1(layerWebSocketConstructorGlobal), provide$1(layerJson))));
7281
+ yield* log(pipe([
7282
+ `# ${note.title}`,
7283
+ join(filter$1([
7284
+ note.author,
7285
+ note.source,
7286
+ note.url ?? ""
7287
+ ], isNonEmpty), " · "),
7288
+ join(map$5(note.tags, (name) => `#${name}`), " "),
7289
+ note.summary,
7290
+ section("Notes", note.body ?? ""),
7291
+ section("Topics", note.topics ?? ""),
7292
+ section("Text in the images", note.screenText ?? ""),
7293
+ section("Source", note.content),
7294
+ section("Transcript", note.transcript ?? ""),
7295
+ section("Issue", note.issue)
7296
+ ], filter$1(isNonEmpty), join("\n\n")));
7297
+ })), withDescription("Save a link or a note to stash and print it as Markdown: title, summary, tags, notes, source text and the transcript with [mm:ss] timestamps. The server reads the link, transcribes its video with published captions or Whisper, and tags it; the CLI waits until it finishes. Needs the tailnet."), withExamples([{
7298
+ command: "vpx @deslop/stash@latest save https://x.com/poteto/status/2102050467505430555",
7299
+ description: "Save the talk attached to an X post and print its note and transcript."
6708
7300
  }]));
6709
- runMain(pipe(make("stash"), withDescription("Read what a video or social post says; the stash server and iOS app share this package."), withSubcommands([media]), run({ version }), scoped, provideService(LogToStderr, true), provide(pipe(Media.layer, provideMerge(merge(layer, layer$1))))));
7301
+ runMain(pipe(make("stash"), withDescription("Save links and notes to stash; the server and iOS app share this package."), withSubcommands([save]), run({ version }), provideService(LogToStderr, true), provide(layer)));
6710
7302
  //#endregion
6711
7303
  export {};