@credibledata/cred-cli 0.1.3 → 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 +804 -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 +5 -0
  113. package/package.json +24 -16
  114. package/src/client/.openapi-generator/FILES +1 -0
  115. package/src/client/api.ts +1999 -696
  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,597 @@
1
+ import { expect } from "chai";
2
+ import crypto from "crypto";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import sinon from "sinon";
6
+ import { PackagesApi } from "../../client/api";
7
+ import { ClientConfiguration } from "../../clientconfiguration";
8
+ import { logger } from "../../logger";
9
+ import { prettifyJson } from "../../utils";
10
+
11
+ // We need to stub archiver before publish.ts imports it.
12
+ // Since this is CommonJS, we replace archiver in the require cache.
13
+ let storedCloseCallback: Function | undefined;
14
+ let mockArchive: any;
15
+
16
+ function createMockArchive(sandbox: sinon.SinonSandbox) {
17
+ storedCloseCallback = undefined;
18
+
19
+ mockArchive = {
20
+ on: sandbox.stub().returnsThis(),
21
+ directory: sandbox.stub().returnsThis(),
22
+ pipe: sandbox.stub().returnsThis(),
23
+ finalize: sandbox.stub().callsFake(function () {
24
+ // Trigger the close event on the WriteStream when finalize is called
25
+ if (storedCloseCallback) {
26
+ // Use process.nextTick to ensure it fires after the promise is set up
27
+ process.nextTick(() => storedCloseCallback!());
28
+ }
29
+ return mockArchive;
30
+ }),
31
+ pointer: sandbox.stub().returns(1024),
32
+ };
33
+ return mockArchive;
34
+ }
35
+
36
+ describe("publish", () => {
37
+ let sandbox: sinon.SinonSandbox;
38
+ let createOrUpdatePackageStub: sinon.SinonStub;
39
+ let loggerStub: sinon.SinonStubbedInstance<typeof logger>;
40
+ let getConfirmationStub: sinon.SinonStub;
41
+ let readFileSyncStub: sinon.SinonStub;
42
+ let existsSyncStub: sinon.SinonStub;
43
+ let unlinkStub: sinon.SinonStub;
44
+ let createWriteStreamStub: sinon.SinonStub;
45
+ let validateManifestStub: sinon.SinonStub;
46
+ let processCwdStub: sinon.SinonStub;
47
+ let publish: (
48
+ controlPlane: string,
49
+ replicationCount: number,
50
+ debug: boolean,
51
+ autoConfirm: boolean,
52
+ setLatest: boolean,
53
+ ) => Promise<void>;
54
+
55
+ // Store the original archiver module so we can restore it
56
+ let originalArchiverModule: any;
57
+ const archiverModulePath = require.resolve("archiver");
58
+
59
+ beforeEach(() => {
60
+ sandbox = sinon.createSandbox();
61
+
62
+ // Create mock archive
63
+ const archive = createMockArchive(sandbox);
64
+
65
+ // Replace archiver in require cache with our mock factory
66
+ originalArchiverModule = require.cache[archiverModulePath];
67
+ require.cache[archiverModulePath] = {
68
+ id: archiverModulePath,
69
+ filename: archiverModulePath,
70
+ loaded: true,
71
+ exports: function () {
72
+ return archive;
73
+ },
74
+ } as any;
75
+
76
+ // Clear publish module from cache so it picks up the stubbed archiver
77
+ const publishModulePath = require.resolve("./publish");
78
+ delete require.cache[publishModulePath];
79
+
80
+ // Now require publish - it will get our mock archiver
81
+ publish = require("./publish").publish;
82
+
83
+ createOrUpdatePackageStub = sandbox.stub();
84
+ loggerStub = sandbox.stub(logger);
85
+ getConfirmationStub = sandbox.stub();
86
+ readFileSyncStub = sandbox.stub(fs, "readFileSync");
87
+ existsSyncStub = sandbox.stub(fs, "existsSync");
88
+ unlinkStub = sandbox.stub(fs, "unlink");
89
+ createWriteStreamStub = sandbox.stub(fs, "createWriteStream");
90
+ validateManifestStub = sandbox.stub();
91
+ sandbox.stub(console, "log");
92
+ processCwdStub = sandbox.stub(process, "cwd");
93
+
94
+ sandbox
95
+ .stub(ClientConfiguration.prototype, "getOrganization")
96
+ .returns("test-org");
97
+ sandbox
98
+ .stub(ClientConfiguration.prototype, "getProject")
99
+ .returns("test-project");
100
+ sandbox
101
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
102
+ .returns(true);
103
+ sandbox
104
+ .stub(ClientConfiguration.prototype, "isTokenValid")
105
+ .returns({ valid: true });
106
+ sandbox
107
+ .stub(ClientConfiguration.prototype, "getHeaders")
108
+ .returns({ Authorization: "Bearer test-token" });
109
+
110
+ sandbox
111
+ .stub(PackagesApi.prototype, "createOrUpdatePackage")
112
+ .callsFake(createOrUpdatePackageStub);
113
+ sandbox
114
+ .stub(require("../../utils"), "getConfirmation")
115
+ .callsFake(getConfirmationStub);
116
+ sandbox
117
+ .stub(require("../../validator"), "validateManifest")
118
+ .callsFake(validateManifestStub);
119
+
120
+ processCwdStub.returns("/test/package-name");
121
+ validateManifestStub.returns(true);
122
+ existsSyncStub.returns(true);
123
+
124
+ // Mock write stream that captures the close callback
125
+ const mockWriteStream = {
126
+ on: sandbox.stub().callsFake(function (
127
+ event: string,
128
+ callback: Function,
129
+ ) {
130
+ if (event === "close") {
131
+ storedCloseCallback = callback;
132
+ }
133
+ return mockWriteStream;
134
+ }),
135
+ once: sandbox.stub().returnsThis(),
136
+ emit: sandbox.stub().returnsThis(),
137
+ write: sandbox.stub(),
138
+ end: sandbox.stub(),
139
+ pipe: sandbox.stub().returnsThis(),
140
+ };
141
+ createWriteStreamStub.returns(mockWriteStream);
142
+ });
143
+
144
+ afterEach(() => {
145
+ sandbox.restore();
146
+ // Restore original archiver module
147
+ if (originalArchiverModule) {
148
+ require.cache[archiverModulePath] = originalArchiverModule;
149
+ } else {
150
+ delete require.cache[archiverModulePath];
151
+ }
152
+ });
153
+
154
+ it("should publish package successfully", async function () {
155
+ this.timeout(5000);
156
+ const mockManifest = {
157
+ name: "test-package",
158
+ version: "1.0.0",
159
+ description: "Test package",
160
+ };
161
+ const mockPackageData = Buffer.from("test package data");
162
+ const mockResponse = {
163
+ data: { name: "test-package", version: "1.0.0" },
164
+ };
165
+
166
+ readFileSyncStub.callsFake((filePath: string) => {
167
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
168
+ return mockPackageData;
169
+ });
170
+ getConfirmationStub.resolves(true);
171
+ createOrUpdatePackageStub.resolves(mockResponse);
172
+ unlinkStub.callsArg(1);
173
+
174
+ await publish("http://test-server", 2, false, true, false);
175
+
176
+ expect(validateManifestStub.calledOnce).to.be.true;
177
+ expect(readFileSyncStub.calledWith("publisher.json")).to.be.true;
178
+ expect(createOrUpdatePackageStub.calledOnce).to.be.true;
179
+ expect(createOrUpdatePackageStub.firstCall.args[0]).to.equal("test-org");
180
+ expect(createOrUpdatePackageStub.firstCall.args[1]).to.equal(
181
+ "test-project",
182
+ );
183
+ expect(createOrUpdatePackageStub.firstCall.args[2]).to.equal(
184
+ "test-package",
185
+ );
186
+ expect(createOrUpdatePackageStub.firstCall.args[3]).to.deep.include({
187
+ name: "test-package",
188
+ description: "Test package",
189
+ replicationCount: 2,
190
+ });
191
+ expect(createOrUpdatePackageStub.firstCall.args[4]).to.deep.include({
192
+ id: "1.0.0",
193
+ });
194
+ expect(
195
+ loggerStub.info.calledWith(
196
+ sinon.match(prettifyJson(mockResponse.data)),
197
+ ),
198
+ ).to.be.true;
199
+ });
200
+
201
+ it("should set latest version when setLatest is true", async function () {
202
+ this.timeout(5000);
203
+ const mockManifest = {
204
+ name: "test-package",
205
+ version: "1.0.0",
206
+ description: "Test package",
207
+ };
208
+ const mockPackageData = Buffer.from("test package data");
209
+
210
+ readFileSyncStub.callsFake((filePath: string) => {
211
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
212
+ return mockPackageData;
213
+ });
214
+ getConfirmationStub.resolves(true);
215
+ createOrUpdatePackageStub.resolves({ data: {} });
216
+ unlinkStub.callsArg(1);
217
+
218
+ await publish("http://test-server", 2, false, true, true);
219
+
220
+ expect(createOrUpdatePackageStub.firstCall.args[3]).to.deep.include({
221
+ latestVersion: "1.0.0",
222
+ });
223
+ });
224
+
225
+ it("should not set latest version when setLatest is false", async function () {
226
+ this.timeout(5000);
227
+ const mockManifest = {
228
+ name: "test-package",
229
+ version: "1.0.0",
230
+ description: "Test package",
231
+ };
232
+ const mockPackageData = Buffer.from("test package data");
233
+
234
+ readFileSyncStub.callsFake((filePath: string) => {
235
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
236
+ return mockPackageData;
237
+ });
238
+ getConfirmationStub.resolves(true);
239
+ createOrUpdatePackageStub.resolves({ data: {} });
240
+ unlinkStub.callsArg(1);
241
+
242
+ await publish("http://test-server", 2, false, true, false);
243
+
244
+ expect(createOrUpdatePackageStub.firstCall.args[3]).to.not.have.property(
245
+ "latestVersion",
246
+ );
247
+ });
248
+
249
+ it("should skip confirmation when autoConfirm is true", async function () {
250
+ this.timeout(5000);
251
+ const mockManifest = {
252
+ name: "test-package",
253
+ version: "1.0.0",
254
+ description: "Test package",
255
+ };
256
+ const mockPackageData = Buffer.from("test package data");
257
+
258
+ readFileSyncStub.callsFake((filePath: string) => {
259
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
260
+ return mockPackageData;
261
+ });
262
+ createOrUpdatePackageStub.resolves({ data: {} });
263
+ unlinkStub.callsArg(1);
264
+
265
+ await publish("http://test-server", 2, false, true, false);
266
+
267
+ expect(getConfirmationStub.called).to.be.false;
268
+ expect(createOrUpdatePackageStub.calledOnce).to.be.true;
269
+ });
270
+
271
+ it("should use package name from cwd directory", async function () {
272
+ this.timeout(5000);
273
+ processCwdStub.returns("/some/path/my-cool-package");
274
+ const mockManifest = {
275
+ name: "test-package",
276
+ version: "1.0.0",
277
+ description: "Test package",
278
+ };
279
+ const mockPackageData = Buffer.from("test package data");
280
+
281
+ readFileSyncStub.callsFake((filePath: string) => {
282
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
283
+ return mockPackageData;
284
+ });
285
+ createOrUpdatePackageStub.resolves({ data: {} });
286
+ unlinkStub.callsArg(1);
287
+
288
+ await publish("http://test-server", 2, false, true, false);
289
+
290
+ // The archive path should use the cwd directory name
291
+ expect(createWriteStreamStub.calledWith("/tmp/my-cool-package.zip")).to.be
292
+ .true;
293
+ });
294
+
295
+ it("should calculate MD5 hash correctly", async function () {
296
+ this.timeout(5000);
297
+ const mockManifest = {
298
+ name: "test-package",
299
+ version: "1.0.0",
300
+ description: "Test package",
301
+ };
302
+ const mockPackageData = Buffer.from("test package data");
303
+ const expectedHash = crypto
304
+ .createHash("md5")
305
+ .update(mockPackageData)
306
+ .digest("hex");
307
+
308
+ readFileSyncStub.callsFake((filePath: string) => {
309
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
310
+ return mockPackageData;
311
+ });
312
+ getConfirmationStub.resolves(true);
313
+ createOrUpdatePackageStub.resolves({ data: {} });
314
+ unlinkStub.callsArg(1);
315
+
316
+ await publish("http://test-server", 2, false, true, false);
317
+
318
+ expect(createOrUpdatePackageStub.firstCall.args[6]).to.equal(
319
+ expectedHash,
320
+ );
321
+ });
322
+
323
+ it("should handle missing config", async () => {
324
+ sandbox.restore();
325
+ sandbox = sinon.createSandbox();
326
+ createOrUpdatePackageStub = sandbox.stub();
327
+ loggerStub = sandbox.stub(logger);
328
+ getConfirmationStub = sandbox.stub();
329
+ readFileSyncStub = sandbox.stub(fs, "readFileSync");
330
+ existsSyncStub = sandbox.stub(fs, "existsSync");
331
+ validateManifestStub = sandbox.stub();
332
+
333
+ sandbox
334
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
335
+ .returns(false);
336
+ sandbox
337
+ .stub(PackagesApi.prototype, "createOrUpdatePackage")
338
+ .callsFake(createOrUpdatePackageStub);
339
+ sandbox
340
+ .stub(require("../../utils"), "getConfirmation")
341
+ .callsFake(getConfirmationStub);
342
+ sandbox
343
+ .stub(require("../../validator"), "validateManifest")
344
+ .callsFake(validateManifestStub);
345
+
346
+ await publish("http://test-server", 2, false, true, false);
347
+
348
+ expect(createOrUpdatePackageStub.called).to.be.false;
349
+ expect(
350
+ loggerStub.error.calledWith(
351
+ sinon.match("Please, make sure that you are logged in"),
352
+ ),
353
+ ).to.be.true;
354
+ });
355
+
356
+ it("should handle invalid token", async () => {
357
+ sandbox.restore();
358
+ sandbox = sinon.createSandbox();
359
+ createOrUpdatePackageStub = sandbox.stub();
360
+ loggerStub = sandbox.stub(logger);
361
+ getConfirmationStub = sandbox.stub();
362
+ readFileSyncStub = sandbox.stub(fs, "readFileSync");
363
+ existsSyncStub = sandbox.stub(fs, "existsSync");
364
+ validateManifestStub = sandbox.stub();
365
+
366
+ sandbox
367
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
368
+ .returns(true);
369
+ sandbox
370
+ .stub(ClientConfiguration.prototype, "isTokenValid")
371
+ .returns({ valid: false, reason: "No token found. Please login." });
372
+ sandbox
373
+ .stub(PackagesApi.prototype, "createOrUpdatePackage")
374
+ .callsFake(createOrUpdatePackageStub);
375
+ sandbox
376
+ .stub(require("../../utils"), "getConfirmation")
377
+ .callsFake(getConfirmationStub);
378
+ sandbox
379
+ .stub(require("../../validator"), "validateManifest")
380
+ .callsFake(validateManifestStub);
381
+
382
+ await publish("http://test-server", 2, false, true, false);
383
+
384
+ expect(createOrUpdatePackageStub.called).to.be.false;
385
+ expect(
386
+ loggerStub.error.calledWith(
387
+ sinon.match("No token found. Please login."),
388
+ ),
389
+ ).to.be.true;
390
+ });
391
+
392
+ it("should handle invalid manifest", async () => {
393
+ validateManifestStub.returns(false);
394
+
395
+ await publish("http://test-server", 2, false, true, false);
396
+
397
+ expect(createOrUpdatePackageStub.called).to.be.false;
398
+ });
399
+
400
+ it("should handle missing organization", async () => {
401
+ sandbox.restore();
402
+ sandbox = sinon.createSandbox();
403
+ createOrUpdatePackageStub = sandbox.stub();
404
+ loggerStub = sandbox.stub(logger);
405
+ getConfirmationStub = sandbox.stub();
406
+ readFileSyncStub = sandbox.stub(fs, "readFileSync");
407
+ existsSyncStub = sandbox.stub(fs, "existsSync");
408
+ validateManifestStub = sandbox.stub();
409
+
410
+ sandbox
411
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
412
+ .returns(true);
413
+ sandbox
414
+ .stub(ClientConfiguration.prototype, "isTokenValid")
415
+ .returns({ valid: true });
416
+ sandbox
417
+ .stub(ClientConfiguration.prototype, "getOrganization")
418
+ .returns("");
419
+ validateManifestStub.returns(true);
420
+ sandbox
421
+ .stub(PackagesApi.prototype, "createOrUpdatePackage")
422
+ .callsFake(createOrUpdatePackageStub);
423
+ sandbox
424
+ .stub(require("../../utils"), "getConfirmation")
425
+ .callsFake(getConfirmationStub);
426
+ sandbox
427
+ .stub(require("../../validator"), "validateManifest")
428
+ .callsFake(validateManifestStub);
429
+
430
+ await publish("http://test-server", 2, false, true, false);
431
+
432
+ expect(createOrUpdatePackageStub.called).to.be.false;
433
+ expect(
434
+ loggerStub.error.calledWith(
435
+ sinon.match("Please, make sure that you are logged in"),
436
+ ),
437
+ ).to.be.true;
438
+ });
439
+
440
+ it("should handle missing project", async () => {
441
+ sandbox.restore();
442
+ sandbox = sinon.createSandbox();
443
+ createOrUpdatePackageStub = sandbox.stub();
444
+ loggerStub = sandbox.stub(logger);
445
+ getConfirmationStub = sandbox.stub();
446
+ readFileSyncStub = sandbox.stub(fs, "readFileSync");
447
+ existsSyncStub = sandbox.stub(fs, "existsSync");
448
+ validateManifestStub = sandbox.stub();
449
+
450
+ sandbox
451
+ .stub(ClientConfiguration.prototype, "doesConfigExists")
452
+ .returns(true);
453
+ sandbox
454
+ .stub(ClientConfiguration.prototype, "isTokenValid")
455
+ .returns({ valid: true });
456
+ sandbox
457
+ .stub(ClientConfiguration.prototype, "getOrganization")
458
+ .returns("test-org");
459
+ sandbox.stub(ClientConfiguration.prototype, "getProject").returns("");
460
+ validateManifestStub.returns(true);
461
+ sandbox
462
+ .stub(PackagesApi.prototype, "createOrUpdatePackage")
463
+ .callsFake(createOrUpdatePackageStub);
464
+ sandbox
465
+ .stub(require("../../utils"), "getConfirmation")
466
+ .callsFake(getConfirmationStub);
467
+ sandbox
468
+ .stub(require("../../validator"), "validateManifest")
469
+ .callsFake(validateManifestStub);
470
+
471
+ await publish("http://test-server", 2, false, true, false);
472
+
473
+ expect(createOrUpdatePackageStub.called).to.be.false;
474
+ expect(
475
+ loggerStub.error.calledWith(
476
+ sinon.match("Please, make sure to set a project"),
477
+ ),
478
+ ).to.be.true;
479
+ });
480
+
481
+ it("should handle missing publisher.json", async () => {
482
+ existsSyncStub.callsFake((filePath: string) => {
483
+ if (filePath === "publisher.json") return false;
484
+ return true;
485
+ });
486
+
487
+ await publish("http://test-server", 2, false, true, false);
488
+
489
+ expect(createOrUpdatePackageStub.called).to.be.false;
490
+ expect(readFileSyncStub.called).to.be.false;
491
+ expect(
492
+ loggerStub.error.calledWith(
493
+ sinon.match(
494
+ "Failed to publish the package. Could not find publisher.json, please ensure you are in a directory containing publisher.json",
495
+ ),
496
+ ),
497
+ ).to.be.true;
498
+ });
499
+
500
+ it("should request confirmation when autoConfirm is false", async function () {
501
+ this.timeout(5000);
502
+ const mockManifest = {
503
+ name: "test-package",
504
+ version: "1.0.0",
505
+ description: "Test package",
506
+ };
507
+ const mockPackageData = Buffer.from("test package data");
508
+
509
+ readFileSyncStub.callsFake((filePath: string) => {
510
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
511
+ return mockPackageData;
512
+ });
513
+ getConfirmationStub.resolves(true);
514
+ createOrUpdatePackageStub.resolves({ data: {} });
515
+ unlinkStub.callsArg(1);
516
+
517
+ await publish("http://test-server", 2, false, false, false);
518
+
519
+ expect(getConfirmationStub.calledOnce).to.be.true;
520
+ expect(createOrUpdatePackageStub.calledOnce).to.be.true;
521
+ });
522
+
523
+ it("should cancel when confirmation is denied", async () => {
524
+ const mockManifest = {
525
+ name: "test-package",
526
+ version: "1.0.0",
527
+ description: "Test package",
528
+ };
529
+
530
+ readFileSyncStub.returns(JSON.stringify(mockManifest));
531
+ getConfirmationStub.resolves(false);
532
+
533
+ await publish("http://test-server", 2, false, false, false);
534
+
535
+ expect(getConfirmationStub.calledOnce).to.be.true;
536
+ expect(createOrUpdatePackageStub.called).to.be.false;
537
+ expect(loggerStub.info.calledWith(sinon.match("Operation cancelled."))).to
538
+ .be.true;
539
+ });
540
+
541
+ it("should handle API errors", async function () {
542
+ this.timeout(5000);
543
+ const mockManifest = {
544
+ name: "test-package",
545
+ version: "1.0.0",
546
+ description: "Test package",
547
+ };
548
+ const mockPackageData = Buffer.from("test package data");
549
+ const mockError = new Error("API Error");
550
+
551
+ readFileSyncStub.callsFake((filePath: string) => {
552
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
553
+ return mockPackageData;
554
+ });
555
+ getConfirmationStub.resolves(true);
556
+ createOrUpdatePackageStub.rejects(mockError);
557
+ unlinkStub.callsArg(1);
558
+
559
+ await publish("http://test-server", 2, true, true, false);
560
+
561
+ expect(createOrUpdatePackageStub.calledOnce).to.be.true;
562
+ expect(
563
+ loggerStub.error.calledWith(sinon.match("Failed to publish package")),
564
+ ).to.be.true;
565
+ });
566
+
567
+ it("should log package URL after successful publish", async function () {
568
+ this.timeout(5000);
569
+ const mockManifest = {
570
+ name: "test-package",
571
+ version: "1.0.0",
572
+ description: "Test package",
573
+ };
574
+ const mockPackageData = Buffer.from("test package data");
575
+ const mockResponse = {
576
+ data: { name: "test-package", version: "1.0.0" },
577
+ };
578
+
579
+ readFileSyncStub.callsFake((filePath: string) => {
580
+ if (filePath === "publisher.json") return JSON.stringify(mockManifest);
581
+ return mockPackageData;
582
+ });
583
+ getConfirmationStub.resolves(true);
584
+ createOrUpdatePackageStub.resolves(mockResponse);
585
+ unlinkStub.callsArg(1);
586
+
587
+ await publish("http://test-server", 2, false, true, false);
588
+
589
+ expect(
590
+ loggerStub.info.calledWith(
591
+ sinon.match(
592
+ "Package available at: test-org/test-project/test-package/1.0.0",
593
+ ),
594
+ ),
595
+ ).to.be.true;
596
+ });
597
+ });
@@ -27,6 +27,14 @@ export async function publish(
27
27
  return;
28
28
  }
