@hubspot/cli 8.11.0-beta.0 → 8.12.0

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 (57) hide show
  1. package/commands/account/clean.js +1 -1
  2. package/commands/account/list.js +1 -1
  3. package/commands/account/remove.js +1 -1
  4. package/commands/account/rename.js +1 -1
  5. package/commands/account/use.js +1 -1
  6. package/commands/api.d.ts +4 -1
  7. package/commands/api.js +11 -14
  8. package/commands/project/appInstallStatus.d.ts +2 -1
  9. package/commands/project/appInstallStatus.js +19 -17
  10. package/commands/project/create.js +0 -1
  11. package/commands/project/deploy.d.ts +2 -1
  12. package/commands/project/deploy.js +31 -14
  13. package/commands/project/dev/index.js +18 -64
  14. package/commands/project/info.d.ts +2 -1
  15. package/commands/project/info.js +8 -6
  16. package/commands/project/installApp.d.ts +2 -1
  17. package/commands/project/installApp.js +25 -26
  18. package/commands/project/list.js +1 -1
  19. package/commands/project/release/create.d.ts +2 -1
  20. package/commands/project/release/create.js +68 -69
  21. package/commands/project/release/info.d.ts +2 -1
  22. package/commands/project/release/info.js +7 -6
  23. package/commands/project/release/list.d.ts +2 -1
  24. package/commands/project/release/list.js +14 -6
  25. package/commands/project/upload.d.ts +2 -1
  26. package/commands/project/upload.js +23 -20
  27. package/commands/project.js +2 -2
  28. package/commands/testAccount/create.d.ts +2 -1
  29. package/commands/testAccount/create.js +7 -7
  30. package/lang/en.d.ts +21 -28
  31. package/lang/en.js +30 -37
  32. package/lib/commonOpts.js +6 -1
  33. package/lib/constants.d.ts +1 -0
  34. package/lib/constants.js +1 -0
  35. package/lib/jsonOutput.d.ts +109 -0
  36. package/lib/jsonOutput.js +94 -0
  37. package/lib/projects/builds.d.ts +2 -0
  38. package/lib/projects/builds.js +22 -0
  39. package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
  40. package/lib/projects/localDev/DevSessionManager.js +4 -30
  41. package/lib/projects/localDev/helpers/account.d.ts +0 -7
  42. package/lib/projects/localDev/helpers/account.js +1 -80
  43. package/lib/projects/release.d.ts +4 -0
  44. package/lib/projects/release.js +90 -0
  45. package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
  46. package/lib/yargs/makeWrappedYargsHandler.js +123 -65
  47. package/mcp-server/Tool.js +32 -26
  48. package/mcp-server/utils/logger.d.ts +3 -0
  49. package/mcp-server/utils/logger.js +30 -0
  50. package/package.json +10 -8
  51. package/types/Yargs.d.ts +3 -1
  52. package/commands/project/dev/deprecatedFlow.d.ts +0 -11
  53. package/commands/project/dev/deprecatedFlow.js +0 -180
  54. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
  55. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
  56. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
  57. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +0 -394
