@trillioncore/cli 1.0.0-next.11 → 1.0.0-next.12
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 +17 -1
- package/dist/index.js +33 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,20 @@ The `tc` CLI signs you into Trillioncore and reads the organizations and integra
|
|
|
4
4
|
|
|
5
5
|
**Requirements:** Node.js 22+, a browser on any device, and a Trillioncore deployment with CLI device login enabled. This is a fresh v1 preview, not v0 command parity; v0 configuration is not imported.
|
|
6
6
|
|
|
7
|
+
## For agents: install and set up Trillioncore for a person
|
|
8
|
+
|
|
9
|
+
When a person asks you to install or set up Trillioncore, run these steps in order:
|
|
10
|
+
|
|
11
|
+
1. Ask whether they already have a Trillioncore account. For a new organization, ask what to call it.
|
|
12
|
+
2. New account: `npm exec --yes --package=@trillioncore/cli@next -- tc signup --organization-name '<name>'`.
|
|
13
|
+
Existing account, new organization: `... tc create-organization --name '<name>'`.
|
|
14
|
+
Existing account and organization: `... tc login`.
|
|
15
|
+
3. The command waits up to five minutes for the browser. Run it in the background with output to a file, and add `--no-browser` when the person's browser is on another machine. Read the URL and the separate eight-character code from the output and relay both to the person. They sign up with their provider (for example Google or Microsoft), confirm the organization name, enter the code, and choose access. Wait for the command to print `Signed in`.
|
|
16
|
+
4. Run `tc whoami --json` to confirm the identity.
|
|
17
|
+
5. Relay the printed `Next:` link. The person connects data sources under Integrations in the app. Then use `tc index`, `tc search`, and `tc get`.
|
|
18
|
+
|
|
19
|
+
Do not ask the person for tokens, passwords, or the verification code in chat. They enter the code only in their browser. Creating an organization makes the person its administrator; it does not approve CLI access by itself.
|
|
20
|
+
|
|
7
21
|
## Get started
|
|
8
22
|
|
|
9
23
|
Once `@next` is published and the hosted login rollout is enabled:
|
|
@@ -20,13 +34,15 @@ npm exec --yes --package=@trillioncore/cli@next -- tc logout
|
|
|
20
34
|
|
|
21
35
|
`tc login` registers a five-minute request and prints a browser URL plus a separate eight-character code. Open the URL on any device and enter the code shown in your terminal. Keep the code private and approve only a login you started. The CLI polls without a callback listener, tunnel, or copied token. After approval it verifies your identity, saves the private session, and acknowledges delivery.
|
|
22
36
|
|
|
23
|
-
Browser sign-in lets you choose one or more organizations and explicitly select enabled accounts within each. Membership alone does not authorize a CLI connection; current organization and account permissions still apply. For a brand-new account,
|
|
37
|
+
Browser sign-in lets you choose one or more organizations and explicitly select enabled accounts within each. Membership alone does not authorize a CLI connection; current organization and account permissions still apply. For a brand-new account, use `tc signup`; the browser asks for an organization name and continues without a rerun. No provider reconnection is required just to authorize the CLI.
|
|
24
38
|
|
|
25
39
|
Prefer `npm exec` during evaluation. `npm install -g @trillioncore/cli@next` replaces your local `tc` executable, even though publishing `next` does not change the npm `latest` tag.
|
|
26
40
|
|
|
27
41
|
## Commands
|
|
28
42
|
|
|
29
43
|
- `login [--no-browser] [--api-url <origin>]`: browser authorization, organization/account selection, and durable local session storage.
|
|
44
|
+
- `signup [--organization-name <name>] [--no-browser] [--api-url <origin>]`: create an account on the sign-up screen, name a new organization (you become its administrator), then finish the same device approval as `login`.
|
|
45
|
+
- `create-organization [--name <name>] [--no-browser] [--api-url <origin>]`: an existing account creates another organization in the browser and becomes its administrator. The CLI then signs in through the same device approval, because a new organization needs its own approval. `tc login` also asks a signed-in person with no organization to name one.
|
|
30
46
|
- `whoami [--json]`: verify the signed-in identity without printing credentials.
|
|
31
47
|
- `logout`: revoke the CLI connection on the server and remove its local session. `--local-only` only forgets local credentials; use the app's **Tokens** page to revoke server access if offline.
|
|
32
48
|
- `organizations [--json]`: list only currently approved organizations, with `--limit` and `--cursor` pagination.
|
package/dist/index.js
CHANGED
|
@@ -3405,10 +3405,22 @@ function verificationUrl(value, requestId) {
|
|
|
3405
3405
|
);
|
|
3406
3406
|
}
|
|
3407
3407
|
}
|
|
3408
|
+
function organizationSetupUrl(url, options) {
|
|
3409
|
+
if (!options.signUp && !options.createOrganization) return url;
|
|
3410
|
+
const next = new URL(url);
|
|
3411
|
+
if (options.signUp) next.pathname = "/connect/cli/sign-up";
|
|
3412
|
+
else next.searchParams.set("create", "organization");
|
|
3413
|
+
if (options.organizationName)
|
|
3414
|
+
next.searchParams.set("name", options.organizationName);
|
|
3415
|
+
return next.toString();
|
|
3416
|
+
}
|
|
3408
3417
|
async function login(options = {}, environment = process.env) {
|
|
3409
3418
|
const issuer = loginOrigin(
|
|
3410
3419
|
options.apiUrl ?? environment.TRILLIONCORE_CLI_API_URL ?? environment.TRILLIONCORE_API_URL ?? DEFAULT_API
|
|
3411
3420
|
);
|
|
3421
|
+
const organizationName = options.organizationName?.trim();
|
|
3422
|
+
if (organizationName !== void 0 && (!organizationName || organizationName.length > 100 || /[\u0000-\u001f\u007f-\u009f]/.test(organizationName)))
|
|
3423
|
+
throw new Error("Organization name must be 1-100 printable characters.");
|
|
3412
3424
|
const abort = new AbortController();
|
|
3413
3425
|
const verifier = randomBytes2(32).toString("base64url");
|
|
3414
3426
|
const alphabet = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
@@ -3475,9 +3487,9 @@ async function login(options = {}, environment = process.env) {
|
|
|
3475
3487
|
() => stop("Sign-in timed out. Run tc login again."),
|
|
3476
3488
|
deadline - Date.now()
|
|
3477
3489
|
);
|
|
3478
|
-
const authorization =
|
|
3479
|
-
registration.verification_uri,
|
|
3480
|
-
|
|
3490
|
+
const authorization = organizationSetupUrl(
|
|
3491
|
+
verificationUrl(registration.verification_uri, requestId),
|
|
3492
|
+
{ ...options, ...organizationName ? { organizationName } : {} }
|
|
3481
3493
|
);
|
|
3482
3494
|
if (options.onAuthorizationUrl)
|
|
3483
3495
|
await options.onAuthorizationUrl(authorization, userCode);
|
|
@@ -3551,7 +3563,7 @@ Only approve a login you started. Keep the code private.`
|
|
|
3551
3563
|
"Signed in, but delivery acknowledgement failed. The temporary delivery expires automatically."
|
|
3552
3564
|
)
|
|
3553
3565
|
);
|
|
3554
|
-
return { issuer, ...who };
|
|
3566
|
+
return { issuer, appUrl: new URL(authorization).origin, ...who };
|
|
3555
3567
|
} catch (error) {
|
|
3556
3568
|
if (!persisted)
|
|
3557
3569
|
await revoke(credentials).catch(
|
|
@@ -4604,17 +4616,19 @@ function createProgram(overrides = {}) {
|
|
|
4604
4616
|
};
|
|
4605
4617
|
const program2 = new Command();
|
|
4606
4618
|
program2.name("tc").description("Trillioncore CLI \u2014 authorized integration record access").version(CLI_VERSION).helpCommand(false);
|
|
4607
|
-
|
|
4608
|
-
"Sign in through your browser and choose an organization and accounts"
|
|
4609
|
-
).option("--api-url <origin>", "Trillioncore API origin").option("--no-browser", "Print the sign-in URL without opening a browser").action(async (options) => {
|
|
4619
|
+
const signIn = async (options, setup = {}) => {
|
|
4610
4620
|
try {
|
|
4611
4621
|
const result = await login({
|
|
4612
|
-
apiUrl: options.apiUrl,
|
|
4613
|
-
noBrowser: options.browser === false
|
|
4622
|
+
...options.apiUrl !== void 0 ? { apiUrl: options.apiUrl } : {},
|
|
4623
|
+
noBrowser: options.browser === false,
|
|
4624
|
+
...setup,
|
|
4625
|
+
...options.organizationName !== void 0 ? { organizationName: options.organizationName } : {}
|
|
4614
4626
|
});
|
|
4615
4627
|
console.log(
|
|
4616
4628
|
`Signed in as ${result.email.replace(/[\u0000-\u001f\u007f-\u009f]/g, "")} to ${(result.organizationName ?? "your approved organizations").replace(/[\u0000-\u001f\u007f-\u009f]/g, "")}.`
|
|
4617
4629
|
);
|
|
4630
|
+
if (setup.signUp || setup.createOrganization)
|
|
4631
|
+
console.log(`Next: connect your data sources under Integrations at ${result.appUrl}`);
|
|
4618
4632
|
if (process.env.TRILLIONCORE_TOKEN || process.env.TRILLIONCORE_ORG_ID)
|
|
4619
4633
|
console.error(
|
|
4620
4634
|
"Manual token/organization environment overrides are set. Unset both to use this browser session."
|
|
@@ -4622,7 +4636,16 @@ function createProgram(overrides = {}) {
|
|
|
4622
4636
|
} catch (error) {
|
|
4623
4637
|
writeError(error, false);
|
|
4624
4638
|
}
|
|
4625
|
-
}
|
|
4639
|
+
};
|
|
4640
|
+
program2.command("login").description(
|
|
4641
|
+
"Sign in through your browser and choose an organization and accounts"
|
|
4642
|
+
).option("--api-url <origin>", "Trillioncore API origin").option("--no-browser", "Print the sign-in URL without opening a browser").action((options) => signIn(options));
|
|
4643
|
+
program2.command("signup").description(
|
|
4644
|
+
"Create a Trillioncore account and organization in your browser, then sign in this CLI"
|
|
4645
|
+
).option("--api-url <origin>", "Trillioncore API origin").option("--no-browser", "Print the sign-up URL without opening a browser").option("--organization-name <name>", "Suggested organization name; the browser asks to confirm it").action((options) => signIn(options, { signUp: true }));
|
|
4646
|
+
program2.command("create-organization").description(
|
|
4647
|
+
"Create another organization in your browser; you become its administrator and this CLI signs in to it"
|
|
4648
|
+
).option("--name <name>", "Suggested organization name; the browser asks to confirm it").option("--api-url <origin>", "Trillioncore API origin").option("--no-browser", "Print the URL without opening a browser").action((options) => signIn({ ...options, organizationName: options.name }, { createOrganization: true }));
|
|
4626
4649
|
program2.command("whoami").description("Verify your current CLI identity").option("-j, --json", "Output identity without credentials").action(async (options) => {
|
|
4627
4650
|
try {
|
|
4628
4651
|
const result = await whoami();
|