@credibledata/cred-cli 0.1.4 → 0.1.5

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.
Files changed (172) hide show
  1. package/.prettierignore +2 -1
  2. package/README.md +0 -2
  3. package/bun.lock +182 -283
  4. package/dist/client/api.js +796 -111
  5. package/dist/client/api.js.map +1 -1
  6. package/dist/clientconfiguration.js +55 -13
  7. package/dist/clientconfiguration.js.map +1 -1
  8. package/dist/clientconfiguration.spec.js +305 -16
  9. package/dist/clientconfiguration.spec.js.map +1 -1
  10. package/dist/commands/add.js +6 -3
  11. package/dist/commands/add.js.map +1 -1
  12. package/dist/commands/connection/createconnections.js +18 -3
  13. package/dist/commands/connection/createconnections.js.map +1 -1
  14. package/dist/commands/connection/createconnections.spec.js +219 -0
  15. package/dist/commands/connection/createconnections.spec.js.map +1 -0
  16. package/dist/commands/connection/deleteconnection.spec.js +130 -0
  17. package/dist/commands/connection/deleteconnection.spec.js.map +1 -0
  18. package/dist/commands/connection/listconnections.js +9 -3
  19. package/dist/commands/connection/listconnections.js.map +1 -1
  20. package/dist/commands/connection/listconnections.spec.js +117 -0
  21. package/dist/commands/connection/listconnections.spec.js.map +1 -0
  22. package/dist/commands/group/addmember.js +2 -0
  23. package/dist/commands/group/addmember.js.map +1 -1
  24. package/dist/commands/group/addmember.spec.js +148 -0
  25. package/dist/commands/group/addmember.spec.js.map +1 -0
  26. package/dist/commands/group/creategroup.spec.js +122 -0
  27. package/dist/commands/group/creategroup.spec.js.map +1 -0
  28. package/dist/commands/group/deletegroup.spec.js +104 -0
  29. package/dist/commands/group/deletegroup.spec.js.map +1 -0
  30. package/dist/commands/group/getgroup.spec.js +111 -0
  31. package/dist/commands/group/getgroup.spec.js.map +1 -0
  32. package/dist/commands/group/listgroups.spec.js +118 -0
  33. package/dist/commands/group/listgroups.spec.js.map +1 -0
  34. package/dist/commands/group/removemember.js +1 -0
  35. package/dist/commands/group/removemember.js.map +1 -1
  36. package/dist/commands/group/removemember.spec.js +138 -0
  37. package/dist/commands/group/removemember.spec.js.map +1 -0
  38. package/dist/commands/groupaccesstoken/createToken.js +6 -2
  39. package/dist/commands/groupaccesstoken/createToken.js.map +1 -1
  40. package/dist/commands/groupaccesstoken/createToken.spec.js +127 -0
  41. package/dist/commands/groupaccesstoken/createToken.spec.js.map +1 -0
  42. package/dist/commands/groupaccesstoken/deleteToken.js.map +1 -1
  43. package/dist/commands/groupaccesstoken/deleteToken.spec.js +103 -0
  44. package/dist/commands/groupaccesstoken/deleteToken.spec.js.map +1 -0
  45. package/dist/commands/groupaccesstoken/groupContainer.js.map +1 -1
  46. package/dist/commands/groupaccesstoken/listTokens.js.map +1 -1
  47. package/dist/commands/groupaccesstoken/listTokens.spec.js +115 -0
  48. package/dist/commands/groupaccesstoken/listTokens.spec.js.map +1 -0
  49. package/dist/commands/list.js +10 -3
  50. package/dist/commands/list.js.map +1 -1
  51. package/dist/commands/misc/login.js +146 -22
  52. package/dist/commands/misc/login.js.map +1 -1
  53. package/dist/commands/misc/login.spec.js +111 -6
  54. package/dist/commands/misc/login.spec.js.map +1 -1
  55. package/dist/commands/misc/logout.spec.js +30 -0
  56. package/dist/commands/misc/logout.spec.js.map +1 -0
  57. package/dist/commands/misc/loopbackOAuth.js +110 -0
  58. package/dist/commands/misc/loopbackOAuth.js.map +1 -0
  59. package/dist/commands/misc/set-access-token.js.map +1 -1
  60. package/dist/commands/misc/set-access-token.spec.js +65 -0
  61. package/dist/commands/misc/set-access-token.spec.js.map +1 -0
  62. package/dist/commands/package/deletepackage.spec.js +136 -0
  63. package/dist/commands/package/deletepackage.spec.js.map +1 -0
  64. package/dist/commands/package/listpackages.js +10 -5
  65. package/dist/commands/package/listpackages.js.map +1 -1
  66. package/dist/commands/package/listpackages.spec.js +129 -0
  67. package/dist/commands/package/listpackages.spec.js.map +1 -0
  68. package/dist/commands/package/publish.js +23 -0
  69. package/dist/commands/package/publish.js.map +1 -1
  70. package/dist/commands/package/publish.spec.js +511 -0
  71. package/dist/commands/package/publish.spec.js.map +1 -0
  72. package/dist/commands/package/updatepackage.spec.js +50 -0
  73. package/dist/commands/package/updatepackage.spec.js.map +1 -1
  74. package/dist/commands/project/createproject.js +11 -1
  75. package/dist/commands/project/createproject.js.map +1 -1
  76. package/dist/commands/project/createproject.spec.js +154 -0
  77. package/dist/commands/project/createproject.spec.js.map +1 -0
  78. package/dist/commands/project/deleteproject.spec.js +106 -0
  79. package/dist/commands/project/deleteproject.spec.js.map +1 -0
  80. package/dist/commands/project/getproject.spec.js +99 -0
  81. package/dist/commands/project/getproject.spec.js.map +1 -0
  82. package/dist/commands/project/listprojects.js +13 -7
  83. package/dist/commands/project/listprojects.js.map +1 -1
  84. package/dist/commands/project/listprojects.spec.js +111 -0
  85. package/dist/commands/project/listprojects.spec.js.map +1 -0
  86. package/dist/commands/project/setproject.spec.js +58 -0
  87. package/dist/commands/project/setproject.spec.js.map +1 -0
  88. package/dist/commands/project/updateproject.js +68 -0
  89. package/dist/commands/project/updateproject.js.map +1 -0
  90. package/dist/commands/project/updateproject.spec.js +129 -0
  91. package/dist/commands/project/updateproject.spec.js.map +1 -0
  92. package/dist/commands/rm.js.map +1 -1
  93. package/dist/commands/update.js +13 -0
  94. package/dist/commands/update.js.map +1 -1
  95. package/dist/commands/version/listversions.spec.js +121 -0
  96. package/dist/commands/version/listversions.spec.js.map +1 -0
  97. package/dist/common/UserGroupId.spec.js +92 -0
  98. package/dist/common/UserGroupId.spec.js.map +1 -0
  99. package/dist/constants.js +49 -13
  100. package/dist/constants.js.map +1 -1
  101. package/dist/index.js +40 -18
  102. package/dist/index.js.map +1 -1
  103. package/dist/logger.spec.js +125 -0
  104. package/dist/logger.spec.js.map +1 -0
  105. package/dist/polyfills/file.polyfill.js.map +1 -1
  106. package/dist/utils.js +59 -0
  107. package/dist/utils.js.map +1 -1
  108. package/dist/utils.spec.js +158 -0
  109. package/dist/utils.spec.js.map +1 -0
  110. package/docker/Dockerfile.ci +11 -3
  111. package/eslint.config.mjs +45 -0
  112. package/generate-client.sh +3 -0
  113. package/package.json +24 -16
  114. package/src/client/.openapi-generator/FILES +1 -0
  115. package/src/client/api.ts +1347 -161
  116. package/src/clientconfiguration.spec.ts +394 -20
  117. package/src/clientconfiguration.ts +74 -15
  118. package/src/commands/add.ts +15 -6
  119. package/src/commands/connection/createconnections.spec.ts +403 -0
  120. package/src/commands/connection/createconnections.ts +30 -5
  121. package/src/commands/connection/deleteconnection.spec.ts +189 -0
  122. package/src/commands/connection/listconnections.spec.ts +132 -0
  123. package/src/commands/connection/listconnections.ts +22 -3
  124. package/src/commands/group/addmember.spec.ts +257 -0
  125. package/src/commands/group/addmember.ts +2 -0
  126. package/src/commands/group/creategroup.spec.ts +146 -0
  127. package/src/commands/group/deletegroup.spec.ts +120 -0
  128. package/src/commands/group/getgroup.spec.ts +129 -0
  129. package/src/commands/group/listgroups.spec.ts +137 -0
  130. package/src/commands/group/removemember.spec.ts +224 -0
  131. package/src/commands/group/removemember.ts +1 -0
  132. package/src/commands/groupaccesstoken/createToken.spec.ts +211 -0
  133. package/src/commands/groupaccesstoken/createToken.ts +55 -51
  134. package/src/commands/groupaccesstoken/deleteToken.spec.ts +147 -0
  135. package/src/commands/groupaccesstoken/deleteToken.ts +16 -11
  136. package/src/commands/groupaccesstoken/groupContainer.ts +51 -51
  137. package/src/commands/groupaccesstoken/listTokens.spec.ts +147 -0
  138. package/src/commands/groupaccesstoken/listTokens.ts +16 -11
  139. package/src/commands/list.ts +50 -9
  140. package/src/commands/misc/login.spec.ts +91 -6
  141. package/src/commands/misc/login.ts +208 -25
  142. package/src/commands/misc/logout.spec.ts +32 -0
  143. package/src/commands/misc/loopbackOAuth.ts +127 -0
  144. package/src/commands/misc/set-access-token.spec.ts +95 -0
  145. package/src/commands/misc/set-access-token.ts +16 -16
  146. package/src/commands/package/deletepackage.spec.ts +164 -0
  147. package/src/commands/package/listpackages.spec.ts +147 -0
  148. package/src/commands/package/listpackages.ts +28 -5
  149. package/src/commands/package/publish.spec.ts +597 -0
  150. package/src/commands/package/publish.ts +32 -0
  151. package/src/commands/package/updatepackage.spec.ts +98 -0
  152. package/src/commands/project/createproject.spec.ts +247 -0
  153. package/src/commands/project/createproject.ts +12 -1
  154. package/src/commands/project/deleteproject.spec.ts +123 -0
  155. package/src/commands/project/getproject.spec.ts +109 -0
  156. package/src/commands/project/listprojects.spec.ts +121 -0
  157. package/src/commands/project/listprojects.ts +33 -7
  158. package/src/commands/project/setproject.spec.ts +63 -0
  159. package/src/commands/project/updateproject.spec.ts +217 -0
  160. package/src/commands/project/updateproject.ts +82 -0
  161. package/src/commands/rm.ts +1 -6
  162. package/src/commands/update.ts +24 -1
  163. package/src/commands/version/listversions.spec.ts +138 -0
  164. package/src/common/UserGroupId.spec.ts +117 -0
  165. package/src/constants.ts +59 -13
  166. package/src/index.ts +46 -20
  167. package/src/logger.spec.ts +158 -0
  168. package/src/polyfills/file.polyfill.ts +1 -0
  169. package/src/utils.spec.ts +135 -0
  170. package/src/utils.ts +81 -0
  171. package/tsconfig.json +15 -18
  172. package/.eslintrc +0 -33