@@ -0,0 +1,90 @@
1
+ import chalk from 'chalk';
2
+ import { fetchProjectBuilds, getBuildStatus, } from '@hubspot/local-dev-lib/api/projects';
3
+ import { BUILD_STATUS } from '@hubspot/local-dev-lib/enums/build';
4
+ import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
5
+ import { meetsMinimumPlatformVersion } from '@hubspot/project-parsing-lib/projects';
6
+ import { PLATFORM_VERSIONS } from '@hubspot/project-parsing-lib/constants';
7
+ import { getLastSuccessfulBuild } from './builds.js';
8
+ import { logError, ApiErrorContext } from '../errorHandlers/index.js';
9
+ import { uiLogger } from '../ui/logger.js';
10
+ import { listPrompt } from '../prompts/promptUtils.js';
11
+ import { commands } from '../../lang/en.js';
12
+ import { createRelease } from '../../api/releases.js';
13
+ function buildChoiceName(build) {
14
+ const base = build.uploadMessage
15
+ ? `${build.buildId} — ${build.uploadMessage}`
16
+ : `${build.buildId} — ${commands.project.release.create.noUploadMessage}`;
17
+ return build.status !== BUILD_STATUS.SUCCESS
18
+ ? `[${chalk.yellow('DISABLED')}] ${base}`
19
+ : base;
20
+ }
21
+ export async function resolveBuildId(accountId, projectName, buildOption, force) {
22
+ if (buildOption) {
23
+ return buildOption;
24
+ }
25
+ if (force) {
26
+ const lastSuccessful = await getLastSuccessfulBuild(accountId, projectName);
27
+ return lastSuccessful ? lastSuccessful.buildId : null;
28
+ }
29
+ let results;
30
+ try {
31
+ ({
32
+ data: { results },
33
+ } = await fetchProjectBuilds(accountId, projectName));
34
+ }
35
+ catch (e) {
36
+ if (isSpecifiedError(e, { statusCode: 404 }) ||
37
+ isSpecifiedError(e, { statusCode: 400 })) {
38
+ return undefined;
39
+ }
40
+ throw e;
41
+ }
42
+ if (results.length === 0) {
43
+ return undefined;
44
+ }
45
+ const lastSuccessful = await getLastSuccessfulBuild(accountId, projectName);
46
+ if (!lastSuccessful) {
47
+ uiLogger.error(commands.project.release.create.errors.noSuccessfulBuilds(projectName));
48
+ return null;
49
+ }
50
+ return listPrompt(commands.project.release.create.buildIdPrompt, {
51
+ choices: results.map(b => ({
52
+ name: buildChoiceName(b),
53
+ value: b.buildId,
54
+ disabled: b.status !== BUILD_STATUS.SUCCESS
55
+ ? `– ${commands.project.release.create.buildStatus[b.status] ?? b.status}`
56
+ : undefined,
57
+ })),
58
+ });
59
+ }
60
+ export async function validateBuildForRelease(accountId, projectName, buildId) {
61
+ try {
62
+ const { data: build } = await getBuildStatus(accountId, projectName, buildId);
63
+ return meetsMinimumPlatformVersion(build.platformVersion, PLATFORM_VERSIONS.v2026_09_BETA);
64
+ }
65
+ catch (e) {
66
+ if (isSpecifiedError(e, { statusCode: 404 })) {
67
+ uiLogger.error(commands.project.release.create.errors.buildNotFound(buildId, projectName));
68
+ }
69
+ else {
70
+ logError(e, new ApiErrorContext({
71
+ accountId,
72
+ request: 'project release create',
73
+ }));
74
+ }
75
+ throw e;
76
+ }
77
+ }
78
+ export async function executeRelease(accountId, projectName, buildId) {
79
+ try {
80
+ const { data: release } = await createRelease(accountId, projectName, buildId);
81
+ return release;
82
+ }
83
+ catch (e) {
84
+ logError(e, new ApiErrorContext({
85
+ accountId,
86
+ request: 'project release create',
87
+ }));
88
+ throw e;
89
+ }
90
+ }
@@ -1,3 +1,7 @@
1
1
  import { ArgumentsCamelCase } from 'yargs';
2
+ import { z } from 'zod';
2
3
  import { CommonArgs } from '../../types/Yargs.js';
3
- export declare function makeWrappedYargsHandler<T extends CommonArgs>(trackingName: string, handler: (args: ArgumentsCamelCase<T>) => Promise<void>): (args: ArgumentsCamelCase<T>) => Promise<void>;
4
+ export type WrappedHandlerOptions = {
5
+ jsonOutputSchema?: z.ZodType;
6
+ };
7
+ export declare function makeWrappedYargsHandler<T extends CommonArgs>(trackingName: string, handler: (args: ArgumentsCamelCase<T>) => Promise<void>, options?: WrappedHandlerOptions): (args: ArgumentsCamelCase<T>) => Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import os from 'os';
2
2
  import path from 'path';
