@primitivedotdev/cli 0.31.2 → 0.31.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/README.md +9 -2
- package/dist/oclif/index.js +258 -73
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -18,8 +18,7 @@ This package wraps the [@primitivedotdev/sdk](https://www.npmjs.com/package/@pri
|
|
|
18
18
|
## Quickstart
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
primitive signin
|
|
23
22
|
primitive whoami
|
|
24
23
|
primitive functions templates
|
|
25
24
|
primitive functions init my-fn
|
|
@@ -32,6 +31,14 @@ primitive emails latest --limit 5
|
|
|
32
31
|
|
|
33
32
|
Run `primitive --help` for the full command list. Per-command help (`primitive functions deploy --help`) carries enough detail that an agent can compose any operation without leaving the terminal.
|
|
34
33
|
|
|
34
|
+
## Authentication
|
|
35
|
+
|
|
36
|
+
Use `primitive signin` for existing accounts. It defaults to browser approval; `primitive signin browser` is the explicit form and `primitive login` remains available for compatibility.
|
|
37
|
+
|
|
38
|
+
Use `primitive signin otp <email> --signup-code <code> --accept-terms`, then `primitive signin otp confirm <email> <code>` for email-code sign-in.
|
|
39
|
+
|
|
40
|
+
Use `primitive signup <email>` for new account creation, then `primitive signup confirm <email> <code>` with the emailed verification code. Non-interactive signup is available with `--signup-code` and `--accept-terms`.
|
|
41
|
+
|
|
35
42
|
## Command style
|
|
36
43
|
|
|
37
44
|
Use task-oriented commands for normal workflows:
|
package/dist/oclif/index.js
CHANGED
|
@@ -11508,7 +11508,7 @@ var PrimitiveApiClient = class {
|
|
|
11508
11508
|
const CREDENTIALS_FILE = "credentials.json";
|
|
11509
11509
|
const CREDENTIALS_LOCK_DIR = "credentials.lock";
|
|
11510
11510
|
const CREDENTIALS_LOCK_STALE_MS = 1800 * 1e3;
|
|
11511
|
-
const MALFORMED_CREDENTIALS_HINT = "Run `primitive logout` and then `primitive
|
|
11511
|
+
const MALFORMED_CREDENTIALS_HINT = "Run `primitive logout` and then `primitive signin`.";
|
|
11512
11512
|
function isRecord$2(value) {
|
|
11513
11513
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11514
11514
|
}
|
|
@@ -11586,10 +11586,10 @@ function loadCliCredentials(configDir) {
|
|
|
11586
11586
|
try {
|
|
11587
11587
|
rmSync(path, { force: true });
|
|
11588
11588
|
} catch {}
|
|
11589
|
-
process.stderr.write("Removed local Primitive CLI API-key login state. API keys are still valid when passed explicitly, but
|
|
11589
|
+
process.stderr.write("Removed local Primitive CLI API-key login state. API keys are still valid when passed explicitly, but saved CLI auth now uses OAuth. Run `primitive signin` to create an OAuth session. No API key was revoked.\n");
|
|
11590
11590
|
return null;
|
|
11591
11591
|
}
|
|
11592
|
-
if (error instanceof SyntaxError) throw new Error("Stored Primitive CLI credentials are not valid JSON. Run `primitive logout` and then `primitive
|
|
11592
|
+
if (error instanceof SyntaxError) throw new Error("Stored Primitive CLI credentials are not valid JSON. Run `primitive logout` and then `primitive signin`.");
|
|
11593
11593
|
throw error;
|
|
11594
11594
|
}
|
|
11595
11595
|
}
|
|
@@ -11872,7 +11872,7 @@ function redactCliEnvironment(environment) {
|
|
|
11872
11872
|
//#region src/oclif/api-client.ts
|
|
11873
11873
|
const API_HEADERS_ENV = "PRIMITIVE_API_HEADERS";
|
|
11874
11874
|
const OAUTH_REFRESH_SKEW_MS = 60 * 1e3;
|
|
11875
|
-
const SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE = "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive
|
|
11875
|
+
const SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE = "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive signin` to authenticate again.";
|
|
11876
11876
|
function mergeHeaders(...headers) {
|
|
11877
11877
|
const merged = {};
|
|
11878
11878
|
for (const headerSet of headers) {
|
|
@@ -11970,7 +11970,7 @@ async function refreshStoredCliCredentials(params) {
|
|
|
11970
11970
|
throw new Errors.CLIError(detail, { exit: 1 });
|
|
11971
11971
|
}
|
|
11972
11972
|
const current = loadCliCredentials(params.configDir);
|
|
11973
|
-
if (!current) throw new Errors.CLIError("Saved Primitive CLI OAuth session is no longer available. Run `primitive
|
|
11973
|
+
if (!current) throw new Errors.CLIError("Saved Primitive CLI OAuth session is no longer available. Run `primitive signin` to authenticate again.", { exit: 1 });
|
|
11974
11974
|
if (!shouldRefresh(current, now)) return current;
|
|
11975
11975
|
const fetchImpl = params.fetch ?? fetch;
|
|
11976
11976
|
const body = new URLSearchParams({
|
|
@@ -12279,26 +12279,26 @@ function coerceParameterValue(parameter, value) {
|
|
|
12279
12279
|
if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return value;
|
|
12280
12280
|
throw new Errors.CLIError(`Unsupported flag value for --${parameter.name}`);
|
|
12281
12281
|
}
|
|
12282
|
-
function cliError$
|
|
12282
|
+
function cliError$7(message) {
|
|
12283
12283
|
return new Errors.CLIError(message, { exit: 1 });
|
|
12284
12284
|
}
|
|
12285
12285
|
function parseJson(source, flagLabel) {
|
|
12286
12286
|
try {
|
|
12287
12287
|
return JSON.parse(source);
|
|
12288
12288
|
} catch (error) {
|
|
12289
|
-
throw cliError$
|
|
12289
|
+
throw cliError$7(`${flagLabel} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
12290
12290
|
}
|
|
12291
12291
|
}
|
|
12292
12292
|
function readJsonBody(flags) {
|
|
12293
12293
|
const bodyFile = flags["body-file"];
|
|
12294
12294
|
const rawBody = flags["raw-body"];
|
|
12295
|
-
if (bodyFile && rawBody) throw cliError$
|
|
12295
|
+
if (bodyFile && rawBody) throw cliError$7("Use either --raw-body or --body-file, not both");
|
|
12296
12296
|
if (typeof bodyFile === "string") {
|
|
12297
12297
|
let contents;
|
|
12298
12298
|
try {
|
|
12299
12299
|
contents = readFileSync(bodyFile, "utf8");
|
|
12300
12300
|
} catch (error) {
|
|
12301
|
-
throw cliError$
|
|
12301
|
+
throw cliError$7(`Could not read --body-file ${bodyFile}: ${error instanceof Error ? error.message : String(error)}`);
|
|
12302
12302
|
}
|
|
12303
12303
|
return parseJson(contents, `--body-file ${bodyFile}`);
|
|
12304
12304
|
}
|
|
@@ -12308,7 +12308,7 @@ function readTextFileFlag(path, flagLabel) {
|
|
|
12308
12308
|
try {
|
|
12309
12309
|
return readFileSync(path, "utf8");
|
|
12310
12310
|
} catch (error) {
|
|
12311
|
-
throw cliError$
|
|
12311
|
+
throw cliError$7(`Could not read ${flagLabel} ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
12312
12312
|
}
|
|
12313
12313
|
}
|
|
12314
12314
|
function extractErrorPayload(raw) {
|
|
@@ -12355,7 +12355,7 @@ function extractErrorCode(payload) {
|
|
|
12355
12355
|
if (typeof direct === "string") return direct;
|
|
12356
12356
|
}
|
|
12357
12357
|
}
|
|
12358
|
-
const ERROR_CODE_HINTS = { [API_ERROR_CODES.unauthorized]: "Hint: run `primitive
|
|
12358
|
+
const ERROR_CODE_HINTS = { [API_ERROR_CODES.unauthorized]: "Hint: run `primitive signin`, pass --api-key explicitly, or set PRIMITIVE_API_KEY in your environment. `primitive whoami` is the fastest way to verify auth is live." };
|
|
12359
12359
|
const NETWORK_ERROR_HINTS = {
|
|
12360
12360
|
ENETUNREACH: "Hint: the network is unreachable. If you're behind a proxy and set HTTP(S)_PROXY, re-run with NODE_USE_ENV_PROXY=1 (Node 22+ ignores those env vars by default). `primitive doctor` reports the local environment in one shot.",
|
|
12361
12361
|
ECONNREFUSED: "Hint: the server refused the connection. Check that your firewall allows egress to *.primitive.dev, that your PRIMITIVE_API_BASE_URL_* overrides (if any) point at a reachable host, and re-run with NODE_USE_ENV_PROXY=1 if you're behind a proxy. `primitive doctor` reports the local environment in one shot.",
|
|
@@ -12393,7 +12393,7 @@ function surfaceUnauthorizedHint(params) {
|
|
|
12393
12393
|
process.stderr.write("Saved Primitive CLI credentials were rejected by the overridden API base URL. The saved credential is preserved; unset PRIMITIVE_API_BASE_URL_1, run `primitive config reset` to clear configured URL overrides, or run `primitive logout` to remove the stored credential.\n");
|
|
12394
12394
|
return;
|
|
12395
12395
|
}
|
|
12396
|
-
process.stderr.write("Your saved Primitive CLI OAuth session was rejected. If the command was working a moment ago, please retry; brief retries often clear transient rejections. If it keeps failing, run `primitive logout && primitive
|
|
12396
|
+
process.stderr.write("Your saved Primitive CLI OAuth session was rejected. If the command was working a moment ago, please retry; brief retries often clear transient rejections. If it keeps failing, run `primitive logout && primitive signin` to mint a fresh session.\n");
|
|
12397
12397
|
}
|
|
12398
12398
|
function formatElapsed(ms) {
|
|
12399
12399
|
const seconds = ms / 1e3;
|
|
@@ -12756,11 +12756,11 @@ function sleep$1(ms) {
|
|
|
12756
12756
|
//#region src/oclif/commands/chat.ts
|
|
12757
12757
|
const DEFAULT_CHAT_TIMEOUT_SECONDS = 120;
|
|
12758
12758
|
const DEFAULT_STRICT_PHASE_SECONDS = 60;
|
|
12759
|
-
function cliError$
|
|
12759
|
+
function cliError$6(message) {
|
|
12760
12760
|
return new Errors.CLIError(message, { exit: 1 });
|
|
12761
12761
|
}
|
|
12762
12762
|
async function readStdinToString() {
|
|
12763
|
-
if (process.stdin.isTTY) throw cliError$
|
|
12763
|
+
if (process.stdin.isTTY) throw cliError$6("No message provided. Pass the message as the second positional argument or pipe it via stdin.");
|
|
12764
12764
|
const chunks = [];
|
|
12765
12765
|
for await (const chunk of process.stdin) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
12766
12766
|
return Buffer.concat(chunks).toString("utf8");
|
|
@@ -12796,7 +12796,7 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
12796
12796
|
};
|
|
12797
12797
|
static flags = {
|
|
12798
12798
|
"api-key": Flags.string({
|
|
12799
|
-
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved `primitive
|
|
12799
|
+
description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved `primitive signin` credentials)",
|
|
12800
12800
|
env: "PRIMITIVE_API_KEY"
|
|
12801
12801
|
}),
|
|
12802
12802
|
"api-base-url-1": Flags.string({
|
|
@@ -12841,7 +12841,7 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
12841
12841
|
async run() {
|
|
12842
12842
|
const { args, flags } = await this.parse(ChatCommand);
|
|
12843
12843
|
const message = args.message !== void 0 && args.message !== "" ? args.message : await readStdinToString();
|
|
12844
|
-
if (!message.trim()) throw cliError$
|
|
12844
|
+
if (!message.trim()) throw cliError$6("Message body is empty.");
|
|
12845
12845
|
await runWithTiming(flags.time, async () => {
|
|
12846
12846
|
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
12847
12847
|
apiKey: flags["api-key"],
|
|
@@ -12879,7 +12879,7 @@ var ChatCommand = class ChatCommand extends Command {
|
|
|
12879
12879
|
return;
|
|
12880
12880
|
}
|
|
12881
12881
|
const sent = sendResult.data?.data;
|
|
12882
|
-
if (!sent) throw cliError$
|
|
12882
|
+
if (!sent) throw cliError$6("Send succeeded but the API returned no data.");
|
|
12883
12883
|
const reply = await waitForReply({
|
|
12884
12884
|
apiClient,
|
|
12885
12885
|
authFailureContext,
|
|
@@ -13203,23 +13203,23 @@ function checkApiKey(opts) {
|
|
|
13203
13203
|
if (typeof parsed?.api_key === "string" && parsed.api_key.length > 0) return {
|
|
13204
13204
|
status: "fail",
|
|
13205
13205
|
message: `${credsPath} contains legacy API-key login state`,
|
|
13206
|
-
hint: "Run `primitive
|
|
13206
|
+
hint: "Run `primitive signin` to create saved OAuth credentials. Existing API keys still work with --api-key or PRIMITIVE_API_KEY."
|
|
13207
13207
|
};
|
|
13208
13208
|
if (parsed) return {
|
|
13209
13209
|
status: "fail",
|
|
13210
13210
|
message: `${credsPath} exists but contains no OAuth access_token`,
|
|
13211
|
-
hint: "Run `primitive logout` to clear it, then `primitive
|
|
13211
|
+
hint: "Run `primitive logout` to clear it, then `primitive signin` to recreate."
|
|
13212
13212
|
};
|
|
13213
13213
|
return {
|
|
13214
13214
|
status: "fail",
|
|
13215
13215
|
message: `${credsPath} exists but is unreadable or malformed${parseError ? ` (${parseError})` : ""}`,
|
|
13216
|
-
hint: "Run `primitive logout` to clear it, then `primitive
|
|
13216
|
+
hint: "Run `primitive logout` to clear it, then `primitive signin` to recreate."
|
|
13217
13217
|
};
|
|
13218
13218
|
}
|
|
13219
13219
|
return {
|
|
13220
13220
|
status: "fail",
|
|
13221
13221
|
message: "no CLI OAuth session or explicit API key found",
|
|
13222
|
-
hint: "Run `primitive
|
|
13222
|
+
hint: "Run `primitive signin`, pass --api-key explicitly, or export PRIMITIVE_API_KEY=prim_..."
|
|
13223
13223
|
};
|
|
13224
13224
|
}
|
|
13225
13225
|
async function checkAccount(client) {
|
|
@@ -13489,7 +13489,7 @@ var EmailsLatestCommand = class EmailsLatestCommand extends Command {
|
|
|
13489
13489
|
//#endregion
|
|
13490
13490
|
//#region src/oclif/commands/emails-wait.ts
|
|
13491
13491
|
const DEFAULT_WAIT_TIMEOUT_SECONDS$1 = 300;
|
|
13492
|
-
function cliError$
|
|
13492
|
+
function cliError$5(message) {
|
|
13493
13493
|
return new Errors.CLIError(message, { exit: 1 });
|
|
13494
13494
|
}
|
|
13495
13495
|
var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
@@ -13564,7 +13564,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
|
13564
13564
|
try {
|
|
13565
13565
|
since = sinceFromFlags(flags);
|
|
13566
13566
|
} catch (error) {
|
|
13567
|
-
throw cliError$
|
|
13567
|
+
throw cliError$5(error instanceof Error ? error.message : String(error));
|
|
13568
13568
|
}
|
|
13569
13569
|
const filters = filtersFromFlags(flags);
|
|
13570
13570
|
const deadline = flags.timeout === 0 ? null : Date.now() + flags.timeout * 1e3;
|
|
@@ -13615,7 +13615,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
|
|
|
13615
13615
|
};
|
|
13616
13616
|
//#endregion
|
|
13617
13617
|
//#region src/oclif/commands/emails-watch.ts
|
|
13618
|
-
function cliError$
|
|
13618
|
+
function cliError$4(message) {
|
|
13619
13619
|
return new Errors.CLIError(message, { exit: 1 });
|
|
13620
13620
|
}
|
|
13621
13621
|
var EmailsWatchCommand = class EmailsWatchCommand extends Command {
|
|
@@ -13686,7 +13686,7 @@ var EmailsWatchCommand = class EmailsWatchCommand extends Command {
|
|
|
13686
13686
|
try {
|
|
13687
13687
|
since = sinceFromFlags(flags);
|
|
13688
13688
|
} catch (error) {
|
|
13689
|
-
throw cliError$
|
|
13689
|
+
throw cliError$4(error instanceof Error ? error.message : String(error));
|
|
13690
13690
|
}
|
|
13691
13691
|
const filters = filtersFromFlags(flags);
|
|
13692
13692
|
const deadline = flags.seconds ? Date.now() + flags.seconds * 1e3 : null;
|
|
@@ -14731,7 +14731,7 @@ The deploy step calls \`primitive functions deploy\` (provided by the
|
|
|
14731
14731
|
\`npm install -g @primitivedotdev/cli\` or run via
|
|
14732
14732
|
\`npx @primitivedotdev/cli@latest <command>\`). It requires
|
|
14733
14733
|
\`PRIMITIVE_API_KEY\` to be set in your shell (or pass \`--api-key\`).
|
|
14734
|
-
Run \`primitive
|
|
14734
|
+
Run \`primitive signin\` once to save a key in your CLI config if you
|
|
14735
14735
|
prefer that to an env var.
|
|
14736
14736
|
`;
|
|
14737
14737
|
}
|
|
@@ -15790,7 +15790,7 @@ var FunctionsTestFunctionCommand = class FunctionsTestFunctionCommand extends Co
|
|
|
15790
15790
|
//#endregion
|
|
15791
15791
|
//#region src/oclif/commands/login.ts
|
|
15792
15792
|
const MAX_CLI_LOGIN_POLL_INTERVAL_SECONDS = 60;
|
|
15793
|
-
function cliError$
|
|
15793
|
+
function cliError$3(message) {
|
|
15794
15794
|
return new Errors.CLIError(message, { exit: 1 });
|
|
15795
15795
|
}
|
|
15796
15796
|
function sleep(ms) {
|
|
@@ -15866,7 +15866,7 @@ async function checkExistingLogin(params) {
|
|
|
15866
15866
|
message: code === API_ERROR_CODES.unauthorized ? "Saved Primitive CLI OAuth credentials were rejected by an API URL different from the one they were saved with. Run `primitive logout` to remove them, or switch back to the original environment before logging in again." : "A saved Primitive CLI OAuth session exists, but the CLI could not verify whether it is still valid. Run `primitive logout` before logging in again."
|
|
15867
15867
|
};
|
|
15868
15868
|
}
|
|
15869
|
-
var LoginCommand = class
|
|
15869
|
+
var LoginCommand = class extends Command {
|
|
15870
15870
|
static description = "Log in by opening Primitive in your browser and saving an org-scoped OAuth session locally.";
|
|
15871
15871
|
static summary = "Log in with browser approval";
|
|
15872
15872
|
static examples = [
|
|
@@ -15884,24 +15884,28 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15884
15884
|
"no-browser": Flags.boolean({ description: "Do not attempt to open the browser automatically" }),
|
|
15885
15885
|
force: Flags.boolean({
|
|
15886
15886
|
char: "f",
|
|
15887
|
-
description: "Replace saved credentials without first verifying the existing
|
|
15887
|
+
description: "Replace saved credentials without first verifying the existing session"
|
|
15888
15888
|
})
|
|
15889
15889
|
};
|
|
15890
15890
|
async run() {
|
|
15891
|
-
const
|
|
15891
|
+
const commandClass = this.constructor;
|
|
15892
|
+
const { flags } = await this.parse(commandClass);
|
|
15892
15893
|
let releaseCredentialsLock;
|
|
15893
15894
|
try {
|
|
15894
15895
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
15895
15896
|
} catch (error) {
|
|
15896
|
-
throw cliError$
|
|
15897
|
+
throw cliError$3(error instanceof Error ? error.message : String(error));
|
|
15897
15898
|
}
|
|
15898
15899
|
try {
|
|
15899
|
-
await this.runWithCredentialLock(flags);
|
|
15900
|
+
await this.runWithCredentialLock(flags, this.retryCommand());
|
|
15900
15901
|
} finally {
|
|
15901
15902
|
releaseCredentialsLock();
|
|
15902
15903
|
}
|
|
15903
15904
|
}
|
|
15904
|
-
|
|
15905
|
+
retryCommand() {
|
|
15906
|
+
return "login";
|
|
15907
|
+
}
|
|
15908
|
+
async runWithCredentialLock(flags, retryCommand) {
|
|
15905
15909
|
const { apiClient, requestConfig } = createCliApiClient({
|
|
15906
15910
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
15907
15911
|
configDir: this.config.configDir
|
|
@@ -15927,8 +15931,8 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15927
15931
|
if (existingStatus.status === "removed_stale") process.stderr.write("Continuing with a new Primitive CLI login...\n");
|
|
15928
15932
|
else if (existingStatus.status === "blocked") {
|
|
15929
15933
|
writeErrorWithHints(existingStatus.payload);
|
|
15930
|
-
throw cliError$
|
|
15931
|
-
} else throw cliError$
|
|
15934
|
+
throw cliError$3(existingStatus.message);
|
|
15935
|
+
} else throw cliError$3(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before logging in again.`);
|
|
15932
15936
|
}
|
|
15933
15937
|
const started = await startCliLogin({
|
|
15934
15938
|
body: { device_name: flags["device-name"] ?? hostname() },
|
|
@@ -15937,11 +15941,11 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15937
15941
|
});
|
|
15938
15942
|
if (started.error) {
|
|
15939
15943
|
writeErrorWithHints(extractErrorPayload(started.error));
|
|
15940
|
-
throw cliError$
|
|
15944
|
+
throw cliError$3("Could not start Primitive CLI login.");
|
|
15941
15945
|
}
|
|
15942
15946
|
const start = unwrapData$2(started.data);
|
|
15943
|
-
if (!start) throw cliError$
|
|
15944
|
-
process.stderr.write(`Your
|
|
15947
|
+
if (!start) throw cliError$3("Primitive API returned an empty CLI login response.");
|
|
15948
|
+
process.stderr.write(`Your sign-in code is: ${start.user_code}\n`);
|
|
15945
15949
|
if (!flags["no-browser"]) {
|
|
15946
15950
|
openBrowser(start.verification_uri_complete);
|
|
15947
15951
|
process.stderr.write("Opening Primitive in your browser...\n");
|
|
@@ -15961,7 +15965,7 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15961
15965
|
});
|
|
15962
15966
|
if (polled.data) {
|
|
15963
15967
|
const login = unwrapData$2(polled.data);
|
|
15964
|
-
if (!login) throw cliError$
|
|
15968
|
+
if (!login) throw cliError$3("Primitive API returned an empty CLI poll response.");
|
|
15965
15969
|
saveCliCredentials(this.config.configDir, {
|
|
15966
15970
|
access_token: login.access_token,
|
|
15967
15971
|
api_base_url_1: apiBaseUrl1,
|
|
@@ -15991,25 +15995,25 @@ var LoginCommand = class LoginCommand extends Command {
|
|
|
15991
15995
|
nextPollDelay = interval;
|
|
15992
15996
|
continue;
|
|
15993
15997
|
}
|
|
15994
|
-
if (code === API_ERROR_CODES.accessDenied) throw cliError$
|
|
15995
|
-
if (code === API_ERROR_CODES.expiredToken) throw cliError$
|
|
15996
|
-
if (code === API_ERROR_CODES.invalidDeviceCode) throw cliError$
|
|
15998
|
+
if (code === API_ERROR_CODES.accessDenied) throw cliError$3("Primitive CLI login was denied in the browser.");
|
|
15999
|
+
if (code === API_ERROR_CODES.expiredToken) throw cliError$3(`Primitive CLI login expired. Run \`primitive ${retryCommand}\` again.`);
|
|
16000
|
+
if (code === API_ERROR_CODES.invalidDeviceCode) throw cliError$3(`Primitive CLI login device code is invalid. Run \`primitive ${retryCommand}\` again.`);
|
|
15997
16001
|
writeErrorWithHints(payload);
|
|
15998
|
-
throw cliError$
|
|
16002
|
+
throw cliError$3("Primitive CLI login failed while polling for approval.");
|
|
15999
16003
|
}
|
|
16000
|
-
throw cliError$
|
|
16004
|
+
throw cliError$3(`Primitive CLI login expired. Run \`primitive ${retryCommand}\` again.`);
|
|
16001
16005
|
}
|
|
16002
16006
|
};
|
|
16003
16007
|
//#endregion
|
|
16004
16008
|
//#region src/oclif/commands/logout.ts
|
|
16005
|
-
function cliError$
|
|
16009
|
+
function cliError$2(message) {
|
|
16006
16010
|
return new Errors.CLIError(message, { exit: 1 });
|
|
16007
16011
|
}
|
|
16008
16012
|
function unwrapData$1(value) {
|
|
16009
16013
|
return value?.data ?? null;
|
|
16010
16014
|
}
|
|
16011
16015
|
function isSavedOAuthSessionExpiredError(error) {
|
|
16012
|
-
return error instanceof Error && error.message === "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive
|
|
16016
|
+
return error instanceof Error && error.message === "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive signin` to authenticate again.";
|
|
16013
16017
|
}
|
|
16014
16018
|
async function runLogoutWithCredentialLock(params) {
|
|
16015
16019
|
const deps = {
|
|
@@ -16027,7 +16031,7 @@ async function runLogoutWithCredentialLock(params) {
|
|
|
16027
16031
|
process.exitCode = 1;
|
|
16028
16032
|
return;
|
|
16029
16033
|
}
|
|
16030
|
-
if (!credentials) throw cliError$
|
|
16034
|
+
if (!credentials) throw cliError$2("Not logged in. Run `primitive signin` to create saved CLI credentials.");
|
|
16031
16035
|
let authenticated;
|
|
16032
16036
|
try {
|
|
16033
16037
|
authenticated = await deps.createAuthenticatedCliApiClient({
|
|
@@ -16059,7 +16063,7 @@ async function runLogoutWithCredentialLock(params) {
|
|
|
16059
16063
|
return;
|
|
16060
16064
|
}
|
|
16061
16065
|
writeErrorWithHints(payload);
|
|
16062
|
-
throw cliError$
|
|
16066
|
+
throw cliError$2("Could not revoke the saved Primitive CLI OAuth grant.");
|
|
16063
16067
|
}
|
|
16064
16068
|
const logout = unwrapData$1(result.data);
|
|
16065
16069
|
deleteCliCredentials(params.configDir);
|
|
@@ -16081,7 +16085,7 @@ var LogoutCommand = class LogoutCommand extends Command {
|
|
|
16081
16085
|
try {
|
|
16082
16086
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16083
16087
|
} catch (error) {
|
|
16084
|
-
throw cliError$
|
|
16088
|
+
throw cliError$2(error instanceof Error ? error.message : String(error));
|
|
16085
16089
|
}
|
|
16086
16090
|
try {
|
|
16087
16091
|
await runLogoutWithCredentialLock({
|
|
@@ -16401,7 +16405,14 @@ const EXPIRED_TOKEN = "expired_token";
|
|
|
16401
16405
|
const INVALID_SIGNUP_TOKEN = "invalid_signup_token";
|
|
16402
16406
|
const SLOW_DOWN = "slow_down";
|
|
16403
16407
|
const PENDING_SIGNUP_FILE = "signup.json";
|
|
16404
|
-
|
|
16408
|
+
const DEFAULT_SIGNUP_COMMAND_COPY = {
|
|
16409
|
+
actionNoun: "signup",
|
|
16410
|
+
actionGerund: "creating a new account",
|
|
16411
|
+
confirmCommand: (email) => `signup confirm ${email} <code>`,
|
|
16412
|
+
resendCommand: (email) => `signup resend ${email}`,
|
|
16413
|
+
startCommand: (email) => `signup ${email}`
|
|
16414
|
+
};
|
|
16415
|
+
function cliError$1(message) {
|
|
16405
16416
|
return new Errors.CLIError(message, { exit: 1 });
|
|
16406
16417
|
}
|
|
16407
16418
|
function unwrapData(value) {
|
|
@@ -16490,9 +16501,10 @@ function loadPendingAgentSignup(configDir, apiBaseUrl1) {
|
|
|
16490
16501
|
};
|
|
16491
16502
|
}
|
|
16492
16503
|
function requirePendingSignupForEmail(params) {
|
|
16504
|
+
const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
|
|
16493
16505
|
const pending = loadPendingAgentSignup(params.configDir, params.apiBaseUrl1);
|
|
16494
|
-
if (!pending) throw cliError(`No pending
|
|
16495
|
-
if (normalizeEmail(pending.email) !== normalizeEmail(params.email)) throw cliError(`Pending
|
|
16506
|
+
if (!pending) throw cliError$1(`No pending ${copy.actionNoun} for ${params.email}. Run \`primitive ${copy.startCommand(params.email)}\` first.`);
|
|
16507
|
+
if (normalizeEmail(pending.email) !== normalizeEmail(params.email)) throw cliError$1(`Pending ${copy.actionNoun} is for ${pending.email}, not ${params.email}. Run \`primitive ${copy.startCommand(params.email)} --force\` to replace it.`);
|
|
16496
16508
|
return pending;
|
|
16497
16509
|
}
|
|
16498
16510
|
function retryAfterSeconds(result) {
|
|
@@ -16529,13 +16541,14 @@ async function promptRequired(question) {
|
|
|
16529
16541
|
}
|
|
16530
16542
|
}
|
|
16531
16543
|
async function confirmTerms() {
|
|
16532
|
-
process$1.stderr.write("By
|
|
16544
|
+
process$1.stderr.write("By continuing, you agree to Primitive's Terms of Service and Privacy Policy:\n");
|
|
16533
16545
|
process$1.stderr.write(" https://primitive.dev/terms\n");
|
|
16534
16546
|
process$1.stderr.write(" https://primitive.dev/privacy\n");
|
|
16535
16547
|
const answer = (await promptRequired("Type 'yes' to continue: ")).toLowerCase();
|
|
16536
|
-
if (answer !== "yes" && answer !== "y") throw cliError("You must accept the terms to create an account.");
|
|
16548
|
+
if (answer !== "yes" && answer !== "y") throw cliError$1("You must accept the terms to create an account.");
|
|
16537
16549
|
}
|
|
16538
16550
|
async function checkExistingCredentials(params) {
|
|
16551
|
+
const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
|
|
16539
16552
|
const checkExistingLoginFn = params.deps.checkExistingLogin ?? checkExistingLogin;
|
|
16540
16553
|
let existing;
|
|
16541
16554
|
try {
|
|
@@ -16547,7 +16560,7 @@ async function checkExistingCredentials(params) {
|
|
|
16547
16560
|
existing = null;
|
|
16548
16561
|
}
|
|
16549
16562
|
if (existing && params.flags.force) {
|
|
16550
|
-
process$1.stderr.write(
|
|
16563
|
+
process$1.stderr.write(`Replacing saved Primitive CLI credentials after ${copy.actionNoun} because --force was set.\n`);
|
|
16551
16564
|
return;
|
|
16552
16565
|
}
|
|
16553
16566
|
if (!existing) return;
|
|
@@ -16563,9 +16576,9 @@ async function checkExistingCredentials(params) {
|
|
|
16563
16576
|
}
|
|
16564
16577
|
if (existingStatus.status === "blocked") {
|
|
16565
16578
|
writeErrorWithHints(existingStatus.payload);
|
|
16566
|
-
throw cliError(existingStatus.message);
|
|
16579
|
+
throw cliError$1(existingStatus.message);
|
|
16567
16580
|
}
|
|
16568
|
-
throw cliError(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before
|
|
16581
|
+
throw cliError$1(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before ${copy.actionGerund}.`);
|
|
16569
16582
|
}
|
|
16570
16583
|
function saveSignupCredentials(params) {
|
|
16571
16584
|
saveCliCredentials(params.configDir, {
|
|
@@ -16582,23 +16595,24 @@ function saveSignupCredentials(params) {
|
|
|
16582
16595
|
token_type: params.signup.token_type
|
|
16583
16596
|
});
|
|
16584
16597
|
}
|
|
16585
|
-
function writeStartInstructions(start) {
|
|
16598
|
+
function writeStartInstructions(start, copy = DEFAULT_SIGNUP_COMMAND_COPY) {
|
|
16586
16599
|
process$1.stderr.write(`Sent a ${start.verification_code_length}-digit verification code to ${start.email}.\n`);
|
|
16587
16600
|
process$1.stderr.write(`The code expires in ${formatSignupSeconds(start.expires_in)}.\n`);
|
|
16588
|
-
process$1.stderr.write(`Run \`primitive
|
|
16601
|
+
process$1.stderr.write(`Run \`primitive ${copy.confirmCommand(start.email)}\` to finish.\n`);
|
|
16589
16602
|
}
|
|
16590
16603
|
async function startSignup(params) {
|
|
16604
|
+
const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
|
|
16591
16605
|
const existingPending = loadPendingAgentSignup(params.configDir, params.apiBaseUrl1);
|
|
16592
16606
|
if (existingPending && !params.flags.force) {
|
|
16593
16607
|
if (normalizeEmail(existingPending.email) === normalizeEmail(params.email)) {
|
|
16594
|
-
process$1.stderr.write(`Continuing pending Primitive
|
|
16595
|
-
process$1.stderr.write(`Run \`primitive
|
|
16608
|
+
process$1.stderr.write(`Continuing pending Primitive ${copy.actionNoun} for ${existingPending.email}.\n`);
|
|
16609
|
+
process$1.stderr.write(`Run \`primitive ${copy.confirmCommand(existingPending.email)}\` to finish, or \`primitive ${copy.resendCommand(existingPending.email)}\` to send a new code.\n`);
|
|
16596
16610
|
return {
|
|
16597
16611
|
pending: existingPending,
|
|
16598
16612
|
started: false
|
|
16599
16613
|
};
|
|
16600
16614
|
}
|
|
16601
|
-
throw cliError(`Pending
|
|
16615
|
+
throw cliError$1(`Pending ${copy.actionNoun} is for ${existingPending.email}. Run \`primitive ${copy.startCommand(params.email)} --force\` to replace it.`);
|
|
16602
16616
|
}
|
|
16603
16617
|
if (params.flags.force) deletePendingAgentSignup(params.configDir);
|
|
16604
16618
|
const promptRequiredFn = params.deps.promptRequired ?? promptRequired;
|
|
@@ -16618,10 +16632,10 @@ async function startSignup(params) {
|
|
|
16618
16632
|
});
|
|
16619
16633
|
if (started.error) {
|
|
16620
16634
|
writeErrorWithHints(extractErrorPayload(started.error));
|
|
16621
|
-
throw cliError("Could not start Primitive agent signup.");
|
|
16635
|
+
throw cliError$1("Could not start Primitive agent signup.");
|
|
16622
16636
|
}
|
|
16623
16637
|
const startResult = unwrapData(started.data);
|
|
16624
|
-
if (!startResult) throw cliError("Primitive API returned an empty agent signup response.");
|
|
16638
|
+
if (!startResult) throw cliError$1("Primitive API returned an empty agent signup response.");
|
|
16625
16639
|
return {
|
|
16626
16640
|
pending: savePendingAgentSignup(params.configDir, startResult, params.apiBaseUrl1),
|
|
16627
16641
|
started: true
|
|
@@ -16659,7 +16673,7 @@ async function resendVerificationCode(params) {
|
|
|
16659
16673
|
}
|
|
16660
16674
|
if (code === EXPIRED_TOKEN || code === INVALID_SIGNUP_TOKEN) deletePendingAgentSignup(params.configDir);
|
|
16661
16675
|
writeErrorWithHints(payload);
|
|
16662
|
-
throw cliError("Could not resend Primitive agent signup verification email.");
|
|
16676
|
+
throw cliError$1("Could not resend Primitive agent signup verification email.");
|
|
16663
16677
|
}
|
|
16664
16678
|
async function runSignupStartWithCredentialLock(params) {
|
|
16665
16679
|
const { configDir, flags } = params;
|
|
@@ -16669,6 +16683,7 @@ async function runSignupStartWithCredentialLock(params) {
|
|
|
16669
16683
|
await checkExistingCredentials({
|
|
16670
16684
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
16671
16685
|
configDir,
|
|
16686
|
+
copy: params.copy,
|
|
16672
16687
|
deps,
|
|
16673
16688
|
flags
|
|
16674
16689
|
});
|
|
@@ -16680,11 +16695,12 @@ async function runSignupStartWithCredentialLock(params) {
|
|
|
16680
16695
|
apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
|
|
16681
16696
|
apiClient,
|
|
16682
16697
|
configDir,
|
|
16698
|
+
copy: params.copy,
|
|
16683
16699
|
deps,
|
|
16684
16700
|
email,
|
|
16685
16701
|
flags
|
|
16686
16702
|
});
|
|
16687
|
-
if (start.started) writeStartInstructions(start.pending);
|
|
16703
|
+
if (start.started) writeStartInstructions(start.pending, params.copy);
|
|
16688
16704
|
}
|
|
16689
16705
|
async function runSignupConfirmWithCredentialLock(params) {
|
|
16690
16706
|
const { configDir, flags } = params;
|
|
@@ -16692,6 +16708,7 @@ async function runSignupConfirmWithCredentialLock(params) {
|
|
|
16692
16708
|
if (!params.skipExistingCredentialCheck) await checkExistingCredentials({
|
|
16693
16709
|
apiBaseUrl1: flags["api-base-url-1"],
|
|
16694
16710
|
configDir,
|
|
16711
|
+
copy: params.copy,
|
|
16695
16712
|
deps,
|
|
16696
16713
|
flags
|
|
16697
16714
|
});
|
|
@@ -16702,6 +16719,7 @@ async function runSignupConfirmWithCredentialLock(params) {
|
|
|
16702
16719
|
const apiBaseUrl1 = requestConfig.resolvedApiBaseUrl1;
|
|
16703
16720
|
const pending = requirePendingSignupForEmail({
|
|
16704
16721
|
apiBaseUrl1,
|
|
16722
|
+
copy: params.copy,
|
|
16705
16723
|
configDir,
|
|
16706
16724
|
email: params.email
|
|
16707
16725
|
});
|
|
@@ -16716,7 +16734,7 @@ async function runSignupConfirmWithCredentialLock(params) {
|
|
|
16716
16734
|
});
|
|
16717
16735
|
if (verified.data) {
|
|
16718
16736
|
const signup = unwrapData(verified.data);
|
|
16719
|
-
if (!signup) throw cliError("Primitive API returned an empty agent signup verification response.");
|
|
16737
|
+
if (!signup) throw cliError$1("Primitive API returned an empty agent signup verification response.");
|
|
16720
16738
|
saveSignupCredentials({
|
|
16721
16739
|
apiBaseUrl1,
|
|
16722
16740
|
configDir,
|
|
@@ -16730,10 +16748,10 @@ async function runSignupConfirmWithCredentialLock(params) {
|
|
|
16730
16748
|
}
|
|
16731
16749
|
const payload = extractErrorPayload(verified.error);
|
|
16732
16750
|
const code = extractErrorCode(payload);
|
|
16733
|
-
if (code === INVALID_VERIFICATION_CODE) throw cliError(
|
|
16751
|
+
if (code === INVALID_VERIFICATION_CODE) throw cliError$1(`Invalid verification code. Try again or run ${(params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY).resendCommand(params.email)}.`);
|
|
16734
16752
|
if (code === EXPIRED_TOKEN || code === INVALID_SIGNUP_TOKEN) deletePendingAgentSignup(configDir);
|
|
16735
16753
|
writeErrorWithHints(payload);
|
|
16736
|
-
throw cliError("Primitive agent signup failed while verifying the account.");
|
|
16754
|
+
throw cliError$1("Primitive agent signup failed while verifying the account.");
|
|
16737
16755
|
}
|
|
16738
16756
|
async function runSignupResendWithCredentialLock(params) {
|
|
16739
16757
|
const deps = params.deps ?? {};
|
|
@@ -16743,6 +16761,7 @@ async function runSignupResendWithCredentialLock(params) {
|
|
|
16743
16761
|
});
|
|
16744
16762
|
const pending = requirePendingSignupForEmail({
|
|
16745
16763
|
apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
|
|
16764
|
+
copy: params.copy,
|
|
16746
16765
|
configDir: params.configDir,
|
|
16747
16766
|
email: params.email
|
|
16748
16767
|
});
|
|
@@ -16857,7 +16876,7 @@ var SignupCommand = class SignupCommand extends Command {
|
|
|
16857
16876
|
try {
|
|
16858
16877
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16859
16878
|
} catch (error) {
|
|
16860
|
-
throw cliError(error instanceof Error ? error.message : String(error));
|
|
16879
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16861
16880
|
}
|
|
16862
16881
|
try {
|
|
16863
16882
|
await runSignupStartWithCredentialLock({
|
|
@@ -16902,7 +16921,7 @@ var SignupConfirmCommand = class SignupConfirmCommand extends Command {
|
|
|
16902
16921
|
try {
|
|
16903
16922
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16904
16923
|
} catch (error) {
|
|
16905
|
-
throw cliError(error instanceof Error ? error.message : String(error));
|
|
16924
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16906
16925
|
}
|
|
16907
16926
|
try {
|
|
16908
16927
|
await runSignupConfirmWithCredentialLock({
|
|
@@ -16935,7 +16954,7 @@ var SignupResendCommand = class SignupResendCommand extends Command {
|
|
|
16935
16954
|
try {
|
|
16936
16955
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16937
16956
|
} catch (error) {
|
|
16938
|
-
throw cliError(error instanceof Error ? error.message : String(error));
|
|
16957
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16939
16958
|
}
|
|
16940
16959
|
try {
|
|
16941
16960
|
await runSignupResendWithCredentialLock({
|
|
@@ -16959,7 +16978,7 @@ var SignupInteractiveCommand = class SignupInteractiveCommand extends Command {
|
|
|
16959
16978
|
try {
|
|
16960
16979
|
releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
|
|
16961
16980
|
} catch (error) {
|
|
16962
|
-
throw cliError(error instanceof Error ? error.message : String(error));
|
|
16981
|
+
throw cliError$1(error instanceof Error ? error.message : String(error));
|
|
16963
16982
|
}
|
|
16964
16983
|
try {
|
|
16965
16984
|
await runSignupInteractiveWithCredentialLock({
|
|
@@ -16972,6 +16991,167 @@ var SignupInteractiveCommand = class SignupInteractiveCommand extends Command {
|
|
|
16972
16991
|
}
|
|
16973
16992
|
};
|
|
16974
16993
|
//#endregion
|
|
16994
|
+
//#region src/oclif/commands/signin.ts
|
|
16995
|
+
function cliError(message) {
|
|
16996
|
+
return new Errors.CLIError(message, { exit: 1 });
|
|
16997
|
+
}
|
|
16998
|
+
const SIGNIN_OTP_COPY = {
|
|
16999
|
+
actionNoun: "sign-in",
|
|
17000
|
+
actionGerund: "signing in",
|
|
17001
|
+
confirmCommand: (email) => `signin otp confirm ${email} <code>`,
|
|
17002
|
+
resendCommand: (email) => `signin otp resend ${email}`,
|
|
17003
|
+
startCommand: (email) => `signin otp ${email}`
|
|
17004
|
+
};
|
|
17005
|
+
function acquireCredentialsLock(configDir) {
|
|
17006
|
+
try {
|
|
17007
|
+
return acquireCliCredentialsLock(configDir);
|
|
17008
|
+
} catch (error) {
|
|
17009
|
+
throw cliError(error instanceof Error ? error.message : String(error));
|
|
17010
|
+
}
|
|
17011
|
+
}
|
|
17012
|
+
function commonOtpStartFlags() {
|
|
17013
|
+
return {
|
|
17014
|
+
"accept-terms": Flags.boolean({ description: "Confirm acceptance of Primitive's Terms of Service and Privacy Policy" }),
|
|
17015
|
+
"api-base-url-1": Flags.string({
|
|
17016
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
17017
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17018
|
+
hidden: true
|
|
17019
|
+
}),
|
|
17020
|
+
"device-name": Flags.string({ description: "Device name used for the created CLI OAuth session" }),
|
|
17021
|
+
force: Flags.boolean({
|
|
17022
|
+
char: "f",
|
|
17023
|
+
description: "Replace saved credentials or pending sign-in state when needed"
|
|
17024
|
+
}),
|
|
17025
|
+
"signup-code": Flags.string({
|
|
17026
|
+
description: "Signup code required to start OTP sign-in",
|
|
17027
|
+
env: "PRIMITIVE_SIGNUP_CODE"
|
|
17028
|
+
})
|
|
17029
|
+
};
|
|
17030
|
+
}
|
|
17031
|
+
var SigninCommand = class extends LoginCommand {
|
|
17032
|
+
static description = `Sign in to an existing Primitive account with browser approval and save an org-scoped OAuth session locally.
|
|
17033
|
+
|
|
17034
|
+
This is the canonical sign-in command. It defaults to the same browser approval flow as \`primitive signin browser\`. For email-code sign-in, use \`primitive signin otp <email> --signup-code <code>\`, then \`primitive signin otp confirm <email> <code>\`. For new account creation, use \`primitive signup <email>\`.`;
|
|
17035
|
+
static summary = "Sign in to an existing account";
|
|
17036
|
+
static examples = [
|
|
17037
|
+
"<%= config.bin %> signin",
|
|
17038
|
+
"<%= config.bin %> signin browser",
|
|
17039
|
+
"<%= config.bin %> signin --no-browser",
|
|
17040
|
+
"<%= config.bin %> signin otp user@example.com --signup-code invite-code --accept-terms",
|
|
17041
|
+
"<%= config.bin %> signin otp confirm user@example.com 123456"
|
|
17042
|
+
];
|
|
17043
|
+
retryCommand() {
|
|
17044
|
+
return "signin";
|
|
17045
|
+
}
|
|
17046
|
+
};
|
|
17047
|
+
var SigninBrowserCommand = class extends LoginCommand {
|
|
17048
|
+
static description = "Sign in to an existing Primitive account by opening Primitive in your browser and saving an org-scoped OAuth session locally.";
|
|
17049
|
+
static summary = "Sign in with browser approval";
|
|
17050
|
+
static examples = [
|
|
17051
|
+
"<%= config.bin %> signin browser",
|
|
17052
|
+
"<%= config.bin %> signin browser --device-name work-laptop",
|
|
17053
|
+
"<%= config.bin %> signin browser --no-browser",
|
|
17054
|
+
"<%= config.bin %> signin browser --force"
|
|
17055
|
+
];
|
|
17056
|
+
retryCommand() {
|
|
17057
|
+
return "signin browser";
|
|
17058
|
+
}
|
|
17059
|
+
};
|
|
17060
|
+
var SigninOtpCommand = class SigninOtpCommand extends Command {
|
|
17061
|
+
static args = { email: Args.string({
|
|
17062
|
+
description: "Email address to sign in with",
|
|
17063
|
+
required: false
|
|
17064
|
+
}) };
|
|
17065
|
+
static description = "Start email-code sign-in using Primitive's signup/auth OTP flow, send a verification code, and save the pending token locally. Requires a signup code.";
|
|
17066
|
+
static summary = "Start OTP sign-in";
|
|
17067
|
+
static examples = ["<%= config.bin %> signin otp user@example.com --signup-code invite-code --accept-terms", "<%= config.bin %> signin otp confirm user@example.com 123456"];
|
|
17068
|
+
static flags = commonOtpStartFlags();
|
|
17069
|
+
async run() {
|
|
17070
|
+
const { args, flags } = await this.parse(SigninOtpCommand);
|
|
17071
|
+
const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
|
|
17072
|
+
try {
|
|
17073
|
+
await runSignupStartWithCredentialLock({
|
|
17074
|
+
configDir: this.config.configDir,
|
|
17075
|
+
copy: SIGNIN_OTP_COPY,
|
|
17076
|
+
email: args.email,
|
|
17077
|
+
flags
|
|
17078
|
+
});
|
|
17079
|
+
} finally {
|
|
17080
|
+
releaseCredentialsLock();
|
|
17081
|
+
}
|
|
17082
|
+
}
|
|
17083
|
+
};
|
|
17084
|
+
var SigninOtpConfirmCommand = class SigninOtpConfirmCommand extends Command {
|
|
17085
|
+
static args = {
|
|
17086
|
+
email: Args.string({
|
|
17087
|
+
description: "Email address used to start OTP sign-in",
|
|
17088
|
+
required: true
|
|
17089
|
+
}),
|
|
17090
|
+
code: Args.string({
|
|
17091
|
+
description: "Verification code from the sign-in email",
|
|
17092
|
+
required: true
|
|
17093
|
+
})
|
|
17094
|
+
};
|
|
17095
|
+
static description = "Confirm a pending OTP sign-in, create an OAuth session, and save CLI credentials locally.";
|
|
17096
|
+
static summary = "Confirm OTP sign-in";
|
|
17097
|
+
static examples = ["<%= config.bin %> signin otp confirm user@example.com 123456", "<%= config.bin %> signin otp confirm user@example.com 123456 --org-id 00000000-0000-4000-8000-000000000000"];
|
|
17098
|
+
static flags = {
|
|
17099
|
+
"api-base-url-1": Flags.string({
|
|
17100
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
17101
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17102
|
+
hidden: true
|
|
17103
|
+
}),
|
|
17104
|
+
force: Flags.boolean({
|
|
17105
|
+
char: "f",
|
|
17106
|
+
description: "Replace saved credentials after verification"
|
|
17107
|
+
}),
|
|
17108
|
+
"org-id": Flags.string({ description: "Workspace id to target when the email belongs to multiple workspaces" })
|
|
17109
|
+
};
|
|
17110
|
+
async run() {
|
|
17111
|
+
const { args, flags } = await this.parse(SigninOtpConfirmCommand);
|
|
17112
|
+
const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
|
|
17113
|
+
try {
|
|
17114
|
+
await runSignupConfirmWithCredentialLock({
|
|
17115
|
+
code: args.code,
|
|
17116
|
+
configDir: this.config.configDir,
|
|
17117
|
+
copy: SIGNIN_OTP_COPY,
|
|
17118
|
+
email: args.email,
|
|
17119
|
+
flags
|
|
17120
|
+
});
|
|
17121
|
+
} finally {
|
|
17122
|
+
releaseCredentialsLock();
|
|
17123
|
+
}
|
|
17124
|
+
}
|
|
17125
|
+
};
|
|
17126
|
+
var SigninOtpResendCommand = class SigninOtpResendCommand extends Command {
|
|
17127
|
+
static args = { email: Args.string({
|
|
17128
|
+
description: "Email address used to start OTP sign-in",
|
|
17129
|
+
required: true
|
|
17130
|
+
}) };
|
|
17131
|
+
static description = "Resend the verification code for a pending OTP sign-in.";
|
|
17132
|
+
static summary = "Resend OTP sign-in code";
|
|
17133
|
+
static examples = ["<%= config.bin %> signin otp resend user@example.com"];
|
|
17134
|
+
static flags = { "api-base-url-1": Flags.string({
|
|
17135
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
17136
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
17137
|
+
hidden: true
|
|
17138
|
+
}) };
|
|
17139
|
+
async run() {
|
|
17140
|
+
const { args, flags } = await this.parse(SigninOtpResendCommand);
|
|
17141
|
+
const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
|
|
17142
|
+
try {
|
|
17143
|
+
await runSignupResendWithCredentialLock({
|
|
17144
|
+
configDir: this.config.configDir,
|
|
17145
|
+
copy: SIGNIN_OTP_COPY,
|
|
17146
|
+
email: args.email,
|
|
17147
|
+
flags
|
|
17148
|
+
});
|
|
17149
|
+
} finally {
|
|
17150
|
+
releaseCredentialsLock();
|
|
17151
|
+
}
|
|
17152
|
+
}
|
|
17153
|
+
};
|
|
17154
|
+
//#endregion
|
|
16975
17155
|
//#region src/oclif/commands/whoami.ts
|
|
16976
17156
|
var WhoamiCommand = class WhoamiCommand extends Command {
|
|
16977
17157
|
static description = `Print the account currently authenticated by saved OAuth credentials or an explicit API key. Useful as a credentials smoke test: confirms auth is live and shows which account it belongs to.`;
|
|
@@ -17243,6 +17423,11 @@ const COMMANDS = {
|
|
|
17243
17423
|
reply: ReplyCommand,
|
|
17244
17424
|
chat: ChatCommand,
|
|
17245
17425
|
login: LoginCommand,
|
|
17426
|
+
signin: SigninCommand,
|
|
17427
|
+
"signin:browser": SigninBrowserCommand,
|
|
17428
|
+
"signin:otp": SigninOtpCommand,
|
|
17429
|
+
"signin:otp:confirm": SigninOtpConfirmCommand,
|
|
17430
|
+
"signin:otp:resend": SigninOtpResendCommand,
|
|
17246
17431
|
signup: SignupCommand,
|
|
17247
17432
|
"signup:confirm": SignupConfirmCommand,
|
|
17248
17433
|
"signup:interactive": SignupInteractiveCommand,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primitivedotdev/cli",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.3",
|
|
4
4
|
"description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -46,6 +46,9 @@
|
|
|
46
46
|
"sending": {
|
|
47
47
|
"description": "Send outbound emails. Prefer `primitive send` for fresh sends and `primitive reply --id <inbound-id>` for replies; use `primitive sending list`, `primitive sending get`, and `primitive sending permissions` for outbound history and permissions."
|
|
48
48
|
},
|
|
49
|
+
"signin": {
|
|
50
|
+
"description": "Sign in to an existing Primitive account"
|
|
51
|
+
},
|
|
49
52
|
"sent": {
|
|
50
53
|
"description": "Short aliases for outbound sent-email history: `primitive sent list` and `primitive sent get`."
|
|
51
54
|
},
|