@zuplo/cli 6.69.0 → 6.69.2

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 (82) hide show
  1. package/dist/__tests__/integration/info.integration.test.d.ts +2 -0
  2. package/dist/__tests__/integration/info.integration.test.d.ts.map +1 -0
  3. package/dist/__tests__/integration/info.integration.test.js +246 -0
  4. package/dist/__tests__/integration/info.integration.test.js.map +1 -0
  5. package/dist/__tests__/integration/jest-mocks-setup.js +6 -1
  6. package/dist/__tests__/integration/jest-mocks-setup.js.map +1 -1
  7. package/dist/cli.js +2 -0
  8. package/dist/cli.js.map +1 -1
  9. package/dist/cmds/info.d.ts +9 -0
  10. package/dist/cmds/info.d.ts.map +1 -0
  11. package/dist/cmds/info.js +19 -0
  12. package/dist/cmds/info.js.map +1 -0
  13. package/dist/cmds/project/index.d.ts.map +1 -1
  14. package/dist/cmds/project/index.js +2 -1
  15. package/dist/cmds/project/index.js.map +1 -1
  16. package/dist/cmds/project/info.d.ts +10 -0
  17. package/dist/cmds/project/info.d.ts.map +1 -0
  18. package/dist/cmds/project/info.js +50 -0
  19. package/dist/cmds/project/info.js.map +1 -0
  20. package/dist/common/api/lib.d.ts +6 -1
  21. package/dist/common/api/lib.d.ts.map +1 -1
  22. package/dist/common/api/lib.js.map +1 -1
  23. package/dist/common/middleware/authentication.d.ts +5 -2
  24. package/dist/common/middleware/authentication.d.ts.map +1 -1
  25. package/dist/common/middleware/authentication.js +27 -20
  26. package/dist/common/middleware/authentication.js.map +1 -1
  27. package/dist/common/read-linked-config.d.ts +1 -0
  28. package/dist/common/read-linked-config.d.ts.map +1 -1
  29. package/dist/common/read-linked-config.js +1 -0
  30. package/dist/common/read-linked-config.js.map +1 -1
  31. package/dist/common/read-linked-config.test.js +15 -0
  32. package/dist/common/read-linked-config.test.js.map +1 -1
  33. package/dist/common/utils/pretty-print-environment-prompt.d.ts.map +1 -1
  34. package/dist/common/utils/pretty-print-environment-prompt.js +9 -15
  35. package/dist/common/utils/pretty-print-environment-prompt.js.map +1 -1
  36. package/dist/common/utils/pretty-print-environment-prompt.test.d.ts +2 -0
  37. package/dist/common/utils/pretty-print-environment-prompt.test.d.ts.map +1 -0
  38. package/dist/common/utils/pretty-print-environment-prompt.test.js +44 -0
  39. package/dist/common/utils/pretty-print-environment-prompt.test.js.map +1 -0
  40. package/dist/project/info/handler.d.ts +7 -0
  41. package/dist/project/info/handler.d.ts.map +1 -0
  42. package/dist/project/info/handler.js +109 -0
  43. package/dist/project/info/handler.js.map +1 -0
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/node_modules/@zuplo/core/package.json +1 -1
  46. package/node_modules/@zuplo/graphql/package.json +1 -1
  47. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  48. package/node_modules/@zuplo/otel/package.json +1 -1
  49. package/node_modules/@zuplo/runtime/package.json +1 -1
  50. package/node_modules/uuid/dist/cjs/v35.js +3 -0
  51. package/node_modules/uuid/dist/cjs/v6.js +3 -0
  52. package/node_modules/uuid/dist/cjs-browser/v35.js +3 -0
  53. package/node_modules/uuid/dist/cjs-browser/v6.js +3 -0
  54. package/node_modules/uuid/dist/esm/v35.js +3 -0
  55. package/node_modules/uuid/dist/esm/v6.js +3 -0
  56. package/node_modules/uuid/dist/esm-browser/v35.js +3 -0
  57. package/node_modules/uuid/dist/esm-browser/v6.js +3 -0
  58. package/node_modules/uuid/package.json +1 -1
  59. package/package.json +6 -10
  60. package/node_modules/as-table/.babelrc +0 -3
  61. package/node_modules/as-table/.eslintrc +0 -6
  62. package/node_modules/as-table/.travis.yml +0 -24
  63. package/node_modules/as-table/CHANGELOG.md +0 -3
  64. package/node_modules/as-table/LICENSE +0 -21
  65. package/node_modules/as-table/README.md +0 -113
  66. package/node_modules/as-table/as-table.d.ts +0 -32
  67. package/node_modules/as-table/as-table.js +0 -89
  68. package/node_modules/as-table/build/as-table.js +0 -86
  69. package/node_modules/as-table/package.json +0 -67
  70. package/node_modules/as-table/test.js +0 -223
  71. package/node_modules/printable-characters/.babelrc +0 -3
  72. package/node_modules/printable-characters/.eslintrc +0 -6
  73. package/node_modules/printable-characters/.gitattributes +0 -2
  74. package/node_modules/printable-characters/.npmignore +0 -8
  75. package/node_modules/printable-characters/.travis.yml +0 -24
  76. package/node_modules/printable-characters/CHANGELOG.md +0 -1
  77. package/node_modules/printable-characters/LICENSE +0 -24
  78. package/node_modules/printable-characters/README.md +0 -88
  79. package/node_modules/printable-characters/build/printable-characters.js +0 -53
  80. package/node_modules/printable-characters/package.json +0 -72
  81. package/node_modules/printable-characters/printable-characters.js +0 -44
  82. package/node_modules/printable-characters/test.js +0 -77
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=info.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.integration.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/info.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,246 @@
1
+ import nock from "nock";
2
+ import yargs from "yargs/yargs";
3
+ import infoCommand from "../../cmds/info.js";
4
+ import { cleanupTest, setupAuthenticatedNock, setupTestEnvironment, TEST_ACCOUNT_NAME, TEST_API_BASE, TEST_AUTH_TOKEN, TEST_PROJECT_NAME, } from "./test-utils.js";
5
+ const TEST_ACCOUNT = TEST_ACCOUNT_NAME;
6
+ const TEST_PROJECT = TEST_PROJECT_NAME;
7
+ jest.mock("../../common/read-linked-config.js", () => ({
8
+ __esModule: true,
9
+ readLinkedConfig: jest.fn().mockResolvedValue({}),
10
+ confirmLinkedValue: jest.fn().mockResolvedValue(true),
11
+ USE_LINKED_DETAILS: "useLinkedDetails",
12
+ ignoreLinkedDetails: jest.fn(),
13
+ }));
14
+ const { readLinkedConfig } = jest.requireMock("../../common/read-linked-config.js");
15
+ async function executeInfoCommand(args) {
16
+ const yargsInstance = yargs([])
17
+ .command(infoCommand)
18
+ .help(false)
19
+ .version(false)
20
+ .exitProcess(false);
21
+ const commandArgs = ["info"];
22
+ if (args["api-key"]) {
23
+ commandArgs.push("--api-key", args["api-key"]);
24
+ }
25
+ return await yargsInstance.parse(commandArgs);
26
+ }
27
+ const mockPrintResult = jest.mocked(require("../../common/output.js").printResultToConsoleAndExitGracefully);
28
+ const mockPrintCriticalFailure = jest.mocked(require("../../common/output.js").printCriticalFailureToConsoleAndExit);
29
+ const mockPrintWarning = jest.mocked(require("../../common/output.js").printWarningToConsole);
30
+ describe("Info Command Integration Tests", () => {
31
+ beforeEach(() => {
32
+ setupTestEnvironment();
33
+ nock.cleanAll();
34
+ nock.disableNetConnect();
35
+ jest.clearAllMocks();
36
+ readLinkedConfig.mockResolvedValue({});
37
+ });
38
+ afterEach(() => {
39
+ cleanupTest();
40
+ });
41
+ it("should show 'no project linked' when .env.zuplo is missing", async () => {
42
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
43
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
44
+ const output = mockPrintResult.mock.calls[0][0];
45
+ expect(output).toContain("No project linked");
46
+ expect(output).toContain("zuplo link");
47
+ });
48
+ it("should show 'no project linked' when unauthenticated and not linked", async () => {
49
+ await executeInfoCommand({});
50
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
51
+ const output = mockPrintResult.mock.calls[0][0];
52
+ expect(output).toContain("No project linked");
53
+ expect(output).toContain("zuplo link");
54
+ expect(mockPrintCriticalFailure).not.toHaveBeenCalled();
55
+ });
56
+ it("should show full project info when linked", async () => {
57
+ readLinkedConfig.mockResolvedValue({
58
+ accountName: TEST_ACCOUNT,
59
+ projectName: TEST_PROJECT,
60
+ environmentType: "working_copy",
61
+ });
62
+ setupAuthenticatedNock(nock(TEST_API_BASE))
63
+ .get(`/v1/projects`)
64
+ .query({ accountName: TEST_ACCOUNT })
65
+ .reply(200, {
66
+ data: [
67
+ {
68
+ name: TEST_PROJECT,
69
+ sourceRepoUrl: "https://github.com/josh-twist/josh-poc",
70
+ sourceControlProvider: "GITHUB",
71
+ },
72
+ ],
73
+ });
74
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
75
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
76
+ const output = mockPrintResult.mock.calls[0][0];
77
+ expect(output).toContain(`Project: ${TEST_PROJECT}`);
78
+ expect(output).toContain(`Account: ${TEST_ACCOUNT}`);
79
+ expect(output).toContain(`Portal: https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}`);
80
+ expect(output).toContain("Environment Type: working_copy");
81
+ expect(output).toContain("Source Control: https://github.com/josh-twist/josh-poc");
82
+ });
83
+ it("should show source control deep link when no repo is connected", async () => {
84
+ readLinkedConfig.mockResolvedValue({
85
+ accountName: TEST_ACCOUNT,
86
+ projectName: TEST_PROJECT,
87
+ environmentType: "production",
88
+ });
89
+ setupAuthenticatedNock(nock(TEST_API_BASE))
90
+ .get(`/v1/projects`)
91
+ .query({ accountName: TEST_ACCOUNT })
92
+ .reply(200, {
93
+ data: [
94
+ {
95
+ name: TEST_PROJECT,
96
+ sourceRepoUrl: null,
97
+ sourceControlProvider: "NONE",
98
+ },
99
+ ],
100
+ });
101
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
102
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
103
+ const output = mockPrintResult.mock.calls[0][0];
104
+ expect(output).toContain(`Source Control: none, connect at https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}/settings/source-control-settings`);
105
+ });
106
+ it("should omit environment type when not in linked config", async () => {
107
+ readLinkedConfig.mockResolvedValue({
108
+ accountName: TEST_ACCOUNT,
109
+ projectName: TEST_PROJECT,
110
+ });
111
+ setupAuthenticatedNock(nock(TEST_API_BASE))
112
+ .get(`/v1/projects`)
113
+ .query({ accountName: TEST_ACCOUNT })
114
+ .reply(200, {
115
+ data: [
116
+ {
117
+ name: TEST_PROJECT,
118
+ sourceRepoUrl: null,
119
+ sourceControlProvider: "NONE",
120
+ },
121
+ ],
122
+ });
123
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
124
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
125
+ const output = mockPrintResult.mock.calls[0][0];
126
+ expect(output).not.toContain("Environment Type:");
127
+ });
128
+ it("should exit with error when API returns 401 and --api-key was used", async () => {
129
+ readLinkedConfig.mockResolvedValue({
130
+ accountName: TEST_ACCOUNT,
131
+ projectName: TEST_PROJECT,
132
+ environmentType: "development",
133
+ });
134
+ setupAuthenticatedNock(nock(TEST_API_BASE))
135
+ .get(`/v1/projects`)
136
+ .query({ accountName: TEST_ACCOUNT })
137
+ .reply(401, {
138
+ type: "https://httpproblems.com/http-status/401",
139
+ title: "Unauthorized",
140
+ status: 401,
141
+ detail: "Invalid token",
142
+ });
143
+ await expect(executeInfoCommand({ "api-key": TEST_AUTH_TOKEN })).rejects.toThrow("Process would exit");
144
+ expect(mockPrintCriticalFailure).toHaveBeenCalledWith("The provided --api-key was rejected. Check that it is valid and not expired, or run `zuplo login` to authenticate interactively.");
145
+ expect(mockPrintResult).not.toHaveBeenCalled();
146
+ expect(mockPrintWarning).not.toHaveBeenCalled();
147
+ });
148
+ it("should exit with error when API returns 401 and saved credentials were used", async () => {
149
+ readLinkedConfig.mockResolvedValue({
150
+ accountName: TEST_ACCOUNT,
151
+ projectName: TEST_PROJECT,
152
+ environmentType: "development",
153
+ });
154
+ setupAuthenticatedNock(nock(TEST_API_BASE))
155
+ .get(`/v1/projects`)
156
+ .query({ accountName: TEST_ACCOUNT })
157
+ .reply(401, {
158
+ type: "https://httpproblems.com/http-status/401",
159
+ title: "Unauthorized",
160
+ status: 401,
161
+ detail: "Invalid token",
162
+ });
163
+ await expect(executeInfoCommand({})).rejects.toThrow("Process would exit");
164
+ expect(mockPrintCriticalFailure).toHaveBeenCalledWith("Your saved credentials were rejected. They may be expired — run `zuplo login` to re-authenticate, or pass a valid --api-key.");
165
+ expect(mockPrintResult).not.toHaveBeenCalled();
166
+ expect(mockPrintWarning).not.toHaveBeenCalled();
167
+ });
168
+ it("should show local info with warning when API returns a server error", async () => {
169
+ readLinkedConfig.mockResolvedValue({
170
+ accountName: TEST_ACCOUNT,
171
+ projectName: TEST_PROJECT,
172
+ environmentType: "development",
173
+ });
174
+ setupAuthenticatedNock(nock(TEST_API_BASE))
175
+ .get(`/v1/projects`)
176
+ .query({ accountName: TEST_ACCOUNT })
177
+ .reply(500, { error: "Internal Server Error" });
178
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
179
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
180
+ const output = mockPrintResult.mock.calls[0][0];
181
+ expect(output).toContain(`Project: ${TEST_PROJECT}`);
182
+ expect(output).toContain(`Account: ${TEST_ACCOUNT}`);
183
+ expect(output).not.toContain("Source Control:");
184
+ expect(mockPrintWarning).toHaveBeenCalledWith("Unable to fetch project details, some information may be missing");
185
+ });
186
+ it("should exit with error when API returns a non-401 4xx", async () => {
187
+ readLinkedConfig.mockResolvedValue({
188
+ accountName: TEST_ACCOUNT,
189
+ projectName: TEST_PROJECT,
190
+ environmentType: "development",
191
+ });
192
+ setupAuthenticatedNock(nock(TEST_API_BASE))
193
+ .get(`/v1/projects`)
194
+ .query({ accountName: TEST_ACCOUNT })
195
+ .reply(403, { error: "Forbidden" });
196
+ await expect(executeInfoCommand({ "api-key": TEST_AUTH_TOKEN })).rejects.toThrow("Process would exit");
197
+ expect(mockPrintCriticalFailure).toHaveBeenCalledWith(`The Zuplo API returned 403 Forbidden. Verify the account "${TEST_ACCOUNT}" and your credentials.`);
198
+ expect(mockPrintResult).not.toHaveBeenCalled();
199
+ expect(mockPrintWarning).not.toHaveBeenCalled();
200
+ });
201
+ it("should show local info with warning on network error", async () => {
202
+ readLinkedConfig.mockResolvedValue({
203
+ accountName: TEST_ACCOUNT,
204
+ projectName: TEST_PROJECT,
205
+ environmentType: "development",
206
+ });
207
+ setupAuthenticatedNock(nock(TEST_API_BASE))
208
+ .get(`/v1/projects`)
209
+ .query({ accountName: TEST_ACCOUNT })
210
+ .replyWithError("ECONNREFUSED");
211
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
212
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
213
+ const output = mockPrintResult.mock.calls[0][0];
214
+ expect(output).toContain(`Project: ${TEST_PROJECT}`);
215
+ expect(output).toContain(`Account: ${TEST_ACCOUNT}`);
216
+ expect(output).not.toContain("Source Control:");
217
+ expect(mockPrintWarning).toHaveBeenCalledWith("Unable to fetch project details, some information may be missing");
218
+ });
219
+ it("should warn and omit source control when linked project is not in API response", async () => {
220
+ readLinkedConfig.mockResolvedValue({
221
+ accountName: TEST_ACCOUNT,
222
+ projectName: TEST_PROJECT,
223
+ environmentType: "working_copy",
224
+ });
225
+ setupAuthenticatedNock(nock(TEST_API_BASE))
226
+ .get(`/v1/projects`)
227
+ .query({ accountName: TEST_ACCOUNT })
228
+ .reply(200, {
229
+ data: [
230
+ {
231
+ name: "some-other-project",
232
+ sourceRepoUrl: "https://github.com/josh-twist/other",
233
+ sourceControlProvider: "GITHUB",
234
+ },
235
+ ],
236
+ });
237
+ await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
238
+ expect(mockPrintResult).toHaveBeenCalledTimes(1);
239
+ const output = mockPrintResult.mock.calls[0][0];
240
+ expect(output).toContain(`Project: ${TEST_PROJECT}`);
241
+ expect(output).toContain(`Account: ${TEST_ACCOUNT}`);
242
+ expect(output).not.toContain("Source Control:");
243
+ expect(mockPrintWarning).toHaveBeenCalledWith(`Project "${TEST_PROJECT}" was not found in account "${TEST_ACCOUNT}". Run \`zuplo link\` to link a project.`);
244
+ });
245
+ });
246
+ //# sourceMappingURL=info.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/info.integration.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Integration tests for the info command\n */\n/// <reference types=\"jest\" />\nimport nock from \"nock\";\nimport yargs from \"yargs/yargs\";\nimport infoCommand from \"../../cmds/info.js\";\nimport {\n cleanupTest,\n setupAuthenticatedNock,\n setupTestEnvironment,\n TEST_ACCOUNT_NAME,\n TEST_API_BASE,\n TEST_AUTH_TOKEN,\n TEST_PROJECT_NAME,\n} from \"./test-utils.js\";\n\nconst TEST_ACCOUNT = TEST_ACCOUNT_NAME;\nconst TEST_PROJECT = TEST_PROJECT_NAME;\n\njest.mock(\"../../common/read-linked-config.js\", () => ({\n __esModule: true,\n readLinkedConfig: jest.fn().mockResolvedValue({}),\n confirmLinkedValue: jest.fn().mockResolvedValue(true),\n USE_LINKED_DETAILS: \"useLinkedDetails\",\n ignoreLinkedDetails: jest.fn(),\n}));\n\nconst { readLinkedConfig } = jest.requireMock(\n \"../../common/read-linked-config.js\"\n) as { readLinkedConfig: jest.Mock };\n\nasync function executeInfoCommand(args: { \"api-key\"?: string }) {\n const yargsInstance = yargs([])\n .command(infoCommand)\n .help(false)\n .version(false)\n .exitProcess(false);\n\n const commandArgs = [\"info\"];\n\n if (args[\"api-key\"]) {\n commandArgs.push(\"--api-key\", args[\"api-key\"]);\n }\n\n return await yargsInstance.parse(commandArgs);\n}\n\nconst mockPrintResult = jest.mocked(\n require(\"../../common/output.js\").printResultToConsoleAndExitGracefully\n);\nconst mockPrintCriticalFailure = jest.mocked(\n require(\"../../common/output.js\").printCriticalFailureToConsoleAndExit\n);\nconst mockPrintWarning = jest.mocked(\n require(\"../../common/output.js\").printWarningToConsole\n);\n\ndescribe(\"Info Command Integration Tests\", () => {\n beforeEach(() => {\n setupTestEnvironment();\n nock.cleanAll();\n nock.disableNetConnect();\n jest.clearAllMocks();\n readLinkedConfig.mockResolvedValue({});\n });\n\n afterEach(() => {\n cleanupTest();\n });\n\n it(\"should show 'no project linked' when .env.zuplo is missing\", async () => {\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"No project linked\");\n expect(output).toContain(\"zuplo link\");\n });\n\n it(\"should show 'no project linked' when unauthenticated and not linked\", async () => {\n await executeInfoCommand({});\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"No project linked\");\n expect(output).toContain(\"zuplo link\");\n expect(mockPrintCriticalFailure).not.toHaveBeenCalled();\n });\n\n it(\"should show full project info when linked\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"working_copy\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: \"https://github.com/josh-twist/josh-poc\",\n sourceControlProvider: \"GITHUB\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).toContain(\n `Portal: https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}`\n );\n expect(output).toContain(\"Environment Type: working_copy\");\n expect(output).toContain(\n \"Source Control: https://github.com/josh-twist/josh-poc\"\n );\n });\n\n it(\"should show source control deep link when no repo is connected\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"production\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\n `Source Control: none, connect at https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}/settings/source-control-settings`\n );\n });\n\n it(\"should omit environment type when not in linked config\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).not.toContain(\"Environment Type:\");\n });\n\n it(\"should exit with error when API returns 401 and --api-key was used\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(401, {\n type: \"https://httpproblems.com/http-status/401\",\n title: \"Unauthorized\",\n status: 401,\n detail: \"Invalid token\",\n });\n\n await expect(\n executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN })\n ).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n \"The provided --api-key was rejected. Check that it is valid and not expired, or run `zuplo login` to authenticate interactively.\"\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should exit with error when API returns 401 and saved credentials were used\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(401, {\n type: \"https://httpproblems.com/http-status/401\",\n title: \"Unauthorized\",\n status: 401,\n detail: \"Invalid token\",\n });\n\n await expect(executeInfoCommand({})).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n \"Your saved credentials were rejected. They may be expired — run `zuplo login` to re-authenticate, or pass a valid --api-key.\"\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should show local info with warning when API returns a server error\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(500, { error: \"Internal Server Error\" });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n \"Unable to fetch project details, some information may be missing\"\n );\n });\n\n it(\"should exit with error when API returns a non-401 4xx\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(403, { error: \"Forbidden\" });\n\n await expect(\n executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN })\n ).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n `The Zuplo API returned 403 Forbidden. Verify the account \"${TEST_ACCOUNT}\" and your credentials.`\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should show local info with warning on network error\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .replyWithError(\"ECONNREFUSED\");\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n \"Unable to fetch project details, some information may be missing\"\n );\n });\n\n it(\"should warn and omit source control when linked project is not in API response\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"working_copy\",\n });\n\n // API returns projects but none match the linked project name (stale .env.zuplo)\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: \"some-other-project\",\n sourceRepoUrl: \"https://github.com/josh-twist/other\",\n sourceControlProvider: \"GITHUB\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n `Project \"${TEST_PROJECT}\" was not found in account \"${TEST_ACCOUNT}\". Run \\`zuplo link\\` to link a project.`\n );\n });\n});\n"]}
@@ -32,7 +32,12 @@ jest.mock("../../common/analytics/lib.js", () => ({
32
32
  }));
