@toon-protocol/rig 2.4.0 → 2.5.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/README.md +18 -5
- package/dist/chunk-AFJNFDUQ.js +281 -0
- package/dist/chunk-AFJNFDUQ.js.map +1 -0
- package/dist/{chunk-OIJNRACA.js → chunk-EBXZUWV3.js} +10 -10
- package/dist/chunk-EBXZUWV3.js.map +1 -0
- package/dist/{chunk-W2SDL2PE.js → chunk-PTXKCR5R.js} +5 -5
- package/dist/cli/rig.js +257 -44
- package/dist/cli/rig.js.map +1 -1
- package/dist/index.js +9 -9
- package/dist/network-bootstrap-WNSHRC5P.js +34 -0
- package/dist/network-bootstrap-WNSHRC5P.js.map +1 -0
- package/dist/standalone/index.d.ts +48 -23
- package/dist/standalone/index.js +1 -1
- package/dist/{standalone-mode-VH2XPOPK.js → standalone-mode-BIFFNDH3.js} +19 -269
- package/dist/standalone-mode-BIFFNDH3.js.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-OIJNRACA.js.map +0 -1
- package/dist/standalone-mode-VH2XPOPK.js.map +0 -1
- /package/dist/{chunk-W2SDL2PE.js.map → chunk-PTXKCR5R.js.map} +0 -0
package/dist/cli/rig.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
OversizeObjectsError,
|
|
7
7
|
collectRepoObjects,
|
|
8
8
|
executePush,
|
|
9
|
+
hexToNpub,
|
|
9
10
|
isSafeRefname,
|
|
10
11
|
missingObjectsMessage,
|
|
11
12
|
ownerToHex,
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
setHeadSymref,
|
|
18
19
|
updateRef,
|
|
19
20
|
writeGitObjects
|
|
20
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-PTXKCR5R.js";
|
|
21
22
|
import {
|
|
22
23
|
DEFAULT_KEYSTORE_PASSWORD,
|
|
23
24
|
MissingIdentityError,
|
|
@@ -27,6 +28,15 @@ import {
|
|
|
27
28
|
readClientConfigFile,
|
|
28
29
|
resolveIdentity
|
|
29
30
|
} from "../chunk-XGFBDUQX.js";
|
|
31
|
+
import {
|
|
32
|
+
ChannelMapStore,
|
|
33
|
+
channelStatus,
|
|
34
|
+
defaultDaemonPort,
|
|
35
|
+
resolveChannelPaths
|
|
36
|
+
} from "../chunk-SW7ZHMGS.js";
|
|
37
|
+
import {
|
|
38
|
+
MAX_OBJECT_SIZE
|
|
39
|
+
} from "../chunk-X2CZPPDM.js";
|
|
30
40
|
import {
|
|
31
41
|
COMMENT_KIND,
|
|
32
42
|
authorizedStatusAuthors,
|
|
@@ -39,15 +49,6 @@ import {
|
|
|
39
49
|
parseMaintainers,
|
|
40
50
|
queryRelay
|
|
41
51
|
} from "../chunk-3HRFDH7H.js";
|
|
42
|
-
import {
|
|
43
|
-
ChannelMapStore,
|
|
44
|
-
channelStatus,
|
|
45
|
-
defaultDaemonPort,
|
|
46
|
-
resolveChannelPaths
|
|
47
|
-
} from "../chunk-SW7ZHMGS.js";
|
|
48
|
-
import {
|
|
49
|
-
MAX_OBJECT_SIZE
|
|
50
|
-
} from "../chunk-X2CZPPDM.js";
|
|
51
52
|
|
|
52
53
|
// src/cli/rig.ts
|
|
53
54
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
@@ -263,7 +264,7 @@ var NotAGitRepositoryError = class extends Error {
|
|
|
263
264
|
constructor(cwd) {
|
|
264
265
|
super(
|
|
265
266
|
`not a git repository: ${cwd}
|
|
266
|
-
rig
|
|
267
|
+
rig can create one for you: re-run \`rig init --git-init\` (in a terminal, plain \`rig init\` offers the same via a prompt). Or run \`git init\` yourself first, then re-run.`
|
|
267
268
|
);
|
|
268
269
|
this.name = "NotAGitRepositoryError";
|
|
269
270
|
}
|
|
@@ -607,6 +608,9 @@ async function resolveRepoRoot(cwd) {
|
|
|
607
608
|
);
|
|
608
609
|
}
|
|
609
610
|
}
|
|
611
|
+
async function initGitRepository(dir) {
|
|
612
|
+
await git(dir, ["init"]);
|
|
613
|
+
}
|
|
610
614
|
async function readToonConfig(repoPath) {
|
|
611
615
|
const [repoId, owner, relays] = await Promise.all([
|
|
612
616
|
git(repoPath, ["config", "--get", "toon.repoid"], [1]),
|
|
@@ -639,6 +643,10 @@ async function listGitRemotes(repoPath) {
|
|
|
639
643
|
}
|
|
640
644
|
return remotes;
|
|
641
645
|
}
|
|
646
|
+
async function setGitAuthor(repoPath, author) {
|
|
647
|
+
await git(repoPath, ["config", "--local", "user.name", author.name]);
|
|
648
|
+
await git(repoPath, ["config", "--local", "user.email", author.email]);
|
|
649
|
+
}
|
|
642
650
|
async function addGitRemote(repoPath, name, url) {
|
|
643
651
|
await git(repoPath, ["remote", "add", name, url]);
|
|
644
652
|
}
|
|
@@ -905,7 +913,7 @@ function loadPaidSession(deps, relayUrl) {
|
|
|
905
913
|
});
|
|
906
914
|
}
|
|
907
915
|
var defaultLoadStandalone = async (options) => {
|
|
908
|
-
const mod = await import("../standalone-mode-
|
|
916
|
+
const mod = await import("../standalone-mode-BIFFNDH3.js");
|
|
909
917
|
return mod.createStandaloneContext(options);
|
|
910
918
|
};
|
|
911
919
|
function identityReport(ctx) {
|
|
@@ -1215,14 +1223,26 @@ async function runPush(args, deps) {
|
|
|
1215
1223
|
// src/cli/balance.ts
|
|
1216
1224
|
var BALANCE_USAGE = `Usage: rig balance [--json]
|
|
1217
1225
|
|
|
1218
|
-
Show the active identity's money: on-chain wallet
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1226
|
+
Show the active identity's money: the full on-chain wallet view \u2014 native coin
|
|
1227
|
+
plus USDC on every configured chain (EVM / Solana / Mina) \u2014 and recorded
|
|
1228
|
+
payment-channel holdings (deposited / claimed / available). Free \u2014 reads chain
|
|
1229
|
+
RPCs and local state only; nothing is signed or paid. An unreachable chain RPC
|
|
1230
|
+
degrades to a per-chain notice without failing the others.
|
|
1222
1231
|
|
|
1223
1232
|
Options:
|
|
1224
1233
|
--json machine-readable envelope (base units as strings)
|
|
1225
1234
|
-h, --help show this help`;
|
|
1235
|
+
function formatUnits(amount, decimals) {
|
|
1236
|
+
if (decimals === void 0 || decimals <= 0) return amount;
|
|
1237
|
+
const neg = amount.startsWith("-");
|
|
1238
|
+
const digits = (neg ? amount.slice(1) : amount).padStart(decimals + 1, "0");
|
|
1239
|
+
const whole = digits.slice(0, digits.length - decimals);
|
|
1240
|
+
const frac = digits.slice(digits.length - decimals).replace(/0+$/, "");
|
|
1241
|
+
return (neg ? "-" : "") + (frac ? `${whole}.${frac}` : whole);
|
|
1242
|
+
}
|
|
1243
|
+
function renderAmount(a) {
|
|
1244
|
+
return `${a.symbol ?? "token"} ${formatUnits(a.amount, a.decimals)}`;
|
|
1245
|
+
}
|
|
1226
1246
|
async function runBalance(args, deps) {
|
|
1227
1247
|
const { io: io2, env } = deps;
|
|
1228
1248
|
let json = false;
|
|
@@ -1254,7 +1274,7 @@ async function runBalance(args, deps) {
|
|
|
1254
1274
|
requireUplink: false
|
|
1255
1275
|
});
|
|
1256
1276
|
const identity = identityReport(ctx);
|
|
1257
|
-
const wallet = ctx.money ? await ctx.money.
|
|
1277
|
+
const wallet = ctx.money ? await ctx.money.walletChainBalances() : [];
|
|
1258
1278
|
const store = new ChannelMapStore(resolveChannelPaths(env));
|
|
1259
1279
|
const channels = store.list().filter((record) => record.identity === identity.pubkey).map((record) => {
|
|
1260
1280
|
const watermark = store.readWatermark(record.channelId);
|
|
@@ -1291,13 +1311,23 @@ async function runBalance(args, deps) {
|
|
|
1291
1311
|
io2.out("Wallet (on-chain):");
|
|
1292
1312
|
if (wallet.length === 0) {
|
|
1293
1313
|
io2.out(
|
|
1294
|
-
" (no
|
|
1314
|
+
" (no chain configured for this identity \u2014 nothing to read)"
|
|
1295
1315
|
);
|
|
1296
1316
|
}
|
|
1297
|
-
for (const
|
|
1298
|
-
io2.out(
|
|
1299
|
-
|
|
1300
|
-
|
|
1317
|
+
for (const chain of wallet) {
|
|
1318
|
+
io2.out(` ${chain.chainKey.padEnd(11)} ${chain.address}`);
|
|
1319
|
+
if (chain.unreadable) {
|
|
1320
|
+
io2.out(
|
|
1321
|
+
` unreadable (RPC unreachable)` + (chain.error ? ` \u2014 ${chain.error}` : "")
|
|
1322
|
+
);
|
|
1323
|
+
continue;
|
|
1324
|
+
}
|
|
1325
|
+
const assets = [...chain.native ? [chain.native] : [], ...chain.tokens];
|
|
1326
|
+
if (assets.length === 0) {
|
|
1327
|
+
io2.out(" (no balance readable)");
|
|
1328
|
+
continue;
|
|
1329
|
+
}
|
|
1330
|
+
io2.out(` ${assets.map(renderAmount).join(" ")}`);
|
|
1301
1331
|
}
|
|
1302
1332
|
io2.out("");
|
|
1303
1333
|
io2.out("Channels (recorded):");
|
|
@@ -3439,7 +3469,9 @@ pays). The identity comes from RIG_MNEMONIC (env or a project .env) or the
|
|
|
3439
3469
|
~/.toon-client keystore/config; the faucet from TOON_CLIENT_FAUCET_URL, the
|
|
3440
3470
|
faucetUrl config field, or the deployed devnet faucet when the network is
|
|
3441
3471
|
devnet \u2014 including when a configured *.devnet.toonprotocol.dev origin infers
|
|
3442
|
-
it
|
|
3472
|
+
it (a devnet relay/proxy/btp endpoint, or the git origin remote from
|
|
3473
|
+
\`rig remote add origin <devnet relay>\`). The faucet drips a FIXED amount per
|
|
3474
|
+
chain (there is no --amount). On a
|
|
3443
3475
|
network without a faucet, prints the wallet address(es) to fund externally
|
|
3444
3476
|
instead.
|
|
3445
3477
|
|
|
@@ -3450,24 +3482,50 @@ Options:
|
|
|
3450
3482
|
--json machine-readable envelope
|
|
3451
3483
|
-h, --help show this help`;
|
|
3452
3484
|
var SHARED_DEVNET_SUFFIX = ".devnet.toonprotocol.dev";
|
|
3453
|
-
function
|
|
3485
|
+
function devnetHost(url) {
|
|
3486
|
+
if (!url) return void 0;
|
|
3487
|
+
try {
|
|
3488
|
+
const { hostname } = new URL(url);
|
|
3489
|
+
if (hostname.endsWith(SHARED_DEVNET_SUFFIX) || hostname === SHARED_DEVNET_SUFFIX.slice(1)) {
|
|
3490
|
+
return url;
|
|
3491
|
+
}
|
|
3492
|
+
} catch {
|
|
3493
|
+
}
|
|
3494
|
+
return void 0;
|
|
3495
|
+
}
|
|
3496
|
+
function sharedDevnetOrigin(env, file, originRelays = []) {
|
|
3454
3497
|
const candidates = [
|
|
3455
3498
|
env["TOON_CLIENT_RELAY_URL"] ?? file.relayUrl,
|
|
3456
3499
|
env["TOON_CLIENT_PROXY_URL"] ?? file.proxyUrl,
|
|
3457
|
-
env["TOON_CLIENT_BTP_URL"] ?? file.btpUrl
|
|
3500
|
+
env["TOON_CLIENT_BTP_URL"] ?? file.btpUrl,
|
|
3501
|
+
...originRelays
|
|
3458
3502
|
];
|
|
3459
3503
|
for (const url of candidates) {
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
const { hostname } = new URL(url);
|
|
3463
|
-
if (hostname.endsWith(SHARED_DEVNET_SUFFIX) || hostname === SHARED_DEVNET_SUFFIX.slice(1)) {
|
|
3464
|
-
return url;
|
|
3465
|
-
}
|
|
3466
|
-
} catch {
|
|
3467
|
-
}
|
|
3504
|
+
const hit = devnetHost(url);
|
|
3505
|
+
if (hit) return hit;
|
|
3468
3506
|
}
|
|
3469
3507
|
return void 0;
|
|
3470
3508
|
}
|
|
3509
|
+
async function resolveOriginRelays(cwd) {
|
|
3510
|
+
let repoRoot;
|
|
3511
|
+
try {
|
|
3512
|
+
repoRoot = await resolveRepoRoot(cwd);
|
|
3513
|
+
} catch {
|
|
3514
|
+
return [];
|
|
3515
|
+
}
|
|
3516
|
+
try {
|
|
3517
|
+
const toonConfig = await readToonConfig(repoRoot);
|
|
3518
|
+
const resolved = await resolveRelays({
|
|
3519
|
+
relayFlags: [],
|
|
3520
|
+
remoteName: void 0,
|
|
3521
|
+
repoRoot,
|
|
3522
|
+
toonRelays: toonConfig.relays
|
|
3523
|
+
});
|
|
3524
|
+
return resolved.relays;
|
|
3525
|
+
} catch {
|
|
3526
|
+
return [];
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3471
3529
|
function noFaucetGuidance(network, devnetOrigin) {
|
|
3472
3530
|
const head = `no faucet is configured for network ${JSON.stringify(network ?? "custom")}`;
|
|
3473
3531
|
const external = "To fund the wallet externally instead, send the settlement token plus native gas to the address below for the chain your channels settle on.";
|
|
@@ -3534,7 +3592,9 @@ async function runFund(args, deps) {
|
|
|
3534
3592
|
);
|
|
3535
3593
|
}
|
|
3536
3594
|
const network = env["TOON_CLIENT_NETWORK"] ?? file.network;
|
|
3537
|
-
const
|
|
3595
|
+
const canInfer = network === void 0 || network === "custom";
|
|
3596
|
+
const originRelays = canInfer ? await resolveOriginRelays(deps.cwd) : [];
|
|
3597
|
+
const devnetOrigin = sharedDevnetOrigin(env, file, originRelays);
|
|
3538
3598
|
const inferredDevnet = devnetOrigin !== void 0 && (network === void 0 || network === "custom");
|
|
3539
3599
|
const effectiveNetwork = inferredDevnet ? "devnet" : network;
|
|
3540
3600
|
const faucetUrl = env["TOON_CLIENT_FAUCET_URL"] ?? file.faucetUrl ?? (effectiveNetwork === "devnet" ? DEVNET_FAUCET_URL : void 0);
|
|
@@ -4063,6 +4123,82 @@ async function defaultReadSecretLine(prompt, isInteractive) {
|
|
|
4063
4123
|
// src/cli/init.ts
|
|
4064
4124
|
import { basename as basename2 } from "path";
|
|
4065
4125
|
import { parseArgs as parseArgs11 } from "util";
|
|
4126
|
+
|
|
4127
|
+
// src/cli/git-author.ts
|
|
4128
|
+
var PROFILE_KIND = 0;
|
|
4129
|
+
var DEFAULT_PROFILE_TIMEOUT_MS = 3e3;
|
|
4130
|
+
var PROFILE_TIMEOUT_ENV = "RIG_PROFILE_TIMEOUT_MS";
|
|
4131
|
+
function isWebSocketRelay(url) {
|
|
4132
|
+
return /^wss?:\/\//i.test(url);
|
|
4133
|
+
}
|
|
4134
|
+
function displayNameFromKind0(content) {
|
|
4135
|
+
let parsed;
|
|
4136
|
+
try {
|
|
4137
|
+
parsed = JSON.parse(content);
|
|
4138
|
+
} catch {
|
|
4139
|
+
return void 0;
|
|
4140
|
+
}
|
|
4141
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
4142
|
+
const fields = parsed;
|
|
4143
|
+
for (const key of ["display_name", "name"]) {
|
|
4144
|
+
const value = fields[key];
|
|
4145
|
+
if (typeof value === "string" && value.trim() !== "") return value.trim();
|
|
4146
|
+
}
|
|
4147
|
+
return void 0;
|
|
4148
|
+
}
|
|
4149
|
+
async function resolveGitAuthor(options) {
|
|
4150
|
+
const npub = hexToNpub(options.pubkey);
|
|
4151
|
+
const email = `${npub}@nostr`;
|
|
4152
|
+
const fallback = { name: npub, email, npub, source: "npub" };
|
|
4153
|
+
const { relayUrl } = options;
|
|
4154
|
+
if (relayUrl === void 0 || !isWebSocketRelay(relayUrl)) {
|
|
4155
|
+
return fallback;
|
|
4156
|
+
}
|
|
4157
|
+
const query = options.queryRelayImpl ?? queryRelay;
|
|
4158
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_PROFILE_TIMEOUT_MS;
|
|
4159
|
+
const factory = options.webSocketFactory ?? defaultWebSocketFactory2;
|
|
4160
|
+
try {
|
|
4161
|
+
const events = await query(
|
|
4162
|
+
relayUrl,
|
|
4163
|
+
{ kinds: [PROFILE_KIND], authors: [options.pubkey], limit: 20 },
|
|
4164
|
+
timeoutMs,
|
|
4165
|
+
factory
|
|
4166
|
+
);
|
|
4167
|
+
let latest;
|
|
4168
|
+
for (const event of events) {
|
|
4169
|
+
if (event.kind !== PROFILE_KIND) continue;
|
|
4170
|
+
if (event.pubkey !== options.pubkey) continue;
|
|
4171
|
+
if (!latest || event.created_at > latest.created_at) {
|
|
4172
|
+
latest = { created_at: event.created_at, content: event.content };
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
if (latest) {
|
|
4176
|
+
const name = displayNameFromKind0(latest.content);
|
|
4177
|
+
if (name !== void 0) {
|
|
4178
|
+
return { name, email, npub, source: "profile" };
|
|
4179
|
+
}
|
|
4180
|
+
}
|
|
4181
|
+
} catch {
|
|
4182
|
+
}
|
|
4183
|
+
return fallback;
|
|
4184
|
+
}
|
|
4185
|
+
function profileTimeoutFromEnv(env) {
|
|
4186
|
+
const raw = env[PROFILE_TIMEOUT_ENV]?.trim();
|
|
4187
|
+
if (!raw) return void 0;
|
|
4188
|
+
const ms = Number.parseInt(raw, 10);
|
|
4189
|
+
return Number.isFinite(ms) && ms > 0 ? ms : void 0;
|
|
4190
|
+
}
|
|
4191
|
+
function defaultWebSocketFactory2(url) {
|
|
4192
|
+
const ctor = globalThis.WebSocket;
|
|
4193
|
+
if (!ctor) {
|
|
4194
|
+
throw new Error(
|
|
4195
|
+
"No global WebSocket constructor (Node >= 22 required) for the kind:0 read"
|
|
4196
|
+
);
|
|
4197
|
+
}
|
|
4198
|
+
return new ctor(url);
|
|
4199
|
+
}
|
|
4200
|
+
|
|
4201
|
+
// src/cli/init.ts
|
|
4066
4202
|
var INIT_USAGE = `Usage: rig init [options]
|
|
4067
4203
|
|
|
4068
4204
|
Set up the current git repository for rig (one-shot, idempotent, free):
|
|
@@ -4071,19 +4207,35 @@ keystore/config), then writes toon.repoid and toon.owner to the repo's
|
|
|
4071
4207
|
LOCAL git config. Re-running updates and reports; it never errors on an
|
|
4072
4208
|
already-initialized repo. The seed phrase is never written anywhere.
|
|
4073
4209
|
|
|
4210
|
+
It also sets the repo's LOCAL git commit-author from your nostr identity
|
|
4211
|
+
(never --global) so \`rig commit\`/\`git commit\` work out of the box and every
|
|
4212
|
+
commit is attributed to the signer: user.email = <npub>@nostr, user.name =
|
|
4213
|
+
your kind:0 profile display name when published (read best-effort from a
|
|
4214
|
+
relay, latest-wins) else the npub. Re-running refreshes the name from a
|
|
4215
|
+
now-readable profile.
|
|
4216
|
+
|
|
4074
4217
|
The follow-up step is adding a relay: \`rig remote add origin <relay-url>\`
|
|
4075
4218
|
(a real git remote \u2014 \`git remote -v\` shows it). A deprecated v0.1
|
|
4076
4219
|
\`git config toon.relay\` is migrated to the origin remote automatically
|
|
4077
4220
|
when no origin exists (the old key stays readable and is removed in v0.3).
|
|
4078
4221
|
|
|
4079
|
-
When
|
|
4080
|
-
|
|
4081
|
-
does it non-interactively
|
|
4082
|
-
|
|
4222
|
+
When the directory is NOT inside a git repository, init does not dead-end: in
|
|
4223
|
+
a terminal it offers to create one (\`Initialize a git repository here?
|
|
4224
|
+
[y/N]\`), and \`--git-init\` does it non-interactively. Likewise, when NO
|
|
4225
|
+
identity resolves it offers to generate one (\`Create a new identity now?
|
|
4226
|
+
[y/N]\`), and \`--generate-identity\` does it non-interactively (equivalent to
|
|
4227
|
+
\`rig identity create\` \u2014 the phrase is shown once to back up). Nothing \u2014 repo
|
|
4228
|
+
or identity \u2014 is ever created without your yes. \`--git-init
|
|
4229
|
+
--generate-identity\` is a fully non-interactive fresh setup.
|
|
4083
4230
|
|
|
4084
4231
|
Options:
|
|
4085
4232
|
--repo-id <id> repository id / NIP-34 d-tag (default: the existing
|
|
4086
4233
|
toon.repoid, then the repo directory basename)
|
|
4234
|
+
--git-init when the cwd is not a git repo, run \`git init\` here
|
|
4235
|
+
first, then proceed (no prompt)
|
|
4236
|
+
--relay <url> relay to read your kind:0 profile from for the git
|
|
4237
|
+
author name (default: origin/toon.relay, then the
|
|
4238
|
+
genesis seed; skipped if none is resolvable)
|
|
4087
4239
|
--generate-identity when no identity resolves, mint a fresh one (no prompt)
|
|
4088
4240
|
--json machine-readable report
|
|
4089
4241
|
-h, --help show this help`;
|
|
@@ -4092,6 +4244,8 @@ function parseInitArgs(args) {
|
|
|
4092
4244
|
args,
|
|
4093
4245
|
options: {
|
|
4094
4246
|
"repo-id": { type: "string" },
|
|
4247
|
+
"git-init": { type: "boolean", default: false },
|
|
4248
|
+
relay: { type: "string" },
|
|
4095
4249
|
"generate-identity": { type: "boolean", default: false },
|
|
4096
4250
|
json: { type: "boolean", default: false },
|
|
4097
4251
|
help: { type: "boolean", short: "h", default: false }
|
|
@@ -4102,6 +4256,7 @@ function parseInitArgs(args) {
|
|
|
4102
4256
|
throw new Error(`rig init takes no positional arguments`);
|
|
4103
4257
|
}
|
|
4104
4258
|
const flags = {
|
|
4259
|
+
gitInit: values["git-init"] ?? false,
|
|
4105
4260
|
generateIdentity: values["generate-identity"] ?? false,
|
|
4106
4261
|
json: values.json ?? false,
|
|
4107
4262
|
help: values.help ?? false
|
|
@@ -4111,8 +4266,46 @@ function parseInitArgs(args) {
|
|
|
4111
4266
|
if (repoId.trim() === "") throw new Error("--repo-id must not be empty");
|
|
4112
4267
|
flags.repoId = repoId;
|
|
4113
4268
|
}
|
|
4269
|
+
const relay = values.relay;
|
|
4270
|
+
if (relay !== void 0) {
|
|
4271
|
+
if (relay.trim() === "") throw new Error("--relay must not be empty");
|
|
4272
|
+
flags.relay = relay.trim();
|
|
4273
|
+
}
|
|
4114
4274
|
return flags;
|
|
4115
4275
|
}
|
|
4276
|
+
function isWebSocketRelay2(url) {
|
|
4277
|
+
return /^wss?:\/\//i.test(url);
|
|
4278
|
+
}
|
|
4279
|
+
async function resolveProfileRelay(flagRelay, originRelay, toonRelays) {
|
|
4280
|
+
const candidates = [
|
|
4281
|
+
flagRelay,
|
|
4282
|
+
originRelay,
|
|
4283
|
+
...toonRelays
|
|
4284
|
+
].filter((u) => u !== void 0 && isWebSocketRelay2(u));
|
|
4285
|
+
if (candidates[0] !== void 0) return candidates[0];
|
|
4286
|
+
try {
|
|
4287
|
+
const { loadGenesisSeed } = await import("../network-bootstrap-WNSHRC5P.js");
|
|
4288
|
+
const seed = loadGenesisSeed();
|
|
4289
|
+
if (seed?.relayUrl && isWebSocketRelay2(seed.relayUrl)) return seed.relayUrl;
|
|
4290
|
+
} catch {
|
|
4291
|
+
}
|
|
4292
|
+
return void 0;
|
|
4293
|
+
}
|
|
4294
|
+
async function resolveOrInitGitRepo(deps, flags) {
|
|
4295
|
+
const { io: io2 } = deps;
|
|
4296
|
+
try {
|
|
4297
|
+
return { repoRoot: await resolveRepoRoot(deps.cwd), initialized: false };
|
|
4298
|
+
} catch {
|
|
4299
|
+
let doInit = flags.gitInit;
|
|
4300
|
+
if (!doInit && io2.isInteractive && !flags.json) {
|
|
4301
|
+
io2.err("Not a git repository \u2014 rig keeps its config and objects in one.");
|
|
4302
|
+
doInit = await io2.confirm("Initialize a git repository here? [y/N] ");
|
|
4303
|
+
}
|
|
4304
|
+
if (!doInit) throw new NotAGitRepositoryError(deps.cwd);
|
|
4305
|
+
await initGitRepository(deps.cwd);
|
|
4306
|
+
return { repoRoot: await resolveRepoRoot(deps.cwd), initialized: true };
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4116
4309
|
async function resolveOrGenerateIdentity(deps, flags) {
|
|
4117
4310
|
const { io: io2, env } = deps;
|
|
4118
4311
|
const resolve2 = deps.resolveIdentityImpl ?? resolveIdentity;
|
|
@@ -4158,12 +4351,7 @@ async function runInit(args, deps) {
|
|
|
4158
4351
|
return 0;
|
|
4159
4352
|
}
|
|
4160
4353
|
try {
|
|
4161
|
-
|
|
4162
|
-
try {
|
|
4163
|
-
repoRoot = await resolveRepoRoot(deps.cwd);
|
|
4164
|
-
} catch {
|
|
4165
|
-
throw new NotAGitRepositoryError(deps.cwd);
|
|
4166
|
-
}
|
|
4354
|
+
const { repoRoot, initialized: initializedGitRepo } = await resolveOrInitGitRepo(deps, flags);
|
|
4167
4355
|
const { identity, generated } = await resolveOrGenerateIdentity(deps, flags);
|
|
4168
4356
|
const existing = await readToonConfig(repoRoot);
|
|
4169
4357
|
const repoId = flags.repoId ?? existing.repoId ?? basename2(repoRoot);
|
|
@@ -4182,10 +4370,26 @@ async function runInit(args, deps) {
|
|
|
4182
4370
|
}
|
|
4183
4371
|
const origin = remotes.find((r) => r.name === "origin");
|
|
4184
4372
|
const originRelay = origin !== void 0 && origin.urls.length === 1 && isRelayUrl(origin.urls[0]) ? origin.urls[0] : void 0;
|
|
4373
|
+
const profileRelay = await resolveProfileRelay(
|
|
4374
|
+
flags.relay,
|
|
4375
|
+
originRelay,
|
|
4376
|
+
existing.relays
|
|
4377
|
+
);
|
|
4378
|
+
const resolveAuthor = deps.resolveGitAuthorImpl ?? resolveGitAuthor;
|
|
4379
|
+
const gitAuthor = await resolveAuthor({
|
|
4380
|
+
pubkey: identity.pubkey,
|
|
4381
|
+
relayUrl: profileRelay,
|
|
4382
|
+
...profileTimeoutFromEnv(deps.env) !== void 0 ? { timeoutMs: profileTimeoutFromEnv(deps.env) } : {}
|
|
4383
|
+
});
|
|
4384
|
+
await setGitAuthor(repoRoot, {
|
|
4385
|
+
name: gitAuthor.name,
|
|
4386
|
+
email: gitAuthor.email
|
|
4387
|
+
});
|
|
4185
4388
|
if (flags.json) {
|
|
4186
4389
|
const output = {
|
|
4187
4390
|
command: "init",
|
|
4188
4391
|
repoRoot,
|
|
4392
|
+
initializedGitRepo,
|
|
4189
4393
|
repoId,
|
|
4190
4394
|
owner: identity.pubkey,
|
|
4191
4395
|
identity: {
|
|
@@ -4198,6 +4402,11 @@ async function runInit(args, deps) {
|
|
|
4198
4402
|
remotes,
|
|
4199
4403
|
origin: originRelay ?? null,
|
|
4200
4404
|
migratedToonRelay,
|
|
4405
|
+
gitAuthor: {
|
|
4406
|
+
name: gitAuthor.name,
|
|
4407
|
+
email: gitAuthor.email,
|
|
4408
|
+
source: gitAuthor.source
|
|
4409
|
+
},
|
|
4201
4410
|
changed,
|
|
4202
4411
|
...generated ? {
|
|
4203
4412
|
generatedIdentity: {
|
|
@@ -4221,6 +4430,7 @@ async function runInit(args, deps) {
|
|
|
4221
4430
|
for (const line of createdIdentityBanner(generated)) io2.out(line);
|
|
4222
4431
|
if (generated.shadowedBy) io2.err(shadowNote(generated.shadowedBy));
|
|
4223
4432
|
}
|
|
4433
|
+
if (initializedGitRepo) io2.out(`Created a git repository at ${repoRoot}`);
|
|
4224
4434
|
io2.out(`Initialized rig for ${repoRoot}`);
|
|
4225
4435
|
io2.out(renderIdentityLine(identity));
|
|
4226
4436
|
io2.out(
|
|
@@ -4229,6 +4439,9 @@ async function runInit(args, deps) {
|
|
|
4229
4439
|
io2.out(
|
|
4230
4440
|
` toon.owner = ${identity.pubkey}` + (changed.owner ? "" : " (unchanged)") + (existing.owner && changed.owner ? ` (was ${existing.owner})` : "")
|
|
4231
4441
|
);
|
|
4442
|
+
io2.out(
|
|
4443
|
+
`Git author: ${gitAuthor.name} <${gitAuthor.email}> (from ${gitAuthor.source === "profile" ? "nostr profile" : "npub"})`
|
|
4444
|
+
);
|
|
4232
4445
|
if (originRelay !== void 0) {
|
|
4233
4446
|
io2.out(
|
|
4234
4447
|
` origin = ${originRelay}` + (migratedToonRelay ? " (migrated from git config toon.relay)" : "")
|