@credibledata/cred-cli 0.0.6

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 (259) hide show
  1. package/.github/workflows/build.yml +23 -0
  2. package/.mocharc.json +10 -0
  3. package/.prettierignore +2 -0
  4. package/.prettierrc +4 -0
  5. package/README-DEV.md +40 -0
  6. package/README.md +11 -0
  7. package/bun.lock +1158 -0
  8. package/dist/client/api.js +7715 -0
  9. package/dist/client/api.js.map +1 -0
  10. package/dist/client/base.js +69 -0
  11. package/dist/client/base.js.map +1 -0
  12. package/dist/client/common.js +162 -0
  13. package/dist/client/common.js.map +1 -0
  14. package/dist/client/configuration.js +44 -0
  15. package/dist/client/configuration.js.map +1 -0
  16. package/dist/client/index.js +32 -0
  17. package/dist/client/index.js.map +1 -0
  18. package/dist/clientconfiguration.js +205 -0
  19. package/dist/clientconfiguration.js.map +1 -0
  20. package/dist/clientconfiguration.spec.js +381 -0
  21. package/dist/clientconfiguration.spec.js.map +1 -0
  22. package/dist/commands/add.js +66 -0
  23. package/dist/commands/add.js.map +1 -0
  24. package/dist/commands/connection/createconnections.js +89 -0
  25. package/dist/commands/connection/createconnections.js.map +1 -0
  26. package/dist/commands/connection/createconnections.spec.js +219 -0
  27. package/dist/commands/connection/createconnections.spec.js.map +1 -0
  28. package/dist/commands/connection/deleteconnection.js +52 -0
  29. package/dist/commands/connection/deleteconnection.js.map +1 -0
  30. package/dist/commands/connection/deleteconnection.spec.js +130 -0
  31. package/dist/commands/connection/deleteconnection.spec.js.map +1 -0
  32. package/dist/commands/connection/listconnections.js +50 -0
  33. package/dist/commands/connection/listconnections.js.map +1 -0
  34. package/dist/commands/connection/listconnections.spec.js +117 -0
  35. package/dist/commands/connection/listconnections.spec.js.map +1 -0
  36. package/dist/commands/get.js +28 -0
  37. package/dist/commands/get.js.map +1 -0
  38. package/dist/commands/group/addmember.js +75 -0
  39. package/dist/commands/group/addmember.js.map +1 -0
  40. package/dist/commands/group/addmember.spec.js +148 -0
  41. package/dist/commands/group/addmember.spec.js.map +1 -0
  42. package/dist/commands/group/creategroup.js +55 -0
  43. package/dist/commands/group/creategroup.js.map +1 -0
  44. package/dist/commands/group/creategroup.spec.js +122 -0
  45. package/dist/commands/group/creategroup.spec.js.map +1 -0
  46. package/dist/commands/group/deletegroup.js +48 -0
  47. package/dist/commands/group/deletegroup.js.map +1 -0
  48. package/dist/commands/group/deletegroup.spec.js +104 -0
  49. package/dist/commands/group/deletegroup.spec.js.map +1 -0
  50. package/dist/commands/group/getgroup.js +50 -0
  51. package/dist/commands/group/getgroup.js.map +1 -0
  52. package/dist/commands/group/getgroup.spec.js +111 -0
  53. package/dist/commands/group/getgroup.spec.js.map +1 -0
  54. package/dist/commands/group/listgroups.js +56 -0
  55. package/dist/commands/group/listgroups.js.map +1 -0
  56. package/dist/commands/group/listgroups.spec.js +118 -0
  57. package/dist/commands/group/listgroups.spec.js.map +1 -0
  58. package/dist/commands/group/removemember.js +69 -0
  59. package/dist/commands/group/removemember.js.map +1 -0
  60. package/dist/commands/group/removemember.spec.js +138 -0
  61. package/dist/commands/group/removemember.spec.js.map +1 -0
  62. package/dist/commands/groupaccesstoken/createToken.js +53 -0
  63. package/dist/commands/groupaccesstoken/createToken.js.map +1 -0
  64. package/dist/commands/groupaccesstoken/createToken.spec.js +127 -0
  65. package/dist/commands/groupaccesstoken/createToken.spec.js.map +1 -0
  66. package/dist/commands/groupaccesstoken/deleteToken.js +24 -0
  67. package/dist/commands/groupaccesstoken/deleteToken.js.map +1 -0
  68. package/dist/commands/groupaccesstoken/deleteToken.spec.js +103 -0
  69. package/dist/commands/groupaccesstoken/deleteToken.spec.js.map +1 -0
  70. package/dist/commands/groupaccesstoken/groupContainer.js +71 -0
  71. package/dist/commands/groupaccesstoken/groupContainer.js.map +1 -0
  72. package/dist/commands/groupaccesstoken/listTokens.js +25 -0
  73. package/dist/commands/groupaccesstoken/listTokens.js.map +1 -0
  74. package/dist/commands/groupaccesstoken/listTokens.spec.js +115 -0
  75. package/dist/commands/groupaccesstoken/listTokens.spec.js.map +1 -0
  76. package/dist/commands/list.js +75 -0
  77. package/dist/commands/list.js.map +1 -0
  78. package/dist/commands/misc/login.js +290 -0
  79. package/dist/commands/misc/login.js.map +1 -0
  80. package/dist/commands/misc/login.spec.js +243 -0
  81. package/dist/commands/misc/login.spec.js.map +1 -0
  82. package/dist/commands/misc/logout.js +11 -0
  83. package/dist/commands/misc/logout.js.map +1 -0
  84. package/dist/commands/misc/logout.spec.js +30 -0
  85. package/dist/commands/misc/logout.spec.js.map +1 -0
  86. package/dist/commands/misc/loopbackOAuth.js +110 -0
  87. package/dist/commands/misc/loopbackOAuth.js.map +1 -0
  88. package/dist/commands/misc/set-access-token.js +27 -0
  89. package/dist/commands/misc/set-access-token.js.map +1 -0
  90. package/dist/commands/misc/set-access-token.spec.js +65 -0
  91. package/dist/commands/misc/set-access-token.spec.js.map +1 -0
  92. package/dist/commands/package/deletepackage.js +54 -0
  93. package/dist/commands/package/deletepackage.js.map +1 -0
  94. package/dist/commands/package/deletepackage.spec.js +136 -0
  95. package/dist/commands/package/deletepackage.spec.js.map +1 -0
  96. package/dist/commands/package/listpackages.js +57 -0
  97. package/dist/commands/package/listpackages.js.map +1 -0
  98. package/dist/commands/package/listpackages.spec.js +129 -0
  99. package/dist/commands/package/listpackages.spec.js.map +1 -0
  100. package/dist/commands/package/publish.js +157 -0
  101. package/dist/commands/package/publish.js.map +1 -0
  102. package/dist/commands/package/publish.spec.js +511 -0
  103. package/dist/commands/package/publish.spec.js.map +1 -0
  104. package/dist/commands/package/updatepackage.js +75 -0
  105. package/dist/commands/package/updatepackage.js.map +1 -0
  106. package/dist/commands/package/updatepackage.spec.js +189 -0
  107. package/dist/commands/package/updatepackage.spec.js.map +1 -0
  108. package/dist/commands/project/createproject.js +75 -0
  109. package/dist/commands/project/createproject.js.map +1 -0
  110. package/dist/commands/project/createproject.spec.js +154 -0
  111. package/dist/commands/project/createproject.spec.js.map +1 -0
  112. package/dist/commands/project/deleteproject.js +49 -0
  113. package/dist/commands/project/deleteproject.js.map +1 -0
  114. package/dist/commands/project/deleteproject.spec.js +106 -0
  115. package/dist/commands/project/deleteproject.spec.js.map +1 -0
  116. package/dist/commands/project/getproject.js +44 -0
  117. package/dist/commands/project/getproject.js.map +1 -0
  118. package/dist/commands/project/getproject.spec.js +99 -0
  119. package/dist/commands/project/getproject.spec.js.map +1 -0
  120. package/dist/commands/project/listprojects.js +52 -0
  121. package/dist/commands/project/listprojects.js.map +1 -0
  122. package/dist/commands/project/listprojects.spec.js +111 -0
  123. package/dist/commands/project/listprojects.spec.js.map +1 -0
  124. package/dist/commands/project/setproject.js +26 -0
  125. package/dist/commands/project/setproject.js.map +1 -0
  126. package/dist/commands/project/setproject.spec.js +58 -0
  127. package/dist/commands/project/setproject.spec.js.map +1 -0
  128. package/dist/commands/project/updateproject.js +68 -0
  129. package/dist/commands/project/updateproject.js.map +1 -0
  130. package/dist/commands/project/updateproject.spec.js +129 -0
  131. package/dist/commands/project/updateproject.spec.js.map +1 -0
  132. package/dist/commands/rm.js +68 -0
  133. package/dist/commands/rm.js.map +1 -0
  134. package/dist/commands/set.js +17 -0
  135. package/dist/commands/set.js.map +1 -0
  136. package/dist/commands/update.js +42 -0
  137. package/dist/commands/update.js.map +1 -0
  138. package/dist/commands/version/archive-unarchive-version.js +79 -0
  139. package/dist/commands/version/archive-unarchive-version.js.map +1 -0
  140. package/dist/commands/version/archive-unarchive-version.spec.js +244 -0
  141. package/dist/commands/version/archive-unarchive-version.spec.js.map +1 -0
  142. package/dist/commands/version/listversions.js +46 -0
  143. package/dist/commands/version/listversions.js.map +1 -0
  144. package/dist/commands/version/listversions.spec.js +121 -0
  145. package/dist/commands/version/listversions.spec.js.map +1 -0
  146. package/dist/common/UserGroupId.js +112 -0
  147. package/dist/common/UserGroupId.js.map +1 -0
  148. package/dist/common/UserGroupId.spec.js +92 -0
  149. package/dist/common/UserGroupId.spec.js.map +1 -0
  150. package/dist/constants.js +90 -0
  151. package/dist/constants.js.map +1 -0
  152. package/dist/index.js +159 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/logger.js +77 -0
  155. package/dist/logger.js.map +1 -0
  156. package/dist/logger.spec.js +125 -0
  157. package/dist/logger.spec.js.map +1 -0
  158. package/dist/polyfills/file.polyfill.js +6 -0
  159. package/dist/polyfills/file.polyfill.js.map +1 -0
  160. package/dist/utils.js +110 -0
  161. package/dist/utils.js.map +1 -0
  162. package/dist/utils.spec.js +158 -0
  163. package/dist/utils.spec.js.map +1 -0
  164. package/dist/validator.js +53 -0
  165. package/dist/validator.js.map +1 -0
  166. package/dist/validator.spec.js +41 -0
  167. package/dist/validator.spec.js.map +1 -0
  168. package/docker/Dockerfile.ci +18 -0
  169. package/docker-compose.yml +18 -0
  170. package/eslint.config.mjs +45 -0
  171. package/generate-client.sh +27 -0
  172. package/mocha.setup.ts +4 -0
  173. package/openapitools.json +7 -0
  174. package/package.json +75 -0
  175. package/src/client/.openapi-generator/FILES +9 -0
  176. package/src/client/.openapi-generator/VERSION +1 -0
  177. package/src/client/.openapi-generator-ignore +23 -0
  178. package/src/client/api.ts +9729 -0
  179. package/src/client/base.ts +86 -0
  180. package/src/client/common.ts +150 -0
  181. package/src/client/configuration.ts +110 -0
  182. package/src/client/git_push.sh +57 -0
  183. package/src/client/index.ts +18 -0
  184. package/src/clientconfiguration.spec.ts +490 -0
  185. package/src/clientconfiguration.ts +263 -0
  186. package/src/commands/add.ts +125 -0
  187. package/src/commands/connection/createconnections.spec.ts +403 -0
  188. package/src/commands/connection/createconnections.ts +109 -0
  189. package/src/commands/connection/deleteconnection.spec.ts +189 -0
  190. package/src/commands/connection/deleteconnection.ts +57 -0
  191. package/src/commands/connection/listconnections.spec.ts +132 -0
  192. package/src/commands/connection/listconnections.ts +58 -0
  193. package/src/commands/get.ts +31 -0
  194. package/src/commands/group/addmember.spec.ts +257 -0
  195. package/src/commands/group/addmember.ts +85 -0
  196. package/src/commands/group/creategroup.spec.ts +146 -0
  197. package/src/commands/group/creategroup.ts +54 -0
  198. package/src/commands/group/deletegroup.spec.ts +120 -0
  199. package/src/commands/group/deletegroup.ts +45 -0
  200. package/src/commands/group/getgroup.spec.ts +129 -0
  201. package/src/commands/group/getgroup.ts +47 -0
  202. package/src/commands/group/listgroups.spec.ts +137 -0
  203. package/src/commands/group/listgroups.ts +45 -0
  204. package/src/commands/group/removemember.spec.ts +224 -0
  205. package/src/commands/group/removemember.ts +75 -0
  206. package/src/commands/groupaccesstoken/createToken.spec.ts +211 -0
  207. package/src/commands/groupaccesstoken/createToken.ts +72 -0
  208. package/src/commands/groupaccesstoken/deleteToken.spec.ts +147 -0
  209. package/src/commands/groupaccesstoken/deleteToken.ts +29 -0
  210. package/src/commands/groupaccesstoken/groupContainer.ts +83 -0
  211. package/src/commands/groupaccesstoken/listTokens.spec.ts +147 -0
  212. package/src/commands/groupaccesstoken/listTokens.ts +29 -0
  213. package/src/commands/list.ts +131 -0
  214. package/src/commands/misc/login.spec.ts +213 -0
  215. package/src/commands/misc/login.ts +325 -0
  216. package/src/commands/misc/logout.spec.ts +32 -0
  217. package/src/commands/misc/logout.ts +9 -0
  218. package/src/commands/misc/loopbackOAuth.ts +127 -0
  219. package/src/commands/misc/set-access-token.spec.ts +95 -0
  220. package/src/commands/misc/set-access-token.ts +32 -0
  221. package/src/commands/package/deletepackage.spec.ts +164 -0
  222. package/src/commands/package/deletepackage.ts +58 -0
  223. package/src/commands/package/listpackages.spec.ts +147 -0
  224. package/src/commands/package/listpackages.ts +67 -0
  225. package/src/commands/package/publish.spec.ts +597 -0
  226. package/src/commands/package/publish.ts +211 -0
  227. package/src/commands/package/updatepackage.spec.ts +319 -0
  228. package/src/commands/package/updatepackage.ts +95 -0
  229. package/src/commands/project/createproject.spec.ts +247 -0
  230. package/src/commands/project/createproject.ts +70 -0
  231. package/src/commands/project/deleteproject.spec.ts +123 -0
  232. package/src/commands/project/deleteproject.ts +48 -0
  233. package/src/commands/project/getproject.spec.ts +109 -0
  234. package/src/commands/project/getproject.ts +43 -0
  235. package/src/commands/project/listprojects.spec.ts +121 -0
  236. package/src/commands/project/listprojects.ts +62 -0
  237. package/src/commands/project/setproject.spec.ts +63 -0
  238. package/src/commands/project/setproject.ts +14 -0
  239. package/src/commands/project/updateproject.spec.ts +217 -0
  240. package/src/commands/project/updateproject.ts +82 -0
  241. package/src/commands/rm.ts +101 -0
  242. package/src/commands/set.ts +16 -0
  243. package/src/commands/update.ts +64 -0
  244. package/src/commands/version/archive-unarchive-version.spec.ts +456 -0
  245. package/src/commands/version/archive-unarchive-version.ts +111 -0
  246. package/src/commands/version/listversions.spec.ts +138 -0
  247. package/src/commands/version/listversions.ts +45 -0
  248. package/src/common/UserGroupId.spec.ts +117 -0
  249. package/src/common/UserGroupId.ts +137 -0
  250. package/src/constants.ts +116 -0
  251. package/src/index.ts +209 -0
  252. package/src/logger.spec.ts +158 -0
  253. package/src/logger.ts +86 -0
  254. package/src/polyfills/file.polyfill.ts +6 -0
  255. package/src/utils.spec.ts +135 -0
  256. package/src/utils.ts +115 -0
  257. package/src/validator.spec.ts +51 -0
  258. package/src/validator.ts +44 -0
  259. package/tsconfig.json +17 -0