@@ -0,0 +1,147 @@
1
+ import { expect } from "chai";
2
+ import sinon from "sinon";
3
+ import { GroupsApi } from "../../client/api";
4
+ import { ClientConfiguration } from "../../clientconfiguration";
5
+ import { logger } from "../../logger";
6
+ import { listGroupAccessTokens } from "./listTokens";
7
+
8
+ describe("list-group-access-tokens", () => {
9
+ let sandbox: sinon.SinonSandbox;
10
+ let listGroupAccessTokensStub: sinon.SinonStub;
11
+ let loggerStub: sinon.SinonStubbedInstance<typeof logger>;
12
+ let consoleLogStub: sinon.SinonStub;
13
+ let processExitStub: sinon.SinonStub;
14
+
15
+ beforeEach(() => {
16
+ sandbox = sinon.createSandbox();
17
+ listGroupAccessTokensStub = sandbox.stub();
18
+ loggerStub = sandbox.stub(logger);
19
+ consoleLogStub = sandbox.stub(console, "log");
20
+ processExitStub = sandbox.stub(process, "exit");
21
+
22
+ sandbox
23
+ .stub(ClientConfiguration.prototype, "getOrganization")
24
+ .returns("test-org");
25
+ sandbox
26
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
27
+ .returns(true);
28
+ sandbox
29
+ .stub(ClientConfiguration.prototype, "getAuthenticationHeader")
30
+ .returns("Bearer test-token");
31
+
32
+ sandbox
33
+ .stub(GroupsApi.prototype, "listGroupAccessTokens")
34
+ .callsFake(listGroupAccessTokensStub);
35
+ });
36
+
37
+ afterEach(() => {
38
+ sandbox.restore();
39
+ });
40
+
41
+ it("should list group access tokens successfully", async () => {
42
+ const mockTokens = [
43
+ { tokenName: "token1", createdAt: "2024-01-01" },
44
+ { tokenName: "token2", createdAt: "2024-01-02" },
45
+ ];
46
+ const mockResponse = {
47
+ data: mockTokens,
48
+ };
49
+ listGroupAccessTokensStub.resolves(mockResponse);
50
+
51
+ const result = await listGroupAccessTokens(
52
+ "http://test-server",
53
+ "test-group",
54
+ false,
55
+ );
56
+
57
+ expect(listGroupAccessTokensStub.calledOnce).to.be.true;
58
+ expect(listGroupAccessTokensStub.firstCall.args[0]).to.equal("test-org");
59
+ expect(listGroupAccessTokensStub.firstCall.args[1]).to.equal(
60
+ "test-group",
61
+ );
62
+ expect(consoleLogStub.called).to.be.true;
63
+ expect(
64
+ loggerStub.info.calledWith(
65
+ sinon.match("Group access tokens listed successfully"),
66
+ ),
67
+ ).to.be.true;
68
+ expect(result).to.deep.equal(mockTokens);
69
+ });
70
+
71
+ it("should handle missing config", async () => {
72
+ sandbox.restore();
73
+ sandbox = sinon.createSandbox();
74
+ listGroupAccessTokensStub = sandbox.stub();
75
+ loggerStub = sandbox.stub(logger);
76
+ consoleLogStub = sandbox.stub(console, "log");
77
+ processExitStub = sandbox.stub(process, "exit");
78
+
79
+ sandbox
80
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
81
+ .returns(false);
82
+ sandbox
83
+ .stub(GroupsApi.prototype, "listGroupAccessTokens")
84
+ .callsFake(listGroupAccessTokensStub);
85
+
86
+ const result = await listGroupAccessTokens(
87
+ "http://test-server",
88
+ "test-group",
89
+ false,
90
+ );
91
+
92
+ expect(listGroupAccessTokensStub.called).to.be.false;
93
+ expect(result).to.be.undefined;
94
+ expect(
95
+ loggerStub.error.calledWith(
96
+ sinon.match("Please, make sure that you are logged in"),
97
+ ),
98
+ ).to.be.true;
99
+ });
100
+
101
+ it("should handle missing organization", async () => {
102
+ sandbox.restore();
103
+ sandbox = sinon.createSandbox();
104
+ listGroupAccessTokensStub = sandbox.stub();
105
+ loggerStub = sandbox.stub(logger);
106
+ consoleLogStub = sandbox.stub(console, "log");
107
+ processExitStub = sandbox.stub(process, "exit");
108
+
109
+ sandbox
110
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
111
+ .returns(true);
112
+ sandbox
113
+ .stub(ClientConfiguration.prototype, "getOrganization")
114
+ .returns(undefined);
115
+ sandbox
116
+ .stub(GroupsApi.prototype, "listGroupAccessTokens")
117
+ .callsFake(listGroupAccessTokensStub);
118
+
119
+ const result = await listGroupAccessTokens(
120
+ "http://test-server",
121
+ "test-group",
122
+ false,
123
+ );
124
+
125
+ expect(listGroupAccessTokensStub.called).to.be.false;
126
+ expect(result).to.be.undefined;
127
+ expect(
128
+ loggerStub.error.calledWith(
129
+ sinon.match(
130
+ "No organization set. Please login or set an organization.",
131
+ ),
132
+ ),
133
+ ).to.be.true;
134
+ });
135
+
136
+ it("should handle API errors", async () => {
137
+ const mockError = new Error("API Error");
138
+ listGroupAccessTokensStub.rejects(mockError);
139
+
140
+ await listGroupAccessTokens("http://test-server", "test-group", true);
141
+
142
+ expect(listGroupAccessTokensStub.calledOnce).to.be.true;
143
+ expect(loggerStub.error.calledWith(sinon.match("Operation failed"))).to.be
144
+ .true;
145
+ expect(processExitStub.calledWith(1)).to.be.true;
146
+ });
147
+ });
@@ -2,23 +2,28 @@ import { logger } from "../../logger";
2
2
  import { withGroupContext } from "./groupContainer";