3
+ import { z } from 'zod';
3
4
  import { getConfig } from '@hubspot/local-dev-lib/config';
4
5
  import { getStateValue, setStateValue, } from '@hubspot/local-dev-lib/config/state';
5
6
  import { STATE_FLAGS } from '@hubspot/local-dev-lib/constants/config';
@@ -11,7 +12,8 @@ import { lib } from '../../lang/en.js';
11
12
  import { EXIT_CODES } from '../enums/exitCodes.js';
12
13
  import { isPromptExitError } from '../errors/PromptExitError.js';
13
14
  import { debugError } from '../errorHandlers/index.js';
14
- const HANDLER_LOG_DIR = path.join(os.homedir(), '.hscli', 'logs');
15
+ import { MAX_LOG_FILES } from '../constants.js';
16
+ const HANDLER_LOG_DIR = path.join(os.homedir(), '.hscli', 'logs', 'cli');
15
17
  function logUsageTrackingMessage(isJsonOutput) {
16
18
  if (isJsonOutput) {
17
19
  return;
@@ -32,90 +34,146 @@ function logUsageTrackingMessage(isJsonOutput) {
32
34
  return;
33
35
  }
34
36
  }
35
- export function makeWrappedYargsHandler(trackingName, handler) {
36
- return async (args) => {
37
- const startTime = Date.now();
38
- const meta = {};
39
- let trackingFired = false;
40
- const trackingArgs = args;
41
- const addUsageMetadata = (newMeta) => {
42
- Object.assign(meta, newMeta);
43
- };
44
- trackingArgs.addUsageMetadata = addUsageMetadata;
45
- const trackCommandUsage = async (successful) => {
46
- if (trackingFired) {
47
- return;
48
- }
49
- trackingFired = true;
50
- try {
51
- const { accountId: overrideAccountId, ...trackingMeta } = meta;
52
- trackingMeta.successful = successful;
53
- trackingMeta.executionTime = Date.now() - startTime;
54
- await _trackCommandUsage(trackingName, trackingMeta, overrideAccountId ?? args.derivedAccountId);
37
+ function createUsageTracker(trackingName, derivedAccountId) {
38
+ const startTime = Date.now();
39
+ const meta = {};
40
+ let fired = false;
41
+ const addMetadata = (newMeta) => {
42
+ Object.assign(meta, newMeta);
43
+ };
44
+ const track = async (successful) => {
45
+ if (fired) {
46
+ return;
47
+ }
48
+ fired = true;
49
+ try {
50
+ const { accountId: overrideAccountId, ...trackingMeta } = meta;
51
+ trackingMeta.successful = successful;
52
+ trackingMeta.executionTime = Date.now() - startTime;
53
+ await _trackCommandUsage(trackingName, trackingMeta, overrideAccountId ?? derivedAccountId);
54
+ }
55
+ catch (_e) { }
56
+ };
57
+ const onForcedExit = () => {
58
+ process.exit(EXIT_CODES.SUCCESS);
59
+ };
60
+ const onSigint = async () => {
61
+ process.removeListener('SIGINT', onSigint);
62
+ process.on('SIGINT', onForcedExit);
63
+ try {
64
+ await track(false);
65
+ }
66
+ catch (_e) { }
67
+ process.removeListener('SIGINT', onForcedExit);
68
+ process.exit(EXIT_CODES.SUCCESS);
69
+ };
70
+ process.on('SIGINT', onSigint);
71
+ const trackAndCleanup = async (successful) => {
72
+ await track(successful);
73
+ process.removeListener('SIGINT', onSigint);
74
+ process.removeListener('SIGINT', onForcedExit);
75
+ };
76
+ return { addMetadata, trackAndCleanup };
77
+ }
78
+ function createJsonOutputManager(isJsonOutput, schema) {
79
+ const data = {};
80
+ let emitted = false;
81
+ const add = (newData) => {
82
+ Object.assign(data, newData);
83
+ };
84
+ const emit = () => {
85
+ if (!emitted && isJsonOutput && Object.keys(data).length > 0) {
86
+ emitted = true;
87
+ if (schema) {
88
+ const result = schema.safeParse(data);
89
+ if (!result.success) {
90
+ uiLogger.json(data);
91
+ uiLogger.warn(lib.jsonSchema.validationFailed);
92
+ return false;
93
+ }
55
94
  }
56
- catch (_e) { }
57
- };
58
- const onForcedExit = () => {
59
- process.exit(EXIT_CODES.SUCCESS);
60
- };
61
- const onSigint = async () => {
62
- process.removeListener('SIGINT', onSigint);
63
- process.on('SIGINT', onForcedExit);
64
- try {
65
- await trackCommandUsage(false);
95
+ uiLogger.json(data);
96
+ }
97
+ return true;
98
+ };
99
+ return { add, emit };
100
+ }
101
+ function createLogFileWriter(trackingName, isJsonOutput) {
102
+ const writeLogFile = () => {
103
+ if (isJsonOutput) {
104
+ return null;
105
+ }
106
+ return ldlLogger.writeBufferedLogsToFile({
107
+ dir: HANDLER_LOG_DIR,
108
+ filenamePrefix: trackingName,
109
+ maxFiles: MAX_LOG_FILES,
110
+ });
111
+ };
112
+ const writeFailureLogFile = () => {
113
+ const savedPath = writeLogFile();
114
+ if (savedPath) {
115
+ uiLogger.log('');
116
+ uiLogger.error(lib.handlerLogFile.saved(savedPath));
117
+ }
118
+ };
119
+ return { writeLogFile, writeFailureLogFile };
120
+ }
121
+ export function makeWrappedYargsHandler(trackingName, handler, options) {
122
+ return async (args) => {
123
+ const wrappedHandlerArgs = args;
124
+ const isJsonOutput = Boolean(wrappedHandlerArgs.json || wrappedHandlerArgs.formatOutputAsJson);
125
+ const schema = options?.jsonOutputSchema;
126
+ const tracker = createUsageTracker(trackingName, args.derivedAccountId);
127
+ if (wrappedHandlerArgs.jsonSchema) {
128
+ if (schema) {
129
+ uiLogger.json(z.toJSONSchema(schema));
66
130
  }
67
- catch (_e) { }
68
- process.removeListener('SIGINT', onForcedExit);
69
- process.exit(EXIT_CODES.SUCCESS);
70
- };
71
- process.on('SIGINT', onSigint);
72
- const trackCommandUsageAndRemoveListeners = async (successful) => {
73
- await trackCommandUsage(successful);
74
- process.removeListener('SIGINT', onSigint);
75
- process.removeListener('SIGINT', onForcedExit);
76
- };
77
- const jsonArgs = args;
78
- const isJsonOutput = Boolean(jsonArgs.json || jsonArgs.formatOutputAsJson);
79
- const writeFailureLogFile = () => {
80
- // Skip in JSON output modes so the side effect + stderr message don't
81
- // interfere with structured output consumers.
82
- if (isJsonOutput) {
83
- return;
131
+ else {
132
+ uiLogger.json({ error: lib.jsonSchema.noSchemaForCommand });
84
133
  }
85
- const savedPath = ldlLogger.writeBufferedLogsToFile({
86
- dir: HANDLER_LOG_DIR,
87
- filenamePrefix: trackingName,
88
- });
89
- if (savedPath) {
90
- uiLogger.log('');
91
- uiLogger.error(lib.handlerLogFile.saved(savedPath));
134
+ await tracker.trackAndCleanup(true);
135
+ return process.exit(EXIT_CODES.SUCCESS);
136
+ }
137
+ const json = createJsonOutputManager(isJsonOutput, schema);
138
+ const logs = createLogFileWriter(trackingName, isJsonOutput);
139
+ wrappedHandlerArgs.addUsageMetadata = tracker.addMetadata;
140
+ wrappedHandlerArgs.addJsonOutput = json.add;
141
+ wrappedHandlerArgs.exit = async (code) => {
142
+ const jsonValid = json.emit();
143
+ const exitCode = !jsonValid && code === EXIT_CODES.SUCCESS ? EXIT_CODES.WARNING : code;
144
+ await tracker.trackAndCleanup(exitCode !== EXIT_CODES.ERROR);
145
+ if (exitCode === EXIT_CODES.ERROR) {
146
+ logs.writeFailureLogFile();
92
147
  }
93
- };
94
- trackingArgs.exit = async (code) => {
95
- await trackCommandUsageAndRemoveListeners(code !== EXIT_CODES.ERROR);
96
- if (code === EXIT_CODES.ERROR) {
97
- writeFailureLogFile();
148
+ else {
149
+ logs.writeLogFile();
98
150
  }
99
- return process.exit(code);
151
+ return process.exit(exitCode);
100
152
  };
101
153
  logUsageTrackingMessage(isJsonOutput);
102
154
  try {
103
- await handler(trackingArgs);
155
+ await handler(wrappedHandlerArgs);
104
156
  }
105
157
  catch (e) {
106
158
  const isSuccessfulPromptExit = isPromptExitError(e)
107
159
  ? e.exitCode !== EXIT_CODES.ERROR
108
160
  : false;
109
- await trackCommandUsageAndRemoveListeners(isSuccessfulPromptExit);
161
+ await tracker.trackAndCleanup(isSuccessfulPromptExit);
110
162
  if (isPromptExitError(e)) {
163
+ logs.writeLogFile();
111
164
  return process.exit(e.exitCode);
112
165
  }
113
166
  else {
114
167
  debugError(e);
115
- writeFailureLogFile();
168
+ logs.writeFailureLogFile();
116
169
  return process.exit(EXIT_CODES.ERROR);
117
170
  }
118
171
  }
119
- await trackCommandUsageAndRemoveListeners(true);
172
+ const jsonValid = json.emit();
173
+ await tracker.trackAndCleanup(true);
174
+ logs.writeLogFile();
175
+ if (!jsonValid) {
176
+ return process.exit(EXIT_CODES.WARNING);
177
+ }
120
178
  };
121
179
  }
@@ -22,6 +22,7 @@ export class Tool {
22
22
  return runCommandInDir(directory, command, async (chunk) => {
23
23
  try {
24
24
  const message = `${chunk.trimEnd()}`;
25
+ this.logger.debug(this.toolName, message);
25
26
  const token = extra?._meta?.progressToken;
26
27
  if (token !== undefined && extra?.sendNotification) {
27
28
  progressCount++;
@@ -43,31 +44,36 @@ export class Tool {
43
44
  getTrackingMeta(_input) {
44
45
  return undefined;
45
46
  }
46
- async wrappedHandler(input, extra) {
47
- const startTime = Date.now();
48
- try {
49
- // `input` is logged unredacted. Tool input schemas MUST NOT include
50
- // credentials or other sensitive values, since MCP clients (Claude
51
- // Desktop, Inspector, etc.) will display these logs.
52
- this.logger.debug(this.toolName, {
53
- message: 'Tool invoked',
54
- args: input,
55
- });
56
- await trackToolUsage(this.toolName, this.getTrackingMeta(input));
57
- const result = await this.handler(input, extra);
58
- this.logger.debug(this.toolName, {
59
- message: 'Tool completed',
60
- durationMs: Date.now() - startTime,
61
- });
62
- return result;
63
- }
64
- catch (error) {
65
- this.logger.error(this.toolName, {
66
- message: 'Tool failed',
67
- error: error instanceof Error ? error.message : String(error),
68
- durationMs: Date.now() - startTime,
69
- });
70
- return formatTextContents(getErrorMessage(error));
71
- }
47
+ wrappedHandler(input, extra) {
48
+ return this.logger.runWithBuffer(async () => {
49
+ const startTime = Date.now();
50
+ try {
51
+ // `input` is logged unredacted. Tool input schemas MUST NOT include
52
+ // credentials or other sensitive values, since MCP clients (Claude
53
+ // Desktop, Inspector, etc.) will display these logs.
54
+ this.logger.debug(this.toolName, {
55
+ message: 'Tool invoked',
56
+ args: input,
57
+ });
58
+ await trackToolUsage(this.toolName, this.getTrackingMeta(input));
59
+ const result = await this.handler(input, extra);
60
+ this.logger.debug(this.toolName, {
61
+ message: 'Tool completed',
62
+ durationMs: Date.now() - startTime,
63
+ });
64
+ return result;
65
+ }
66
+ catch (error) {
67
+ this.logger.error(this.toolName, {
68
+ message: 'Tool failed',
69
+ error: error instanceof Error ? error.message : String(error),
70
+ durationMs: Date.now() - startTime,
71
+ });
72
+ return formatTextContents(getErrorMessage(error));
73
+ }
74
+ finally {
75
+ this.logger.flushLogsToFile(this.toolName);
76
+ }
77
+ });
72
78
  }
73
79
  }
@@ -1,10 +1,13 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  export declare class McpLogger {
3
3
  private mcpServer;
4
+ private invocationStorage;
4
5
  constructor(mcpServer: McpServer);
5
6
  private log;
6
7
  debug(logger: string, data: unknown): void;
7
8
  info(logger: string, data: unknown): void;
8
9
  warn(logger: string, data: unknown): void;
9
10
  error(logger: string, data: unknown): void;
11
+ runWithBuffer<T>(fn: () => Promise<T>): Promise<T>;
12
+ flushLogsToFile(filenamePrefix: string): string | null;
10
13
  }
@@ -1,10 +1,22 @@
1
+ import os from 'os';
2
+ import path from 'path';
3
+ import { AsyncLocalStorage } from 'node:async_hooks';
4
+ import { LogBuffer } from '@hubspot/local-dev-lib/LogBuffer';
5
+ import { MAX_LOG_FILES } from '../../lib/constants.js';
6
+ const MCP_LOG_DIR = path.join(os.homedir(), '.hscli', 'logs', 'tools');
1
7
  export class McpLogger {
2
8
  mcpServer;
9
+ invocationStorage = new AsyncLocalStorage();
3
10
  constructor(mcpServer) {
4
11
  this.mcpServer = mcpServer;
5
12
  }
6
13
  log(level, logger, data) {
7
14
  try {
15
+ const buffer = this.invocationStorage.getStore();
16
+ if (buffer) {
17
+ const serialized = typeof data === 'string' ? data : JSON.stringify(data);
18
+ buffer.record(level, [logger, serialized]);
19
+ }
8
20
  this.mcpServer.sendLoggingMessage({ level, logger, data });
9
21
  }
10
22
  catch (error) {
@@ -26,4 +38,22 @@ export class McpLogger {
26
38
  error(logger, data) {
27
39
  this.log('error', logger, data);
28
40
  }
41
+ // Runs fn in a fresh per-invocation log buffer context. All log calls made
42
+ // within fn (including nested async callbacks like progress chunks) record
43
+ // into this buffer rather than a shared one, so concurrent tool calls never
44
+ // intermix their logs.
45
+ runWithBuffer(fn) {
46
+ return this.invocationStorage.run(new LogBuffer(), fn);
47
+ }
48
+ flushLogsToFile(filenamePrefix) {
49
+ const buffer = this.invocationStorage.getStore();
50
+ if (!buffer) {
51
+ return null;
52
+ }
53
+ return buffer.writeToFile({
54
+ dir: MCP_LOG_DIR,
55
+ filenamePrefix,
56
+ maxFiles: MAX_LOG_FILES,
57
+ });
58
+ }
29
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "8.11.0-beta.0",
3
+ "version": "8.12.0",
4
4
  "description": "The official CLI for developing on HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": "https://github.com/HubSpot/hubspot-cli",
@@ -10,10 +10,10 @@
10
10
  "!**/__tests__/**"
11
11
  ],
12
12
  "dependencies": {
13
- "@hubspot/local-dev-lib": "5.10.0",
14
- "@hubspot/project-parsing-lib": "0.19.1",
13
+ "@hubspot/local-dev-lib": "5.10.1",
14
+ "@hubspot/project-parsing-lib": "0.21.0",
15
15
  "@hubspot/serverless-dev-runtime": "7.0.7",
16
- "@hubspot/ui-extensions-dev-server": "2.0.10",
16
+ "@hubspot/ui-extensions-dev-server": "2.0.13",
17
17
  "@inquirer/prompts": "7.1.0",
18
18
  "@modelcontextprotocol/sdk": "1.29.0",
19
19
  "archiver": "7.0.1",
@@ -40,10 +40,11 @@
40
40
  "update-notifier": "7.3.1",
41
41
  "ws": "8.20.0",
42
42
  "yargs": "17.7.2",
43
- "yargs-parser": "21.1.1"
43
+ "yargs-parser": "21.1.1",
44
+ "zod": "^4.4.3"
44
45
  },
45
46
  "devDependencies": {
46
- "@hubspot/npm-scripts": "0.2.2",
47
+ "@hubspot/npm-scripts": "0.3.1",
47
48
  "@types/archiver": "^6.0.3",
48
49
  "@types/cli-progress": "^3.11.6",
49
50
  "@types/express": "^5.0.0",
@@ -60,7 +61,7 @@
60
61
  "@typescript-eslint/eslint-plugin": "^8.30.1",
61
62
  "@typescript-eslint/parser": "^8.11.0",
62
63
  "@vitest/coverage-v8": "^2.1.9",
63
- "axios": "1.16.0",
64
+ "axios": "1.18.1",
64
65
  "eslint": "^8.56.0",
65
66
  "eslint-plugin-import": "^2.31.0",
66
67
  "husky": "^4.3.8",
@@ -123,6 +124,7 @@
123
124
  "registry": "https://registry.npmjs.org/"
124
125
  },
125
126
  "resolutions": {
126
- "eslint-visitor-keys": "4.2.0"
127
+ "eslint-visitor-keys": "4.2.0",
128
+ "@eslint-community/eslint-utils": "4.9.0"
127
129
  }
128
130
  }
package/types/Yargs.d.ts CHANGED
@@ -38,9 +38,11 @@ export type OverwriteArgs = Options & {
38
38
  export type StringArgType = Options & {
39
39
  type: 'string';
40
40
  };
41
- export type JSONOutputArgs = Options & {
41
+ export type JSONOutputArgs<J extends Record<string, unknown> = Record<string, unknown>> = Options & {
42
42
  json?: boolean;
43
+ jsonSchema?: boolean;
43
44
  formatOutputAsJson?: boolean;
45
+ addJsonOutput: (data: Partial<J>) => void;
44
46
  };
45
47
  export type ProjectDevArgs = CommonArgs & ConfigArgs & EnvironmentArgs & {
46
48
  profile?: string;
@@ -1,11 +0,0 @@
1
- import { ArgumentsCamelCase } from 'yargs';
2
- import { ProjectConfig } from '../../../types/Projects.js';
3
- import { ProjectDevArgs } from '../../../types/Yargs.js';
4
- type DeprecatedProjectDevFlowArgs = {
5
- args: ArgumentsCamelCase<ProjectDevArgs>;
6
- accountId: number;
7
- projectConfig: ProjectConfig;
8
- projectDir: string;
9
- };
10
- export declare function deprecatedProjectDevFlow({ args, accountId, projectConfig, projectDir, }: DeprecatedProjectDevFlowArgs): Promise<void>;
11
- export {};