29
29
 
30
+ const tokenValidation = clientConfig.isTokenValid();
31
+ if (!tokenValidation.valid) {
32
+ logger.error(
33
+ tokenValidation.reason || "Please, make sure that you are logged in",
34
+ );
35
+ return;
36
+ }
37
+
30
38
  if (!validateManifest()) {
31
39
  return;
32
40
  }
@@ -34,11 +42,23 @@ export async function publish(
34
42
  const projectName = clientConfig.getProject();
35
43
  const organizationName = clientConfig.getOrganization();
36
44
 
45
+ if (!organizationName) {
46
+ logger.error("Please, make sure that you are logged in");
47
+ return;
48
+ }
49
+
37
50
  if (!projectName) {
38
51
  logger.error("Please, make sure to set a project");
39
52
  return;
40
53
  }
41
54
 
55
+ if (!fs.existsSync(PACKAGE_MANIFEST_NAME)) {
56
+ logger.error(
57
+ `Failed to publish the package. Could not find ${PACKAGE_MANIFEST_NAME}, please ensure you are in a directory containing ${PACKAGE_MANIFEST_NAME}`,
58
+ );
59
+ return;
60
+ }
61
+
42
62
  const packageManifestJson = fs.readFileSync(PACKAGE_MANIFEST_NAME);
43
63
  const packageManifest = JSON.parse(packageManifestJson.toString());
44
64
 
@@ -141,6 +161,18 @@ async function pushTmpPackageToRemoteServer(
141
161
  .createHash("md5")
142
162
  .update(fs.readFileSync(tmpPackagePath))
143
163
  .digest("hex");
164
+ if (debug) {
165
+ logger.debug("Package contents: " + packageContents);
166
+ logger.debug("Organization name: " + organizationName);
167
+ logger.debug("Project name: " + projectName);
168
+ logger.debug("Name: " + name);
169
+ logger.debug("Package: " + JSON.stringify(_package));
170
+ logger.debug("Version: " + JSON.stringify(version));
171
+ logger.debug("Control plane: " + controlPlane);
172
+ logger.debug(
173
+ "Client config: " + JSON.stringify(clientConfig.getHeaders()),
174
+ );
175
+ }
144
176
  const response = await packagesApi.createOrUpdatePackage(
145
177
  organizationName,
146
178
  projectName,