3
3
 
4
4
  export async function listGroupAccessTokens(
5
- controlPlane: string,
6
- groupName: string,
7
- debug: boolean,
5
+ controlPlane: string,
6
+ groupName: string,
7
+ debug: boolean,
8
8
  ) {
9
- return withGroupContext(controlPlane, async (context) => {
10
- const { organizationName, groupsApi, options } = context;
9
+ return withGroupContext(
10
+ controlPlane,
11
+ async (context) => {
12
+ const { organizationName, groupsApi, options } = context;
11
13
 
12
- logger.info(
14
+ logger.info(
13
15
  `Listing access tokens for group ${groupName} in organization ${organizationName}`,
14
- );
16
+ );
15
17
 
16
- const response = await groupsApi.listGroupAccessTokens(
18
+ const response = await groupsApi.listGroupAccessTokens(
17
19
  organizationName,
18
20
  groupName,
19
21
  options,
20
- );
22
+ );
21
23
 
22
- return response.data;
23
- }, "Group access tokens listed successfully", debug);
24
+ return response.data;
25
+ },
26
+ "Group access tokens listed successfully",
27
+ debug,
28
+ );
24
29
  }
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import { controlPlanesByEnv, Environment } from "../constants";
3
+ import { DEFAULT_PAGE_SIZE, DEFAULT_PAGE } from "../utils";
3
4
  import { listConnections } from "./connection/listconnections";
