@usesocial/cli 0.3.2 → 0.3.3
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/CHANGELOG.md +6 -0
- package/README.md +5 -5
- package/dist/index.mjs +64 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @usesocial/cli
|
|
2
2
|
|
|
3
|
+
## 0.3.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#14](https://github.com/usesocial/monorepo/pull/14) [`22ba757`](https://github.com/usesocial/monorepo/commit/22ba757efd459a0cb3009c91ba833687e2ce2796) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Ask for phone number during `social account login`, save it after device approval, and include it in account identity output.
|
|
8
|
+
|
|
3
9
|
## 0.3.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -212,12 +212,12 @@ jq -r '.items[].id' /tmp/recent-posts.json \
|
|
|
212
212
|
default; clear Write in the prompt to grant read-only access.
|
|
213
213
|
2. Asks for your email address.
|
|
214
214
|
3. Sends a magic link to that email with the device approval screen already
|
|
215
|
-
attached.
|
|
215
|
+
attached while asking for your phone number.
|
|
216
216
|
4. Waits until you click the magic link and approve the CLI session in the
|
|
217
|
-
browser.
|
|
218
|
-
5.
|
|
219
|
-
|
|
220
|
-
`~/.social/credentials.json` (mode `0600`)
|
|
217
|
+
browser, then stores the returned token in your OS keyring.
|
|
218
|
+
5. Stores the phone number, then confirms billing checkout in the terminal when
|
|
219
|
+
a seat is needed. If no keyring is available, credentials fall back to
|
|
220
|
+
`~/.social/credentials.json` (mode `0600`).
|
|
221
221
|
Non-production `SOCIAL_API_URL` values use an API-specific credential
|
|
222
222
|
namespace so staging tests do not overwrite the production session.
|
|
223
223
|
|
package/dist/index.mjs
CHANGED
|
@@ -9583,6 +9583,7 @@ const user = pgTable("user", {
|
|
|
9583
9583
|
emailVerified: boolean("emailVerified").notNull().default(false),
|
|
9584
9584
|
name: text$1("name").notNull(),
|
|
9585
9585
|
image: text$1("image"),
|
|
9586
|
+
phoneNumber: text$1("phone_number"),
|
|
9586
9587
|
createdAt: timestamp("createdAt", { mode: "date" }).notNull().defaultNow(),
|
|
9587
9588
|
updatedAt: timestamp("updatedAt", { mode: "date" }).notNull().defaultNow().$onUpdate(() => /* @__PURE__ */ new Date())
|
|
9588
9589
|
});
|
|
@@ -21058,7 +21059,7 @@ const createInstance = (defaults) => {
|
|
|
21058
21059
|
const ky = createInstance();
|
|
21059
21060
|
//#endregion
|
|
21060
21061
|
//#region package.json
|
|
21061
|
-
var version$1 = "0.3.
|
|
21062
|
+
var version$1 = "0.3.3";
|
|
21062
21063
|
//#endregion
|
|
21063
21064
|
//#region src/lib/env.ts
|
|
21064
21065
|
const URLWithTrailingSlash = url().transform(ensureTrailingSlash);
|
|
@@ -27411,6 +27412,23 @@ const accessPhase = async (ctx) => {
|
|
|
27411
27412
|
};
|
|
27412
27413
|
};
|
|
27413
27414
|
//#endregion
|
|
27415
|
+
//#region ../../packages/lib/src/cli-schema-contract.ts
|
|
27416
|
+
const isZodSchema = (value) => Boolean(value && typeof value === "object" && "safeParse" in value && typeof value.safeParse === "function");
|
|
27417
|
+
const isZodUnknownSchema = (value) => value instanceof ZodUnknown;
|
|
27418
|
+
const zodToJSONSchema = (schema, options) => toJSONSchema(schema, { io: options?.io ?? "output" });
|
|
27419
|
+
const unknownOutputContract = (message = "Output schema is not declared.") => ({
|
|
27420
|
+
outputSchema: { unknown: true },
|
|
27421
|
+
hazards: [{
|
|
27422
|
+
code: "output_schema_unknown",
|
|
27423
|
+
message
|
|
27424
|
+
}]
|
|
27425
|
+
});
|
|
27426
|
+
new TextEncoder();
|
|
27427
|
+
//#endregion
|
|
27428
|
+
//#region ../../packages/lib/src/phone.ts
|
|
27429
|
+
const phoneFormattingRegex = /[\s().-]/g;
|
|
27430
|
+
const PhoneNumber = string().trim().transform((value) => value.replace(phoneFormattingRegex, "")).pipe(string().regex(/^\+[1-9]\d{1,14}$/, { message: "Enter a phone number with +country code." }));
|
|
27431
|
+
//#endregion
|
|
27414
27432
|
//#region src/login/phases/0.sign-in.ts
|
|
27415
27433
|
const CLIENT_ID = "social-cli";
|
|
27416
27434
|
const DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
@@ -27495,7 +27513,30 @@ const sendMagicLinkSignIn = async (email, callbackURL, deps = {}) => {
|
|
|
27495
27513
|
throw new Error(authErrorMessage("Could not send sign-in email", response, error));
|
|
27496
27514
|
}
|
|
27497
27515
|
};
|
|
27498
|
-
const
|
|
27516
|
+
const startMagicLinkSignIn = (email, callbackURL) => sendMagicLinkSignIn(email, callbackURL).then(() => ({ status: "fulfilled" }), (error) => ({
|
|
27517
|
+
status: "rejected",
|
|
27518
|
+
error
|
|
27519
|
+
}));
|
|
27520
|
+
const waitForMagicLinkEmail = async (ctx, emailPromise) => {
|
|
27521
|
+
const result = await emailPromise;
|
|
27522
|
+
if (result.status === "rejected") {
|
|
27523
|
+
ctx.ui.error("Could not send sign-in email");
|
|
27524
|
+
throw result.error;
|
|
27525
|
+
}
|
|
27526
|
+
};
|
|
27527
|
+
const isMissingPhoneEndpointError = (error) => isRecord$2(error) && "status" in error && error.status === 404 && "message" in error && typeof error.message === "string" && error.message.toLowerCase().includes("not found");
|
|
27528
|
+
const updatePhoneNumber = async (ctx, phoneNumber) => {
|
|
27529
|
+
try {
|
|
27530
|
+
await ctx.client.cli.user.updatePhone({ phoneNumber });
|
|
27531
|
+
} catch (error) {
|
|
27532
|
+
if (isMissingPhoneEndpointError(error)) {
|
|
27533
|
+
ctx.ui.warn("Phone number could not be saved yet; login is complete.");
|
|
27534
|
+
return;
|
|
27535
|
+
}
|
|
27536
|
+
throw error;
|
|
27537
|
+
}
|
|
27538
|
+
};
|
|
27539
|
+
const waitForDeviceToken = async (ctx, deviceCode, phoneNumber) => {
|
|
27499
27540
|
const spinner = ctx.ui.spinner();
|
|
27500
27541
|
const message = "Waiting for magic link approval";
|
|
27501
27542
|
spinner.start(message);
|
|
@@ -27509,6 +27550,7 @@ const waitForDeviceToken = async (ctx, deviceCode) => {
|
|
|
27509
27550
|
expiresAt: tokenExpiresAt,
|
|
27510
27551
|
scope: token.scope
|
|
27511
27552
|
});
|
|
27553
|
+
await updatePhoneNumber(ctx, phoneNumber);
|
|
27512
27554
|
clearTick();
|
|
27513
27555
|
spinner.stop(LOGIN_SUCCESS_MESSAGE);
|
|
27514
27556
|
ctx.ui.info(NEXT_COMMANDS_MESSAGE);
|
|
@@ -27530,14 +27572,17 @@ const signInPhase = async (ctx) => {
|
|
|
27530
27572
|
const expiresAt = new Date(Date.now() + deviceCode.expires_in * 1e3).toISOString();
|
|
27531
27573
|
const callbackURL = deviceCallbackURLFor(deviceCode, email);
|
|
27532
27574
|
const userCode = formatUserCode(deviceCode.user_code);
|
|
27533
|
-
|
|
27575
|
+
const emailPromise = startMagicLinkSignIn(email, callbackURL);
|
|
27576
|
+
const phoneNumber = await resolvePhoneNumber(ctx);
|
|
27577
|
+
await waitForMagicLinkEmail(ctx, emailPromise);
|
|
27534
27578
|
ctx.ui.note(`Code: ${userCode}\nEmail: ${email}\n\nClick the magic link in your inbox to approve this CLI session.\n\n${onboardingLegalNotice()}`, "Check your email");
|
|
27535
27579
|
return {
|
|
27536
27580
|
status: "done",
|
|
27537
27581
|
data: {
|
|
27538
27582
|
email,
|
|
27539
27583
|
expiresAt,
|
|
27540
|
-
|
|
27584
|
+
phoneNumber,
|
|
27585
|
+
scope: (await waitForDeviceToken(ctx, deviceCode, phoneNumber)).scope
|
|
27541
27586
|
}
|
|
27542
27587
|
};
|
|
27543
27588
|
};
|
|
@@ -27547,6 +27592,17 @@ const resolveEmail = async (ctx) => await ctx.ui.text({
|
|
|
27547
27592
|
placeholder: "you@example.com",
|
|
27548
27593
|
validate: (value) => value?.includes("@") ? void 0 : "Enter an email address."
|
|
27549
27594
|
});
|
|
27595
|
+
const resolvePhoneNumber = async (ctx) => {
|
|
27596
|
+
const phoneNumber = await ctx.ui.text({
|
|
27597
|
+
message: "Phone number",
|
|
27598
|
+
placeholder: "+1 555 123 4567",
|
|
27599
|
+
validate: (value) => {
|
|
27600
|
+
const result = PhoneNumber.safeParse(value);
|
|
27601
|
+
return result.success ? void 0 : result.error.issues[0]?.message;
|
|
27602
|
+
}
|
|
27603
|
+
});
|
|
27604
|
+
return PhoneNumber.parse(phoneNumber);
|
|
27605
|
+
};
|
|
27550
27606
|
//#endregion
|
|
27551
27607
|
//#region src/login/phases/1.scope.ts
|
|
27552
27608
|
const DEFAULT_SCOPE_ALIAS = "read,write";
|
|
@@ -27691,7 +27747,8 @@ const ScopeAlias = _enum(["read", "read,write"]);
|
|
|
27691
27747
|
const LoginUserOutput = object({
|
|
27692
27748
|
id: string(),
|
|
27693
27749
|
email: string().nullable(),
|
|
27694
|
-
name: string().nullable()
|
|
27750
|
+
name: string().nullable(),
|
|
27751
|
+
phoneNumber: string().nullable()
|
|
27695
27752
|
});
|
|
27696
27753
|
const LoginSeatsOutput = object({
|
|
27697
27754
|
total: number().int().nonnegative(),
|
|
@@ -28111,7 +28168,8 @@ const AccountSessionOutput = object({
|
|
|
28111
28168
|
user: object({
|
|
28112
28169
|
id: string(),
|
|
28113
28170
|
email: string().nullable(),
|
|
28114
|
-
name: string().nullable()
|
|
28171
|
+
name: string().nullable(),
|
|
28172
|
+
phoneNumber: string().nullable()
|
|
28115
28173
|
}),
|
|
28116
28174
|
scope: _enum(["read", "read,write"]),
|
|
28117
28175
|
capabilities: array(string())
|
|
@@ -28591,18 +28649,6 @@ const createCLIDeps = () => {
|
|
|
28591
28649
|
};
|
|
28592
28650
|
};
|
|
28593
28651
|
//#endregion
|
|
28594
|
-
//#region ../../packages/lib/src/cli-schema-contract.ts
|
|
28595
|
-
const isZodSchema = (value) => Boolean(value && typeof value === "object" && "safeParse" in value && typeof value.safeParse === "function");
|
|
28596
|
-
const isZodUnknownSchema = (value) => value instanceof ZodUnknown;
|
|
28597
|
-
const zodToJSONSchema = (schema, options) => toJSONSchema(schema, { io: options?.io ?? "output" });
|
|
28598
|
-
const unknownOutputContract = (message = "Output schema is not declared.") => ({
|
|
28599
|
-
outputSchema: { unknown: true },
|
|
28600
|
-
hazards: [{
|
|
28601
|
-
code: "output_schema_unknown",
|
|
28602
|
-
message
|
|
28603
|
-
}]
|
|
28604
|
-
});
|
|
28605
|
-
//#endregion
|
|
28606
28652
|
//#region src/schema/index.ts
|
|
28607
28653
|
const HTTPMethod = _enum([
|
|
28608
28654
|
"DELETE",
|