sequoia-cli 0.3.0 → 0.3.1
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/index.js +127 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -99159,6 +99159,25 @@ async function deleteOAuthSession(did) {
|
|
|
99159
99159
|
function getOAuthStorePath() {
|
|
99160
99160
|
return OAUTH_FILE;
|
|
99161
99161
|
}
|
|
99162
|
+
async function setOAuthHandle(did, handle) {
|
|
99163
|
+
const store = await loadOAuthStore();
|
|
99164
|
+
if (!store.handles) {
|
|
99165
|
+
store.handles = {};
|
|
99166
|
+
}
|
|
99167
|
+
store.handles[did] = handle;
|
|
99168
|
+
await saveOAuthStore(store);
|
|
99169
|
+
}
|
|
99170
|
+
async function getOAuthHandle(did) {
|
|
99171
|
+
const store = await loadOAuthStore();
|
|
99172
|
+
return store.handles?.[did];
|
|
99173
|
+
}
|
|
99174
|
+
async function listOAuthSessionsWithHandles() {
|
|
99175
|
+
const store = await loadOAuthStore();
|
|
99176
|
+
return Object.keys(store.sessions).map((did) => ({
|
|
99177
|
+
did,
|
|
99178
|
+
handle: store.handles?.[did]
|
|
99179
|
+
}));
|
|
99180
|
+
}
|
|
99162
99181
|
|
|
99163
99182
|
// src/lib/oauth-client.ts
|
|
99164
99183
|
var CALLBACK_PORT = 4000;
|
|
@@ -99330,9 +99349,17 @@ async function uploadImage(agent, imagePath) {
|
|
|
99330
99349
|
}
|
|
99331
99350
|
}
|
|
99332
99351
|
async function resolveImagePath(ogImage, imagesDir, contentDir) {
|
|
99333
|
-
const filename = path4.basename(ogImage);
|
|
99334
99352
|
if (imagesDir) {
|
|
99335
|
-
const
|
|
99353
|
+
const imagesDirBaseName = path4.basename(imagesDir);
|
|
99354
|
+
const imagesDirIndex = ogImage.indexOf(imagesDirBaseName);
|
|
99355
|
+
let relativePath;
|
|
99356
|
+
if (imagesDirIndex !== -1) {
|
|
99357
|
+
const afterImagesDir = ogImage.substring(imagesDirIndex + imagesDirBaseName.length);
|
|
99358
|
+
relativePath = afterImagesDir.replace(/^[/\\]/, "");
|
|
99359
|
+
} else {
|
|
99360
|
+
relativePath = path4.basename(ogImage);
|
|
99361
|
+
}
|
|
99362
|
+
const imagePath = path4.join(imagesDir, relativePath);
|
|
99336
99363
|
if (await fileExists2(imagePath)) {
|
|
99337
99364
|
const stat2 = await fs3.stat(imagePath);
|
|
99338
99365
|
if (stat2.size > 0) {
|
|
@@ -99727,14 +99754,25 @@ async function tryLoadOAuthCredentials(profile) {
|
|
|
99727
99754
|
if (profile.startsWith("did:")) {
|
|
99728
99755
|
const session = await getOAuthSession(profile);
|
|
99729
99756
|
if (session) {
|
|
99757
|
+
const handle = await getOAuthHandle(profile);
|
|
99730
99758
|
return {
|
|
99731
99759
|
type: "oauth",
|
|
99732
99760
|
did: profile,
|
|
99733
|
-
handle: profile,
|
|
99761
|
+
handle: handle || profile,
|
|
99734
99762
|
pdsUrl: "https://bsky.social"
|
|
99735
99763
|
};
|
|
99736
99764
|
}
|
|
99737
99765
|
}
|
|
99766
|
+
const sessions = await listOAuthSessionsWithHandles();
|
|
99767
|
+
const match2 = sessions.find((s) => s.handle === profile);
|
|
99768
|
+
if (match2) {
|
|
99769
|
+
return {
|
|
99770
|
+
type: "oauth",
|
|
99771
|
+
did: match2.did,
|
|
99772
|
+
handle: match2.handle || match2.did,
|
|
99773
|
+
pdsUrl: "https://bsky.social"
|
|
99774
|
+
};
|
|
99775
|
+
}
|
|
99738
99776
|
return null;
|
|
99739
99777
|
}
|
|
99740
99778
|
async function loadCredentials(projectIdentity) {
|
|
@@ -99779,10 +99817,11 @@ async function loadCredentials(projectIdentity) {
|
|
|
99779
99817
|
if (oauthDids.length === 1 && oauthDids[0]) {
|
|
99780
99818
|
const session = await getOAuthSession(oauthDids[0]);
|
|
99781
99819
|
if (session) {
|
|
99820
|
+
const handle = await getOAuthHandle(oauthDids[0]);
|
|
99782
99821
|
return {
|
|
99783
99822
|
type: "oauth",
|
|
99784
99823
|
did: oauthDids[0],
|
|
99785
|
-
handle: oauthDids[0],
|
|
99824
|
+
handle: handle || oauthDids[0],
|
|
99786
99825
|
pdsUrl: "https://bsky.social"
|
|
99787
99826
|
};
|
|
99788
99827
|
}
|
|
@@ -99801,6 +99840,18 @@ async function listCredentials() {
|
|
|
99801
99840
|
const store = await loadCredentialsStore();
|
|
99802
99841
|
return Object.keys(store);
|
|
99803
99842
|
}
|
|
99843
|
+
async function listAllCredentials() {
|
|
99844
|
+
const store = await loadCredentialsStore();
|
|
99845
|
+
const oauthDids = await listOAuthSessions();
|
|
99846
|
+
const result = [];
|
|
99847
|
+
for (const id of Object.keys(store)) {
|
|
99848
|
+
result.push({ id, type: "app-password" });
|
|
99849
|
+
}
|
|
99850
|
+
for (const did of oauthDids) {
|
|
99851
|
+
result.push({ id: did, type: "oauth" });
|
|
99852
|
+
}
|
|
99853
|
+
return result;
|
|
99854
|
+
}
|
|
99804
99855
|
async function saveCredentials(credentials) {
|
|
99805
99856
|
const store = await loadCredentialsStore();
|
|
99806
99857
|
store[credentials.identifier] = credentials;
|
|
@@ -100491,13 +100542,13 @@ var loginCommand = import_cmd_ts4.command({
|
|
|
100491
100542
|
},
|
|
100492
100543
|
handler: async ({ logout, list }) => {
|
|
100493
100544
|
if (list) {
|
|
100494
|
-
const sessions = await
|
|
100545
|
+
const sessions = await listOAuthSessionsWithHandles();
|
|
100495
100546
|
if (sessions.length === 0) {
|
|
100496
100547
|
R2.info("No OAuth sessions stored");
|
|
100497
100548
|
} else {
|
|
100498
100549
|
R2.info("OAuth sessions:");
|
|
100499
|
-
for (const did2 of sessions) {
|
|
100500
|
-
console.log(` - ${did2}`);
|
|
100550
|
+
for (const { did: did2, handle: handle2 } of sessions) {
|
|
100551
|
+
console.log(` - ${handle2 || did2} (${did2})`);
|
|
100501
100552
|
}
|
|
100502
100553
|
}
|
|
100503
100554
|
return;
|
|
@@ -100591,12 +100642,11 @@ var loginCommand = import_cmd_ts4.command({
|
|
|
100591
100642
|
}
|
|
100592
100643
|
s.message("Completing authentication...");
|
|
100593
100644
|
const { session } = await client.callback(new URLSearchParams(result.params));
|
|
100594
|
-
|
|
100595
|
-
|
|
100596
|
-
|
|
100597
|
-
} catch {
|
|
100598
|
-
displayName = session.did;
|
|
100645
|
+
const handleToStore = handle.startsWith("did:") ? undefined : handle;
|
|
100646
|
+
if (handleToStore) {
|
|
100647
|
+
await setOAuthHandle(session.did, handleToStore);
|
|
100599
100648
|
}
|
|
100649
|
+
const displayName = handleToStore || session.did;
|
|
100600
100650
|
s.stop(`Logged in as ${displayName}`);
|
|
100601
100651
|
R2.success(`OAuth session saved to ${getOAuthStorePath()}`);
|
|
100602
100652
|
R2.info("Your session will refresh automatically when needed.");
|
|
@@ -100727,23 +100777,51 @@ var publishCommand = import_cmd_ts5.command({
|
|
|
100727
100777
|
R2.info(`Content directory: ${config.contentDir}`);
|
|
100728
100778
|
let credentials = await loadCredentials(config.identity);
|
|
100729
100779
|
if (!credentials) {
|
|
100730
|
-
const identities = await
|
|
100780
|
+
const identities = await listAllCredentials();
|
|
100731
100781
|
if (identities.length === 0) {
|
|
100732
|
-
R2.error("No credentials found. Run 'sequoia auth' first.");
|
|
100782
|
+
R2.error("No credentials found. Run 'sequoia login' or 'sequoia auth' first.");
|
|
100733
100783
|
R2.info("Or set ATP_IDENTIFIER and ATP_APP_PASSWORD environment variables.");
|
|
100734
100784
|
process.exit(1);
|
|
100735
100785
|
}
|
|
100786
|
+
const options = await Promise.all(identities.map(async (cred) => {
|
|
100787
|
+
if (cred.type === "oauth") {
|
|
100788
|
+
const handle = await getOAuthHandle(cred.id);
|
|
100789
|
+
return {
|
|
100790
|
+
value: cred.id,
|
|
100791
|
+
label: `${handle || cred.id} (OAuth)`
|
|
100792
|
+
};
|
|
100793
|
+
}
|
|
100794
|
+
return {
|
|
100795
|
+
value: cred.id,
|
|
100796
|
+
label: `${cred.id} (App Password)`
|
|
100797
|
+
};
|
|
100798
|
+
}));
|
|
100736
100799
|
R2.info("Multiple identities found. Select one to use:");
|
|
100737
100800
|
const selected = exitOnCancel(await qt({
|
|
100738
100801
|
message: "Identity:",
|
|
100739
|
-
options
|
|
100802
|
+
options
|
|
100740
100803
|
}));
|
|
100741
|
-
|
|
100804
|
+
const selectedCred = identities.find((c) => c.id === selected);
|
|
100805
|
+
if (selectedCred?.type === "oauth") {
|
|
100806
|
+
const session = await getOAuthSession(selected);
|
|
100807
|
+
if (session) {
|
|
100808
|
+
const handle = await getOAuthHandle(selected);
|
|
100809
|
+
credentials = {
|
|
100810
|
+
type: "oauth",
|
|
100811
|
+
did: selected,
|
|
100812
|
+
handle: handle || selected,
|
|
100813
|
+
pdsUrl: "https://bsky.social"
|
|
100814
|
+
};
|
|
100815
|
+
}
|
|
100816
|
+
} else {
|
|
100817
|
+
credentials = await getCredentials(selected);
|
|
100818
|
+
}
|
|
100742
100819
|
if (!credentials) {
|
|
100743
100820
|
R2.error("Failed to load selected credentials.");
|
|
100744
100821
|
process.exit(1);
|
|
100745
100822
|
}
|
|
100746
|
-
|
|
100823
|
+
const displayId = credentials.type === "oauth" ? credentials.handle || credentials.did : credentials.identifier;
|
|
100824
|
+
R2.info(`Tip: Add "identity": "${displayId}" to sequoia.json to use this by default.`);
|
|
100747
100825
|
}
|
|
100748
100826
|
const contentDir = path10.isAbsolute(config.contentDir) ? config.contentDir : path10.join(configDir, config.contentDir);
|
|
100749
100827
|
const imagesDir = config.imagesDir ? path10.isAbsolute(config.imagesDir) ? config.imagesDir : path10.join(configDir, config.imagesDir) : undefined;
|
|
@@ -100969,17 +101047,44 @@ var syncCommand = import_cmd_ts6.command({
|
|
|
100969
101047
|
R2.info(`Publication: ${config.publicationUri}`);
|
|
100970
101048
|
let credentials = await loadCredentials(config.identity);
|
|
100971
101049
|
if (!credentials) {
|
|
100972
|
-
const identities = await
|
|
101050
|
+
const identities = await listAllCredentials();
|
|
100973
101051
|
if (identities.length === 0) {
|
|
100974
|
-
R2.error("No credentials found. Run 'sequoia auth' first.");
|
|
101052
|
+
R2.error("No credentials found. Run 'sequoia login' or 'sequoia auth' first.");
|
|
100975
101053
|
process.exit(1);
|
|
100976
101054
|
}
|
|
101055
|
+
const options = await Promise.all(identities.map(async (cred) => {
|
|
101056
|
+
if (cred.type === "oauth") {
|
|
101057
|
+
const handle = await getOAuthHandle(cred.id);
|
|
101058
|
+
return {
|
|
101059
|
+
value: cred.id,
|
|
101060
|
+
label: `${handle || cred.id} (OAuth)`
|
|
101061
|
+
};
|
|
101062
|
+
}
|
|
101063
|
+
return {
|
|
101064
|
+
value: cred.id,
|
|
101065
|
+
label: `${cred.id} (App Password)`
|
|
101066
|
+
};
|
|
101067
|
+
}));
|
|
100977
101068
|
R2.info("Multiple identities found. Select one to use:");
|
|
100978
101069
|
const selected = exitOnCancel(await qt({
|
|
100979
101070
|
message: "Identity:",
|
|
100980
|
-
options
|
|
101071
|
+
options
|
|
100981
101072
|
}));
|
|
100982
|
-
|
|
101073
|
+
const selectedCred = identities.find((c) => c.id === selected);
|
|
101074
|
+
if (selectedCred?.type === "oauth") {
|
|
101075
|
+
const session = await getOAuthSession(selected);
|
|
101076
|
+
if (session) {
|
|
101077
|
+
const handle = await getOAuthHandle(selected);
|
|
101078
|
+
credentials = {
|
|
101079
|
+
type: "oauth",
|
|
101080
|
+
did: selected,
|
|
101081
|
+
handle: handle || selected,
|
|
101082
|
+
pdsUrl: "https://bsky.social"
|
|
101083
|
+
};
|
|
101084
|
+
}
|
|
101085
|
+
} else {
|
|
101086
|
+
credentials = await getCredentials(selected);
|
|
101087
|
+
}
|
|
100983
101088
|
if (!credentials) {
|
|
100984
101089
|
R2.error("Failed to load selected credentials.");
|
|
100985
101090
|
process.exit(1);
|
|
@@ -101501,7 +101606,7 @@ Publish evergreen content to the ATmosphere
|
|
|
101501
101606
|
|
|
101502
101607
|
> https://tangled.org/stevedylan.dev/sequoia
|
|
101503
101608
|
`,
|
|
101504
|
-
version: "0.3.
|
|
101609
|
+
version: "0.3.1",
|
|
101505
101610
|
cmds: {
|
|
101506
101611
|
auth: authCommand,
|
|
101507
101612
|
init: initCommand,
|