33
33
  jest.mock("../../common/middleware/authentication.js", () => ({
34
34
  authenticate: jest.fn((argv) => {
35
- return { ...argv, authToken: TEST_AUTH_TOKEN };
35
+ argv.authToken = TEST_AUTH_TOKEN;
36
+ return argv;
37
+ }),
38
+ authenticateNoPrompt: jest.fn((argv) => {
39
+ argv.authToken = TEST_AUTH_TOKEN;
40
+ return argv;
36
41
  }),
37
42
  }));
38
43
  jest.mock("@inquirer/prompts", () => ({
@@ -1 +1 @@
1
- {"version":3,"file":"jest-mocks-setup.js","sourceRoot":"","sources":["../../../src/__tests__/integration/jest-mocks-setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Jest mocks setup - loaded before all test modules\n * This file contains all the Jest mocks that need to be applied before any modules are imported\n */\nimport type { Ora } from \"ora\";\n\nconst TEST_AUTH_TOKEN = \"test-auth-token-123\";\n\n// Mock all output functions to prevent actual console output and process.exit calls\njest.mock(\"../../common/output.js\", () => ({\n __esModule: true,\n default: jest.fn((argv: unknown) => argv), // setBlocking middleware function\n printResultToConsoleAndExitGracefully: jest.fn().mockResolvedValue(undefined),\n printTableToConsoleAndExitGracefully: jest.fn().mockResolvedValue(undefined),\n printJsonToConsoleAndExitGracefully: jest.fn().mockResolvedValue(undefined),\n printResultToConsole: jest.fn().mockResolvedValue(undefined),\n printJsonToConsole: jest.fn().mockResolvedValue(undefined),\n printDiagnosticsToConsole: jest.fn(),\n printWarningToConsole: jest.fn(),\n printSpinnerToConsole: jest.fn().mockReturnValue({\n stop: jest.fn(),\n succeed: jest.fn(),\n fail: jest.fn(),\n suffixText: \"\",\n } as unknown as Ora),\n printCriticalFailureToConsoleAndExit: jest.fn().mockImplementation(() => {\n throw new Error(\"Process would exit\");\n }),\n textOrJson: jest.fn((text: string) => {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }),\n}));\n\n// Mock analytics\njest.mock(\"../../common/analytics/lib.js\", () => ({\n captureEvent: jest.fn().mockResolvedValue(undefined),\n}));\n\n// Mock authentication middleware to add authToken\njest.mock(\"../../common/middleware/authentication.js\", () => ({\n authenticate: jest.fn((argv: Record<string, unknown>) => {\n return { ...argv, authToken: TEST_AUTH_TOKEN };\n }),\n}));\n\n// Mock inquirer prompts to return predictable values for tests\njest.mock(\"@inquirer/prompts\", () => ({\n select: jest.fn().mockImplementation(({ choices }) => {\n if (Array.isArray(choices) && choices.length > 0) {\n // Skip null sentinel values (e.g. \"+ Create a new project\") and return the first real project.\n const firstReal = choices.find((c) => c.value !== null) ?? choices[0];\n return Promise.resolve(firstReal.value);\n }\n return Promise.resolve(\"test-default\");\n }),\n input: jest.fn().mockResolvedValue(\"test-new-project\"),\n}));\n\n// Mock other middleware to pass through arguments\njest.mock(\"../../common/middleware/user-configuration.js\", () => ({\n configure: jest.fn((argv: unknown) => argv),\n}));\n\njest.mock(\"../../common/middleware/user-identification.js\", () => ({\n identify: jest.fn((argv: unknown) => argv),\n}));\n\n// Mock validators to pass through\njest.mock(\"../../common/validators/lib.js\", () => ({\n YargsChecker: jest.fn().mockImplementation(() => ({\n check: jest.fn().mockResolvedValue(true),\n })),\n}));\n\n// Mock group handler for commands with subcommands\njest.mock(\"../../common/handler.js\", () => ({\n groupHandler: jest.fn(),\n}));\n\n// Mock token functions to prevent file system and HTTP calls\njest.mock(\"../../login/tokens.js\", () => ({\n getAuthToken: jest.fn().mockResolvedValue(TEST_AUTH_TOKEN),\n refreshAccessToken: jest.fn().mockResolvedValue({\n access_token: TEST_AUTH_TOKEN,\n id_token: \"mock-id-token\",\n expires_in: 3600,\n token_type: \"Bearer\",\n scope: \"openid profile email\",\n }),\n}));\n"]}
1
+ {"version":3,"file":"jest-mocks-setup.js","sourceRoot":"","sources":["../../../src/__tests__/integration/jest-mocks-setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Jest mocks setup - loaded before all test modules\n * This file contains all the Jest mocks that need to be applied before any modules are imported\n */\nimport type { Ora } from \"ora\";\n\nconst TEST_AUTH_TOKEN = \"test-auth-token-123\";\n\n// Mock all output functions to prevent actual console output and process.exit calls\njest.mock(\"../../common/output.js\", () => ({\n __esModule: true,\n default: jest.fn((argv: unknown) => argv), // setBlocking middleware function\n printResultToConsoleAndExitGracefully: jest.fn().mockResolvedValue(undefined),\n printTableToConsoleAndExitGracefully: jest.fn().mockResolvedValue(undefined),\n printJsonToConsoleAndExitGracefully: jest.fn().mockResolvedValue(undefined),\n printResultToConsole: jest.fn().mockResolvedValue(undefined),\n printJsonToConsole: jest.fn().mockResolvedValue(undefined),\n printDiagnosticsToConsole: jest.fn(),\n printWarningToConsole: jest.fn(),\n printSpinnerToConsole: jest.fn().mockReturnValue({\n stop: jest.fn(),\n succeed: jest.fn(),\n fail: jest.fn(),\n suffixText: \"\",\n } as unknown as Ora),\n printCriticalFailureToConsoleAndExit: jest.fn().mockImplementation(() => {\n throw new Error(\"Process would exit\");\n }),\n textOrJson: jest.fn((text: string) => {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }),\n}));\n\n// Mock analytics\njest.mock(\"../../common/analytics/lib.js\", () => ({\n captureEvent: jest.fn().mockResolvedValue(undefined),\n}));\n\n// Mock authentication middleware to add authToken\njest.mock(\"../../common/middleware/authentication.js\", () => ({\n authenticate: jest.fn((argv: Record<string, unknown>) => {\n argv.authToken = TEST_AUTH_TOKEN;\n return argv;\n }),\n authenticateNoPrompt: jest.fn((argv: Record<string, unknown>) => {\n argv.authToken = TEST_AUTH_TOKEN;\n return argv;\n }),\n}));\n\n// Mock inquirer prompts to return predictable values for tests\njest.mock(\"@inquirer/prompts\", () => ({\n select: jest.fn().mockImplementation(({ choices }) => {\n if (Array.isArray(choices) && choices.length > 0) {\n // Skip null sentinel values (e.g. \"+ Create a new project\") and return the first real project.\n const firstReal = choices.find((c) => c.value !== null) ?? choices[0];\n return Promise.resolve(firstReal.value);\n }\n return Promise.resolve(\"test-default\");\n }),\n input: jest.fn().mockResolvedValue(\"test-new-project\"),\n}));\n\n// Mock other middleware to pass through arguments\njest.mock(\"../../common/middleware/user-configuration.js\", () => ({\n configure: jest.fn((argv: unknown) => argv),\n}));\n\njest.mock(\"../../common/middleware/user-identification.js\", () => ({\n identify: jest.fn((argv: unknown) => argv),\n}));\n\n// Mock validators to pass through\njest.mock(\"../../common/validators/lib.js\", () => ({\n YargsChecker: jest.fn().mockImplementation(() => ({\n check: jest.fn().mockResolvedValue(true),\n })),\n}));\n\n// Mock group handler for commands with subcommands\njest.mock(\"../../common/handler.js\", () => ({\n groupHandler: jest.fn(),\n}));\n\n// Mock token functions to prevent file system and HTTP calls\njest.mock(\"../../login/tokens.js\", () => ({\n getAuthToken: jest.fn().mockResolvedValue(TEST_AUTH_TOKEN),\n refreshAccessToken: jest.fn().mockResolvedValue({\n access_token: TEST_AUTH_TOKEN,\n id_token: \"mock-id-token\",\n expires_in: 3600,\n token_type: \"Bearer\",\n scope: \"openid profile email\",\n }),\n}));\n"]}
package/dist/cli.js CHANGED
@@ -16,6 +16,7 @@ import deploy from "./cmds/deploy.js";
16
16
  import dev from "./cmds/dev.js";
17
17
  import docs from "./cmds/docs.js";
18
18
  import editor from "./cmds/editor.js";
19
+ import info from "./cmds/info.js";
19
20
  import init from "./cmds/init.js";
20
21
  import link from "./cmds/link.js";
21
22
  import list from "./cmds/list.js";
@@ -88,6 +89,7 @@ if (gte(process.versions.node, MIN_NODE_VERSION)) {
88
89
  .command(dev)
89
90
  .command(docs)
90
91
  .command(editor)
92
+ .command(info)
91
93
  .command(init)
92
94
  .command(list)
93
95
  .command(link)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import * as dotenv from \"dotenv\";\n\ndotenv.config();\n\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { confirm } from \"@inquirer/prompts\";\nimport * as Sentry from \"@sentry/node\";\nimport { gte } from \"semver\";\n// Undici must be imported first to set the global dispatcher\n// If fetch is used before undici, the process will crash\nimport undici from \"undici\";\nimport { hideBin } from \"yargs/helpers\";\nimport yargs from \"yargs/yargs\";\nimport build from \"./cmds/build.js\";\nimport compile from \"./cmds/compile.js\";\nimport customDomain from \"./cmds/custom-domain/index.js\";\nimport deleteZup from \"./cmds/delete.js\";\nimport deploy from \"./cmds/deploy.js\";\nimport dev from \"./cmds/dev.js\";\nimport docs from \"./cmds/docs.js\";\nimport editor from \"./cmds/editor.js\";\nimport init from \"./cmds/init.js\";\nimport link from \"./cmds/link.js\";\nimport list from \"./cmds/list.js\";\nimport login from \"./cmds/login.js\";\nimport mtlsCertificates from \"./cmds/mtls-certificates/index.js\";\nimport oas from \"./cmds/open-api/index.js\";\nimport project from \"./cmds/project/index.js\";\nimport proxies from \"./cmds/proxies/index.js\";\nimport source from \"./cmds/source/index.js\";\nimport test from \"./cmds/test.js\";\nimport tunnel from \"./cmds/tunnel/index.js\";\nimport variable from \"./cmds/variable/index.js\";\nimport whoami from \"./cmds/whoami.js\";\nimport { shutdownAnalytics } from \"./common/analytics/lib.js\";\nimport { MAX_WAIT_PENDING_TIME_MS, SENTRY_DSN } from \"./common/constants.js\";\nimport { logger } from \"./common/logger.js\";\nimport { logLevel } from \"./common/middleware/logging.js\";\nimport { warnIfOutdatedVersion, warnNodeVersion } from \"./common/outdated.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"./common/output.js\";\n\n// This allows us to stop the CLI from executing so we can connect the profiler\n\n// biome-ignore lint/style/noProcessEnv: Migrated from ESLint\nif (process.env.ZUPLO_CLI_PROFILING) {\n await confirm({ message: \"Continue executing CLI?\", default: true });\n}\n\n// Note: We cannot set this to be higher than 18.0.0 because of the way\n// our documentation works -- we tell them to use npx @zuplo/cli@latest (even in CI/CD jobs)\n// If we set this to be higher than 18.0.0, then we will break them.\n// Instead we set the value in package.json to be engine.node >= 20.0.0, so it will warn\nconst MIN_NODE_VERSION = \"18.0.0\";\nconst RECOMMENDED_NODE_VERSION = \"20.0.0\";\n\nif (gte(process.versions.node, MIN_NODE_VERSION)) {\n let cliVersion: string;\n try {\n const packageJson = JSON.parse(\n readFileSync(\n fileURLToPath(new URL(\"../package.json\", import.meta.url)),\n \"utf-8\"\n )\n );\n cliVersion = packageJson.version;\n } catch (e) {\n cliVersion = \"0.0.0\";\n logger.error(e);\n await printCriticalFailureToConsoleAndExit(\n `Unable to load @zuplo/cli. The package.json is missing or malformed.`\n );\n }\n\n await warnNodeVersion(cliVersion, RECOMMENDED_NODE_VERSION);\n\n undici.setGlobalDispatcher(\n undici.getGlobalDispatcher().compose((dispatch) => {\n return (opts, handler) => {\n opts.headers = {\n ...opts.headers,\n \"user-agent\": `ZuploCLI/${cliVersion}`,\n\n // biome-ignore lint/style/noProcessEnv: Migrated from ESLint\n ...(process.env.ZUPLO_CANARY ? { \"zp-canary\": \"true\" } : {}),\n };\n return dispatch(opts, handler);\n };\n })\n );\n\n Sentry.init({\n dsn: SENTRY_DSN,\n release: cliVersion,\n });\n\n const cli = yargs(hideBin(process.argv))\n // This means that all env vars will have to be prefixed with ZUPLO_\n .env(\"ZUPLO\")\n .option(\"prompt\", {\n type: \"boolean\",\n describe: \"Bypass confirmation prompts\",\n default: true,\n hidden: true,\n })\n .option(\"verbose\", {\n alias: \"v\",\n type: \"count\",\n describe: \"Increase verbosity level (-v, -vv, -vvv)\",\n default: 0,\n })\n .middleware(logLevel)\n .command(compile)\n .command(customDomain)\n .command(deleteZup) // delete is a reserved keyword in JavaScript, so we call this function deleteZup\n .command(deploy)\n .command(dev)\n .command(docs)\n .command(editor)\n .command(init)\n .command(list)\n .command(link)\n .command(login)\n .command(test)\n .command(oas)\n .command(mtlsCertificates)\n .command(project)\n .command(source)\n .command(tunnel)\n .command(variable)\n .command(build)\n .command(proxies)\n .command(whoami)\n .command({\n command: \"hello\",\n handler: async () => {\n await fetch(\"https://393b4699ced44cc2ae87e4ad86184a29.api.mockbin.io/\");\n },\n })\n .demandCommand()\n .strictCommands()\n .version(cliVersion)\n .fail(false)\n .help();\n\n try {\n await cli.argv;\n\n // Don't block\n void warnIfOutdatedVersion(cliVersion);\n\n void Sentry.close(MAX_WAIT_PENDING_TIME_MS).then(() => {\n process.exit(0);\n });\n } catch (err) {\n if (err instanceof Error) {\n Sentry.captureException(err);\n }\n await printCriticalFailureToConsoleAndExit(err.message ?? err);\n cli.showHelp();\n } finally {\n await shutdownAnalytics();\n }\n} else {\n await printCriticalFailureToConsoleAndExit(\n `The Zuplo CLI requires at least node.js v${MIN_NODE_VERSION}. You are using v${process.versions.node}. Please update your version of node.js.\n\n Consider using a Node.js version manager such as https://github.com/nvm-sh/nvm.`\n );\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAG7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,aAAa,CAAC;AAChC,OAAO,KAAK,MAAM,iBAAiB,CAAC;AACpC,OAAO,OAAO,MAAM,mBAAmB,CAAC;AACxC,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,SAAS,MAAM,kBAAkB,CAAC;AACzC,OAAO,MAAM,MAAM,kBAAkB,CAAC;AACtC,OAAO,GAAG,MAAM,eAAe,CAAC;AAChC,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,MAAM,MAAM,kBAAkB,CAAC;AACtC,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,KAAK,MAAM,iBAAiB,CAAC;AACpC,OAAO,gBAAgB,MAAM,mCAAmC,CAAC;AACjE,OAAO,GAAG,MAAM,0BAA0B,CAAC;AAC3C,OAAO,OAAO,MAAM,yBAAyB,CAAC;AAC9C,OAAO,OAAO,MAAM,yBAAyB,CAAC;AAC9C,OAAO,MAAM,MAAM,wBAAwB,CAAC;AAC5C,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,MAAM,MAAM,wBAAwB,CAAC;AAC5C,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAChD,OAAO,MAAM,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,oCAAoC,EAAE,MAAM,oBAAoB,CAAC;AAK1E,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;IACpC,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AACvE,CAAC;AAMD,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAClC,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AAE1C,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE,CAAC;IACjD,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CACV,aAAa,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC1D,OAAO,CACR,CACF,CAAC;QACF,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,UAAU,GAAG,OAAO,CAAC;QACrB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,oCAAoC,CACxC,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC;IAE5D,MAAM,CAAC,mBAAmB,CACxB,MAAM,CAAC,mBAAmB,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChD,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YACvB,IAAI,CAAC,OAAO,GAAG;gBACb,GAAG,IAAI,CAAC,OAAO;gBACf,YAAY,EAAE,YAAY,UAAU,EAAE;gBAGtC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC7D,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC;QACV,GAAG,EAAE,UAAU;QACf,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAErC,GAAG,CAAC,OAAO,CAAC;SACZ,MAAM,CAAC,QAAQ,EAAE;QAChB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,6BAA6B;QACvC,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,IAAI;KACb,CAAC;SACD,MAAM,CAAC,SAAS,EAAE;QACjB,KAAK,EAAE,GAAG;QACV,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,0CAA0C;QACpD,OAAO,EAAE,CAAC;KACX,CAAC;SACD,UAAU,CAAC,QAAQ,CAAC;SACpB,OAAO,CAAC,OAAO,CAAC;SAChB,OAAO,CAAC,YAAY,CAAC;SACrB,OAAO,CAAC,SAAS,CAAC;SAClB,OAAO,CAAC,MAAM,CAAC;SACf,OAAO,CAAC,GAAG,CAAC;SACZ,OAAO,CAAC,IAAI,CAAC;SACb,OAAO,CAAC,MAAM,CAAC;SACf,OAAO,CAAC,IAAI,CAAC;SACb,OAAO,CAAC,IAAI,CAAC;SACb,OAAO,CAAC,IAAI,CAAC;SACb,OAAO,CAAC,IAAI,CAAC;SACb,OAAO,CAAC,KAAK,CAAC;SACd,OAAO,CAAC,IAAI,CAAC;SACb,OAAO,CAAC,GAAG,CAAC;SACZ,OAAO,CAAC,gBAAgB,CAAC;SACzB,OAAO,CAAC,OAAO,CAAC;SAChB,OAAO,CAAC,MAAM,CAAC;SACf,OAAO,CAAC,MAAM,CAAC;SACf,OAAO,CAAC,QAAQ,CAAC;SACjB,OAAO,CAAC,KAAK,CAAC;SACd,OAAO,CAAC,OAAO,CAAC;SAChB,OAAO,CAAC,MAAM,CAAC;SACf,OAAO,CAAC;QACP,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC;SACD,aAAa,EAAE;SACf,cAAc,EAAE;SAChB,OAAO,CAAC,UAAU,CAAC;SACnB,IAAI,CAAC,KAAK,CAAC;SACX,IAAI,EAAE,CAAC;IAEV,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,IAAI,CAAC;QAGf,KAAK,qBAAqB,CAAC,UAAU,CAAC,CAAC;QAEvC,KAAK,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,oCAAoC,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC;QAC/D,GAAG,CAAC,QAAQ,EAAE,CAAC;IACjB,CAAC;YAAS,CAAC;QACT,MAAM,iBAAiB,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC;KAAM,CAAC;IACN,MAAM,oCAAoC,CACxC,4CAA4C,gBAAgB,oBAAoB,OAAO,CAAC,QAAQ,CAAC,IAAI;;oFAErB,CACjF,CAAC;AACJ,CAAC","sourcesContent":["import * as dotenv from \"dotenv\";\n\ndotenv.config();\n\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { confirm } from \"@inquirer/prompts\";\nimport * as Sentry from \"@sentry/node\";\nimport { gte } from \"semver\";\n// Undici must be imported first to set the global dispatcher\n// If fetch is used before undici, the process will crash\nimport undici from \"undici\";\nimport { hideBin } from \"yargs/helpers\";\nimport yargs from \"yargs/yargs\";\nimport build from \"./cmds/build.js\";\nimport compile from \"./cmds/compile.js\";\nimport customDomain from \"./cmds/custom-domain/index.js\";\nimport deleteZup from \"./cmds/delete.js\";\nimport deploy from \"./cmds/deploy.js\";\nimport dev from \"./cmds/dev.js\";\nimport docs from \"./cmds/docs.js\";\nimport editor from \"./cmds/editor.js\";\nimport info from \"./cmds/info.js\";\nimport init from \"./cmds/init.js\";\nimport link from \"./cmds/link.js\";\nimport list from \"./cmds/list.js\";\nimport login from \"./cmds/login.js\";\nimport mtlsCertificates from \"./cmds/mtls-certificates/index.js\";\nimport oas from \"./cmds/open-api/index.js\";\nimport project from \"./cmds/project/index.js\";\nimport proxies from \"./cmds/proxies/index.js\";\nimport source from \"./cmds/source/index.js\";\nimport test from \"./cmds/test.js\";\nimport tunnel from \"./cmds/tunnel/index.js\";\nimport variable from \"./cmds/variable/index.js\";\nimport whoami from \"./cmds/whoami.js\";\nimport { shutdownAnalytics } from \"./common/analytics/lib.js\";\nimport { MAX_WAIT_PENDING_TIME_MS, SENTRY_DSN } from \"./common/constants.js\";\nimport { logger } from \"./common/logger.js\";\nimport { logLevel } from \"./common/middleware/logging.js\";\nimport { warnIfOutdatedVersion, warnNodeVersion } from \"./common/outdated.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"./common/output.js\";\n\n// This allows us to stop the CLI from executing so we can connect the profiler\n\n// biome-ignore lint/style/noProcessEnv: Migrated from ESLint\nif (process.env.ZUPLO_CLI_PROFILING) {\n await confirm({ message: \"Continue executing CLI?\", default: true });\n}\n\n// Note: We cannot set this to be higher than 18.0.0 because of the way\n// our documentation works -- we tell them to use npx @zuplo/cli@latest (even in CI/CD jobs)\n// If we set this to be higher than 18.0.0, then we will break them.\n// Instead we set the value in package.json to be engine.node >= 20.0.0, so it will warn\nconst MIN_NODE_VERSION = \"18.0.0\";\nconst RECOMMENDED_NODE_VERSION = \"20.0.0\";\n\nif (gte(process.versions.node, MIN_NODE_VERSION)) {\n let cliVersion: string;\n try {\n const packageJson = JSON.parse(\n readFileSync(\n fileURLToPath(new URL(\"../package.json\", import.meta.url)),\n \"utf-8\"\n )\n );\n cliVersion = packageJson.version;\n } catch (e) {\n cliVersion = \"0.0.0\";\n logger.error(e);\n await printCriticalFailureToConsoleAndExit(\n `Unable to load @zuplo/cli. The package.json is missing or malformed.`\n );\n }\n\n await warnNodeVersion(cliVersion, RECOMMENDED_NODE_VERSION);\n\n undici.setGlobalDispatcher(\n undici.getGlobalDispatcher().compose((dispatch) => {\n return (opts, handler) => {\n opts.headers = {\n ...opts.headers,\n \"user-agent\": `ZuploCLI/${cliVersion}`,\n\n // biome-ignore lint/style/noProcessEnv: Migrated from ESLint\n ...(process.env.ZUPLO_CANARY ? { \"zp-canary\": \"true\" } : {}),\n };\n return dispatch(opts, handler);\n };\n })\n );\n\n Sentry.init({\n dsn: SENTRY_DSN,\n release: cliVersion,\n });\n\n const cli = yargs(hideBin(process.argv))\n // This means that all env vars will have to be prefixed with ZUPLO_\n .env(\"ZUPLO\")\n .option(\"prompt\", {\n type: \"boolean\",\n describe: \"Bypass confirmation prompts\",\n default: true,\n hidden: true,\n })\n .option(\"verbose\", {\n alias: \"v\",\n type: \"count\",\n describe: \"Increase verbosity level (-v, -vv, -vvv)\",\n default: 0,\n })\n .middleware(logLevel)\n .command(compile)\n .command(customDomain)\n .command(deleteZup) // delete is a reserved keyword in JavaScript, so we call this function deleteZup\n .command(deploy)\n .command(dev)\n .command(docs)\n .command(editor)\n .command(info)\n .command(init)\n .command(list)\n .command(link)\n .command(login)\n .command(test)\n .command(oas)\n .command(mtlsCertificates)\n .command(project)\n .command(source)\n .command(tunnel)\n .command(variable)\n .command(build)\n .command(proxies)\n .command(whoami)\n .command({\n command: \"hello\",\n handler: async () => {\n await fetch(\"https://393b4699ced44cc2ae87e4ad86184a29.api.mockbin.io/\");\n },\n })\n .demandCommand()\n .strictCommands()\n .version(cliVersion)\n .fail(false)\n .help();\n\n try {\n await cli.argv;\n\n // Don't block\n void warnIfOutdatedVersion(cliVersion);\n\n void Sentry.close(MAX_WAIT_PENDING_TIME_MS).then(() => {\n process.exit(0);\n });\n } catch (err) {\n if (err instanceof Error) {\n Sentry.captureException(err);\n }\n await printCriticalFailureToConsoleAndExit(err.message ?? err);\n cli.showHelp();\n } finally {\n await shutdownAnalytics();\n }\n} else {\n await printCriticalFailureToConsoleAndExit(\n `The Zuplo CLI requires at least node.js v${MIN_NODE_VERSION}. You are using v${process.versions.node}. Please update your version of node.js.\n\n Consider using a Node.js version manager such as https://github.com/nvm-sh/nvm.`\n );\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { Argv } from "yargs";
2
+ declare const _default: {
3
+ desc: string;
4
+ builder: (yargs: Argv) => Argv<unknown>;
5
+ handler: (argv: unknown) => Promise<void>;
6
+ command: string;
7
+ };
8
+ export default _default;
9
+ //# sourceMappingURL=info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/cmds/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;qBAYV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAOf,OAAO;;;AAV/B,wBAcE"}
@@ -0,0 +1,19 @@
1
+ import { captureEvent } from "../common/analytics/lib.js";
2
+ import { info } from "../project/info/handler.js";
3
+ import projectInfo, { configureInfoOptions } from "./project/info.js";
4
+ export default {
5
+ ...projectInfo,
6
+ desc: "Alias for `project info`",
7
+ builder: (yargs) => {
8
+ return configureInfoOptions(yargs)
9
+ .usage("$0 info [options]")
10
+ .example([
11
+ ["$0 info", "Display information about the current linked project"],
12
+ ]);
13
+ },
14
+ handler: async (argv) => {
15
+ await captureEvent({ argv, event: "zuplo info" });
16
+ await info(argv);
17
+ },
18
+ };
19
+ //# sourceMappingURL=info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/cmds/info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAa,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,WAAW,EAAE,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAMtE,eAAe;IACb,GAAG,WAAW;IACd,IAAI,EAAE,0BAA0B;IAChC,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,oBAAoB,CAAC,KAAK,CAAC;aAC/B,KAAK,CAAC,mBAAmB,CAAC;aAC1B,OAAO,CAAC;YACP,CAAC,SAAS,EAAE,sDAAsD,CAAC;SACpE,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,CAAC,IAAiB,CAAC,CAAC;IAChC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../common/analytics/lib.js\";\nimport { Arguments, info } from \"../project/info/handler.js\";\nimport projectInfo, { configureInfoOptions } from \"./project/info.js\";\n\n/**\n * Top-level alias for `zuplo project info`. Emits a distinct analytics event\n * so adoption of the alias can be measured separately from the subcommand.\n */\nexport default {\n ...projectInfo,\n desc: \"Alias for `project info`\",\n builder: (yargs: Argv): Argv<unknown> => {\n return configureInfoOptions(yargs)\n .usage(\"$0 info [options]\")\n .example([\n [\"$0 info\", \"Display information about the current linked project\"],\n ]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo info\" });\n await info(argv as Arguments);\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cmds/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAItC,QAAA,MAAM,QAAQ,EAAE,aAOf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cmds/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAKtC,QAAA,MAAM,QAAQ,EAAE,aAOf,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -1,10 +1,11 @@
1
1
  import { groupHandler } from "../../common/handler.js";
2
2
  import create from "./create.js";
3
+ import info from "./info.js";
3
4
  const commands = {
4
5
  describe: "Project management commands",
5
6
  command: "project",
6
7
  builder: (yargs) => {
7
- return yargs.command(create).help();
8
+ return yargs.command(create).command(info).help();
8
9
  },
9
10
  handler: groupHandler,
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cmds/project/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,QAAQ,GAAkB;IAC9B,QAAQ,EAAE,6BAA6B;IACvC,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACjB,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { CommandModule } from \"yargs\";\nimport { groupHandler } from \"../../common/handler.js\";\nimport create from \"./create.js\";\n\nconst commands: CommandModule = {\n describe: \"Project management commands\",\n command: \"project\",\n builder: (yargs) => {\n return yargs.command(create).help();\n },\n handler: groupHandler,\n};\n\nexport default commands;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cmds/project/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,QAAQ,GAAkB;IAC9B,QAAQ,EAAE,6BAA6B;IACvC,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACjB,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { CommandModule } from \"yargs\";\nimport { groupHandler } from \"../../common/handler.js\";\nimport create from \"./create.js\";\nimport info from \"./info.js\";\n\nconst commands: CommandModule = {\n describe: \"Project management commands\",\n command: \"project\",\n builder: (yargs) => {\n return yargs.command(create).command(info).help();\n },\n handler: groupHandler,\n};\n\nexport default commands;\n"]}
@@ -0,0 +1,10 @@
1
+ import { Argv } from "yargs";
2
+ export declare function configureInfoOptions(yargs: Argv): Argv<unknown>;
3
+ declare const _default: {
4
+ desc: string;
5
+ command: string;
6
+ builder: (yargs: Argv) => Argv<unknown>;
7
+ handler: (argv: unknown) => Promise<void>;
8
+ };
9
+ export default _default;
10
+ //# sourceMappingURL=info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../../src/cmds/project/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AA0B7B,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAgB/D;;;;qBAKkB,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAUf,OAAO;;AAb/B,wBAiBE"}
@@ -0,0 +1,50 @@
1
+ import { captureEvent } from "../../common/analytics/lib.js";
2
+ import { authenticateNoPrompt } from "../../common/middleware/authentication.js";
3
+ import { identify } from "../../common/middleware/user-identification.js";
4
+ import setBlocking from "../../common/output.js";
5
+ import { readLinkedConfig } from "../../common/read-linked-config.js";
6
+ import { info } from "../../project/info/handler.js";
7
+ async function authenticateIfLinked(argv) {
8
+ const linked = await readLinkedConfig(argv);
9
+ if (linked.accountName && linked.projectName) {
10
+ argv.account = linked.accountName;
11
+ argv.project = linked.projectName;
12
+ await authenticateNoPrompt(argv);
13
+ }
14
+ }
15
+ export function configureInfoOptions(yargs) {
16
+ return yargs
17
+ .option("api-key", {
18
+ type: "string",
19
+ describe: "The API Key from Zuplo",
20
+ envVar: "API_KEY",
21
+ alias: "apikey",
22
+ })
23
+ .option("dir", {
24
+ type: "string",
25
+ describe: "The directory containing your Zuplo API",
26
+ default: ".",
27
+ normalize: true,
28
+ hidden: true,
29
+ })
30
+ .middleware([setBlocking, authenticateIfLinked, identify]);
31
+ }
32
+ export default {
33
+ desc: "Displays information about the current project and linked environment",
34
+ command: "info",
35
+ builder: (yargs) => {
36
+ return configureInfoOptions(yargs)
37
+ .usage("$0 project info [options]")
38
+ .example([
39
+ [
40
+ "$0 project info",
41
+ "Display information about the current linked project",
42
+ ],
43
+ ]);
44
+ },
45
+ handler: async (argv) => {
46
+ await captureEvent({ argv, event: "zuplo project info" });
47
+ await info(argv);
48
+ },
49
+ };
50
+ //# sourceMappingURL=info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/cmds/project/info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC1E,OAAO,WAAW,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAa,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAMhE,KAAK,UAAU,oBAAoB,CAAC,IAKnC;IACC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC;QAClC,MAAM,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAW;IAC9C,OAAO,KAAK;SACT,MAAM,CAAC,SAAS,EAAE;QACjB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,wBAAwB;QAClC,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,QAAQ;KAChB,CAAC;SACD,MAAM,CAAC,KAAK,EAAE;QACb,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,yCAAyC;QACnD,OAAO,EAAE,GAAG;QACZ,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb,CAAC;SACD,UAAU,CAAC,CAAC,WAAW,EAAE,oBAAoB,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,eAAe;IACb,IAAI,EAAE,uEAAuE;IAC7E,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,oBAAoB,CAAC,KAAK,CAAC;aAC/B,KAAK,CAAC,2BAA2B,CAAC;aAClC,OAAO,CAAC;YACP;gBACE,iBAAiB;gBACjB,sDAAsD;aACvD;SACF,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,IAAiB,CAAC,CAAC;IAChC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { authenticateNoPrompt } from \"../../common/middleware/authentication.js\";\nimport { identify } from \"../../common/middleware/user-identification.js\";\nimport setBlocking from \"../../common/output.js\";\nimport { readLinkedConfig } from \"../../common/read-linked-config.js\";\nimport { Arguments, info } from \"../../project/info/handler.js\";\n\n// Skip auth when there's no linked project so the handler can show the\n// \"No project linked\" guidance instead of an unhelpful auth error. Also\n// surfaces the linked account/project on argv so the `identify` middleware\n// can tag Sentry events with that context.\nasync function authenticateIfLinked(argv: {\n \"api-key\"?: string;\n account?: string;\n project?: string;\n [key: string]: unknown;\n}) {\n const linked = await readLinkedConfig(argv);\n if (linked.accountName && linked.projectName) {\n argv.account = linked.accountName;\n argv.project = linked.projectName;\n await authenticateNoPrompt(argv);\n }\n}\n\nexport function configureInfoOptions(yargs: Argv): Argv<unknown> {\n return yargs\n .option(\"api-key\", {\n type: \"string\",\n describe: \"The API Key from Zuplo\",\n envVar: \"API_KEY\",\n alias: \"apikey\",\n })\n .option(\"dir\", {\n type: \"string\",\n describe: \"The directory containing your Zuplo API\",\n default: \".\",\n normalize: true,\n hidden: true,\n })\n .middleware([setBlocking, authenticateIfLinked, identify]);\n}\n\nexport default {\n desc: \"Displays information about the current project and linked environment\",\n command: \"info\",\n builder: (yargs: Argv): Argv<unknown> => {\n return configureInfoOptions(yargs)\n .usage(\"$0 project info [options]\")\n .example([\n [\n \"$0 project info\",\n \"Display information about the current linked project\",\n ],\n ]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo project info\" });\n await info(argv as Arguments);\n },\n};\n"]}
@@ -12,6 +12,11 @@ export interface Environment {
12
12
  projectName: string;
13
13
  createdOn: Date | null;
14
14
  branchName: string;
15
- environmentType: "production" | "preview" | "development" | "working_copy";
15
+ environmentType:
16
+ | "production"
17
+ | "preview"
18
+ | "development"
19
+ | "working_copy"
20
+ | "working-copy";
16
21
  }
17
22
  //# sourceMappingURL=lib.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/common/api/lib.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,CAAC;CAC5E"}
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/common/api/lib.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EACX,YAAY,GACZ,SAAS,GACT,aAAa,GACb,cAAc,GACd,cAAc,CAAC;CACpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/common/api/lib.ts"],"names":[],"mappings":"","sourcesContent":["export interface Account {\n id: string;\n name: string;\n}\n\nexport interface Project {\n id: string;\n name: string;\n}\n\nexport interface Environment {\n name: string;\n accountName: string;\n projectName: string;\n createdOn: Date | null;\n branchName: string;\n environmentType: \"production\" | \"preview\" | \"development\" | \"working_copy\";\n}\n"]}
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/common/api/lib.ts"],"names":[],"mappings":"","sourcesContent":["export interface Account {\n id: string;\n name: string;\n}\n\nexport interface Project {\n id: string;\n name: string;\n}\n\nexport interface Environment {\n name: string;\n accountName: string;\n projectName: string;\n createdOn: Date | null;\n branchName: string;\n environmentType:\n | \"production\"\n | \"preview\"\n | \"development\"\n | \"working_copy\"\n | \"working-copy\";\n}\n"]}
@@ -1,4 +1,7 @@
1
- export declare function authenticate(argv: {
1
+ export declare const authenticate: (argv: {
2
2
  "api-key"?: string;
3
- }): Promise<void>;
3
+ }) => Promise<void>;
4
+ export declare const authenticateNoPrompt: (argv: {
5
+ "api-key"?: string;
6
+ }) => Promise<void>;
4
7
  //# sourceMappingURL=authentication.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.d.ts","sourceRoot":"","sources":["../../../src/common/middleware/authentication.ts"],"names":[],"mappings":"AAwBA,wBAAsB,YAAY,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,iBAmC9D"}
1
+ {"version":3,"file":"authentication.d.ts","sourceRoot":"","sources":["../../../src/common/middleware/authentication.ts"],"names":[],"mappings":"AAmEA,eAAO,MAAM,YAAY,SA1CkB;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,kBA0CI,CAAC;AACtE,eAAO,MAAM,oBAAoB,SA3CU;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,kBA2Ca,CAAC"}