create-kanojo 0.0.0 → 0.1.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/README.md +3 -9
- package/dist/index.mjs +186 -49
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
# create-kanojo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Create your girlfriend with `create-kanojo`. If you want to create your boyfriend, please use `create-kareshi` instead.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- `role: male`
|
|
7
|
-
- `target: female`
|
|
5
|
+
## Usage
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
bun packages/create-kanojo/src/index.ts
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
公開用 bundle は `bun run --filter create-kanojo build` で `dist/index.mjs` に出力されます。
|
|
7
|
+
See https://github.com/nakasyou/matching-app
|
package/dist/index.mjs
CHANGED
|
@@ -9630,7 +9630,13 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9630
9630
|
Wt(theme.banner(` ${preset.brand} `));
|
|
9631
9631
|
try {
|
|
9632
9632
|
const parsed = extractProfileOverride(rawArgs);
|
|
9633
|
-
|
|
9633
|
+
const command = parseCommandFlags(parsed.args);
|
|
9634
|
+
const [rootCommand] = command.positionals;
|
|
9635
|
+
if (command.flags.help || rootCommand === "help") {
|
|
9636
|
+
Vt(renderCliUsage(preset), "Usage");
|
|
9637
|
+
return;
|
|
9638
|
+
}
|
|
9639
|
+
await dispatchCommand(command, parsed.profileName);
|
|
9634
9640
|
Gt(theme.accent("Connected quietly. Ready for the next good match."));
|
|
9635
9641
|
} catch (error) {
|
|
9636
9642
|
if (error instanceof CancelledFlowError) {
|
|
@@ -9642,18 +9648,18 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9642
9648
|
service.close();
|
|
9643
9649
|
}
|
|
9644
9650
|
} };
|
|
9645
|
-
async function dispatchCommand(
|
|
9646
|
-
const [command, subcommand, ...rest] =
|
|
9651
|
+
async function dispatchCommand(parsedArgs, profileOverride) {
|
|
9652
|
+
const [command, subcommand, ...rest] = parsedArgs.positionals;
|
|
9647
9653
|
if (!command) {
|
|
9648
9654
|
await runHome(profileOverride);
|
|
9649
9655
|
return;
|
|
9650
9656
|
}
|
|
9651
9657
|
if (command === "profile") {
|
|
9652
|
-
await runProfileCommand(subcommand, rest, profileOverride);
|
|
9658
|
+
await runProfileCommand(subcommand, rest, parsedArgs.flags, profileOverride);
|
|
9653
9659
|
return;
|
|
9654
9660
|
}
|
|
9655
9661
|
if (command === "listing") {
|
|
9656
|
-
await runListingCommand(subcommand, rest, profileOverride);
|
|
9662
|
+
await runListingCommand(subcommand, rest, parsedArgs.flags, profileOverride);
|
|
9657
9663
|
return;
|
|
9658
9664
|
}
|
|
9659
9665
|
if (command === "discover") {
|
|
@@ -9669,11 +9675,11 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9669
9675
|
return;
|
|
9670
9676
|
}
|
|
9671
9677
|
if (command === "chat") {
|
|
9672
|
-
await runChat(profileOverride, subcommand);
|
|
9678
|
+
await runChat(profileOverride, subcommand, parsedArgs.flags);
|
|
9673
9679
|
return;
|
|
9674
9680
|
}
|
|
9675
9681
|
if (command === "config") {
|
|
9676
|
-
await runConfigCommand(subcommand, profileOverride);
|
|
9682
|
+
await runConfigCommand(subcommand, parsedArgs.flags, profileOverride);
|
|
9677
9683
|
return;
|
|
9678
9684
|
}
|
|
9679
9685
|
throw new Error(`Unknown command: ${command}`);
|
|
@@ -9761,9 +9767,20 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9761
9767
|
return;
|
|
9762
9768
|
}
|
|
9763
9769
|
}
|
|
9764
|
-
async function runProfileCommand(subcommand, args, profileOverride) {
|
|
9770
|
+
async function runProfileCommand(subcommand, args, flags, profileOverride) {
|
|
9765
9771
|
if (subcommand === "create") {
|
|
9766
|
-
await promptProfileCreate(
|
|
9772
|
+
await promptProfileCreate({
|
|
9773
|
+
profileName: getStringFlag(flags, "name", "profile-name"),
|
|
9774
|
+
displayName: getStringFlag(flags, "display-name"),
|
|
9775
|
+
ageRange: getStringFlag(flags, "age-range"),
|
|
9776
|
+
region: getStringFlag(flags, "region"),
|
|
9777
|
+
bio: getStringFlag(flags, "bio"),
|
|
9778
|
+
interests: getStringFlag(flags, "interests"),
|
|
9779
|
+
lookingForAge: getStringFlag(flags, "looking-age", "looking-age-range"),
|
|
9780
|
+
lookingForRegions: getStringFlag(flags, "looking-regions"),
|
|
9781
|
+
lookingForNotes: getStringFlag(flags, "looking-notes"),
|
|
9782
|
+
relays: getStringFlag(flags, "relays")
|
|
9783
|
+
});
|
|
9767
9784
|
return;
|
|
9768
9785
|
}
|
|
9769
9786
|
if (subcommand === "use") {
|
|
@@ -9786,10 +9803,15 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9786
9803
|
}
|
|
9787
9804
|
throw new Error("Use `profile create|use|list|show`.");
|
|
9788
9805
|
}
|
|
9789
|
-
async function runListingCommand(subcommand, _args, profileOverride) {
|
|
9806
|
+
async function runListingCommand(subcommand, _args, flags, profileOverride) {
|
|
9790
9807
|
const profile = await ensureProfile(profileOverride);
|
|
9791
9808
|
if (subcommand === "publish") {
|
|
9792
|
-
await handlePublishListing(profile
|
|
9809
|
+
await handlePublishListing(profile, {
|
|
9810
|
+
headline: getStringFlag(flags, "title", "headline"),
|
|
9811
|
+
summary: getStringFlag(flags, "summary"),
|
|
9812
|
+
region: getStringFlag(flags, "region"),
|
|
9813
|
+
desiredTags: getStringFlag(flags, "tags", "desired-tags")
|
|
9814
|
+
});
|
|
9793
9815
|
return;
|
|
9794
9816
|
}
|
|
9795
9817
|
if (subcommand === "list") {
|
|
@@ -9805,7 +9827,11 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9805
9827
|
R.info("There are no open listings to close.");
|
|
9806
9828
|
return;
|
|
9807
9829
|
}
|
|
9808
|
-
const
|
|
9830
|
+
const listingIdArg = getStringFlag(flags, "id", "listing-id");
|
|
9831
|
+
const listingAddressArg = getStringFlag(flags, "address", "listing-address");
|
|
9832
|
+
const selectedListing = openListings.find((listing) => listing.id === listingIdArg || listing.address === listingAddressArg) ?? null;
|
|
9833
|
+
if ((listingIdArg || listingAddressArg) && !selectedListing) throw new Error("Listing not found. Use `listing list` to check the id or address.");
|
|
9834
|
+
const listingId = selectedListing?.id ?? await askSelect({
|
|
9809
9835
|
message: "Choose a listing to close.",
|
|
9810
9836
|
options: openListings.map((listing) => ({
|
|
9811
9837
|
value: listing.id,
|
|
@@ -9829,17 +9855,17 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9829
9855
|
async function runMatches(profileOverride) {
|
|
9830
9856
|
await handleMatches(await ensureProfile(profileOverride));
|
|
9831
9857
|
}
|
|
9832
|
-
async function runChat(profileOverride, matchIdArg) {
|
|
9833
|
-
await handleChat(await ensureProfile(profileOverride), matchIdArg);
|
|
9858
|
+
async function runChat(profileOverride, matchIdArg, flags = {}) {
|
|
9859
|
+
await handleChat(await ensureProfile(profileOverride), matchIdArg, void 0, getStringFlag(flags, "message"));
|
|
9834
9860
|
}
|
|
9835
|
-
async function runConfigCommand(subcommand, profileOverride) {
|
|
9861
|
+
async function runConfigCommand(subcommand, flags, profileOverride) {
|
|
9836
9862
|
const profile = await ensureProfile(profileOverride);
|
|
9837
9863
|
if (subcommand === "show") {
|
|
9838
9864
|
Vt(renderProfileCard(profile, true), "Advanced Config");
|
|
9839
9865
|
return;
|
|
9840
9866
|
}
|
|
9841
9867
|
if (subcommand === "relays") {
|
|
9842
|
-
const nextProfile = await promptRelayConfig(profile);
|
|
9868
|
+
const nextProfile = await promptRelayConfig(profile, getStringFlag(flags, "relays"));
|
|
9843
9869
|
await store.saveProfile(nextProfile);
|
|
9844
9870
|
R.success("Relay list updated.");
|
|
9845
9871
|
return;
|
|
@@ -9863,8 +9889,8 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9863
9889
|
if (profiles.length > 1) return promptProfileUse();
|
|
9864
9890
|
return promptProfileCreate();
|
|
9865
9891
|
}
|
|
9866
|
-
async function promptProfileCreate() {
|
|
9867
|
-
const profileName = await
|
|
9892
|
+
async function promptProfileCreate(initial = {}) {
|
|
9893
|
+
const profileName = await resolveRequiredInput(initial.profileName, {
|
|
9868
9894
|
message: "Choose a profile name.",
|
|
9869
9895
|
placeholder: "main",
|
|
9870
9896
|
defaultValue: "main",
|
|
@@ -9874,50 +9900,51 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9874
9900
|
if (!/^[a-z0-9-]+$/.test(normalized)) return "Use lowercase letters, digits, and hyphens only.";
|
|
9875
9901
|
}
|
|
9876
9902
|
});
|
|
9877
|
-
const displayName = await
|
|
9903
|
+
const displayName = await resolveRequiredInput(initial.displayName, {
|
|
9878
9904
|
message: "What display name should we show?",
|
|
9879
9905
|
placeholder: preset.brand === "create-kanojo" ? "たくみ" : "あや",
|
|
9880
9906
|
validate(value) {
|
|
9881
9907
|
if (!(value?.trim() ?? "")) return "Display name is required.";
|
|
9882
9908
|
}
|
|
9883
9909
|
});
|
|
9884
|
-
const ageRange = await
|
|
9910
|
+
const ageRange = await resolveRequiredInput(initial.ageRange, {
|
|
9885
9911
|
message: "How would you describe your age range?",
|
|
9886
9912
|
placeholder: "20代後半",
|
|
9887
9913
|
validate(value) {
|
|
9888
9914
|
if (!(value?.trim() ?? "")) return "Age range is required.";
|
|
9889
9915
|
}
|
|
9890
9916
|
});
|
|
9891
|
-
const region = await
|
|
9917
|
+
const region = await resolveRequiredInput(initial.region, {
|
|
9892
9918
|
message: "Which area do you usually meet in?",
|
|
9893
9919
|
placeholder: "東京",
|
|
9894
9920
|
validate(value) {
|
|
9895
9921
|
if (!(value?.trim() ?? "")) return "Region is required.";
|
|
9896
9922
|
}
|
|
9897
9923
|
});
|
|
9898
|
-
const bio = await
|
|
9924
|
+
const bio = await resolveRequiredInput(initial.bio, {
|
|
9899
9925
|
message: "Write a short intro.",
|
|
9900
9926
|
placeholder: "映画とコーヒーが好きです。",
|
|
9901
9927
|
validate(value) {
|
|
9902
9928
|
if (!(value?.trim() ?? "")) return "Bio is required.";
|
|
9903
9929
|
}
|
|
9904
9930
|
});
|
|
9905
|
-
const interests = await
|
|
9931
|
+
const interests = await resolveOptionalInput(initial.interests, {
|
|
9906
9932
|
message: "List interests or vibe tags, comma separated.",
|
|
9907
9933
|
placeholder: "映画, カフェ, 散歩"
|
|
9908
9934
|
});
|
|
9909
|
-
const lookingForAge = await
|
|
9935
|
+
const lookingForAge = await resolveOptionalInput(initial.lookingForAge, {
|
|
9910
9936
|
message: "What age range are you looking for?",
|
|
9911
9937
|
placeholder: "20代"
|
|
9912
9938
|
});
|
|
9913
|
-
const lookingForRegions = await
|
|
9939
|
+
const lookingForRegions = await resolveOptionalInput(initial.lookingForRegions, {
|
|
9914
9940
|
message: "Which regions do you want to meet in? Use commas.",
|
|
9915
9941
|
placeholder: region
|
|
9916
9942
|
});
|
|
9917
|
-
const lookingForNotes = await
|
|
9943
|
+
const lookingForNotes = await resolveOptionalInput(initial.lookingForNotes, {
|
|
9918
9944
|
message: "What kind of person feels right for you?",
|
|
9919
9945
|
placeholder: "落ち着いて話せる人"
|
|
9920
9946
|
});
|
|
9947
|
+
const relays = initial.relays ? normalizeRelayList(initial.relays) : DEFAULT_RELAYS;
|
|
9921
9948
|
const credentials = createGeneratedCredentials();
|
|
9922
9949
|
const profile = createDefaultProfile(preset, {
|
|
9923
9950
|
profileName,
|
|
@@ -9932,7 +9959,7 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9932
9959
|
notes: lookingForNotes
|
|
9933
9960
|
},
|
|
9934
9961
|
nostr: credentials,
|
|
9935
|
-
relays
|
|
9962
|
+
relays
|
|
9936
9963
|
});
|
|
9937
9964
|
const published = await withSpinner("Preparing profile...", async () => {
|
|
9938
9965
|
await service.publishProfile(profile);
|
|
@@ -9964,26 +9991,26 @@ function createMatchingCli(preset, options = {}) {
|
|
|
9964
9991
|
Vt(renderProfileCard(profile), "Active Profile");
|
|
9965
9992
|
return profile;
|
|
9966
9993
|
}
|
|
9967
|
-
async function handlePublishListing(profile) {
|
|
9968
|
-
const headline = await
|
|
9994
|
+
async function handlePublishListing(profile, initial = {}) {
|
|
9995
|
+
const headline = await resolveRequiredInput(initial.headline, {
|
|
9969
9996
|
message: "Enter the listing title.",
|
|
9970
9997
|
placeholder: "週末に一緒に映画を見に行ける人",
|
|
9971
9998
|
validate(value) {
|
|
9972
9999
|
if (!(value?.trim() ?? "")) return "Title is required.";
|
|
9973
10000
|
}
|
|
9974
10001
|
});
|
|
9975
|
-
const summary = await
|
|
10002
|
+
const summary = await resolveRequiredInput(initial.summary, {
|
|
9976
10003
|
message: "Write a short summary.",
|
|
9977
10004
|
placeholder: "まずはお茶からゆっくり話したいです。",
|
|
9978
10005
|
validate(value) {
|
|
9979
10006
|
if (!(value?.trim() ?? "")) return "Summary is required.";
|
|
9980
10007
|
}
|
|
9981
10008
|
});
|
|
9982
|
-
const region = await
|
|
10009
|
+
const region = await resolveOptionalInput(initial.region, {
|
|
9983
10010
|
message: "Which region is this listing for?",
|
|
9984
10011
|
defaultValue: profile.region
|
|
9985
10012
|
});
|
|
9986
|
-
const desiredTags = await
|
|
10013
|
+
const desiredTags = await resolveOptionalInput(initial.desiredTags, {
|
|
9987
10014
|
message: "Enter tags, comma separated.",
|
|
9988
10015
|
placeholder: "映画, 落ち着き, 夜カフェ"
|
|
9989
10016
|
});
|
|
@@ -10092,7 +10119,7 @@ function createMatchingCli(preset, options = {}) {
|
|
|
10092
10119
|
})) return handleChat(nextProfile, void 0, buildConversations(nextProfile).filter((conversation) => conversation.source === "matched"));
|
|
10093
10120
|
return nextProfile;
|
|
10094
10121
|
}
|
|
10095
|
-
async function handleChat(profile, threadIdArg, availableConversations) {
|
|
10122
|
+
async function handleChat(profile, threadIdArg, availableConversations, initialMessage) {
|
|
10096
10123
|
let nextProfile = profile;
|
|
10097
10124
|
if (!availableConversations) {
|
|
10098
10125
|
nextProfile = await withSpinner("Syncing conversation...", () => service.syncInbox(profile));
|
|
@@ -10105,6 +10132,11 @@ function createMatchingCli(preset, options = {}) {
|
|
|
10105
10132
|
}
|
|
10106
10133
|
const conversation = (threadIdArg ? conversations.find((item) => item.threadId === threadIdArg) : null) ?? await promptConversation(conversations);
|
|
10107
10134
|
if (!conversation) throw new Error("Conversation not found.");
|
|
10135
|
+
if (initialMessage !== void 0) {
|
|
10136
|
+
const body = initialMessage.trim();
|
|
10137
|
+
if (!body) throw new Error("Message is required.");
|
|
10138
|
+
return sendChatMessage(nextProfile, conversation, body);
|
|
10139
|
+
}
|
|
10108
10140
|
Vt(renderConversation(conversation), `chat | ${conversation.peerProfileName}`);
|
|
10109
10141
|
while (true) {
|
|
10110
10142
|
const body = await askText({
|
|
@@ -10113,21 +10145,26 @@ function createMatchingCli(preset, options = {}) {
|
|
|
10113
10145
|
defaultValue: ""
|
|
10114
10146
|
});
|
|
10115
10147
|
if (!body.trim()) return nextProfile;
|
|
10116
|
-
nextProfile = await
|
|
10117
|
-
matchId: conversation.threadId,
|
|
10118
|
-
recipientPubkey: conversation.peerPubkey,
|
|
10119
|
-
recipientRelays: conversation.peerRelays,
|
|
10120
|
-
body
|
|
10121
|
-
}));
|
|
10122
|
-
await store.saveProfile(nextProfile);
|
|
10123
|
-
const refreshedConversation = buildConversations(nextProfile).find((item) => item.threadId === conversation.threadId);
|
|
10124
|
-
if (refreshedConversation) Vt(renderConversation(refreshedConversation), `chat | ${refreshedConversation.peerProfileName}`);
|
|
10148
|
+
nextProfile = await sendChatMessage(nextProfile, conversation, body);
|
|
10125
10149
|
if (!await askConfirm({
|
|
10126
10150
|
message: "Send another message?",
|
|
10127
10151
|
initialValue: false
|
|
10128
10152
|
})) return nextProfile;
|
|
10129
10153
|
}
|
|
10130
10154
|
}
|
|
10155
|
+
async function sendChatMessage(profile, conversation, body) {
|
|
10156
|
+
const nextProfile = await withSpinner("Sending message...", () => service.sendChat(profile, {
|
|
10157
|
+
matchId: conversation.threadId,
|
|
10158
|
+
recipientPubkey: conversation.peerPubkey,
|
|
10159
|
+
recipientRelays: conversation.peerRelays,
|
|
10160
|
+
body
|
|
10161
|
+
}));
|
|
10162
|
+
await store.saveProfile(nextProfile);
|
|
10163
|
+
const refreshedConversation = buildConversations(nextProfile).find((item) => item.threadId === conversation.threadId);
|
|
10164
|
+
if (refreshedConversation) Vt(renderConversation(refreshedConversation), `chat | ${refreshedConversation.peerProfileName}`);
|
|
10165
|
+
R.success("Message sent.");
|
|
10166
|
+
return nextProfile;
|
|
10167
|
+
}
|
|
10131
10168
|
async function promptConfig(profile) {
|
|
10132
10169
|
const action = await askSelect({
|
|
10133
10170
|
message: "Advanced config",
|
|
@@ -10155,19 +10192,20 @@ function createMatchingCli(preset, options = {}) {
|
|
|
10155
10192
|
if (action === "relays") return promptRelayConfig(profile);
|
|
10156
10193
|
return profile;
|
|
10157
10194
|
}
|
|
10158
|
-
async function promptRelayConfig(profile) {
|
|
10195
|
+
async function promptRelayConfig(profile, relayInputArg) {
|
|
10159
10196
|
Vt(profile.relays.join("\n"), "Current Relays");
|
|
10160
|
-
const relayInput = await askText({
|
|
10197
|
+
const relayInput = relayInputArg ?? await askText({
|
|
10161
10198
|
message: "Enter new relays, comma separated.",
|
|
10162
10199
|
defaultValue: profile.relays.join(", "),
|
|
10163
10200
|
validate(value) {
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10201
|
+
try {
|
|
10202
|
+
normalizeRelayList(value ?? "");
|
|
10203
|
+
} catch (error) {
|
|
10204
|
+
return error instanceof Error ? error.message : "Invalid relay list.";
|
|
10205
|
+
}
|
|
10168
10206
|
}
|
|
10169
10207
|
});
|
|
10170
|
-
const nextProfile = await withSpinner("Updating relays...", () => service.updateRelays(profile,
|
|
10208
|
+
const nextProfile = await withSpinner("Updating relays...", () => service.updateRelays(profile, normalizeRelayList(relayInput)));
|
|
10171
10209
|
await store.saveProfile(nextProfile);
|
|
10172
10210
|
return nextProfile;
|
|
10173
10211
|
}
|
|
@@ -10180,6 +10218,31 @@ function createTheme(preset) {
|
|
|
10180
10218
|
banner: (label) => accent(import_picocolors.default.inverse(label))
|
|
10181
10219
|
};
|
|
10182
10220
|
}
|
|
10221
|
+
function renderCliUsage(preset) {
|
|
10222
|
+
const sampleDisplayName = preset.brand === "create-kanojo" ? "たくみ" : "あや";
|
|
10223
|
+
return [
|
|
10224
|
+
`${preset.brand} [command] [options]`,
|
|
10225
|
+
"",
|
|
10226
|
+
"Interactive",
|
|
10227
|
+
` ${preset.brand}`,
|
|
10228
|
+
"",
|
|
10229
|
+
"Quick commands",
|
|
10230
|
+
" profile list",
|
|
10231
|
+
" profile use <name>",
|
|
10232
|
+
" profile show",
|
|
10233
|
+
" profile create --name main --display-name \"<name>\" --age-range \"20代後半\" --region 東京 --bio \"映画とコーヒーが好きです。\" --interests \"映画, カフェ\" --looking-age \"20代\" --looking-regions \"東京, 神奈川\" --looking-notes \"落ち着いて話せる人\"",
|
|
10234
|
+
" listing publish --title \"週末に一緒に映画を見に行ける人\" --summary \"まずはお茶からゆっくり話したいです。\" --region 東京 --tags \"映画, 夜カフェ\"",
|
|
10235
|
+
" listing close --id <listing-id>",
|
|
10236
|
+
" chat <thread-id> --message \"こんにちは\"",
|
|
10237
|
+
" config relays --relays \"wss://relay1.example,wss://relay2.example\"",
|
|
10238
|
+
"",
|
|
10239
|
+
"Global options",
|
|
10240
|
+
" --profile <name> Use a specific profile",
|
|
10241
|
+
" --help Show this help",
|
|
10242
|
+
"",
|
|
10243
|
+
`Example: ${preset.brand} profile create --name main --display-name "${sampleDisplayName}" --age-range "20代後半" --region 東京 --bio "映画とコーヒーが好きです。"`
|
|
10244
|
+
].join("\n");
|
|
10245
|
+
}
|
|
10183
10246
|
function extractProfileOverride(args) {
|
|
10184
10247
|
const remaining = [];
|
|
10185
10248
|
let profileName = null;
|
|
@@ -10197,6 +10260,48 @@ function extractProfileOverride(args) {
|
|
|
10197
10260
|
profileName
|
|
10198
10261
|
};
|
|
10199
10262
|
}
|
|
10263
|
+
function parseCommandFlags(args) {
|
|
10264
|
+
const positionals = [];
|
|
10265
|
+
const flags = {};
|
|
10266
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
10267
|
+
const value = args[index] ?? "";
|
|
10268
|
+
if (!value.startsWith("-") || value === "-") {
|
|
10269
|
+
positionals.push(value);
|
|
10270
|
+
continue;
|
|
10271
|
+
}
|
|
10272
|
+
if (value === "--") {
|
|
10273
|
+
positionals.push(...args.slice(index + 1));
|
|
10274
|
+
break;
|
|
10275
|
+
}
|
|
10276
|
+
if (value === "-h") {
|
|
10277
|
+
flags.help = true;
|
|
10278
|
+
continue;
|
|
10279
|
+
}
|
|
10280
|
+
if (!value.startsWith("--")) {
|
|
10281
|
+
positionals.push(value);
|
|
10282
|
+
continue;
|
|
10283
|
+
}
|
|
10284
|
+
const trimmed = value.slice(2);
|
|
10285
|
+
const separatorIndex = trimmed.indexOf("=");
|
|
10286
|
+
if (separatorIndex >= 0) {
|
|
10287
|
+
const name = trimmed.slice(0, separatorIndex).toLowerCase();
|
|
10288
|
+
flags[name] = trimmed.slice(separatorIndex + 1);
|
|
10289
|
+
continue;
|
|
10290
|
+
}
|
|
10291
|
+
const name = trimmed.toLowerCase();
|
|
10292
|
+
const next = args[index + 1];
|
|
10293
|
+
if (next && !next.startsWith("-")) {
|
|
10294
|
+
flags[name] = next;
|
|
10295
|
+
index += 1;
|
|
10296
|
+
continue;
|
|
10297
|
+
}
|
|
10298
|
+
flags[name] = true;
|
|
10299
|
+
}
|
|
10300
|
+
return {
|
|
10301
|
+
positionals,
|
|
10302
|
+
flags
|
|
10303
|
+
};
|
|
10304
|
+
}
|
|
10200
10305
|
async function askText(options) {
|
|
10201
10306
|
const answer = await Zt(options);
|
|
10202
10307
|
if (Ct$1(answer)) throw new CancelledFlowError();
|
|
@@ -10310,6 +10415,38 @@ function renderConversation(conversation) {
|
|
|
10310
10415
|
function splitComma(value) {
|
|
10311
10416
|
return [...new Set(value.split(",").map((item) => item.trim()).filter(Boolean))];
|
|
10312
10417
|
}
|
|
10418
|
+
function getStringFlag(flags, ...names) {
|
|
10419
|
+
for (const name of names) {
|
|
10420
|
+
const value = flags[name];
|
|
10421
|
+
if (typeof value === "string") return value;
|
|
10422
|
+
if (value === true) return "";
|
|
10423
|
+
}
|
|
10424
|
+
}
|
|
10425
|
+
async function resolveRequiredInput(providedValue, options) {
|
|
10426
|
+
if (providedValue !== void 0) {
|
|
10427
|
+
const normalized = providedValue.trim();
|
|
10428
|
+
const validation = options.validate?.(normalized);
|
|
10429
|
+
if (validation) throw new Error(String(validation));
|
|
10430
|
+
return normalized;
|
|
10431
|
+
}
|
|
10432
|
+
return askText(options);
|
|
10433
|
+
}
|
|
10434
|
+
async function resolveOptionalInput(providedValue, options) {
|
|
10435
|
+
if (providedValue !== void 0) {
|
|
10436
|
+
const normalized = providedValue.trim();
|
|
10437
|
+
const validation = options.validate?.(normalized);
|
|
10438
|
+
if (validation) throw new Error(String(validation));
|
|
10439
|
+
return normalized;
|
|
10440
|
+
}
|
|
10441
|
+
return askText(options);
|
|
10442
|
+
}
|
|
10443
|
+
function normalizeRelayList(value) {
|
|
10444
|
+
const items = splitComma(value);
|
|
10445
|
+
if (items.length === 0) throw new Error("At least one relay is required.");
|
|
10446
|
+
if (items.length > 3) throw new Error("Use up to 3 relays.");
|
|
10447
|
+
if (!items.every((item) => item.startsWith("wss://"))) throw new Error("Relay URLs must start with wss://.");
|
|
10448
|
+
return items;
|
|
10449
|
+
}
|
|
10313
10450
|
async function askSwipeAction() {
|
|
10314
10451
|
if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
|
|
10315
10452
|
const normalized = normalizeSwipeAction(await askText({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-kanojo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "A Nostr-based dating CLI for finding a kanojo.",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"vite-plus": "^0.1.11"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"typescript": "^5"
|
|
30
|
+
"typescript": "^5",
|
|
31
|
+
"@repo/shared": "@repo/shared"
|
|
31
32
|
}
|
|
32
33
|
}
|