@seamapi/cli 0.19.0 → 0.20.0
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 +4 -4
- package/bin/cli.js +2 -2
- package/bin/cli.js.map +1 -1
- package/lib/auth/operations.d.ts +14 -14
- package/lib/auth/operations.js +39 -32
- package/lib/auth/operations.js.map +1 -1
- package/lib/auth/validate-token.js +1 -1
- package/lib/auth/validate-token.js.map +1 -1
- package/lib/blueprint/index.d.ts +1 -1
- package/lib/blueprint/index.js +2 -2
- package/lib/blueprint/index.js.map +1 -1
- package/lib/blueprint/source-remote.d.ts +2 -2
- package/lib/blueprint/source-remote.js +3 -3
- package/lib/blueprint/source-remote.js.map +1 -1
- package/lib/commands/local/login.js +3 -3
- package/lib/commands/local/login.js.map +1 -1
- package/lib/commands/local/{select-server.d.ts → select-endpoint.d.ts} +1 -1
- package/lib/commands/local/select-endpoint.js +27 -0
- package/lib/commands/local/select-endpoint.js.map +1 -0
- package/lib/commands/registry.js +2 -4
- package/lib/commands/registry.js.map +1 -1
- package/lib/context.d.ts +5 -5
- package/lib/context.js +9 -7
- package/lib/context.js.map +1 -1
- package/lib/env.d.ts +2 -2
- package/lib/env.js +2 -2
- package/lib/env.js.map +1 -1
- package/lib/http/client.js +2 -2
- package/lib/http/client.js.map +1 -1
- package/lib/interactions/endpoint-selection.d.ts +1 -0
- package/lib/interactions/endpoint-selection.js +39 -0
- package/lib/interactions/endpoint-selection.js.map +1 -0
- package/lib/interactions/index.d.ts +1 -1
- package/lib/interactions/index.js +1 -1
- package/lib/interactions/index.js.map +1 -1
- package/lib/interactions/login.js +2 -2
- package/lib/interactions/login.js.map +1 -1
- package/lib/interactions/workspace-id.js +1 -1
- package/lib/interactions/workspace-id.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/bin/cli.ts +2 -2
- package/src/lib/auth/operations.ts +43 -35
- package/src/lib/auth/validate-token.ts +1 -1
- package/src/lib/blueprint/index.ts +3 -3
- package/src/lib/blueprint/source-remote.ts +3 -3
- package/src/lib/commands/local/login.ts +3 -3
- package/src/lib/commands/local/select-endpoint.ts +30 -0
- package/src/lib/commands/registry.ts +2 -4
- package/src/lib/context.ts +17 -13
- package/src/lib/env.ts +2 -2
- package/src/lib/http/client.ts +2 -2
- package/src/lib/interactions/{server-selection.ts → endpoint-selection.ts} +16 -13
- package/src/lib/interactions/index.ts +1 -1
- package/src/lib/interactions/login.ts +2 -2
- package/src/lib/interactions/workspace-id.ts +1 -1
- package/src/lib/version.ts +1 -1
- package/lib/commands/local/config-set-fake-server.d.ts +0 -3
- package/lib/commands/local/config-set-fake-server.js +0 -20
- package/lib/commands/local/config-set-fake-server.js.map +0 -1
- package/lib/commands/local/select-server.js +0 -27
- package/lib/commands/local/select-server.js.map +0 -1
- package/lib/interactions/server-selection.d.ts +0 -1
- package/lib/interactions/server-selection.js +0 -36
- package/lib/interactions/server-selection.js.map +0 -1
- package/src/lib/commands/local/config-set-fake-server.ts +0 -21
- package/src/lib/commands/local/select-server.ts +0 -30
package/lib/http/client.js
CHANGED
|
@@ -3,7 +3,7 @@ import { resolveAuth } from '../context.js';
|
|
|
3
3
|
import { tokenEnvVar, workspaceIdEnvVar } from '../env.js';
|
|
4
4
|
export const getSeam = async (auth = resolveAuth()) => {
|
|
5
5
|
const token = getRequiredToken(auth);
|
|
6
|
-
const options = { endpoint: auth.
|
|
6
|
+
const options = { endpoint: auth.endpoint };
|
|
7
7
|
if (isPersonalAccessToken(token)) {
|
|
8
8
|
return SeamHttp.fromPersonalAccessToken(token, getRequiredWorkspaceId(auth), options);
|
|
9
9
|
}
|
|
@@ -14,7 +14,7 @@ export const getSeam = async (auth = resolveAuth()) => {
|
|
|
14
14
|
};
|
|
15
15
|
export const getSeamMultiWorkspace = async (auth = resolveAuth()) => {
|
|
16
16
|
const token = getRequiredToken(auth);
|
|
17
|
-
const options = { endpoint: auth.
|
|
17
|
+
const options = { endpoint: auth.endpoint };
|
|
18
18
|
if (isPersonalAccessToken(token)) {
|
|
19
19
|
return SeamHttpWithoutWorkspace.fromPersonalAccessToken(token, options);
|
|
20
20
|
}
|
package/lib/http/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/http/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,QAAQ,EACR,wBAAwB,GACzB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAoB,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAE3D,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAC1B,OAAoB,WAAW,EAAE,EACd,EAAE;IACrB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAEpC,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/http/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,QAAQ,EACR,wBAAwB,GACzB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAoB,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAE3D,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAC1B,OAAoB,WAAW,EAAE,EACd,EAAE;IACrB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAEpC,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;IAE3C,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC,uBAAuB,CACrC,KAAK,EACL,sBAAsB,CAAC,IAAI,CAAC,EAC5B,OAAO,CACR,CAAA;IACH,CAAC;IAED,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC,uBAAuB,CACrC,KAAK,EACL,sBAAsB,CAAC,IAAI,CAAC,EAC5B,OAAO,CACR,CAAA;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AAC5C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,OAAoB,WAAW,EAAE,EACa,EAAE;IAChD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACpC,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;IAE3C,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,wBAAwB,CAAC,uBAAuB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC,CAAA;AAED,MAAM,gBAAgB,GAAG,CAAC,IAAiB,EAAU,EAAE;IACrD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IAEtB,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,8CAA8C,WAAW,uBAAuB,CACjF,CAAA;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,sBAAsB,GAAG,CAAC,IAAiB,EAAU,EAAE;IAC3D,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAE5B,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,iEAAiE,iBAAiB,uBAAuB,CAC1G,CAAA;IACH,CAAC;IAED,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function interactForEndpointSelection(): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { assertMutable, selectEndpoint, selectFakeEndpoint, } from '../auth/operations.js';
|
|
3
|
+
import { getConfigStore } from '../config/index.js';
|
|
4
|
+
import { resolveAuth } from '../context.js';
|
|
5
|
+
import { getOutput } from '../output/get-output.js';
|
|
6
|
+
import { promptAutocomplete, promptText } from '../prompt.js';
|
|
7
|
+
export async function interactForEndpointSelection() {
|
|
8
|
+
const config = getConfigStore();
|
|
9
|
+
assertMutable(resolveAuth(config), 'endpoint', 'select an endpoint');
|
|
10
|
+
const endpoints = [
|
|
11
|
+
'http://localhost:3020',
|
|
12
|
+
'https://connect.getseam.com',
|
|
13
|
+
'https://fakeseamconnect.seam.vc',
|
|
14
|
+
];
|
|
15
|
+
// Searchable, as selecting a device or a command is.
|
|
16
|
+
const endpoint = await promptAutocomplete({
|
|
17
|
+
message: 'Select an endpoint:',
|
|
18
|
+
choices: endpoints.map((endpoint) => ({
|
|
19
|
+
label: endpoint,
|
|
20
|
+
value: endpoint,
|
|
21
|
+
})),
|
|
22
|
+
});
|
|
23
|
+
const output = getOutput();
|
|
24
|
+
if (endpoint === endpoints[2]) {
|
|
25
|
+
let userUrlSeed = await promptText({
|
|
26
|
+
message: 'You can input a custom endpoint URL or leave this field empty to use a new fakeserver.',
|
|
27
|
+
});
|
|
28
|
+
if (userUrlSeed.trim().length === 0) {
|
|
29
|
+
userUrlSeed = randomBytes(5).toString('hex');
|
|
30
|
+
}
|
|
31
|
+
selectFakeEndpoint({ urlSeed: userUrlSeed, config });
|
|
32
|
+
output.info(`PAT set to use fakeseamconnect with "seam_apikey1_token"`);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
selectEndpoint(endpoint, config);
|
|
36
|
+
}
|
|
37
|
+
output.info(`Endpoint set to ${endpoint}`);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=endpoint-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint-selection.js","sourceRoot":"","sources":["../../src/lib/interactions/endpoint-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,EACL,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE9D,MAAM,CAAC,KAAK,UAAU,4BAA4B;IAChD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAC/B,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAA;IAEpE,MAAM,SAAS,GAAG;QAChB,uBAAuB;QACvB,6BAA6B;QAC7B,iCAAiC;KAClC,CAAA;IAED,qDAAqD;IACrD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC;QACxC,OAAO,EAAE,qBAAqB;QAC9B,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACpC,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;KACJ,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,IAAI,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9B,IAAI,WAAW,GAAG,MAAM,UAAU,CAAC;YACjC,OAAO,EACL,wFAAwF;SAC3F,CAAC,CAAA;QAEF,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC9C,CAAC;QACD,kBAAkB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAA;QACpD,MAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAA;IACzE,CAAC;SAAM,CAAC;QACN,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAClC,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAA;AAC5C,CAAC"}
|
|
@@ -10,9 +10,9 @@ export * from './command-selection.js';
|
|
|
10
10
|
export * from './connected-account.js';
|
|
11
11
|
export * from './custom-metadata.js';
|
|
12
12
|
export * from './device.js';
|
|
13
|
+
export * from './endpoint-selection.js';
|
|
13
14
|
export * from './login.js';
|
|
14
15
|
export * from './resource.js';
|
|
15
|
-
export * from './server-selection.js';
|
|
16
16
|
export * from './timestamp.js';
|
|
17
17
|
export * from './use-remote-api-defs.js';
|
|
18
18
|
export * from './user-identity.js';
|
|
@@ -10,9 +10,9 @@ export * from './command-selection.js';
|
|
|
10
10
|
export * from './connected-account.js';
|
|
11
11
|
export * from './custom-metadata.js';
|
|
12
12
|
export * from './device.js';
|
|
13
|
+
export * from './endpoint-selection.js';
|
|
13
14
|
export * from './login.js';
|
|
14
15
|
export * from './resource.js';
|
|
15
|
-
export * from './server-selection.js';
|
|
16
16
|
export * from './timestamp.js';
|
|
17
17
|
export * from './use-remote-api-defs.js';
|
|
18
18
|
export * from './user-identity.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/interactions/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,0BAA0B,CAAA;AACxC,cAAc,YAAY,CAAA;AAC1B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/interactions/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,0BAA0B,CAAA;AACxC,cAAc,YAAY,CAAA;AAC1B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,yBAAyB,CAAA;AACvC,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA"}
|
|
@@ -14,8 +14,8 @@ export const interactForLogin = async () => {
|
|
|
14
14
|
const auth = resolveAuth(config);
|
|
15
15
|
// Refuse before prompting: nothing typed here could be stored.
|
|
16
16
|
assertMutable(auth, 'token', 'log in');
|
|
17
|
-
if (auth.
|
|
18
|
-
output.info(`You're using a local Seam Connect instance, you can enter the API Key to your local user, you can create a new user from:\n\n${auth.
|
|
17
|
+
if (auth.endpoint.includes('localhost')) {
|
|
18
|
+
output.info(`You're using a local Seam Connect instance, you can enter the API Key to your local user, you can create a new user from:\n\n${auth.endpoint}/admin/create_user_with_api_key`);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
output.info(`To login, navigate to the URL below and create a new Personal Access Token (PAT) and paste the PAT in the provided box:\n\nhttps://console.seam.co/settings/access-tokens\n\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/lib/interactions/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AACvE,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;IACzC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAC/B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAEhC,+DAA+D;IAC/D,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IAEtC,IAAI,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/lib/interactions/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AACvE,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;IACzC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAC/B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAEhC,+DAA+D;IAC/D,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IAEtC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CACT,gIAAgI,IAAI,CAAC,QAAQ,iCAAiC,CAC/K,CAAA;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CACT,+KAA+K,CAChL,CAAA;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CACT,KAAK,CAAC,IAAI,CACR,mEAAmE,CACpE,CACF,CAAA;IAED,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;QAC3B,OAAO,EAAE,wBAAwB;KAClC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAExB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;IACtC,CAAC;IAED,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAA;IACrC,CAAC;SAAM,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,WAAW,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAA;IACxE,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAA;IACH,CAAC;IAED,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IACzB,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;AAC1D,CAAC,CAAA"}
|
|
@@ -11,7 +11,7 @@ export const interactForWorkspaceId = async (personalAccessToken) => {
|
|
|
11
11
|
assertMutable(resolveAuth(config), 'workspaceId', 'select a workspace');
|
|
12
12
|
const seam = personalAccessToken
|
|
13
13
|
? SeamHttpWithoutWorkspace.fromPersonalAccessToken(personalAccessToken, {
|
|
14
|
-
endpoint: resolveAuth(config).
|
|
14
|
+
endpoint: resolveAuth(config).endpoint,
|
|
15
15
|
})
|
|
16
16
|
: await getSeamMultiWorkspace();
|
|
17
17
|
const workspaces = await withLoading('Fetching workspaces...', () => seam.workspaces.list());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-id.js","sourceRoot":"","sources":["../../src/lib/interactions/workspace-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,mBAA4B,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAE/B,kEAAkE;IAClE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAA;IAEvE,MAAM,IAAI,GAAG,mBAAmB;QAC9B,CAAC,CAAC,wBAAwB,CAAC,uBAAuB,CAAC,mBAAmB,EAAE;YACpE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"workspace-id.js","sourceRoot":"","sources":["../../src/lib/interactions/workspace-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,mBAA4B,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;IAE/B,kEAAkE;IAClE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAA;IAEvE,MAAM,IAAI,GAAG,mBAAmB;QAC9B,CAAC,CAAC,wBAAwB,CAAC,uBAAuB,CAAC,mBAAmB,EAAE;YACpE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ;SACvC,CAAC;QACJ,CAAC,CAAC,MAAM,qBAAqB,EAAE,CAAA;IAEjC,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAClE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CACvB,CAAA;IACD,yEAAyE;IACzE,wCAAwC;IACxC,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAS;QACnD,OAAO,EAAE,qBAAqB;QAC9B,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,SAAc,EAAE,EAAE,CAAC,CAAC;YAC3C,KAAK,EAAE,SAAS,CAAC,IAAI;YACrB,KAAK,EAAE,SAAS,CAAC,YAAY;YAC7B,IAAI,EAAE,SAAS,CAAC,YAAY;SAC7B,CAAC,CAAC;KACJ,CAAC,CAAA;IAEF,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IACpC,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA"}
|
package/lib/version.d.ts
CHANGED
package/lib/version.js
CHANGED
package/package.json
CHANGED
package/src/bin/cli.ts
CHANGED
|
@@ -122,12 +122,12 @@ async function cli(args: ParsedArgs, argv: string[]) {
|
|
|
122
122
|
const localCommand = findLocalCommand(args._)
|
|
123
123
|
|
|
124
124
|
// Commands declared not to need a token bypass the login gate. A partial
|
|
125
|
-
// path keeps the historical rule: only login and select
|
|
125
|
+
// path keeps the historical rule: only login and select endpoint may be
|
|
126
126
|
// reached logged out.
|
|
127
127
|
const requiresAuth =
|
|
128
128
|
localCommand != null
|
|
129
129
|
? localCommand.requiresAuth
|
|
130
|
-
: !(args._[0] === 'login' || isEqual(args._, ['select', '
|
|
130
|
+
: !(args._[0] === 'login' || isEqual(args._, ['select', 'endpoint']))
|
|
131
131
|
|
|
132
132
|
if (requiresAuth && resolveAuth(config).token == null) {
|
|
133
133
|
output.error(`Not logged in. Please run "seam login" or set ${tokenEnvVar}`)
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import { validateToken } from './validate-token.js'
|
|
13
13
|
|
|
14
14
|
/** A stored auth setting an environment variable may override. */
|
|
15
|
-
export type AuthSetting = '
|
|
15
|
+
export type AuthSetting = 'endpoint' | 'token' | 'workspaceId'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Refuse to store a setting the environment overrides.
|
|
@@ -29,10 +29,10 @@ export const assertMutable = (
|
|
|
29
29
|
action: string,
|
|
30
30
|
): void => {
|
|
31
31
|
const { envVar, source, value } = {
|
|
32
|
-
|
|
32
|
+
endpoint: {
|
|
33
33
|
envVar: endpointEnvVar,
|
|
34
|
-
source: auth.
|
|
35
|
-
value: auth.
|
|
34
|
+
source: auth.endpointSource,
|
|
35
|
+
value: auth.endpoint,
|
|
36
36
|
},
|
|
37
37
|
token: { envVar: tokenEnvVar, source: auth.tokenSource, value: auth.token },
|
|
38
38
|
workspaceId: {
|
|
@@ -47,7 +47,7 @@ export const assertMutable = (
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
export interface LoginOptions {
|
|
50
|
-
|
|
50
|
+
endpoint?: string | undefined
|
|
51
51
|
token?: string | undefined
|
|
52
52
|
workspaceId?: string | undefined
|
|
53
53
|
}
|
|
@@ -55,13 +55,13 @@ export interface LoginOptions {
|
|
|
55
55
|
/**
|
|
56
56
|
* Store the given credentials, validating the token first.
|
|
57
57
|
*
|
|
58
|
-
* The token is stored under the
|
|
59
|
-
*
|
|
58
|
+
* The token is stored under the endpoint it will be used with, so a given
|
|
59
|
+
* endpoint is stored and re-resolved before the token key is derived.
|
|
60
60
|
*
|
|
61
61
|
* Validation reaches the network, so a test may inject its own `validate`.
|
|
62
62
|
*/
|
|
63
63
|
export const login = async (
|
|
64
|
-
{
|
|
64
|
+
{ endpoint, token, workspaceId }: LoginOptions,
|
|
65
65
|
config: ConfigStore = getConfigStore(),
|
|
66
66
|
validate: typeof validateToken = validateToken,
|
|
67
67
|
): Promise<void> => {
|
|
@@ -70,20 +70,19 @@ export const login = async (
|
|
|
70
70
|
// Nothing is stored while the environment overrides it, so refuse before
|
|
71
71
|
// storing anything rather than part way through.
|
|
72
72
|
assertMutable(auth, 'token', 'log in')
|
|
73
|
-
if (
|
|
73
|
+
if (endpoint != null) assertMutable(auth, 'endpoint', 'select an endpoint')
|
|
74
74
|
if (workspaceId != null) {
|
|
75
75
|
assertMutable(auth, 'workspaceId', 'select a workspace')
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
config.delete('current_workspace_id')
|
|
78
|
+
if (endpoint != null) {
|
|
79
|
+
storeEndpoint(endpoint, config)
|
|
81
80
|
auth = resolveAuth(config)
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
if (token != null) {
|
|
85
84
|
await validate(token, workspaceId)
|
|
86
|
-
config.set(`${auth.
|
|
85
|
+
config.set(`${auth.endpoint}.pat`, token)
|
|
87
86
|
config.delete('current_workspace_id')
|
|
88
87
|
}
|
|
89
88
|
|
|
@@ -92,39 +91,38 @@ export const login = async (
|
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
/** Store the token for the current
|
|
94
|
+
/** Store the token for the current endpoint, e.g., one just prompted for. */
|
|
96
95
|
export const storeToken = (
|
|
97
96
|
token: string,
|
|
98
97
|
config: ConfigStore = getConfigStore(),
|
|
99
98
|
): void => {
|
|
100
99
|
const auth = resolveAuth(config)
|
|
101
100
|
assertMutable(auth, 'token', 'log in')
|
|
102
|
-
config.set(`${auth.
|
|
101
|
+
config.set(`${auth.endpoint}.pat`, token)
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
/** Remove the stored token and workspace selection. */
|
|
106
105
|
export const logout = (config: ConfigStore = getConfigStore()): void => {
|
|
107
106
|
const auth = resolveAuth(config)
|
|
108
107
|
assertMutable(auth, 'token', 'log out')
|
|
109
|
-
config.delete(`${auth.
|
|
110
|
-
// Configs written before tokens were stored per
|
|
108
|
+
config.delete(`${auth.endpoint}.pat`)
|
|
109
|
+
// Configs written before tokens were stored per endpoint may still hold an
|
|
111
110
|
// un-namespaced token, so drop that too.
|
|
112
111
|
config.delete('pat')
|
|
113
112
|
config.delete('current_workspace_id')
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
/**
|
|
117
|
-
* Store the
|
|
116
|
+
* Store the endpoint to make requests against.
|
|
118
117
|
*
|
|
119
|
-
* The workspace selection belongs to the previous
|
|
118
|
+
* The workspace selection belongs to the previous endpoint, so it is cleared.
|
|
120
119
|
*/
|
|
121
|
-
export const
|
|
122
|
-
|
|
120
|
+
export const selectEndpoint = (
|
|
121
|
+
endpoint: string,
|
|
123
122
|
config: ConfigStore = getConfigStore(),
|
|
124
123
|
): void => {
|
|
125
|
-
assertMutable(resolveAuth(config), '
|
|
126
|
-
|
|
127
|
-
config.delete('current_workspace_id')
|
|
124
|
+
assertMutable(resolveAuth(config), 'endpoint', 'select an endpoint')
|
|
125
|
+
storeEndpoint(endpoint, config)
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
/** Store the workspace requests are made against. */
|
|
@@ -137,33 +135,43 @@ export const selectWorkspace = (
|
|
|
137
135
|
}
|
|
138
136
|
|
|
139
137
|
/**
|
|
140
|
-
* Point the CLI at a fake Seam Connect
|
|
141
|
-
* token it accepts. Returns the generated
|
|
138
|
+
* Point the CLI at a fake Seam Connect endpoint and store the well-known
|
|
139
|
+
* token it accepts. Returns the generated endpoint URL for reporting.
|
|
142
140
|
*/
|
|
143
|
-
export const
|
|
141
|
+
export const selectFakeEndpoint = ({
|
|
144
142
|
urlSeed = randomBytes(5).toString('hex'),
|
|
145
143
|
config = getConfigStore(),
|
|
146
144
|
}: {
|
|
147
145
|
urlSeed?: string
|
|
148
146
|
config?: ConfigStore
|
|
149
|
-
} = {}): {
|
|
147
|
+
} = {}): { endpoint: string; token: string } => {
|
|
150
148
|
const auth = resolveAuth(config)
|
|
151
|
-
assertMutable(auth, '
|
|
149
|
+
assertMutable(auth, 'endpoint', 'select an endpoint')
|
|
152
150
|
assertMutable(auth, 'token', 'log in')
|
|
153
151
|
|
|
154
|
-
const
|
|
152
|
+
const endpoint = `https://${urlSeed}.fakeseamconnect.seam.vc`
|
|
155
153
|
const token = 'seam_apikey1_token'
|
|
156
|
-
|
|
157
|
-
config.set(`${
|
|
158
|
-
config.delete('current_workspace_id')
|
|
154
|
+
storeEndpoint(endpoint, config)
|
|
155
|
+
config.set(`${endpoint}.pat`, token)
|
|
159
156
|
|
|
160
|
-
return {
|
|
157
|
+
return { endpoint, token }
|
|
161
158
|
}
|
|
162
159
|
|
|
163
|
-
/** Store whether API definitions come from the
|
|
160
|
+
/** Store whether API definitions come from the endpoint instead of npm. */
|
|
164
161
|
export const setUseRemoteApiDefs = (
|
|
165
162
|
useRemoteApiDefs: boolean,
|
|
166
163
|
config: ConfigStore = getConfigStore(),
|
|
167
164
|
): void => {
|
|
168
165
|
config.set('use_remote_api_defs', useRemoteApiDefs)
|
|
169
166
|
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Write the endpoint, dropping what belonged to the previous one: the
|
|
170
|
+
* workspace selection, and any value left under the legacy `server` key that
|
|
171
|
+
* {@link resolveAuth} would otherwise still fall back to.
|
|
172
|
+
*/
|
|
173
|
+
const storeEndpoint = (endpoint: string, config: ConfigStore): void => {
|
|
174
|
+
config.set('endpoint', endpoint)
|
|
175
|
+
config.delete('server')
|
|
176
|
+
config.delete('current_workspace_id')
|
|
177
|
+
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { resolveAuth } from 'lib/context.js'
|
|
9
9
|
|
|
10
10
|
export const validateToken = async (token: string, workspaceId?: string) => {
|
|
11
|
-
const options = { endpoint: resolveAuth().
|
|
11
|
+
const options = { endpoint: resolveAuth().endpoint }
|
|
12
12
|
|
|
13
13
|
if (isPersonalAccessToken(token)) {
|
|
14
14
|
const seam = workspaceId
|
|
@@ -7,7 +7,7 @@ export type ApiBlueprint = Blueprint
|
|
|
7
7
|
|
|
8
8
|
export interface GetApiBlueprintOptions {
|
|
9
9
|
/**
|
|
10
|
-
* Build from the OpenAPI document the configured
|
|
10
|
+
* Build from the OpenAPI document the configured endpoint is currently
|
|
11
11
|
* running, instead of the published npm types.
|
|
12
12
|
*/
|
|
13
13
|
useRemoteDefinitions?: boolean
|
|
@@ -19,8 +19,8 @@ export const getApiBlueprint = async ({
|
|
|
19
19
|
useRemoteDefinitions = false,
|
|
20
20
|
update = false,
|
|
21
21
|
}: GetApiBlueprintOptions = {}): Promise<ApiBlueprint> => {
|
|
22
|
-
// Remote definitions describe whatever the
|
|
23
|
-
// build them directly from
|
|
22
|
+
// Remote definitions describe whatever the endpoint is currently running, so
|
|
23
|
+
// build them directly from that endpoint's OpenAPI document.
|
|
24
24
|
if (useRemoteDefinitions) return await createRemoteBlueprint()
|
|
25
25
|
|
|
26
26
|
return await getBlueprint({ update })
|
|
@@ -3,15 +3,15 @@ import type { Blueprint } from '@seamapi/blueprint'
|
|
|
3
3
|
import { resolveAuth } from 'lib/context.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Build a blueprint from the OpenAPI document the current
|
|
7
|
-
* describing exactly what that
|
|
6
|
+
* Build a blueprint from the OpenAPI document the current endpoint is running,
|
|
7
|
+
* describing exactly what that endpoint accepts rather than what is published.
|
|
8
8
|
*/
|
|
9
9
|
export const createRemoteBlueprint = async (): Promise<Blueprint> => {
|
|
10
10
|
const [{ createBlueprint }, { getOpenapiSchema }] = await Promise.all([
|
|
11
11
|
import('@seamapi/blueprint'),
|
|
12
12
|
import('@seamapi/http/connect'),
|
|
13
13
|
])
|
|
14
|
-
const openapi = await getOpenapiSchema(resolveAuth().
|
|
14
|
+
const openapi = await getOpenapiSchema(resolveAuth().endpoint)
|
|
15
15
|
|
|
16
16
|
return await createBlueprint({ openapi }, { omitUndocumented: true })
|
|
17
17
|
}
|
|
@@ -12,17 +12,17 @@ export const loginCommand: Command = {
|
|
|
12
12
|
description:
|
|
13
13
|
'Prompts for a personal access token unless one is passed with --token.',
|
|
14
14
|
flags: [
|
|
15
|
-
stringFlag('
|
|
15
|
+
stringFlag('endpoint', 'Seam API endpoint to log in to.'),
|
|
16
16
|
stringFlag('token', 'Personal access token to log in with.'),
|
|
17
17
|
stringFlag('workspace-id', 'Workspace to select after logging in.'),
|
|
18
18
|
],
|
|
19
19
|
},
|
|
20
20
|
requiresAuth: false,
|
|
21
21
|
execute: async ({ args }, ctx) => {
|
|
22
|
-
if (args['token'] || args['workspace_id'] || args['
|
|
22
|
+
if (args['token'] || args['workspace_id'] || args['endpoint']) {
|
|
23
23
|
await login(
|
|
24
24
|
{
|
|
25
|
-
|
|
25
|
+
endpoint: args['endpoint'] ? args['endpoint'] : undefined,
|
|
26
26
|
token: args['token'] ? String(args['token']).trim() : undefined,
|
|
27
27
|
workspaceId: args['workspace_id'] ? args['workspace_id'] : undefined,
|
|
28
28
|
},
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { assertMutable, selectEndpoint } from 'lib/auth/operations.js'
|
|
2
|
+
import type { Command } from 'lib/commands/registry.js'
|
|
3
|
+
import { stringFlag } from 'lib/commands/spec.js'
|
|
4
|
+
import { NonInteractiveError } from 'lib/errors.js'
|
|
5
|
+
import { interactForEndpointSelection } from 'lib/interactions/index.js'
|
|
6
|
+
|
|
7
|
+
export const selectEndpointCommand: Command = {
|
|
8
|
+
definition: {
|
|
9
|
+
path: ['select', 'endpoint'],
|
|
10
|
+
kind: 'cli',
|
|
11
|
+
title: 'Select the Seam API endpoint.',
|
|
12
|
+
description: '',
|
|
13
|
+
flags: [stringFlag('endpoint', 'Seam API endpoint to select.')],
|
|
14
|
+
},
|
|
15
|
+
requiresAuth: false,
|
|
16
|
+
execute: async ({ args }, ctx) => {
|
|
17
|
+
assertMutable(ctx.auth, 'endpoint', 'select an endpoint')
|
|
18
|
+
if (args['endpoint']) {
|
|
19
|
+
selectEndpoint(args['endpoint'], ctx.config)
|
|
20
|
+
return { kind: 'done' }
|
|
21
|
+
}
|
|
22
|
+
if (ctx.interactivity === 'non-interactive') {
|
|
23
|
+
throw new NonInteractiveError(
|
|
24
|
+
'Missing required parameter for select endpoint: --endpoint',
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
await interactForEndpointSelection()
|
|
28
|
+
return { kind: 'done' }
|
|
29
|
+
},
|
|
30
|
+
}
|
|
@@ -7,12 +7,11 @@ import type { CliContext } from 'lib/context.js'
|
|
|
7
7
|
import { executeApiCommand } from './api-command.js'
|
|
8
8
|
import { createCompletionCommands } from './local/completion.js'
|
|
9
9
|
import { configRevealLocationCommand } from './local/config-reveal-location.js'
|
|
10
|
-
import { configSetFakeServerCommand } from './local/config-set-fake-server.js'
|
|
11
10
|
import { configUseRemoteApiDefsCommand } from './local/config-use-remote-api-defs.js'
|
|
12
11
|
import { healthCommand } from './local/health.js'
|
|
13
12
|
import { loginCommand } from './local/login.js'
|
|
14
13
|
import { logoutCommand } from './local/logout.js'
|
|
15
|
-
import {
|
|
14
|
+
import { selectEndpointCommand } from './local/select-endpoint.js'
|
|
16
15
|
import { selectWorkspaceCommand } from './local/select-workspace.js'
|
|
17
16
|
import { wizardCommand } from './local/wizard.js'
|
|
18
17
|
import {
|
|
@@ -72,12 +71,11 @@ const completionCommands = createCompletionCommands(
|
|
|
72
71
|
export const localCommands: Command[] = [
|
|
73
72
|
...completionCommands,
|
|
74
73
|
configRevealLocationCommand,
|
|
75
|
-
configSetFakeServerCommand,
|
|
76
74
|
configUseRemoteApiDefsCommand,
|
|
77
75
|
healthCommand,
|
|
78
76
|
loginCommand,
|
|
79
77
|
logoutCommand,
|
|
80
|
-
|
|
78
|
+
selectEndpointCommand,
|
|
81
79
|
selectWorkspaceCommand,
|
|
82
80
|
wizardCommand,
|
|
83
81
|
]
|
package/src/lib/context.ts
CHANGED
|
@@ -9,21 +9,21 @@ import {
|
|
|
9
9
|
import type { SeamApi } from './http/api.js'
|
|
10
10
|
import type { Output } from './output/output.js'
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const defaultEndpoint = 'https://connect.getseam.com'
|
|
13
13
|
|
|
14
14
|
/** Where a resolved value came from, e.g., to refuse writes the env shadows. */
|
|
15
15
|
export type ValueSource = 'env' | 'config' | 'default'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* The
|
|
18
|
+
* The endpoint, token, and workspace requests are made with.
|
|
19
19
|
*
|
|
20
20
|
* Resolved in one place so the precedence rule exists once: an environment
|
|
21
|
-
* variable wins over the stored value, and the
|
|
21
|
+
* variable wins over the stored value, and the endpoint falls back to Seam.
|
|
22
22
|
* The source tags say where each value came from.
|
|
23
23
|
*/
|
|
24
24
|
export interface AuthContext {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
endpoint: string
|
|
26
|
+
endpointSource: ValueSource
|
|
27
27
|
token: string | null
|
|
28
28
|
tokenSource: Exclude<ValueSource, 'default'> | null
|
|
29
29
|
workspaceId: string | null
|
|
@@ -33,21 +33,25 @@ export interface AuthContext {
|
|
|
33
33
|
export const resolveAuth = (
|
|
34
34
|
config: ConfigStore = getConfigStore(),
|
|
35
35
|
): AuthContext => {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const envEndpoint = getEndpointFromEnv()
|
|
37
|
+
// Configs written before the endpoint was called one still hold it under
|
|
38
|
+
// `server`, so fall back to that key rather than silently resetting them.
|
|
39
|
+
const storedEndpoint = config.get('endpoint') ?? config.get('server')
|
|
40
|
+
const endpoint =
|
|
41
|
+
envEndpoint ?? (typeof storedEndpoint === 'string' ? storedEndpoint : null)
|
|
40
42
|
|
|
41
43
|
const envToken = getTokenFromEnv()
|
|
42
|
-
const storedToken = readString(
|
|
44
|
+
const storedToken = readString(
|
|
45
|
+
config.get(`${endpoint ?? defaultEndpoint}.pat`),
|
|
46
|
+
)
|
|
43
47
|
|
|
44
48
|
const envWorkspaceId = getWorkspaceIdFromEnv()
|
|
45
49
|
const storedWorkspaceId = readString(config.get('current_workspace_id'))
|
|
46
50
|
|
|
47
51
|
return {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
endpoint: endpoint ?? defaultEndpoint,
|
|
53
|
+
endpointSource:
|
|
54
|
+
envEndpoint != null ? 'env' : endpoint != null ? 'config' : 'default',
|
|
51
55
|
token: envToken ?? storedToken,
|
|
52
56
|
tokenSource:
|
|
53
57
|
envToken != null ? 'env' : storedToken != null ? 'config' : null,
|
package/src/lib/env.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Credentials and the
|
|
2
|
+
* Credentials and the endpoint may be given in the environment.
|
|
3
3
|
*
|
|
4
4
|
* Each variable overrides the corresponding stored value for as long as it
|
|
5
5
|
* is set, so any of them may be used per command or per shell. Commands that
|
|
@@ -12,7 +12,7 @@ export const tokenEnvVar = 'SEAM_CLI_TOKEN'
|
|
|
12
12
|
/** Overrides the workspace stored by `seam select workspace`. */
|
|
13
13
|
export const workspaceIdEnvVar = 'SEAM_CLI_WORKSPACE_ID'
|
|
14
14
|
|
|
15
|
-
/** Overrides the
|
|
15
|
+
/** Overrides the endpoint stored by `seam select endpoint`. */
|
|
16
16
|
export const endpointEnvVar = 'SEAM_CLI_ENDPOINT'
|
|
17
17
|
|
|
18
18
|
/** Every variable read here is declared on `ProcessEnv` in `env.d.ts`. */
|
package/src/lib/http/client.ts
CHANGED
|
@@ -13,7 +13,7 @@ export const getSeam = async (
|
|
|
13
13
|
): Promise<SeamHttp> => {
|
|
14
14
|
const token = getRequiredToken(auth)
|
|
15
15
|
|
|
16
|
-
const options = { endpoint: auth.
|
|
16
|
+
const options = { endpoint: auth.endpoint }
|
|
17
17
|
|
|
18
18
|
if (isPersonalAccessToken(token)) {
|
|
19
19
|
return SeamHttp.fromPersonalAccessToken(
|
|
@@ -38,7 +38,7 @@ export const getSeamMultiWorkspace = async (
|
|
|
38
38
|
auth: AuthContext = resolveAuth(),
|
|
39
39
|
): Promise<SeamHttpWithoutWorkspace | SeamHttp> => {
|
|
40
40
|
const token = getRequiredToken(auth)
|
|
41
|
-
const options = { endpoint: auth.
|
|
41
|
+
const options = { endpoint: auth.endpoint }
|
|
42
42
|
|
|
43
43
|
if (isPersonalAccessToken(token)) {
|
|
44
44
|
return SeamHttpWithoutWorkspace.fromPersonalAccessToken(token, options)
|