@deslop/stash 0.1.1090 → 0.1.1092
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/README.md +4 -1
- package/dist/cli.js +112 -5
- package/dist/{contracts-CdQiWFv_.mjs → contracts-nyOWldn4.mjs} +856 -206
- package/dist/server.js +1196 -602
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# @deslop/stash
|
|
2
2
|
|
|
3
|
-
Saves a link or text to the owner's stash server
|
|
3
|
+
Saves a link or text to the owner's stash server and prints the read, tagged note as Markdown.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
+
vpx @deslop/stash@latest login '<api key>'
|
|
6
7
|
vpx @deslop/stash@latest save '<link or text>' [--server <url>]
|
|
7
8
|
```
|
|
9
|
+
|
|
10
|
+
`login` keeps an API key created at https://auth.mp281x.xyz in `~/.config/stash/api-key`.
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --max-old-space-size=16384 --heapsnapshot-near-heap-limit=3 --report-on-fatalerror
|
|
2
|
-
import { $
|
|
2
|
+
import { $d as get, $t as FalseLiterals, Al as squash, B as Terminal, Ba as shutdownUnsafe, Bl as provide$2, Bo as catchFilter, C as AuthError, Cc as whileLoop, Cf as match$1, Cl as hasInterrupts, Cr as fromInput, Ct as makeCollectorUnsafe, Dc as withParentSpan, Df as some, Dn as decodeSync, Dr as merge, Ds as mapError, Dt as SocketErrorReason, Du as sync, Et as SocketError, F as runMain, Fd as isSuccess, Fo as cached, Gs as raceFirst, Gt as BooleanLiterals, Hs as provideContext, I as errorExitCode, Ic as min, Ii as filter$1, In as is, Io as callback, Is as onInterrupt, J as String$7, Jl as addFinalizerExit, Jn as optionalKey, Jo as delay, Kf as format, Kl as Scope, Ko as context, L as errorReported, La as offerAll, Ld as succeed$2, Lo as catchCause, Lt as HttpClientErrorSchema, M as LogToStderr, Mc as exponential, Mr as make$2, Mt as layerWebSocketConstructorGlobal, Na as end, Nr as value, Ns as onError, Os as match$2, Pa as failCause, Pf as Prototype, Pl as effect, Qc as replace, Qd as empty$1, Qo as fail$1, R as layer, Rc as spaced, Rf as withFiber$1, Rl as merge$1, Ro as catchCauseIf, Rs as orDie, Ru as taggedEnum, S as RpcAuth, Sf as map$3, Sr as empty, Ss as logInfo, St as Collector, Ti as FileSystem, Tl as interruptors, Ts as map$2, Tt as Socket, U as Crypto, Uo as catchTag, Us as provideService, Ut as ArraySchema, V as isQuitError, Va as take, Vs as provide$1, Wi as fromQueue, Wo as catchTags, Wu as empty$2, Xa as interrupt$2, Xd as Service, Xf as hasProperty, Xo as ensuring, Xu as findFirstIndex, Ya as getCurrent, Yd as Reference, Yn as tag, Ys as retryOrElse, Yt as Defect, Yu as findFirst, Z as option, Zd as add, Zn as toCodecStringTree, Zs as runForkWith, Zt as Error$1, Zu as findLast, _c as uninterruptibleMask, _f as getOrUndefined, _n as TrueLiterals, _s as isEffect, ac as suspend, as as forEach, at as RpcSerialization, b as AUTH_URL, bc as useSpan, bl as findError, bs as logError, bt as spanAttributes, cc as tapCause, cd as isReadonlyArrayNonEmpty, cf as exists, cl as round, cs as forkIn, da as runHead, dp as dual, du as die, ec as scoped, ep as isNotUndefined, fc as timeoutOrElse, fd as map$4, fs as gen, ft as constPing, fu as fail, gd as reduce, gn as TaggedError, gs as interruptible, gu as isFailure, h as NotesError, hf as getOrElse, hp as pipeArguments, hs as interrupt$1, ht as exitSchema, is as fnUntraced, it as withRunClient, iu as MinimumLogLevel, ja as bounded, jn as encodeEffect, jo as annotateLogs, jt as layerWebSocket, kd as fail$2, kn as decodeUnknownEffect, ko as andThen, ks as matchCauseEffect, kt as SocketReadError, ld as join, lf as filter, ll as Clock, lp as constVoid, ls as forkScoped, lt as RequestId, mf as fromUndefinedOr, mp as pipe, ms as ignoreCause, mu as interrupt, nf as getUnsafe, nt as Stdio, oc as sync$1, os as forever, pd as match, pn as String$6, pp as identity, ps as ignore, pu as failCause$1, qa as makeUnsafe, qc as isNonEmpty, qd as toMillis, ql as addFinalizer, qn as optional$2, qs as result, qu as filter$2, rc as succeed$1, rf as make$3, rn as Literal, sn as NonEmptyArray, st as layerJson, t as RpcContracts, tc as serviceOption, td as getSomes, tf as getOrUndefinedUnsafe, ts as flatMap$1, uc as timeout, vd as some$1, vf as isNone, vt as getStreamSchemas, wc as withFiber, wf as none, wn as Union, ws as makeSpanScoped, xa as unwrap, xc as void_, xt as spanName, yf as isSome, yt as isStreamSchema, yu as ConsoleRef, z as QuitError, zf as assignProperty } from "./contracts-nyOWldn4.mjs";
|
|
3
3
|
//#region ../../node_modules/.pnpm/effect@4.0.5/node_modules/effect/dist/workers/WorkerError.js
|
|
4
4
|
/**
|
|
5
5
|
* Worker error reason for failures while spawning or setting up a worker.
|
|
@@ -1524,6 +1524,51 @@ const Choice = (choices) => {
|
|
|
1524
1524
|
return Object.assign(primitive, { choiceKeys: choices.map(([key]) => key) });
|
|
1525
1525
|
};
|
|
1526
1526
|
/**
|
|
1527
|
+
* Creates a primitive that wraps string input in `Redacted`.
|
|
1528
|
+
*
|
|
1529
|
+
* **Details**
|
|
1530
|
+
*
|
|
1531
|
+
* The wrapped value is hidden when formatted or inspected, while the original
|
|
1532
|
+
* string remains available through the `Redacted` API when explicitly needed.
|
|
1533
|
+
*
|
|
1534
|
+
* **Example** (Parsing redacted values)
|
|
1535
|
+
*
|
|
1536
|
+
* ```ts import.meta.vitest
|
|
1537
|
+
* import { Effect, FileSystem, Layer, Path, Redacted, Stdio, Terminal } from "effect"
|
|
1538
|
+
* import { Primitive } from "effect/cli"
|
|
1539
|
+
* import { ChildProcessSpawner } from "effect/process"
|
|
1540
|
+
*
|
|
1541
|
+
* const CliTestLayer = Layer.mergeAll(
|
|
1542
|
+
* FileSystem.layerNoop({}),
|
|
1543
|
+
* Path.layer,
|
|
1544
|
+
* Stdio.layerTest({}),
|
|
1545
|
+
* Layer.succeed(Terminal.Terminal, Terminal.make({
|
|
1546
|
+
* columns: Effect.succeed(80),
|
|
1547
|
+
* rows: Effect.succeed(24),
|
|
1548
|
+
* readInput: Effect.die("unused"),
|
|
1549
|
+
* readLine: Effect.die("unused"),
|
|
1550
|
+
* display: () => Effect.void
|
|
1551
|
+
* })),
|
|
1552
|
+
* Layer.succeed(
|
|
1553
|
+
* ChildProcessSpawner.ChildProcessSpawner,
|
|
1554
|
+
* ChildProcessSpawner.make(() => Effect.die("unused"))
|
|
1555
|
+
* )
|
|
1556
|
+
* )
|
|
1557
|
+
*
|
|
1558
|
+
* const parseRedacted = Effect.gen(function*() {
|
|
1559
|
+
* const result = yield* Primitive.Redacted.parse("secret-password")
|
|
1560
|
+
* return [Redacted.value(result), String(result)] as const
|
|
1561
|
+
* })
|
|
1562
|
+
*
|
|
1563
|
+
* await Effect.runPromise(parseRedacted.pipe(Effect.provide(CliTestLayer))) // => ["secret-password", "<redacted>"]
|
|
1564
|
+
* ```
|
|
1565
|
+
*
|
|
1566
|
+
* @stability unstable
|
|
1567
|
+
* @category constructors
|
|
1568
|
+
* @since 4.0.0
|
|
1569
|
+
*/
|
|
1570
|
+
const Redacted$2 = /*#__PURE__*/ makePrimitive("Redacted", (value) => succeed$1(make$2(value)));
|
|
1571
|
+
/**
|
|
1527
1572
|
* Gets a human-readable type name for a primitive.
|
|
1528
1573
|
*
|
|
1529
1574
|
* **When to use**
|
|
@@ -3406,6 +3451,34 @@ const ChoiceWithValue$1 = (kind, name, choices) => makeSingle({
|
|
|
3406
3451
|
primitiveType: Choice(choices),
|
|
3407
3452
|
kind
|
|
3408
3453
|
});
|
|
3454
|
+
/**
|
|
3455
|
+
* Creates a redacted parameter for sensitive data like passwords.
|
|
3456
|
+
* The value is masked in help output and logging.
|
|
3457
|
+
*
|
|
3458
|
+
* **Example** (Creating redacted parameters)
|
|
3459
|
+
*
|
|
3460
|
+
* ```ts import.meta.vitest
|
|
3461
|
+
* import { Param } from "effect/cli"
|
|
3462
|
+
*
|
|
3463
|
+
* // Create a password parameter
|
|
3464
|
+
* const password = Param.Redacted(Param.flagKind, "password")
|
|
3465
|
+
*
|
|
3466
|
+
* // Create an API key argument
|
|
3467
|
+
* const apiKey = Param.Redacted(Param.argumentKind, "api-key")
|
|
3468
|
+
*
|
|
3469
|
+
* // Usage: --password (value will be hidden in help/logs)
|
|
3470
|
+
* const kinds = [password.kind, apiKey.kind] // => ["flag", "argument"]
|
|
3471
|
+
* ```
|
|
3472
|
+
*
|
|
3473
|
+
* @stability unstable
|
|
3474
|
+
* @category constructors
|
|
3475
|
+
* @since 4.0.0
|
|
3476
|
+
*/
|
|
3477
|
+
const Redacted$1 = (kind, name) => makeSingle({
|
|
3478
|
+
name,
|
|
3479
|
+
primitiveType: Redacted$2,
|
|
3480
|
+
kind
|
|
3481
|
+
});
|
|
3409
3482
|
const FLAG_DASH_REGEXP = /^-+/;
|
|
3410
3483
|
/**
|
|
3411
3484
|
* Adds an alias to an option.
|
|
@@ -3943,6 +4016,23 @@ const getParamMetadata = (param) => {
|
|
|
3943
4016
|
*/
|
|
3944
4017
|
const String$2 = (name) => String$3(argumentKind, name);
|
|
3945
4018
|
/**
|
|
4019
|
+
* Creates a positional redacted argument that obscures its value.
|
|
4020
|
+
*
|
|
4021
|
+
* **Example** (Creating a redacted argument)
|
|
4022
|
+
*
|
|
4023
|
+
* ```ts import.meta.vitest
|
|
4024
|
+
* import { Argument } from "effect/cli"
|
|
4025
|
+
*
|
|
4026
|
+
* const secret = Argument.Redacted("secret")
|
|
4027
|
+
* secret.kind // => "argument"
|
|
4028
|
+
* ```
|
|
4029
|
+
*
|
|
4030
|
+
* @stability unstable
|
|
4031
|
+
* @category constructors
|
|
4032
|
+
* @since 4.0.0
|
|
4033
|
+
*/
|
|
4034
|
+
const Redacted = (name) => Redacted$1(argumentKind, name);
|
|
4035
|
+
/**
|
|
3946
4036
|
* Adds a description to a positional argument.
|
|
3947
4037
|
*
|
|
3948
4038
|
* **Example** (Adding an argument description)
|
|
@@ -7600,15 +7690,27 @@ const runWith = (command, config) => {
|
|
|
7600
7690
|
};
|
|
7601
7691
|
//#endregion
|
|
7602
7692
|
//#region package.json
|
|
7603
|
-
var version = "0.1.
|
|
7693
|
+
var version = "0.1.1092";
|
|
7604
7694
|
//#endregion
|
|
7605
7695
|
//#region src/main.cli.ts
|
|
7696
|
+
const server = pipe(String$1("server"), withDescription$1("Stash server; defaults to STASH_SERVER, then https://stash.mp281x.xyz"), withFallbackConfig(String$7("STASH_SERVER")), withDefault("https://stash.mp281x.xyz"));
|
|
7697
|
+
const keyFolder = map$2(String$7("HOME"), (home) => `${home}/.config/stash`);
|
|
7606
7698
|
function section(title, text) {
|
|
7607
7699
|
return pipe(fromUndefinedOr(text), filter(isNonEmpty), map$3((found) => `## ${title}\n\n${found}`));
|
|
7608
7700
|
}
|
|
7701
|
+
const login = pipe(make("login", { key: pipe(Redacted("api-key"), withDescription$2(`An API key created at ${AUTH_URL}`)) }, fnUntraced(function* (input) {
|
|
7702
|
+
const fs = yield* FileSystem;
|
|
7703
|
+
const folder = yield* keyFolder;
|
|
7704
|
+
yield* fs.makeDirectory(folder, { recursive: true });
|
|
7705
|
+
yield* fs.writeFileString(`${folder}/api-key`, value(input.key), { mode: 384 });
|
|
7706
|
+
yield* logInfo(`Signed in; the API key is in ${folder}/api-key`);
|
|
7707
|
+
})), withDescription(`Keep an API key created at ${AUTH_URL} in ~/.config/stash/api-key for save.`), withExamples([{
|
|
7708
|
+
command: "vpx @deslop/stash@latest login '<api key>'",
|
|
7709
|
+
description: `Sign in with a key from ${AUTH_URL}.`
|
|
7710
|
+
}]));
|
|
7609
7711
|
const save = pipe(make("save", {
|
|
7610
7712
|
entry: pipe(String$2("text"), withDescription$2("A link, or the text of a note")),
|
|
7611
|
-
server
|
|
7713
|
+
server
|
|
7612
7714
|
}, fnUntraced(function* (input) {
|
|
7613
7715
|
const note = yield* pipe(gen(function* () {
|
|
7614
7716
|
const client = yield* make$1(RpcContracts);
|
|
@@ -7639,10 +7741,15 @@ const save = pipe(make("save", {
|
|
|
7639
7741
|
section("Transcript", note.transcript),
|
|
7640
7742
|
section("Issue", note.issue)
|
|
7641
7743
|
], getSomes, filter$2(isNonEmpty), join("\n\n")));
|
|
7642
|
-
})), provide((input) => pipe(layerProtocolSocket({ pingTimeout: "15 seconds" }), provide$2(layerWebSocket(pipe(new URL("/api/rpc", input.server).href, replace(/^http/u, "ws")))), provide$2(layerWebSocketConstructorGlobal), provide$2(layerJson))
|
|
7744
|
+
})), provide((input) => merge$1(pipe(layerProtocolSocket({ pingTimeout: "15 seconds" }), provide$2(layerWebSocket(pipe(new URL("/api/rpc", input.server).href, replace(/^http/u, "ws")))), provide$2(layerWebSocketConstructorGlobal), provide$2(layerJson)), RpcAuth.layerClient(pipe(gen(function* () {
|
|
7745
|
+
return yield* (yield* FileSystem).readFileString(`${yield* keyFolder}/api-key`);
|
|
7746
|
+
}), mapError((cause) => AuthError.make({
|
|
7747
|
+
cause,
|
|
7748
|
+
message: `Sign in first: create an API key at ${AUTH_URL}, then run stash login '<api key>'`
|
|
7749
|
+
})))))), 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 `stash login` first."), withExamples([{
|
|
7643
7750
|
command: "vpx @deslop/stash@latest save https://x.com/poteto/status/2102050467505430555",
|
|
7644
7751
|
description: "Save the talk attached to an X post and print its note and transcript."
|
|
7645
7752
|
}]));
|
|
7646
|
-
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$1(layer)));
|
|
7753
|
+
runMain(pipe(make("stash"), withDescription("Save links and notes to stash; the server and iOS app share this package."), withSubcommands([login, save]), run({ version }), provideService(LogToStderr, true), provide$1(layer)));
|
|
7647
7754
|
//#endregion
|
|
7648
7755
|
export {};
|