@@ -0,0 +1,138 @@
1
+ import { expect } from "chai";
2
+ import sinon from "sinon";
3
+ import { VersionsApi } from "../../client/api";
4
+ import { ClientConfiguration } from "../../clientconfiguration";
5
+ import { logger } from "../../logger";
6
+ import { prettifyJson } from "../../utils";
7
+ import { listVersions } from "./listversions";
8
+
9
+ describe("list-versions", () => {
10
+ let sandbox: sinon.SinonSandbox;
11
+ let listVersionsStub: sinon.SinonStub;
12
+ let loggerStub: sinon.SinonStubbedInstance<typeof logger>;
13
+ let consoleLogStub: sinon.SinonStub;
14
+
15
+ beforeEach(() => {
16
+ sandbox = sinon.createSandbox();
17
+ listVersionsStub = sandbox.stub();
18
+ loggerStub = sandbox.stub(logger);
19
+ consoleLogStub = sandbox.stub(console, "log");
20
+
21
+ sandbox
22
+ .stub(ClientConfiguration.prototype, "getOrganization")
23
+ .returns("test-org");
24
+ sandbox
25
+ .stub(ClientConfiguration.prototype, "getProject")
26
+ .returns("test-project");
27
+ sandbox
28
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
29
+ .returns(true);
30
+ sandbox
31
+ .stub(ClientConfiguration.prototype, "getHeaders")
32
+ .returns({ Authorization: "Bearer test-token" });
33
+
34
+ sandbox
35
+ .stub(VersionsApi.prototype, "listVersions")
36
+ .callsFake(listVersionsStub);
37
+ });
38
+
39
+ afterEach(() => {
40
+ sandbox.restore();
41
+ });
42
+
43
+ it("should list versions successfully", async () => {
44
+ const mockVersions = [
45
+ { id: "1.0.0", archiveStatus: "active" },
46
+ { id: "2.0.0", archiveStatus: "active" },
47
+ ];
48
+ const mockResponse = {
49
+ data: mockVersions,
50
+ };
51
+ listVersionsStub.resolves(mockResponse);
52
+
53
+ await listVersions("http://test-server", "/test-package", false);
54
+
55
+ expect(listVersionsStub.calledOnce).to.be.true;
56
+ expect(listVersionsStub.firstCall.args[0]).to.equal("test-org");
57
+ expect(listVersionsStub.firstCall.args[1]).to.equal("test-project");
58
+ expect(listVersionsStub.firstCall.args[2]).to.equal("test-package");
59
+ expect(listVersionsStub.firstCall.args[3]).to.deep.include({
60
+ baseURL: "http://test-server",
61
+ headers: { Authorization: "Bearer test-token" },
62
+ });
63
+ expect(consoleLogStub.calledWith(prettifyJson(mockVersions))).to.be.true;
64
+ });
65
+
66
+ it("should handle package path without leading slash", async () => {
67
+ const mockVersions = [{ id: "1.0.0" }];
68
+ const mockResponse = {
69
+ data: mockVersions,
70
+ };
71
+ listVersionsStub.resolves(mockResponse);
72
+
73
+ await listVersions("http://test-server", "test-package", false);
74
+
75
+ expect(listVersionsStub.firstCall.args[2]).to.equal("test-package");
76
+ });
77
+
78
+ it("should handle missing config", async () => {
79
+ sandbox.restore();
80
+ sandbox = sinon.createSandbox();
81
+ listVersionsStub = sandbox.stub();
82
+ loggerStub = sandbox.stub(logger);
83
+ consoleLogStub = sandbox.stub(console, "log");
84
+
85
+ sandbox
86
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
87
+ .returns(false);
88
+ sandbox
89
+ .stub(VersionsApi.prototype, "listVersions")
90
+ .callsFake(listVersionsStub);
91
+
92
+ await listVersions("http://test-server", "/test-package", false);
93
+
94
+ expect(listVersionsStub.called).to.be.false;
95
+ expect(
96
+ loggerStub.error.calledWith(
97
+ sinon.match("Please, make sure that you are logged in"),
98
+ ),
99
+ ).to.be.true;
100
+ });
101
+
102
+ it("should handle missing project", async () => {
103
+ sandbox.restore();
104
+ sandbox = sinon.createSandbox();
105
+ listVersionsStub = sandbox.stub();
106
+ loggerStub = sandbox.stub(logger);
107
+ consoleLogStub = sandbox.stub(console, "log");
108
+
109
+ sandbox
110
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
111
+ .returns(true);
112
+ sandbox.stub(ClientConfiguration.prototype, "getProject").returns("");
113
+ sandbox
114
+ .stub(VersionsApi.prototype, "listVersions")
115
+ .callsFake(listVersionsStub);
116
+
117
+ await listVersions("http://test-server", "/test-package", false);
118
+
119
+ expect(listVersionsStub.called).to.be.false;
120
+ expect(
121
+ loggerStub.error.calledWith(
122
+ sinon.match("Please, make sure to set a project"),
123
+ ),
124
+ ).to.be.true;
125
+ });
126
+
127
+ it("should handle API errors", async () => {
128
+ const mockError = new Error("API Error");
129
+ listVersionsStub.rejects(mockError);
130
+
131
+ await listVersions("http://test-server", "/test-package", true);
132
+
133
+ expect(listVersionsStub.calledOnce).to.be.true;
134
+ expect(
135
+ loggerStub.error.calledWith(sinon.match("Failed to list versions")),
136
+ ).to.be.true;
137
+ });
138
+ });
@@ -0,0 +1,45 @@
1
+ import { VersionsApi } from "../../client/api";
2
+ import { Configuration } from "../../client/configuration";
3
+ import { ClientConfiguration } from "../../clientconfiguration";
4
+ import { logger } from "../../logger";
5
+ import { prettifyJson, printOutError } from "../../utils";
6
+
7
+ const versionsApi = new VersionsApi(new Configuration());
8
+
9
+ export async function listVersions(
10
+ controlPlane: string,
11
+ packagePath: string,
12
+ debug: boolean,
13
+ ) {
14
+ const clientConfig = new ClientConfiguration();
15
+ const organizationName = clientConfig.getOrganization();
16
+ const projectName = clientConfig.getProject();
17
+
18
+ if (!clientConfig.doesConfigExists()) {
19
+ logger.error("Please, make sure that you are logged in");
20
+ return;
21
+ }
22
+
23
+ if (!projectName) {
24
+ logger.error("Please, make sure to set a project");
25
+ return;
26
+ }
27
+
28
+ try {
29
+ const packageName = packagePath.replace("/", "");
30
+ const response = await versionsApi.listVersions(
31
+ organizationName,
32
+ projectName,
33
+ packageName,
34
+ {
35
+ baseURL: controlPlane,
36
+ headers: clientConfig.getHeaders(),
37
+ },
38
+ );
39
+
40
+ console.log(prettifyJson(response.data));
41
+ } catch (e) {
42
+ logger.error("Failed to list versions");
43
+ printOutError(e, debug);
44
+ }
45
+ }
@@ -0,0 +1,117 @@
1
+ import { expect } from "chai";
2
+ import { ResourceType, UserGroupId } from "./UserGroupId";
3
+
4
+ describe("UserGroupId", () => {
5
+ describe("constructor", () => {
6
+ it("should parse a valid user id", () => {
7
+ const id = new UserGroupId("user:john");
8
+ expect(id.getResourceType()).to.equal(ResourceType.USER);
9
+ expect(id.getResourceName()).to.equal("john");
10
+ expect(id.getValue()).to.equal("user:john");
11
+ });
12
+
13
+ it("should parse a valid group id", () => {
14
+ const id = new UserGroupId("group:admins");
15
+ expect(id.getResourceType()).to.equal(ResourceType.GROUP);
16
+ expect(id.getResourceName()).to.equal("admins");
17
+ expect(id.getValue()).to.equal("group:admins");
18
+ });
19
+
20
+ it("should trim whitespace from input", () => {
21
+ const id = new UserGroupId(" user:john ");
22
+ expect(id.getValue()).to.equal("user:john");
23
+ expect(id.getResourceName()).to.equal("john");
24
+ });
25
+
26
+ it("should throw for null or empty input", () => {
27
+ expect(() => new UserGroupId("")).to.throw("cannot be null or empty");
28
+ expect(() => new UserGroupId(" ")).to.throw(
29
+ "cannot be null or empty",
30
+ );
31
+ });
32
+
33
+ it("should throw for invalid format", () => {
34
+ expect(() => new UserGroupId("invalid")).to.throw(
35
+ "Invalid UserGroupId format",
36
+ );
37
+ expect(() => new UserGroupId("user:")).to.throw(
38
+ "Invalid UserGroupId format",
39
+ );
40
+ expect(() => new UserGroupId("foo:bar")).to.throw(
41
+ "Invalid UserGroupId format",
42
+ );
43
+ expect(() => new UserGroupId("user:a:b")).to.throw(
44
+ "Invalid UserGroupId format",
45
+ );
46
+ });
47
+ });
48
+
49
+ describe("static factory methods", () => {
50
+ it("forPublicAccess should create user:* id", () => {
51
+ const id = UserGroupId.forPublicAccess();
52
+ expect(id.getResourceType()).to.equal(ResourceType.USER);
53
+ expect(id.getResourceName()).to.equal("*");
54
+ expect(id.getValue()).to.equal("user:*");
55
+ });
56
+
57
+ it("forUser should create a user id", () => {
58
+ const id = UserGroupId.forUser("alice");
59
+ expect(id.getResourceType()).to.equal(ResourceType.USER);
60
+ expect(id.getResourceName()).to.equal("alice");
61
+ });
62
+
63
+ it("forUser should throw for undefined user name", () => {
64
+ expect(() => UserGroupId.forUser(undefined)).to.throw(
65
+ "cannot be undefined",
66
+ );
67
+ });
68
+
69
+ it("forGroup should create a group id", () => {
70
+ const id = UserGroupId.forGroup("developers");
71
+ expect(id.getResourceType()).to.equal(ResourceType.GROUP);
72
+ expect(id.getResourceName()).to.equal("developers");
73
+ });
74
+
75
+ it("create should build from ResourceType and name", () => {
76
+ const userId = UserGroupId.create(ResourceType.USER, "bob");
77
+ expect(userId.getResourceType()).to.equal(ResourceType.USER);
78
+ expect(userId.getResourceName()).to.equal("bob");
79
+
80
+ const groupId = UserGroupId.create(ResourceType.GROUP, "team");
81
+ expect(groupId.getResourceType()).to.equal(ResourceType.GROUP);
82
+ expect(groupId.getResourceName()).to.equal("team");
83
+ });
84
+ });
85
+
86
+ describe("serialization", () => {
87
+ it("toString should return original value", () => {
88
+ const id = new UserGroupId("user:john");
89
+ expect(id.toString()).to.equal("user:john");
90
+ });
91
+
92
+ it("toJSON should return original value for JSON serialization", () => {
93
+ const id = new UserGroupId("group:admins");
94
+ expect(id.toJSON()).to.equal("group:admins");
95
+ expect(JSON.stringify(id)).to.equal('"group:admins"');
96
+ });
97
+ });
98
+
99
+ describe("isPublicAccess", () => {
100
+ it("should return false for regular user ids", () => {
101
+ const id = new UserGroupId("user:john");
102
+ expect(id.isPublicAccess()).to.be.false;
103
+ });
104
+
105
+ it("should return false for group ids", () => {
106
+ const id = new UserGroupId("group:admins");
107
+ expect(id.isPublicAccess()).to.be.false;
108
+ });
109
+
110
+ it("should return false for user:* (checks originalValue not resourceName)", () => {
111
+ // isPublicAccess checks this.originalValue === "*" which is never true
112
+ // since originalValue is the full string "user:*"
113
+ const id = UserGroupId.forPublicAccess();
114
+ expect(id.isPublicAccess()).to.be.false;
115
+ });
116
+ });
117
+ });
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Enum representing the different types of user/group resources.
3
+ */
4
+ export enum ResourceType {
5
+ USER = "USER",
6
+ GROUP = "GROUP",
7
+ }
8
+
9
+ /**
10
+ * Represents a user or group identifier in the format 'user:userId' or 'group:groupId'.
11
+ * This class parses the input string and provides methods to extract the
12
+ * resource type and name.
13
+ */
14
+ export class UserGroupId {
15
+ private readonly resourceType: ResourceType;
16
+ private readonly resourceName: string;
17
+ private readonly originalValue: string;
18
+
19
+ static forPublicAccess(): UserGroupId {
20
+ return new UserGroupId(`user:*`);
21
+ }
22
+
23
+ static forUser(userName: string | undefined): UserGroupId {
24
+ if (!userName) {
25
+ throw new Error("User name cannot be undefined");
26
+ }
27
+ return new UserGroupId(`user:${userName}`);
28
+ }
29
+
30
+ static forGroup(groupName: string): UserGroupId {
31
+ return new UserGroupId(`group:${groupName}`);
32
+ }
33
+ /**
34
+ * Creates a UserGroupId from a string in the format 'user:userId' or 'group:groupId'.
35
+ *
36
+ * @param value the string to parse
37
+ * @throws BadRequestException if the format is invalid
38
+ */
39
+ constructor(value: string) {
40
+ if (!value || value.trim().length === 0) {
41
+ throw new Error("UserGroupId cannot be null or empty");
42
+ }
43
+
44
+ this.originalValue = value.trim();
45
+
46
+ if (!this.originalValue.match(/^(user:[^:]+|group:[^:]+)$/)) {
47
+ throw new Error(
48
+ `Invalid UserGroupId format. Expected 'user:userId' or 'group:groupId', got: ${this.originalValue}`,
49
+ );
50
+ }
51
+
52
+ const parts = this.originalValue.split(":", 2);
53
+ const typeStr = parts[0];
54
+ const name = parts[1];
55
+
56
+ if (!name || name.length === 0) {
57
+ throw new Error(
58
+ `UserGroupId name cannot be empty. Expected 'user:userId' or 'group:groupId', got: ${this.originalValue}`,
59
+ );
60
+ }
61
+
62
+ switch (typeStr) {
63
+ case "user":
64
+ this.resourceType = ResourceType.USER;
65
+ break;
66
+ case "group":
67
+ this.resourceType = ResourceType.GROUP;
68
+ break;
69
+ default:
70
+ throw new Error(
71
+ `Invalid UserGroupId type. Expected 'user' or 'group', got: ${typeStr}`,
72
+ );
73
+ }
74
+
75
+ this.resourceName = name;
76
+ }
77
+
78
+ /**
79
+ * Creates a UserGroupId from resource type and name.
80
+ *
81
+ * @param resourceType the resource type
82
+ * @param userName the user or group name
83
+ */
84
+ public static create(
85
+ resourceType: ResourceType,
86
+ userName: string,
87
+ ): UserGroupId {
88
+ return new UserGroupId(`${resourceType.toLowerCase()}:${userName}`);
89
+ }
90
+
91
+ /**
92
+ * Returns the resource type (USER or GROUP).
93
+ *
94
+ * @return the resource type
95
+ */
96
+ public getResourceType(): ResourceType {
97
+ return this.resourceType;
98
+ }
99
+
100
+ /**
101
+ * Returns the resource name (the part after the colon).
102
+ *
103
+ * @return the resource name
104
+ */
105
+ public getResourceName(): string {
106
+ return this.resourceName;
107
+ }
108
+
109
+ /**
110
+ * Returns the original string value.
111
+ *
112
+ * @return the original string value
113
+ */
114
+ public getValue(): string {
115
+ return this.originalValue;
116
+ }
117
+
118
+ public toString(): string {
119
+ return this.originalValue;
120
+ }
121
+
122
+ /**
123
+ * Custom JSON serialization method for axios/openapi.
124
+ * This ensures UserGroupId is serialized as a string (originalValue) instead of an object.
125
+ *
126
+ * @return the original string value for JSON serialization
127
+ */
128
+ public toJSON(): string {
129
+ return this.originalValue;
130
+ }
131
+
132
+ public isPublicAccess(): boolean {
133
+ return (
134
+ this.resourceType === ResourceType.USER && this.originalValue === "*"
135
+ );
136
+ }
137
+ }
@@ -0,0 +1,116 @@
1
+ export type Environment =
2
+ | "production"
3
+ | "staging"
4
+ | "dev"
5
+ | "localhost"
6
+ | "e2e-test"
7
+ | "videoamp";
8
+
9
+ export const controlPlanesByEnv: Record<Environment, string> = {
10
+ production: "https://admin.credibledata.com/api/v0",
11
+ dev: "https://dev-admin.credibledata.com/api/v0",
12
+ staging: "https://staging-admin.credibledata.com/api/v0",
13
+ localhost: "http://admin.ms2.localhost/api/v0",
14
+ "e2e-test": "http://admin.ms2.localhost/api/v0",
15
+ videoamp: "https://admin.videoamp-aws-us-east-1.credibledata.com/api/v0",
16
+ };
17
+
18
+ /** Environments that must have an object in `~/.cred` `configPerEnvironment` (avoids undefined on write). */
19
+ export const ALL_ENVIRONMENTS = Object.keys(
20
+ controlPlanesByEnv,
21
+ ) as Environment[];
22
+
23
+ export const auth0ConfigsByEnv: Record<
24
+ Environment,
25
+ {
26
+ domain: string;
27
+ clientId: string;
28
+ clientSecret?: string;
29
+ audience: string;
30
+ }
31
+ > = {
32
+ production: {
33
+ domain: "https://auth.credibledata.com",
34
+ clientId: "ge8JL5TJNwqy7bygAaJkD92KdluqEZgO",
35
+ audience: "https://ms2data.us.auth0.com/api/v2/",
36
+ },
37
+ dev: {
38
+ domain: "https://dev-auth.credibledata.com",
39
+ clientId: "rr6mzJNj9b104MjCc9xWKPPehq1MJx0L",
40
+ audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
41
+ },
42
+ staging: {
43
+ domain: "https://dev-auth.credibledata.com",
44
+ clientId: "rr6mzJNj9b104MjCc9xWKPPehq1MJx0L",
45
+ audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
46
+ },
47
+ localhost: {
48
+ domain: "https://dev-auth.credibledata.com",
49
+ clientId: "rr6mzJNj9b104MjCc9xWKPPehq1MJx0L",
50
+ audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
51
+ },
52
+ "e2e-test": {
53
+ domain: "https://dev-auth.credibledata.com",
54
+ clientId: "atd8n8dEiGUiNRM7Geuvg41fi5s8ZKqY",
55
+ clientSecret:
56
+ "ZrEvs86WLqKO9EPp4y_cOvUn3NQT1qc3XC8111f6DBt9oyaclV5sWHz6Nkyo_bEF",
57
+ audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
58
+ },
59
+ videoamp: {
60
+ domain: "https://auth.credibledata.com",
61
+ clientId: "ge8JL5TJNwqy7bygAaJkD92KdluqEZgO",
62
+ audience: "https://ms2data.us.auth0.com/api/v2/",
63
+ },
64
+ };
65
+
66
+ /**
67
+ * `cred login <organizationName>` → Auth0 Organization ID for org-branded Universal Login.
68
+ *
69
+ * Auth0 documents the `organization` parameter on `/authorize` for Organizations
70
+ * (https://auth0.com/docs/manage-users/organizations/configure-organizations/use-org-name-authentication-api).
71
+ * The Device Authorization Flow documents only `client_id`, `scope`, and `audience` on
72
+ * `POST /oauth/device/code` — not `organization`
73
+ * (https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow/call-your-api-using-the-device-authorization-flow#device-code-parameters),
74
+ * so mapped orgs use Authorization Code + PKCE with `organization` on `/authorize` and
75
+ * {@link AUTH_CLI_LOOPBACK_REDIRECT_URI}.
76
+ *
77
+ * Align with app `ORGANIZATION_HOST_ORG_ID_MAP` / `getAuth0OrganizationAuthorizationParams`.
78
+ *
79
+ * Entries are added when PKCE + Auth0 org id is ready for that CLI name; until then the map may
80
+ * stay empty and `login.spec` stubs {@link getAuth0OrganizationIdForCliLogin} for PKCE coverage.
81
+ */
82
+ export const AUTH0_ORGANIZATION_IDS_BY_CLI_ORG_NAME: Record<string, string> = {
83
+ // videoamp: "org_nMRKafeSuxOiuJeG",
84
+ };
85
+
86
+ /**
87
+ * Allowlisted on the Auth0 Native application (CLI) as an Allowed Callback URL for PKCE logins
88
+ * that pass `organization` on `/authorize` (see Auth0 Organizations + Authentication API docs above).
89
+ */
90
+ export const AUTH_CLI_LOOPBACK_REDIRECT_URI = "http://127.0.0.1:18240/callback";
91
+
92
+ export function getAuth0OrganizationIdForCliLogin(
93
+ organizationName: string,
94
+ ): string | undefined {
95
+ return AUTH0_ORGANIZATION_IDS_BY_CLI_ORG_NAME[
96
+ organizationName.toLowerCase()
97
+ ];
98
+ }
99
+
100
+ // Time constants in ms
101
+ export const SECOND = 1000;
102
+ export const MINUTE = SECOND * 60;
103
+ export const HOUR = MINUTE * 60;
104
+ export const DAY = HOUR * 24;
105
+
106
+ // Login related
107
+ export const LOGIN_TIMEOUT_MS = MINUTE * 5;
108
+
109
+ export const ASCII_TITLE = `
110
+ _____ _ _ _ _ _____ _ _____
111
+ / ____| | (_) | | | / ____| | |_ _|
112
+ | | _ __ ___ __| |_| |__ | | ___ | | | | | |
113
+ | | | '__/ _ \\/ _\` | | '_ \\| |/ _ \\ | | | | | |
114
+ | |____| | | __/ (_| | | |_) | | __/ | |____| |____ _| |_
115
+ \\_____|_| \\___|\\__,_|_|_.__/|_|\\___| \\_____|______|_____|
116
+ `;