4
5
  import { printOutGroups } from "./group/listgroups";
5
6
  import { listGroupAccessTokens } from "./groupaccesstoken/listTokens";
@@ -21,8 +22,23 @@ export const registerListCommands = (
21
22
  .alias("projects")
22
23
  .description("List all projects.")
23
24
  .option("--debug")
25
+ .option(
26
+ "--page <number>",
27
+ `Page number (starts at ${DEFAULT_PAGE})`,
28
+ String(DEFAULT_PAGE),
29
+ )
30
+ .option(
31
+ "--page-size <number>",
32
+ `Items per page (default: all records, max: 500)`,
33
+ String(DEFAULT_PAGE_SIZE),
34
+ )
24
35
  .action((options) => {
25
- printOutProjects(controlPlanesByEnv[environment], options.debug);
36
+ printOutProjects(
37
+ controlPlanesByEnv[environment],
38
+ options.debug,
39
+ options.page,
40
+ options.pageSize,
41
+ );
26
42
  });
27
43
 
28
44
  list
@@ -30,8 +46,23 @@ export const registerListCommands = (
30
46
  .alias("connections")
31
47
  .description("List all connections.")
32
48
  .option("--debug")
49
+ .option(
50
+ "--page <number>",
51
+ `Page number (starts at ${DEFAULT_PAGE})`,
52
+ String(DEFAULT_PAGE),
53
+ )
54
+ .option(
55
+ "--page-size <number>",
56
+ `Items per page (default: all records, max: 500)`,
57
+ String(DEFAULT_PAGE_SIZE),
58
+ )
33
59
  .action((options) => {
34
- listConnections(controlPlanesByEnv[environment], options.debug);
60
+ listConnections(
61
+ controlPlanesByEnv[environment],
62
+ options.debug,
63
+ options.page,
64
+ options.pageSize,
65
+ );
35
66
  });
36
67
 
37
68
  list
@@ -39,8 +70,23 @@ export const registerListCommands = (
39
70
  .alias("packages")
40
71
  .description("List the packages in the active project.")
41
72
  .option("--debug")
73
+ .option(
74
+ "--page <number>",
75
+ `Page number (starts at ${DEFAULT_PAGE})`,
76
+ String(DEFAULT_PAGE),
77
+ )
78
+ .option(
79
+ "--page-size <number>",
80
+ `Items per page (default: all records, max: 500)`,
81
+ String(DEFAULT_PAGE_SIZE),
82
+ )
42
83
  .action((options) => {
43
- printOutPackages(controlPlanesByEnv[environment], options.debug);
84
+ printOutPackages(
85
+ controlPlanesByEnv[environment],
86
+ options.debug,
87
+ options.page,
88
+ options.pageSize,
89
+ );
44
90
  });
45
91
 
46
92
  list
@@ -69,15 +115,11 @@ export const registerListCommands = (
69
115
  printOutGroups(controlPlanesByEnv[environment], options.debug);
70
116
  });
71
117
 
72
-
73
118
  list
74
119
  .command("group-access-token")
75
120
  .alias("group-access-tokens")
76
121
  .description("List all access tokens for a group.")
77
- .argument(
78
- "<groupName>",
79
- "The name of the group",
80
- )
122
+ .argument("<groupName>", "The name of the group")
81
123
  .option("--debug")
82
124
  .action((groupName, options) => {
83
125
  listGroupAccessTokens(
@@ -86,5 +128,4 @@ export const registerListCommands = (
86
128
  options.debug,
87
129
  );
88
130
  });
89
-
90
131
  };
@@ -4,8 +4,11 @@ import fs from "fs";
4
4
  import os from "os";
5
5
  import { join } from "path";
6
6
  import sinon from "sinon";
7
+ import * as credConstants from "../../constants";
7
8
  import { ClientConfiguration } from "../../clientconfiguration";
8
9
  import { login } from "./login";
10
+ import { OrganizationsApi } from "../../client/api";
11
+ import * as loopbackOAuth from "./loopbackOAuth";
9
12
 
10
13
  function createFakeIdToken(payload: Record<string, unknown>): string {
11
14
  const header = Buffer.from(
@@ -18,6 +21,8 @@ function createFakeIdToken(payload: Record<string, unknown>): string {
18
21
  describe("login", () => {
19
22
  let tmpConfigFilePath: string;
20
23
  let axiosStub: sinon.SinonStub;
24
+ let orgPermissionsStub: sinon.SinonStub;
25
+
21
26
  const mockDeviceCodeResponse = {
22
27
  data: {
23
28
  verification_uri_complete: "https://example.com",
@@ -40,15 +45,23 @@ describe("login", () => {
40
45
  },
41
46
  };
42
47
 
48
+ const mockOrgPermissionsResponse = {
49
+ status: 200,
50
+ data: {},
51
+ };
52
+
43
53
  beforeEach(() => {
44
54
  tmpConfigFilePath = join(os.tmpdir(), "cred.json");
45
55
  fs.writeFileSync(tmpConfigFilePath, "{}");
46
56
  axiosStub = sinon.stub(axios, "request");
57
+ orgPermissionsStub = sinon
58
+ .stub(OrganizationsApi.prototype, "getOrganization")
59
+ .resolves(mockOrgPermissionsResponse as any);
47
60
  });
48
61
 
49
62
  afterEach(() => {
50
63
  fs.rmSync(tmpConfigFilePath);
51
- axiosStub.restore();
64
+ sinon.restore();
52
65
  });
53
66
 
54
67
  it("should not delete config properties on login", async function () {
@@ -62,7 +75,7 @@ describe("login", () => {
62
75
  .resolves(mockDeviceCodeResponse)
63
76
  .onSecondCall()
64
77
  .resolves(mockedAccessTokenResponse);
65
- await login("foo", tmpConfigFilePath);
78
+ await login("foo", "http://localhost", tmpConfigFilePath);
66
79
  expect(config.getOrganization()).to.equal("foo");
67
80
  expect(config.getProject()).to.equal("bar");
68
81
  });
@@ -78,7 +91,7 @@ describe("login", () => {
78
91
  config.setEnvironment("localhost");
79
92
  config.setOrganization("foo");
80
93
  config.setProject("bar");
81
- await login("test", tmpConfigFilePath);
94
+ await login("test", "http://localhost", tmpConfigFilePath);
82
95
  expect(config.getOrganization()).to.equal("test");
83
96
  });
84
97
 
@@ -90,7 +103,8 @@ describe("login", () => {
90
103
  .onSecondCall()
91
104
  .resolves(mockedAccessTokenResponse);
92
105
  const config = new ClientConfiguration(tmpConfigFilePath);
93
- await login("test", tmpConfigFilePath);
106
+ config.setEnvironment("localhost");
107
+ await login("test", "http://localhost", tmpConfigFilePath);
94
108
  expect(config.getAccessToken()).to.equal(
95
109
  mockedAccessTokenResponse.data.access_token,
96
110
  );
@@ -107,7 +121,7 @@ describe("login", () => {
107
121
  config.setEnvironment("localhost");
108
122
  config.setOrganization("foo");
109
123
  config.setProject("bar");
110
- await login("not-foo", tmpConfigFilePath);
124
+ await login("not-foo", "http://localhost", tmpConfigFilePath);
111
125
  expect(config.getProject()).to.equal(undefined);
112
126
  });
113
127
 
@@ -122,7 +136,78 @@ describe("login", () => {
122
136
  config.setEnvironment("localhost");
123
137
  config.setOrganization("foo");
124
138
  config.setProject("bar");
125
- await login("foo", tmpConfigFilePath);
139
+ await login("foo", "http://localhost", tmpConfigFilePath);
126
140
  expect(config.getProject()).to.equal("bar");
127
141
  });
142
+
143
+ it("uses auth-code + PKCE with organization in authorize URL for mapped CLI orgs", async function () {
144
+ this.timeout(2000);
145
+ const orgIdStub = sinon
146
+ .stub(credConstants, "getAuth0OrganizationIdForCliLogin")
147
+ .returns("org_nMRKafeSuxOiuJeG");
148
+ const loopbackStub = sinon
149
+ .stub(loopbackOAuth, "authorizationCodeViaLoopback")
150
+ .callsFake(async (opts) => {
151
+ opts.onListening?.();
152
+ return { code: "test-pkce-auth-code" };
153
+ });
154
+ axiosStub.onFirstCall().resolves(mockedAccessTokenResponse);
155
+ const config = new ClientConfiguration(tmpConfigFilePath);
156
+ config.setEnvironment("videoamp");
157
+ await login(
158
+ "videoamp",
159
+ "https://admin.videoamp-aws-us-east-1.credibledata.com/api/v0",
160
+ tmpConfigFilePath,
161
+ );
162
+ expect(orgIdStub.calledOnceWithExactly("videoamp")).to.be.true;
163
+ expect(loopbackStub.calledOnce).to.be.true;
164
+ const call = loopbackStub.getCall(0);
165
+ expect(call.args[0].authorizeUrl).to.contain(
166
+ "organization=org_nMRKafeSuxOiuJeG",
167
+ );
168
+ });
169
+
170
+ it("uses mapped org id for PKCE flow regardless of org name casing", async function () {
171
+ this.timeout(2000);
172
+ const orgIdStub = sinon
173
+ .stub(credConstants, "getAuth0OrganizationIdForCliLogin")
174
+ .callsFake((name: string) =>
175
+ name.toLowerCase() === "videoamp"
176
+ ? "org_nMRKafeSuxOiuJeG"
177
+ : undefined,
178
+ );
179
+ const loopbackStub = sinon
180
+ .stub(loopbackOAuth, "authorizationCodeViaLoopback")
181
+ .callsFake(async (opts) => {
182
+ opts.onListening?.();
183
+ return { code: "test-pkce-auth-code" };
184
+ });
185
+ axiosStub.onFirstCall().resolves(mockedAccessTokenResponse);
186
+ const config = new ClientConfiguration(tmpConfigFilePath);
187
+ config.setEnvironment("videoamp");
188
+ await login(
189
+ "VideoAmp",
190
+ "https://admin.videoamp-aws-us-east-1.credibledata.com/api/v0",
191
+ tmpConfigFilePath,
192
+ );
193
+ expect(orgIdStub.calledOnceWithExactly("VideoAmp")).to.be.true;
194
+ expect(loopbackStub.getCall(0).args[0].authorizeUrl).to.contain(
195
+ "organization=org_nMRKafeSuxOiuJeG",
196
+ );
197
+ });
198
+
199
+ it("should not pass Auth0 organization for unmapped org names", async function () {
200
+ this.timeout(2000);
201
+ axiosStub
202
+ .onFirstCall()
203
+ .resolves(mockDeviceCodeResponse)
204
+ .onSecondCall()
205
+ .resolves(mockedAccessTokenResponse);
206
+ const config = new ClientConfiguration(tmpConfigFilePath);
207
+ config.setEnvironment("localhost");
208
+ await login("test", "http://localhost", tmpConfigFilePath);
209
+ expect(axiosStub.getCall(0).args[0].data).to.not.have.property(
210
+ "organization",
211
+ );
212
+ });
128
213
  });