@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,64 @@
1
+ import { Command } from "commander";
2
+ import { controlPlanesByEnv, Environment } from "../constants";
3
+ import { updatePackage } from "./package/updatepackage";
4
+ import { updateProject } from "./project/updateproject";
5
+
6
+ export const registerUpdateCommands = (
7
+ cli: Command,
8
+ environment: Environment,
9
+ ) => {
10
+ const update = cli
11
+ .command("update")
12
+ .description("Update a resource")
13
+ .argument("<resource>", "The resource to update");
14
+
15
+ update
16
+ .command("project")
17
+ .description("Update a project.")
18
+ .argument("<projectName>", "The name of the project to update.")
19
+ .option(
20
+ "--replication <replicationCount>",
21
+ "The new replication count (must be at least 1).",
22
+ parseInt,
23
+ )
24
+ .option("--debug")
25
+ .option("-y, --yes", "Skip confirmation.")
26
+ .action((projectName, options) => {
27
+ updateProject(
28
+ controlPlanesByEnv[environment],
29
+ projectName,
30
+ {
31
+ replicationCount: options.replication,
32
+ },
33
+ options.debug,
34
+ options.yes,
35
+ );
36
+ });
37
+
38
+ update
39
+ .command("package")
40
+ .description("Update a package.")
41
+ .argument("<packageName>", "The name of the package to update.")
42
+ .option(
43
+ "--replication <replicationCount>",
44
+ "The new replication count (must be at least 1).",
45
+ parseInt,
46
+ )
47
+ .option("--version <latestVersion>", "The new latest version.")
48
+ .option("--desc, --description <description>", "The new description.")
49
+ .option("--debug")
50
+ .option("-y, --yes", "Skip confirmation.")
51
+ .action((packageName, options) => {
52
+ updatePackage(
53
+ controlPlanesByEnv[environment],
54
+ packageName,
55
+ {
56
+ replicationCount: options.replication,
57
+ latestVersion: options.version,
58
+ description: options.description,
59
+ },
60
+ options.debug,
61
+ options.yes,
62
+ );
63
+ });
64
+ };
@@ -0,0 +1,456 @@
1
+ import axios from "axios";
2
+ import { expect } from "chai";
3
+ import sinon from "sinon";
4
+ import { ClientConfiguration } from "../../clientconfiguration";
5
+ import { logger } from "../../logger";
6
+ import { archiveVersion, unarchiveVersion } from "./archive-unarchive-version";
7
+
8
+ describe("archive-unarchive-version", () => {
9
+ let sandbox: sinon.SinonSandbox;
10
+ let axiosStub: sinon.SinonStub;
11
+ let loggerStub: sinon.SinonStubbedInstance<typeof logger>;
12
+
13
+ beforeEach(() => {
14
+ sandbox = sinon.createSandbox();
15
+ axiosStub = sandbox.stub(axios, "patch");
16
+ sandbox.createStubInstance(ClientConfiguration);
17
+ loggerStub = sandbox.stub(logger);
18
+
19
+ // Mock ClientConfiguration constructor
20
+ sandbox
21
+ .stub(ClientConfiguration.prototype, "getOrganization")
22
+ .returns("test-org");
23
+ sandbox
24
+ .stub(ClientConfiguration.prototype, "getProject")
25
+ .returns("test-project");
26
+ sandbox
27
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
28
+ .returns(true);
29
+ sandbox
30
+ .stub(ClientConfiguration.prototype, "getHeaders")
31
+ .returns({ Authorization: "Bearer test-token" });
32
+ });
33
+
34
+ afterEach(() => {
35
+ sandbox.restore();
36
+ });
37
+
38
+ describe("archiveVersion", () => {
39
+ it("should archive a version successfully", async () => {
40
+ const mockResponse = { status: 200 };
41
+ axiosStub.resolves(mockResponse);
42
+
43
+ await archiveVersion(
44
+ "http://test-server",
45
+ "test-package",
46
+ "1.0.0",
47
+ false,
48
+ true,
49
+ );
50
+
51
+ expect(axiosStub.calledOnce).to.be.true;
52
+ expect(axiosStub.firstCall.args[0]).to.equal(
53
+ "http://test-server/organizations/test-org/projects/test-project/packages/test-package/versions/1.0.0",
54
+ );
55
+ expect(axiosStub.firstCall.args[1]).to.deep.equal({
56
+ archiveStatus: "archive",
57
+ });
58
+ expect(axiosStub.firstCall.args[2]).to.deep.equal({
59
+ headers: { Authorization: "Bearer test-token" },
60
+ });
61
+ });
62
+
63
+ it("should handle API errors", async () => {
64
+ const mockError = new Error("API Error");
65
+ axiosStub.rejects(mockError);
66
+
67
+ await archiveVersion(
68
+ "http://test-server",
69
+ "test-package",
70
+ "1.0.0",
71
+ true,
72
+ true,
73
+ );
74
+
75
+ expect(axiosStub.calledOnce).to.be.true;
76
+ expect(
77
+ loggerStub.error.calledWith(
78
+ sinon.match("Failed to archive version"),
79
+ ),
80
+ ).to.be.true;
81
+ });
82
+ });
83
+
84
+ describe("unarchiveVersion", () => {
85
+ it("should unarchive a version successfully", async () => {
86
+ const mockResponse = { status: 200 };
87
+ axiosStub.resolves(mockResponse);
88
+
89
+ await unarchiveVersion(
90
+ "http://test-server",
91
+ "test-package",
92
+ "1.0.0",
93
+ false,
94
+ true,
95
+ );
96
+
97
+ expect(axiosStub.calledOnce).to.be.true;
98
+ expect(axiosStub.firstCall.args[0]).to.equal(
99
+ "http://test-server/organizations/test-org/projects/test-project/packages/test-package/versions/1.0.0",
100
+ );
101
+ expect(axiosStub.firstCall.args[1]).to.deep.equal({
102
+ archiveStatus: "unarchive",
103
+ });
104
+ expect(axiosStub.firstCall.args[2]).to.deep.equal({
105
+ headers: { Authorization: "Bearer test-token" },
106
+ });
107
+ });
108
+
109
+ it("should handle API errors", async () => {
110
+ const mockError = new Error("API Error");
111
+ axiosStub.rejects(mockError);
112
+
113
+ await unarchiveVersion(
114
+ "http://test-server",
115
+ "test-package",
116
+ "1.0.0",
117
+ true,
118
+ true,
119
+ );
120
+
121
+ expect(axiosStub.calledOnce).to.be.true;
122
+ expect(
123
+ loggerStub.error.calledWith(
124
+ sinon.match("Failed to unarchive version"),
125
+ ),
126
+ ).to.be.true;
127
+ });
128
+ });
129
+
130
+ describe("path parsing", () => {
131
+ it("should handle paths with leading slash", async () => {
132
+ const mockResponse = { status: 200 };
133
+ axiosStub.resolves(mockResponse);
134
+
135
+ await archiveVersion(
136
+ "http://test-server",
137
+ "package-name",
138
+ "2.1.0",
139
+ false,
140
+ true,
141
+ );
142
+
143
+ expect(axiosStub.firstCall.args[0]).to.include(
144
+ "/packages/package-name/versions/2.1.0",
145
+ );
146
+ });
147
+
148
+ it("should handle paths without leading slash", async () => {
149
+ const mockResponse = { status: 200 };
150
+ axiosStub.resolves(mockResponse);
151
+
152
+ await archiveVersion(
153
+ "http://test-server",
154
+ "package-name",
155
+ "2.1.0",
156
+ false,
157
+ true,
158
+ );
159
+
160
+ expect(axiosStub.firstCall.args[0]).to.include(
161
+ "/packages/package-name/versions/2.1.0",
162
+ );
163
+ });
164
+ });
165
+
166
+ describe("validators", () => {
167
+ describe("authentication validation", () => {
168
+ it("should fail when user is not logged in", async () => {
169
+ sandbox.restore();
170
+ sandbox = sinon.createSandbox();
171
+ axiosStub = sandbox.stub(axios, "patch");
172
+ loggerStub = sandbox.stub(logger);
173
+
174
+ sandbox
175
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
176
+ .returns(false);
177
+
178
+ await archiveVersion(
179
+ "http://test-server",
180
+ "/test-package/1.0.0",
181
+ "1.0.0",
182
+ false,
183
+ true,
184
+ );
185
+
186
+ expect(axiosStub.called).to.be.false;
187
+ expect(
188
+ loggerStub.error.calledWith(
189
+ sinon.match("Please, make sure that you are logged in"),
190
+ ),
191
+ ).to.be.true;
192
+ });
193
+
194
+ it("should fail when no project is set", async () => {
195
+ sandbox.restore();
196
+ sandbox = sinon.createSandbox();
197
+ axiosStub = sandbox.stub(axios, "patch");
198
+ loggerStub = sandbox.stub(logger);
199
+
200
+ sandbox
201
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
202
+ .returns(true);
203
+ sandbox
204
+ .stub(ClientConfiguration.prototype, "getProject")
205
+ .returns("");
206
+
207
+ await archiveVersion(
208
+ "http://test-server",
209
+ "/test-package/1.0.0",
210
+ "1.0.0",
211
+ false,
212
+ true,
213
+ );
214
+
215
+ expect(axiosStub.called).to.be.false;
216
+ expect(
217
+ loggerStub.error.calledWith(
218
+ sinon.match("Please, make sure to set a project"),
219
+ ),
220
+ ).to.be.true;
221
+ });
222
+ });
223
+
224
+ describe("path format validation", () => {
225
+ it("should accept valid semantic version formats", async () => {
226
+ const mockResponse = { status: 200 };
227
+ axiosStub.resolves(mockResponse);
228
+
229
+ const validVersions = [
230
+ "/package/1.0.0",
231
+ "/package/2.1.3",
232
+ "/package/10.20.30",
233
+ "/package/1.0.0-alpha",
234
+ "/package/1.0.0-beta.1",
235
+ "/package/1.0.0+20130313144700",
236
+ ];
237
+
238
+ for (const version of validVersions) {
239
+ await archiveVersion(
240
+ "http://test-server",
241
+ version,
242
+ "1.0.0",
243
+ false,
244
+ true,
245
+ );
246
+ expect(axiosStub.called).to.be.true;
247
+ axiosStub.reset();
248
+ }
249
+ });
250
+
251
+ it("should reject empty package names", async () => {
252
+ await archiveVersion(
253
+ "http://test-server",
254
+ "",
255
+ "1.0.0",
256
+ false,
257
+ true,
258
+ );
259
+
260
+ expect(axiosStub.called).to.be.false;
261
+ expect(
262
+ loggerStub.error.calledWith(
263
+ sinon.match("Please provide a package name"),
264
+ ),
265
+ ).to.be.true;
266
+ });
267
+
268
+ it("should reject empty version IDs", async () => {
269
+ await archiveVersion(
270
+ "http://test-server",
271
+ "package",
272
+ "",
273
+ false,
274
+ true,
275
+ );
276
+
277
+ expect(axiosStub.called).to.be.false;
278
+ expect(
279
+ loggerStub.error.calledWith(
280
+ sinon.match("Please provide a version ID"),
281
+ ),
282
+ ).to.be.true;
283
+ });
284
+
285
+ it("should reject empty package names", async () => {
286
+ await archiveVersion(
287
+ "http://test-server",
288
+ "",
289
+ "1.0.0",
290
+ false,
291
+ true,
292
+ );
293
+
294
+ expect(axiosStub.called).to.be.false;
295
+ expect(
296
+ loggerStub.error.calledWith(
297
+ sinon.match("Please provide a package name"),
298
+ ),
299
+ ).to.be.true;
300
+ });
301
+
302
+ it("should reject paths with special characters in package name", async () => {
303
+ const invalidPaths = [
304
+ "/package-name/1.0.0",
305
+ "/package_name/1.0.0",
306
+ "/package.name/1.0.0",
307
+ "/package@name/1.0.0",
308
+ "/package#name/1.0.0",
309
+ ];
310
+
311
+ for (const path of invalidPaths) {
312
+ await archiveVersion(
313
+ "http://test-server",
314
+ path,
315
+ "1.0.0",
316
+ false,
317
+ true,
318
+ );
319
+ // These should actually work as they are valid package names
320
+ // The test is to ensure they don't cause parsing errors
321
+ expect(axiosStub.called).to.be.true;
322
+ axiosStub.reset();
323
+ }
324
+ });
325
+ });
326
+
327
+ describe("API response validation", () => {
328
+ it("should handle successful responses", async () => {
329
+ const mockResponse = { status: 200 };
330
+ axiosStub.resolves(mockResponse);
331
+
332
+ await archiveVersion(
333
+ "http://test-server",
334
+ "/test-package/1.0.0",
335
+ "1.0.0",
336
+ false,
337
+ true,
338
+ );
339
+
340
+ expect(axiosStub.calledOnce).to.be.true;
341
+ expect(
342
+ loggerStub.info.calledWith(
343
+ sinon.match("Version archived successfully"),
344
+ ),
345
+ ).to.be.true;
346
+ });
347
+
348
+ it("should handle non-200 responses", async () => {
349
+ const mockResponse = { status: 400 };
350
+ axiosStub.resolves(mockResponse);
351
+
352
+ await archiveVersion(
353
+ "http://test-server",
354
+ "/test-package/1.0.0",
355
+ "1.0.0",
356
+ false,
357
+ true,
358
+ );
359
+
360
+ expect(axiosStub.calledOnce).to.be.true;
361
+ expect(
362
+ loggerStub.error.calledWith(
363
+ sinon.match("Failed to archive version. Status: 400"),
364
+ ),
365
+ ).to.be.true;
366
+ });
367
+
368
+ it("should handle network errors", async () => {
369
+ const mockError = new Error("Network Error");
370
+ axiosStub.rejects(mockError);
371
+
372
+ await archiveVersion(
373
+ "http://test-server",
374
+ "/test-package/1.0.0",
375
+ "1.0.0",
376
+ true,
377
+ true,
378
+ );
379
+
380
+ expect(axiosStub.calledOnce).to.be.true;
381
+ expect(
382
+ loggerStub.error.calledWith(
383
+ sinon.match("Failed to archive version"),
384
+ ),
385
+ ).to.be.true;
386
+ });
387
+
388
+ it("should handle HTTP errors with response data", async () => {
389
+ const mockError = {
390
+ response: {
391
+ status: 404,
392
+ data: { message: "Version not found" },
393
+ },
394
+ };
395
+ axiosStub.rejects(mockError);
396
+
397
+ await archiveVersion(
398
+ "http://test-server",
399
+ "/test-package/1.0.0",
400
+ "1.0.0",
401
+ true,
402
+ true,
403
+ );
404
+
405
+ expect(axiosStub.calledOnce).to.be.true;
406
+ expect(
407
+ loggerStub.error.calledWith(
408
+ sinon.match("Failed to archive version"),
409
+ ),
410
+ ).to.be.true;
411
+ });
412
+ });
413
+
414
+ describe("URL construction validation", () => {
415
+ it("should construct correct API URLs", async () => {
416
+ const mockResponse = { status: 200 };
417
+ axiosStub.resolves(mockResponse);
418
+
419
+ await archiveVersion(
420
+ "https://api.example.com",
421
+ "my-package",
422
+ "2.0.0",
423
+ false,
424
+ true,
425
+ );
426
+
427
+ expect(axiosStub.firstCall.args[0]).to.equal(
428
+ "https://api.example.com/organizations/test-org/projects/test-project/packages/my-package/versions/2.0.0",
429
+ );
430
+ });
431
+
432
+ it("should handle different server URLs", async () => {
433
+ const mockResponse = { status: 200 };
434
+ axiosStub.resolves(mockResponse);
435
+
436
+ const servers = [
437
+ "http://localhost:8080",
438
+ "https://staging-api.example.com",
439
+ "https://api.production.com",
440
+ ];
441
+
442
+ for (const server of servers) {
443
+ await archiveVersion(
444
+ server,
445
+ "test-package",
446
+ "1.0.0",
447
+ false,
448
+ true,
449
+ );
450
+ expect(axiosStub.firstCall.args[0]).to.include(server);
451
+ axiosStub.reset();
452
+ }
453
+ });
454
+ });
455
+ });
456
+ });
@@ -0,0 +1,111 @@
1
+ import axios from "axios";
2
+ import { ClientConfiguration } from "../../clientconfiguration";
3
+ import { logger } from "../../logger";
4
+ import { getConfirmation, printOutError } from "../../utils";
5
+
6
+ export async function archiveVersion(
7
+ packageServer: string,
8
+ packageName: string,
9
+ versionId: string,
10
+ debug: boolean,
11
+ autoConfirm: boolean,
12
+ ) {
13
+ await updateVersionArchiveStatus(
14
+ packageServer,
15
+ packageName,
16
+ versionId,
17
+ "archive",
18
+ debug,
19
+ autoConfirm,
20
+ );
21
+ }
22
+
23
+ export async function unarchiveVersion(
24
+ packageServer: string,
25
+ packageName: string,
26
+ versionId: string,
27
+ debug: boolean,
28
+ autoConfirm: boolean,
29
+ ) {
30
+ await updateVersionArchiveStatus(
31
+ packageServer,
32
+ packageName,
33
+ versionId,
34
+ "unarchive",
35
+ debug,
36
+ autoConfirm,
37
+ );
38
+ }
39
+
40
+ async function updateVersionArchiveStatus(
41
+ packageServer: string,
42
+ packageName: string,
43
+ versionId: string,
44
+ action: "archive" | "unarchive",
45
+ debug: boolean,
46
+ autoConfirm: boolean,
47
+ ) {
48
+ const clientConfig = new ClientConfiguration();
49
+ const organizationName = clientConfig.getOrganization();
50
+ const projectName = clientConfig.getProject();
51
+
52
+ if (!clientConfig.doesConfigExists()) {
53
+ logger.error("Please, make sure that you are logged in");
54
+ return;
55
+ }
56
+
57
+ if (!projectName) {
58
+ logger.error("Please, make sure to set a project");
59
+ return;
60
+ }
61
+
62
+ if (!packageName) {
63
+ logger.error("Please provide a package name");
64
+ return;
65
+ }
66
+
67
+ if (!versionId) {
68
+ logger.error("Please provide a version ID");
69
+ return;
70
+ }
71
+
72
+ if (!autoConfirm) {
73
+ const confirmation = await getConfirmation(
74
+ `Are you sure you want to ${action} version ${packageName}/${versionId}?`,
75
+ );
76
+ if (!confirmation) {
77
+ return;
78
+ }
79
+ }
80
+
81
+ logger.info(
82
+ `${action === "archive" ? "Archiving" : "Unarchiving"} version ${packageName}/${versionId}`,
83
+ );
84
+ console.log(
85
+ `${packageServer}/organizations/${organizationName}/projects/${projectName}/packages/${packageName}/versions/${versionId}`,
86
+ );
87
+ try {
88
+ const response = await axios.patch(
89
+ `${packageServer}/organizations/${organizationName}/projects/${projectName}/packages/${packageName}/versions/${versionId}`,
90
+ {
91
+ archiveStatus: action,
92
+ },
93
+ {
94
+ headers: clientConfig.getHeaders(),
95
+ },
96
+ );
97
+
98
+ if (response.status === 200) {
99
+ logger.info(
100
+ `Version ${action === "archive" ? "archived" : "unarchived"} successfully`,
101
+ );
102
+ } else {
103
+ logger.error(
104
+ `Failed to ${action} version. Status: ${response.status}`,
105
+ );
106
+ }
107
+ } catch (e) {
108
+ logger.error(`Failed to ${action} version`);
109
+ printOutError(e, debug);
110
+ }
111
+ }