@hubspot/cli 8.14.0-beta.0 → 8.14.0-beta.1

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.
@@ -110,6 +110,11 @@ function projectDevBuilder(yargs) {
110
110
  description: commands.project.dev.options.port,
111
111
  default: LOCAL_DEV_DEFAULT_PORT,
112
112
  });
113
+ yargs.option('auto-upload', {
114
+ type: 'boolean',
115
+ description: commands.project.dev.options.autoUpload,
116
+ default: false,
117
+ });
113
118
  yargs.example([['$0 project dev', commands.project.dev.examples.default]]);
114
119
  yargs.conflicts('profile', 'testing-account');
115
120
  yargs.conflicts('profile', 'project-account');
@@ -155,6 +155,13 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
155
155
  noLogs: true,
156
156
  });
157
157
  let project = uploadedProject;
158
+ // Fail fast before the slower project checks below.
159
+ const autoDeployEnabled = (project?.deployedBuild ?? project?.latestBuild)?.isAutoDeployEnabled ??
160
+ true;
161
+ if (args.autoUpload && !autoDeployEnabled) {
162
+ uiLogger.error(commands.project.dev.errors.autoUploadRequiresAutoDeploy);
163
+ return exit(EXIT_CODES.ERROR);
164
+ }
158
165
  if (projectExists && project) {
159
166
  await compareLocalProjectToDeployed(projectConfig, targetProjectAccountId, project.deployedBuild?.buildId, projectNodes, exit, args.profile);
160
167
  }
@@ -189,6 +196,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
189
196
  projectData: project,
190
197
  env,
191
198
  actions: { exit },
199
+ autoUploadEnabled: Boolean(args.autoUpload) && autoDeployEnabled,
192
200
  });
193
201
  const websocketServer = new LocalDevWebsocketServer(localDevProcess, args.debug);
194
202
  const watcher = new LocalDevWatcher(localDevProcess);
@@ -1,5 +1,6 @@
1
- import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- export type ProjectListBuildsArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
1
+ import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
2
+ import { ProjectBuildsListJsonOutput } from '../../lib/jsonOutput.js';
3
+ export type ProjectListBuildsArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs<ProjectBuildsListJsonOutput> & {
3
4
  project?: string;
4
5
  limit?: number;
5
6
  };
@@ -5,6 +5,7 @@ import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/con
5
5
  import { getProjectDetailUrl } from '../../lib/projects/urls.js';
6
6
  import moment from 'moment';
7
7
  import { promptUser } from '../../lib/prompts/promptUtils.js';
8
+ import { isPromptExitError } from '../../lib/errors/PromptExitError.js';
8
9
  import { uiLogger } from '../../lib/ui/logger.js';
9
10
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
10
11
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
@@ -12,6 +13,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
12
13
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
13
14
  import { commands } from '../../lang/en.js';
14
15
  import { renderTable } from '../../ui/render.js';
16
+ import { ProjectBuildsListSchema, mapBuildToJsonOutput, } from '../../lib/jsonOutput.js';
15
17
  const command = 'list-builds';
16
18
  const describe = commands.project.listBuilds.describe;
17
19
  async function fetchAndDisplayBuilds(accountId, project, options) {
@@ -40,7 +42,7 @@ async function fetchAndDisplayBuilds(accountId, project, options) {
40
42
  });
41
43
  renderTable(['Build ID', 'Status', 'Completed', 'Duration', 'Details'], builds);
42
44
  }
43
- if (options && options.after) {
45
+ if (options.after) {
44
46
  if (results.length > 0) {
45
47
  uiLogger.log(commands.project.listBuilds.showingNextBuilds(results.length, project.name));
46
48
  }
@@ -48,7 +50,8 @@ async function fetchAndDisplayBuilds(accountId, project, options) {
48
50
  else {
49
51
  uiLogger.log(commands.project.listBuilds.showingRecentBuilds(results.length, project.name, uiLink(commands.project.listBuilds.viewAllBuildsLink, getProjectDetailUrl(project.name, accountId))));
50
52
  }
51
- if (paging && paging.next) {
53
+ const canPromptForMore = options.limit === undefined && Boolean(process.stdin.isTTY);
54
+ if (paging?.next?.after && canPromptForMore) {
52
55
  await promptUser({
53
56
  name: 'more',
54
57
  message: commands.project.listBuilds.continueOrExitPrompt,
@@ -60,7 +63,7 @@ async function fetchAndDisplayBuilds(accountId, project, options) {
60
63
  }
61
64
  }
62
65
  async function handler(args) {
63
- const { project: projectFlagValue, limit, derivedAccountId, exit } = args;
66
+ const { project: projectFlagValue, limit, derivedAccountId, exit, json: formatOutputAsJson, addJsonOutput, } = args;
64
67
  let projectName = projectFlagValue;
65
68
  if (!projectName) {
66
69
  const { projectConfig, projectDir } = await getProjectConfig();
@@ -78,9 +81,25 @@ async function handler(args) {
78
81
  }
79
82
  try {
80
83
  const { data: project } = await fetchProject(derivedAccountId, projectName);
81
- await fetchAndDisplayBuilds(derivedAccountId, project, { limit });
84
+ if (formatOutputAsJson) {
85
+ const { data: { results, paging }, } = await fetchProjectBuilds(derivedAccountId, project.name, { limit });
86
+ addJsonOutput({
87
+ projectName: project.name,
88
+ deployedBuildId: project.deployedBuildId,
89
+ results: results.map(build => mapBuildToJsonOutput(build, project.deployedBuildId)),
90
+ paging: paging?.next?.after
91
+ ? { next: { after: paging.next.after } }
92
+ : undefined,
93
+ });
94
+ }
95
+ else {
96
+ await fetchAndDisplayBuilds(derivedAccountId, project, { limit });
97
+ }
82
98
  }
83
99
  catch (e) {
100
+ if (isPromptExitError(e)) {
101
+ return exit(e.exitCode);
102
+ }
84
103
  if (isHubSpotHttpError(e) && e.status === 404) {
85
104
  uiLogger.error(commands.project.listBuilds.errors.projectNotFound(projectName));
86
105
  }
@@ -90,6 +109,7 @@ async function handler(args) {
90
109
  projectName,
91
110
  }));
92
111
  }
112
+ return exit(EXIT_CODES.ERROR);
93
113
  }
94
114
  return exit(EXIT_CODES.SUCCESS);
95
115
  }
@@ -101,11 +121,19 @@ function projectListBuildsBuilder(yargs) {
101
121
  },
102
122
  limit: {
103
123
  describe: commands.project.listBuilds.options.limit.describe,
104
- type: 'string',
124
+ type: 'number',
105
125
  },
106
126
  });
107
127
  yargs.example([
108
128
  ['$0 project list-builds', commands.project.listBuilds.examples.default],
129
+ [
130
+ '$0 project list-builds --limit=5',
131
+ commands.project.listBuilds.examples.withLimit,
132
+ ],
133
+ [
134
+ '$0 project list-builds --json',
135
+ commands.project.listBuilds.examples.json,
136
+ ],
109
137
  ]);
110
138
  return yargs;
111
139
  }
@@ -114,11 +142,14 @@ const builder = makeYargsBuilder(projectListBuildsBuilder, command, describe, {
114
142
  useConfigOptions: true,
115
143
  useAccountOptions: true,
116
144
  useEnvironmentOptions: true,
145
+ useJSONOutputOptions: true,
117
146
  });
118
147
  const projectListBuildsCommand = {
119
148
  command,
120
149
  describe,
121
- handler: makeWrappedYargsHandler('project-list-builds', handler),
150
+ handler: makeWrappedYargsHandler('project-list-builds', handler, {
151
+ jsonOutputSchema: ProjectBuildsListSchema,
152
+ }),
122
153
  builder,
123
154
  };
124
155
  export default projectListBuildsCommand;
@@ -118,7 +118,7 @@ async function handler(args) {
118
118
  (!result.buildResult.isAutoDeployEnabled || preview || skipAutoDeploy)) {
119
119
  uiLogger.log(chalk.bold(commands.project.upload.logs.buildSucceeded(result.buildId)));
120
120
  if (!preview) {
121
- if (meetsMinimumPlatformVersion(result.buildResult.platformVersion, PLATFORM_VERSIONS.v2026_09_BETA)) {
121
+ if (meetsMinimumPlatformVersion(result.buildResult.platformVersion, PLATFORM_VERSIONS.v2027_03_BETA)) {
122
122
  const releaseCommand = `hs project release create --build=${result.buildId}`;
123
123
  uiLogger.log(commands.project.upload.logs.releaseManagementRequired(releaseCommand));
124
124
  }
package/lang/en.d.ts CHANGED
@@ -1529,6 +1529,7 @@ export declare const commands: {
1529
1529
  noRunnableComponents: string;
1530
1530
  accountNotCombined: string;
1531
1531
  localDevAlreadyRunning: string;
1532
+ autoUploadRequiresAutoDeploy: string;
1532
1533
  };
1533
1534
  examples: {
1534
1535
  default: string;
@@ -1541,6 +1542,7 @@ export declare const commands: {
1541
1542
  projectAccount: string;
1542
1543
  testingAccount: string;
1543
1544
  port: string;
1545
+ autoUpload: string;
1544
1546
  };
1545
1547
  };
1546
1548
  create: {
@@ -1842,6 +1844,8 @@ export declare const commands: {
1842
1844
  };
1843
1845
  examples: {
1844
1846
  default: string;
1847
+ withLimit: string;
1848
+ json: string;
1845
1849
  };
1846
1850
  };
1847
1851
  logs: {
@@ -3376,6 +3380,7 @@ export declare const lib: {
3376
3380
  learnMoreLocalDevServer: string;
3377
3381
  running: (projectName: string, accountIdentifier: string) => string;
3378
3382
  quitHelper: string;
3383
+ autoUploadEnabled: string;
3379
3384
  viewProjectLink: (name: string, accountId: number) => string;
3380
3385
  viewLocalDevUILink: (accountId: number, showWelcomeScreen: boolean) => string;
3381
3386
  localDevUIAutoMessage: (accountId: number, showWelcomeScreen: boolean) => string;
@@ -3467,6 +3472,10 @@ export declare const lib: {
3467
3472
  LocalDevProcess: {
3468
3473
  projectConfigMismatch: string;
3469
3474
  uploadInitiated: string;
3475
+ autoUploadScheduled: (filePath: string) => string;
3476
+ autoUploadTriggered: string;
3477
+ autoUploadInProgress: string;
3478
+ autoUploadToggled: (enabled: boolean) => string;
3470
3479
  deployInitiated: string;
3471
3480
  uploadFailed: string;
3472
3481
  deployFailed: string;
package/lang/en.js CHANGED
@@ -1545,6 +1545,7 @@ export const commands = {
1545
1545
  noRunnableComponents: `No supported components were found in this project. Run ${uiCommandReference('hs project add')} to see a list of available components and add one to your project.`,
1546
1546
  accountNotCombined: `\nLocal development of unified apps is currently only compatible with accounts that are opted into the unified apps beta. Make sure that this account is opted in or switch accounts using ${uiCommandReference('hs account use')}.`,
1547
1547
  localDevAlreadyRunning: `Another ${uiCommandReference('hs project dev')} process is already running. To proceed with local development of this project, stop the existing process and re-run ${uiCommandReference('hs project dev')}.`,
1548
+ autoUploadRequiresAutoDeploy: `${uiCommandReference('hs project dev --auto-upload')} requires auto-deploy to be enabled for this project, since auto-upload deploys every change. Enable auto-deploy in your project settings, or run ${uiCommandReference('hs project dev')} without it.`,
1548
1549
  },
1549
1550
  examples: {
1550
1551
  default: 'Start local dev for the current project',
@@ -1557,6 +1558,7 @@ export const commands = {
1557
1558
  projectAccount: 'The id of the account to upload your project to. Must be used with --testing-account.',
1558
1559
  testingAccount: 'The id of the account to install apps and test on. Must be used with --project-account.',
1559
1560
  port: `The port for the local dev server. Defaults to ${LOCAL_DEV_DEFAULT_PORT}.`,
1561
+ autoUpload: 'Automatically upload local changes to HubSpot as you edit files, instead of uploading manually from the Local Dev Panel.',
1560
1562
  },
1561
1563
  },
1562
1564
  create: {
@@ -1858,6 +1860,8 @@ export const commands = {
1858
1860
  },
1859
1861
  examples: {
1860
1862
  default: 'List the builds for the current project',
1863
+ withLimit: 'List the five most recent builds for the current project',
1864
+ json: 'Output the builds for the current project as JSON',
1861
1865
  },
1862
1866
  },
1863
1867
  logs: {
@@ -3401,6 +3405,7 @@ export const lib = {
3401
3405
  learnMoreLocalDevServer: uiLink('Learn more about the projects local dev server', 'https://developers.hubspot.com/docs/developer-tooling/local-development/hubspot-cli/project-commands'),
3402
3406
  running: (projectName, accountIdentifier) => chalk.hex(UI_COLORS.SORBET)(`Running ${chalk.bold(projectName)} locally on ${accountIdentifier}, waiting for changes ...`),
3403
3407
  quitHelper: `Press ${chalk.bold('q')} to stop the local dev server`,
3408
+ autoUploadEnabled: `${chalk.bold('Auto-upload is on.')} Changes you make locally will be uploaded to HubSpot automatically.`,
3404
3409
  viewProjectLink: (name, accountId) => uiLink('View project in HubSpot', getProjectDetailUrl(name, accountId) || ''),
3405
3410
  viewLocalDevUILink: (accountId, showWelcomeScreen) => uiLink('View local dev session in HubSpot', getLocalDevUiUrl(accountId, showWelcomeScreen)),
3406
3411
  localDevUIAutoMessage: (accountId, showWelcomeScreen) => `Opening your ${uiLink('local dev session in HubSpot', getLocalDevUiUrl(accountId, showWelcomeScreen))}...`,
@@ -3491,8 +3496,14 @@ export const lib = {
3491
3496
  },
3492
3497
  LocalDevProcess: {
3493
3498
  projectConfigMismatch: `Unable to upload project. The project config has been modified since starting ${uiCommandReference('hs project dev')}.`,
3494
- uploadInitiated: 'Project upload initiated from Local Dev UI.',
3495
- deployInitiated: 'Project deploy initiated from Local Dev UI.',
3499
+ uploadInitiated: 'Project upload initiated.',
3500
+ autoUploadScheduled: (filePath) => `Auto-upload: detected change to ${filePath}, upload scheduled.`,
3501
+ autoUploadTriggered: 'Auto-upload: debounce elapsed, uploading now.',
3502
+ autoUploadInProgress: 'Auto-upload: an upload is already running, will re-run after it finishes.',
3503
+ autoUploadToggled: (enabled) => enabled
3504
+ ? `${chalk.bold('Auto-upload turned on')} from the Local Dev Panel. Changes you make locally will be uploaded to HubSpot automatically.`
3505
+ : `${chalk.bold('Auto-upload turned off')} from the Local Dev Panel. Upload manually from the Local Dev Panel to push your changes.`,
3506
+ deployInitiated: 'Project deploy initiated from the Local Dev Panel.',
3496
3507
  uploadFailed: 'Project upload failed. To proceed with local development, fix any necessary errors, then re-upload your project.',
3497
3508
  deployFailed: 'Project deploy failed. To proceed with local development, fix any necessary errors, then re-deploy your project.',
3498
3509
  uploadSuccess: 'Project upload completed successfully. Resuming local dev...',
@@ -94,6 +94,7 @@ export declare const LOCAL_DEV_UI_MESSAGE_SEND_TYPES: {
94
94
  UPDATE_PROJECT_DATA: string;
95
95
  UPDATE_UPLOAD_WARNINGS: string;
96
96
  DEV_SERVERS_STARTED: string;
97
+ UPLOAD_IN_PROGRESS: string;
97
98
  };
98
99
  export declare const LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES: {
99
100
  UPLOAD: string;
@@ -102,6 +103,7 @@ export declare const LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES: {
102
103
  APP_INSTALL_SUCCESS: string;
103
104
  APP_INSTALL_INITIATED: string;
104
105
  APP_INSTALL_FAILURE: string;
106
+ SET_AUTO_UPLOAD: string;
105
107
  };
106
108
  export declare const APP_INSTALLATION_STATES: {
107
109
  readonly NOT_INSTALLED: "NOT_INSTALLED";
package/lib/constants.js CHANGED
@@ -86,6 +86,7 @@ export const LOCAL_DEV_UI_MESSAGE_SEND_TYPES = {
86
86
  UPDATE_PROJECT_DATA: 'server:updateProjectData',
87
87
  UPDATE_UPLOAD_WARNINGS: 'server:updateUploadWarnings',
88
88
  DEV_SERVERS_STARTED: 'server:devServersStarted',
89
+ UPLOAD_IN_PROGRESS: 'server:uploadInProgress',
89
90
  };
90
91
  export const LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES = {
91
92
  UPLOAD: 'client:upload',
@@ -94,6 +95,7 @@ export const LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES = {
94
95
  APP_INSTALL_SUCCESS: 'client:installSuccess',
95
96
  APP_INSTALL_INITIATED: 'client:installInitiated',
96
97
  APP_INSTALL_FAILURE: 'client:installFailure',
98
+ SET_AUTO_UPLOAD: 'client:setAutoUpload',
97
99
  };
98
100
  export const APP_INSTALLATION_STATES = {
99
101
  NOT_INSTALLED: 'NOT_INSTALLED',
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { Build } from '@hubspot/local-dev-lib/types/Build';
2
3
  import { Release } from '../api/releases.js';
3
4
  declare const ReleaseComponentSchema: z.ZodObject<{
4
5
  buildType: z.ZodString;
@@ -35,6 +36,74 @@ export declare const ReleaseListSchema: z.ZodObject<{
35
36
  }, z.core.$strip>;
36
37
  }, z.core.$strip>>;
37
38
  }, z.core.$strip>;
39
+ declare const BuildSubbuildStatusSchema: z.ZodObject<{
40
+ buildName: z.ZodString;
41
+ buildType: z.ZodString;
42
+ status: z.ZodString;
43
+ errorMessage: z.ZodOptional<z.ZodString>;
44
+ startedAt: z.ZodOptional<z.ZodString>;
45
+ finishedAt: z.ZodOptional<z.ZodString>;
46
+ rootPath: z.ZodOptional<z.ZodString>;
47
+ id: z.ZodOptional<z.ZodString>;
48
+ visible: z.ZodOptional<z.ZodBoolean>;
49
+ }, z.core.$strip>;
50
+ export declare const BuildSchema: z.ZodObject<{
51
+ buildId: z.ZodNumber;
52
+ status: z.ZodString;
53
+ isDeployed: z.ZodBoolean;
54
+ isAutoDeployEnabled: z.ZodOptional<z.ZodBoolean>;
55
+ deployableState: z.ZodOptional<z.ZodString>;
56
+ platformVersion: z.ZodOptional<z.ZodString>;
57
+ uploadMessage: z.ZodOptional<z.ZodString>;
58
+ enqueuedAt: z.ZodOptional<z.ZodString>;
59
+ startedAt: z.ZodOptional<z.ZodString>;
60
+ finishedAt: z.ZodOptional<z.ZodString>;
61
+ createdAt: z.ZodOptional<z.ZodString>;
62
+ subbuildStatuses: z.ZodArray<z.ZodObject<{
63
+ buildName: z.ZodString;
64
+ buildType: z.ZodString;
65
+ status: z.ZodString;
66
+ errorMessage: z.ZodOptional<z.ZodString>;
67
+ startedAt: z.ZodOptional<z.ZodString>;
68
+ finishedAt: z.ZodOptional<z.ZodString>;
69
+ rootPath: z.ZodOptional<z.ZodString>;
70
+ id: z.ZodOptional<z.ZodString>;
71
+ visible: z.ZodOptional<z.ZodBoolean>;
72
+ }, z.core.$strip>>;
73
+ }, z.core.$strip>;
74
+ export declare const ProjectBuildsListSchema: z.ZodObject<{
75
+ projectName: z.ZodString;
76
+ deployedBuildId: z.ZodOptional<z.ZodNumber>;
77
+ results: z.ZodArray<z.ZodObject<{
78
+ buildId: z.ZodNumber;
79
+ status: z.ZodString;
80
+ isDeployed: z.ZodBoolean;
81
+ isAutoDeployEnabled: z.ZodOptional<z.ZodBoolean>;
82
+ deployableState: z.ZodOptional<z.ZodString>;
83
+ platformVersion: z.ZodOptional<z.ZodString>;
84
+ uploadMessage: z.ZodOptional<z.ZodString>;
85
+ enqueuedAt: z.ZodOptional<z.ZodString>;
86
+ startedAt: z.ZodOptional<z.ZodString>;
87
+ finishedAt: z.ZodOptional<z.ZodString>;
88
+ createdAt: z.ZodOptional<z.ZodString>;
89
+ subbuildStatuses: z.ZodArray<z.ZodObject<{
90
+ buildName: z.ZodString;
91
+ buildType: z.ZodString;
92
+ status: z.ZodString;
93
+ errorMessage: z.ZodOptional<z.ZodString>;
94
+ startedAt: z.ZodOptional<z.ZodString>;
95
+ finishedAt: z.ZodOptional<z.ZodString>;
96
+ rootPath: z.ZodOptional<z.ZodString>;
97
+ id: z.ZodOptional<z.ZodString>;
98
+ visible: z.ZodOptional<z.ZodBoolean>;
99
+ }, z.core.$strip>>;
100
+ }, z.core.$strip>>;
101
+ paging: z.ZodOptional<z.ZodObject<{
102
+ next: z.ZodObject<{
103
+ after: z.ZodString;
104
+ }, z.core.$strip>;
105
+ }, z.core.$strip>>;
106
+ }, z.core.$strip>;
38
107
  export declare const ProjectInfoSchema: z.ZodObject<{
39
108
  projectName: z.ZodString;
40
109
  platformVersion: z.ZodString;
@@ -98,6 +167,9 @@ export declare const CreateTestAccountSchema: z.ZodObject<{
98
167
  export type ReleaseComponentJsonOutput = z.infer<typeof ReleaseComponentSchema>;
99
168
  export type ReleaseJsonOutput = z.infer<typeof ReleaseSchema>;
100
169
  export type ReleaseListJsonOutput = z.infer<typeof ReleaseListSchema>;
170
+ export type BuildSubbuildStatusJsonOutput = z.infer<typeof BuildSubbuildStatusSchema>;
171
+ export type BuildJsonOutput = z.infer<typeof BuildSchema>;
172
+ export type ProjectBuildsListJsonOutput = z.infer<typeof ProjectBuildsListSchema>;
101
173
  export type ProjectInfoJsonOutput = z.infer<typeof ProjectInfoSchema>;
102
174
  export type PreviewJsonOutput = z.infer<typeof PreviewSchema>;
103
175
  export type UploadJsonOutput = z.infer<typeof UploadSchema>;
@@ -105,5 +177,6 @@ export type DeployJsonOutput = z.infer<typeof DeploySchema>;
105
177
  export type InstallStatusJsonOutput = z.infer<typeof InstallStatusSchema>;
106
178
  export type InstallAppJsonOutput = z.infer<typeof InstallAppSchema>;
107
179
  export type CreateTestAccountJsonOutput = z.infer<typeof CreateTestAccountSchema>;
180
+ export declare function mapBuildToJsonOutput(build: Build, deployedBuildId?: number): BuildJsonOutput;
108
181
  export declare function mapReleaseToJsonOutput(release: Release): ReleaseJsonOutput;
109
182
  export {};
package/lib/jsonOutput.js CHANGED
@@ -21,6 +21,43 @@ export const ReleaseListSchema = z.object({
21
21
  })
22
22
  .optional(),
23
23
  });
24
+ const BuildSubbuildStatusSchema = z.object({
25
+ buildName: z.string(),
26
+ buildType: z.string(),
27
+ status: z.string(),
28
+ errorMessage: z.string().optional(),
29
+ startedAt: z.string().optional(),
30
+ finishedAt: z.string().optional(),
31
+ rootPath: z.string().optional(),
32
+ id: z.string().optional(),
33
+ visible: z.boolean().optional(),
34
+ });
35
+ export const BuildSchema = z.object({
36
+ buildId: z.number(),
37
+ status: z.string(),
38
+ isDeployed: z.boolean(),
39
+ isAutoDeployEnabled: z.boolean().optional(),
40
+ deployableState: z.string().optional(),
41
+ platformVersion: z.string().optional(),
42
+ uploadMessage: z.string().optional(),
43
+ enqueuedAt: z.string().optional(),
44
+ startedAt: z.string().optional(),
45
+ finishedAt: z.string().optional(),
46
+ createdAt: z.string().optional(),
47
+ subbuildStatuses: z.array(BuildSubbuildStatusSchema),
48
+ });
49
+ export const ProjectBuildsListSchema = z.object({
50
+ projectName: z.string(),
51
+ deployedBuildId: z.number().optional(),
52
+ results: z.array(BuildSchema),
53
+ paging: z
54
+ .object({
55
+ next: z.object({
56
+ after: z.string(),
57
+ }),
58
+ })
59
+ .optional(),
60
+ });
24
61
  export const ProjectInfoSchema = z.object({
25
62
  projectName: z.string(),
26
63
  platformVersion: z.string(),
@@ -78,6 +115,33 @@ export const CreateTestAccountSchema = z.object({
78
115
  accountId: z.number().optional(),
79
116
  personalAccessKey: z.string().optional(),
80
117
  });
118
+ export function mapBuildToJsonOutput(build, deployedBuildId) {
119
+ const { buildId, status, isAutoDeployEnabled, deployableState, platformVersion, uploadMessage, enqueuedAt, startedAt, finishedAt, createdAt, subbuildStatuses, } = build;
120
+ return {
121
+ buildId,
122
+ status,
123
+ isDeployed: buildId === deployedBuildId,
124
+ isAutoDeployEnabled,
125
+ deployableState,
126
+ platformVersion,
127
+ uploadMessage,
128
+ enqueuedAt,
129
+ startedAt,
130
+ finishedAt,
131
+ createdAt,
132
+ subbuildStatuses: subbuildStatuses.map(subbuild => ({
133
+ buildName: subbuild.buildName,
134
+ buildType: subbuild.buildType,
135
+ status: subbuild.status,
136
+ errorMessage: subbuild.errorMessage,
137
+ startedAt: subbuild.startedAt,
138
+ finishedAt: subbuild.finishedAt,
139
+ rootPath: subbuild.rootPath,
140
+ id: subbuild.id,
141
+ visible: subbuild.visible,
142
+ })),
143
+ };
144
+ }
81
145
  export function mapReleaseToJsonOutput(release) {
82
146
  const { releaseTag, buildId, createdAt, components } = release;
83
147
  return {
@@ -22,6 +22,10 @@ declare class LocalDevLogger {
22
22
  cleanupError(): void;
23
23
  cleanupSuccess(): void;
24
24
  uploadInitiated(): void;
25
+ autoUploadScheduled(filePath: string): void;
26
+ autoUploadTriggered(): void;
27
+ autoUploadInProgress(): void;
28
+ autoUploadToggled(enabled: boolean): void;
25
29
  deployInitiated(): void;
26
30
  projectConfigMismatch(): void;
27
31
  uploadError(error: unknown): void;
@@ -99,6 +99,10 @@ class LocalDevLogger {
99
99
  uiLogger.log('');
100
100
  uiLogger.log(lib.LocalDevManager.localDevUIAutoMessage(this.state.targetTestingAccountId, showWelcomeScreen));
101
101
  }
102
+ if (this.state.autoUploadEnabled) {
103
+ uiLogger.log('');
104
+ uiLogger.log(lib.LocalDevManager.autoUploadEnabled);
105
+ }
102
106
  uiLogger.log('');
103
107
  uiLogger.log(lib.LocalDevManager.quitHelper);
104
108
  uiLine();
@@ -122,6 +126,20 @@ class LocalDevLogger {
122
126
  uploadInitiated() {
123
127
  uiLogger.log(lib.LocalDevProcess.uploadInitiated);
124
128
  }
129
+ autoUploadScheduled(filePath) {
130
+ uiLogger.debug(lib.LocalDevProcess.autoUploadScheduled(filePath));
131
+ }
132
+ autoUploadTriggered() {
133
+ uiLogger.debug(lib.LocalDevProcess.autoUploadTriggered);
134
+ }
135
+ autoUploadInProgress() {
136
+ uiLogger.debug(lib.LocalDevProcess.autoUploadInProgress);
137
+ }
138
+ autoUploadToggled(enabled) {
139
+ uiLogger.log('');
140
+ uiLogger.log(lib.LocalDevProcess.autoUploadToggled(enabled));
141
+ uiLogger.log('');
142
+ }
125
143
  deployInitiated() {
126
144
  uiLogger.log(lib.LocalDevProcess.deployInitiated);
127
145
  }
@@ -8,6 +8,9 @@ declare class LocalDevProcess {
8
8
  private _logger;
9
9
  private devServerManager;
10
10
  private devSessionManager;
11
+ private autoUploadTimeout;
12
+ private pendingAutoUpload;
13
+ private autoUploadStopped;
11
14
  constructor(options: LocalDevStateConstructorOptions);
12
15
  get projectDir(): string;
13
16
  get projectData(): Project;
@@ -17,6 +20,10 @@ declare class LocalDevProcess {
17
20
  [key: string]: IntermediateRepresentationNodeLocalDev;
18
21
  };
19
22
  get logger(): LocalDevLogger;
23
+ get autoUploadEnabled(): boolean;
24
+ setAutoUploadEnabled(enabled: boolean): void;
25
+ get autoUploadAvailable(): boolean;
26
+ private isAutoDeployEnabled;
20
27
  private setupDevServers;
21
28
  private startDevServers;
22
29
  private cleanupDevServers;
@@ -27,10 +34,13 @@ declare class LocalDevProcess {
27
34
  private openLocalDevUi;
28
35
  private updateProjectData;
29
36
  handleFileChange(filePath: string, event: string): Promise<void>;
30
- handleConfigFileChange(): Promise<void>;
37
+ handleConfigFileChange(configFilePath: string): Promise<void>;
38
+ private scheduleAutoUpload;
39
+ private runAutoUpload;
31
40
  start(): Promise<void>;
32
41
  stop(showProgress?: boolean): Promise<void>;
33
42
  uploadProject(): Promise<LocalDevProjectUploadResult>;
43
+ private performUpload;
34
44
  deployLatestBuild(force?: boolean): Promise<LocalDevProjectDeployResult>;
35
45
  addStateListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>): void;
36
46
  sendDevServerMessage(message: LocalDevServerMessage): void;
@@ -17,11 +17,15 @@ import { getLocalDevUiUrl } from '../urls.js';
17
17
  import { CONFIG_LOCAL_STATE_FLAGS, PROJECT_DEPLOY_STATES, } from '../../constants.js';
18
18
  import { lib } from '../../../lang/en.js';
19
19
  import { debugError } from '../../errorHandlers/index.js';
20
+ const AUTO_UPLOAD_DEBOUNCE_MS = 2000;
20
21
  class LocalDevProcess {
21
22
  state;
22
23
  _logger;
23
24
  devServerManager;
24
25
  devSessionManager;
26
+ autoUploadTimeout = null;
27
+ pendingAutoUpload = false;
28
+ autoUploadStopped = false;
25
29
  constructor(options) {
26
30
  this.state = new LocalDevState(options);
27
31
  this._logger = new LocalDevLogger(this.state);
@@ -53,6 +57,27 @@ class LocalDevProcess {
53
57
  get logger() {
54
58
  return this._logger;
55
59
  }
60
+ get autoUploadEnabled() {
61
+ return this.state.autoUploadEnabled;
62
+ }
63
+ setAutoUploadEnabled(enabled) {
64
+ this.state.autoUploadEnabled = enabled;
65
+ this.logger.autoUploadToggled(enabled);
66
+ if (!enabled) {
67
+ if (this.autoUploadTimeout) {
68
+ clearTimeout(this.autoUploadTimeout);
69
+ this.autoUploadTimeout = null;
70
+ }
71
+ this.pendingAutoUpload = false;
72
+ }
73
+ }
74
+ get autoUploadAvailable() {
75
+ return this.isAutoDeployEnabled();
76
+ }
77
+ isAutoDeployEnabled() {
78
+ const { deployedBuild, latestBuild } = this.state.projectData;
79
+ return (deployedBuild ?? latestBuild)?.isAutoDeployEnabled ?? true;
80
+ }
56
81
  async setupDevServers() {
57
82
  try {
58
83
  await this.devServerManager.setup();
@@ -141,10 +166,52 @@ class LocalDevProcess {
141
166
  catch (e) {
142
167
  this.logger.fileChangeError(e);
143
168
  }
169
+ this.scheduleAutoUpload(filePath);
144
170
  }
145
- async handleConfigFileChange() {
171
+ async handleConfigFileChange(configFilePath) {
146
172
  await this.updateProjectNodes();
147
- this.logger.uploadWarning();
173
+ if (this.state.autoUploadEnabled) {
174
+ this.scheduleAutoUpload(configFilePath);
175
+ }
176
+ else {
177
+ this.logger.uploadWarning();
178
+ }
179
+ }
180
+ scheduleAutoUpload(changedPath) {
181
+ if (!this.state.autoUploadEnabled || this.autoUploadStopped) {
182
+ return;
183
+ }
184
+ this.logger.autoUploadScheduled(changedPath ?? 'project files');
185
+ if (this.autoUploadTimeout) {
186
+ clearTimeout(this.autoUploadTimeout);
187
+ }
188
+ this.autoUploadTimeout = setTimeout(() => {
189
+ this.autoUploadTimeout = null;
190
+ void this.runAutoUpload();
191
+ }, AUTO_UPLOAD_DEBOUNCE_MS);
192
+ }
193
+ async runAutoUpload() {
194
+ if (this.autoUploadStopped) {
195
+ return;
196
+ }
197
+ if (this.state.uploadInProgress) {
198
+ this.logger.autoUploadInProgress();
199
+ this.pendingAutoUpload = true;
200
+ return;
201
+ }
202
+ this.logger.autoUploadTriggered();
203
+ try {
204
+ await this.uploadProject();
205
+ }
206
+ catch (e) {
207
+ this.logger.uploadError(e);
208
+ }
209
+ finally {
210
+ if (this.pendingAutoUpload) {
211
+ this.pendingAutoUpload = false;
212
+ this.scheduleAutoUpload();
213
+ }
214
+ }
148
215
  }
149
216
  async start() {
150
217
  this.logger.resetSpinnies();
@@ -165,6 +232,12 @@ class LocalDevProcess {
165
232
  this.logger.monitorConsoleOutput();
166
233
  }
167
234
  async stop(showProgress = true) {
235
+ this.autoUploadStopped = true;
236
+ this.pendingAutoUpload = false;
237
+ if (this.autoUploadTimeout) {
238
+ clearTimeout(this.autoUploadTimeout);
239
+ this.autoUploadTimeout = null;
240
+ }
168
241
  if (showProgress) {
169
242
  this.logger.cleanupStart();
170
243
  }
@@ -182,6 +255,15 @@ class LocalDevProcess {
182
255
  return this.state.actions.exit(EXIT_CODES.SUCCESS);
183
256
  }
184
257
  async uploadProject() {
258
+ this.state.uploadInProgress = true;
259
+ try {
260
+ return await this.performUpload();
261
+ }
262
+ finally {
263
+ this.state.uploadInProgress = false;
264
+ }
265
+ }
266
+ async performUpload() {
185
267
  this.logger.uploadInitiated();
186
268
  const isUploadable = await this.projectConfigValidForUpload();
187
269
  if (!isUploadable) {
@@ -21,8 +21,10 @@ declare class LocalDevState {
21
21
  private _devServerMessage;
22
22
  private _uploadWarnings;
23
23
  private _devServersStarted;
24
+ private _autoUploadEnabled;
25
+ private _uploadInProgress;
24
26
  actions: LocalDevActions;
25
- constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectData, debug, initialProjectNodes, initialProjectProfileData, profile, env, actions, }: LocalDevStateConstructorOptions);
27
+ constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectData, debug, initialProjectNodes, initialProjectProfileData, profile, env, actions, autoUploadEnabled, }: LocalDevStateConstructorOptions);
26
28
  private runListeners;
27
29
  get targetProjectAccountId(): number;
28
30
  get targetTestingAccountId(): number;
@@ -56,6 +58,10 @@ declare class LocalDevState {
56
58
  get uploadWarnings(): Set<string>;
57
59
  get devServersStarted(): boolean;
58
60
  set devServersStarted(started: boolean);
61
+ get autoUploadEnabled(): boolean;
62
+ set autoUploadEnabled(autoUploadEnabled: boolean);
63
+ get uploadInProgress(): boolean;
64
+ set uploadInProgress(inProgress: boolean);
59
65
  addUploadWarning(warning: string): void;
60
66
  clearUploadWarnings(): void;
61
67
  addListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>): void;
@@ -16,8 +16,10 @@ class LocalDevState {
16
16
  _devServerMessage;
17
17
  _uploadWarnings;
18
18
  _devServersStarted;
19
+ _autoUploadEnabled;
20
+ _uploadInProgress;
19
21
  actions;
20
- constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectData, debug, initialProjectNodes, initialProjectProfileData, profile, env, actions, }) {
22
+ constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectData, debug, initialProjectNodes, initialProjectProfileData, profile, env, actions, autoUploadEnabled, }) {
21
23
  this._targetProjectAccountId = targetProjectAccountId;
22
24
  this._targetTestingAccountId = targetTestingAccountId;
23
25
  this._profile = profile;
@@ -33,6 +35,8 @@ class LocalDevState {
33
35
  this._devServerMessage = LOCAL_DEV_SERVER_MESSAGE_TYPES.INITIAL;
34
36
  this._uploadWarnings = new Set();
35
37
  this._devServersStarted = false;
38
+ this._autoUploadEnabled = autoUploadEnabled || false;
39
+ this._uploadInProgress = false;
36
40
  this.actions = actions;
37
41
  this._listeners = {};
38
42
  }
@@ -117,6 +121,20 @@ class LocalDevState {
117
121
  this._devServersStarted = started;
118
122
  this.runListeners('devServersStarted');
119
123
  }
124
+ get autoUploadEnabled() {
125
+ return this._autoUploadEnabled;
126
+ }
127
+ set autoUploadEnabled(autoUploadEnabled) {
128
+ this._autoUploadEnabled = autoUploadEnabled;
129
+ this.runListeners('autoUploadEnabled');
130
+ }
131
+ get uploadInProgress() {
132
+ return this._uploadInProgress;
133
+ }
134
+ set uploadInProgress(inProgress) {
135
+ this._uploadInProgress = inProgress;
136
+ this.runListeners('uploadInProgress');
137
+ }
120
138
  addUploadWarning(warning) {
121
139
  this.uploadWarnings.add(warning);
122
140
  this.runListeners('uploadWarnings');
@@ -16,7 +16,7 @@ class LocalDevWatcher {
16
16
  }
17
17
  handleWatchEvent(filePath, event, configPaths) {
18
18
  if (configPaths.includes(filePath)) {
19
- return this.localDevProcess.handleConfigFileChange();
19
+ return this.localDevProcess.handleConfigFileChange(filePath);
20
20
  }
21
21
  return this.localDevProcess.handleFileChange(filePath, event);
22
22
  }
@@ -14,6 +14,7 @@ declare class LocalDevWebsocketServer {
14
14
  private setupAppDataListener;
15
15
  private setupUploadWarningsListener;
16
16
  private setupDevServersStartedListener;
17
+ private setupUploadInProgressListener;
17
18
  private setupStateListeners;
18
19
  start(): Promise<void>;
19
20
  shutdown(): void;
@@ -1,7 +1,7 @@
1
1
  import { addLocalStateFlag } from '@hubspot/local-dev-lib/config';
2
2
  import { LOCAL_DEV_UI_MESSAGE_SEND_TYPES, LOCAL_DEV_SERVER_MESSAGE_TYPES, CONFIG_LOCAL_STATE_FLAGS, LOCAL_DEV_WEBSOCKET_SERVER_INSTANCE_ID, } from '../../constants.js';
3
3
  import { removeAnsiCodes } from '../../ui/removeAnsiCodes.js';
4
- import { isDeployWebsocketMessage, isViewedWelcomeScreenWebsocketMessage, isUploadWebsocketMessage, isAppInstallFailureWebsocketMessage, isAppInstallSuccessWebsocketMessage, isAppInstallInitiatedWebsocketMessage, } from './localDevWebsocketServerUtils.js';
4
+ import { isDeployWebsocketMessage, isViewedWelcomeScreenWebsocketMessage, isUploadWebsocketMessage, isAppInstallFailureWebsocketMessage, isAppInstallSuccessWebsocketMessage, isAppInstallInitiatedWebsocketMessage, isSetAutoUploadWebsocketMessage, } from './localDevWebsocketServerUtils.js';
5
5
  import CLIWebSocketServer from '../../CLIWebSocketServer.js';
6
6
  const LOCAL_DEV_WEBSOCKET_SERVER_VERSION = 2;
7
7
  const LOG_PREFIX = '[LocalDevWebsocketServer]';
@@ -78,6 +78,12 @@ class LocalDevWebsocketServer {
78
78
  this.handleAppInstallInitiated();
79
79
  return true;
80
80
  }
81
+ else if (isSetAutoUploadWebsocketMessage(message)) {
82
+ if (this.localDevProcess.autoUploadAvailable) {
83
+ this.localDevProcess.setAutoUploadEnabled(message.data.enabled);
84
+ }
85
+ return true;
86
+ }
81
87
  return false;
82
88
  }
83
89
  sendProjectData(websocket) {
@@ -90,6 +96,9 @@ class LocalDevWebsocketServer {
90
96
  deployedBuild: this.localDevProcess.projectData.deployedBuild,
91
97
  targetProjectAccountId: this.localDevProcess.targetProjectAccountId,
92
98
  targetTestingAccountId: this.localDevProcess.targetTestingAccountId,
99
+ autoUploadEnabled: this.localDevProcess.autoUploadAvailable
100
+ ? this.localDevProcess.autoUploadEnabled
101
+ : undefined,
93
102
  },
94
103
  });
95
104
  }
@@ -143,11 +152,24 @@ class LocalDevWebsocketServer {
143
152
  this.localDevProcess.removeStateListener('devServersStarted', listener);
144
153
  });
145
154
  }
155
+ setupUploadInProgressListener(websocket) {
156
+ const listener = (uploadInProgress) => {
157
+ this.cliWebSocketServer.sendMessage(websocket, {
158
+ type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPLOAD_IN_PROGRESS,
159
+ data: { uploadInProgress },
160
+ });
161
+ };
162
+ this.localDevProcess.addStateListener('uploadInProgress', listener);
163
+ websocket.on('close', () => {
164
+ this.localDevProcess.removeStateListener('uploadInProgress', listener);
165
+ });
166
+ }
146
167
  setupStateListeners(websocket) {
147
168
  this.setupProjectNodesListener(websocket);
148
169
  this.setupAppDataListener(websocket);
149
170
  this.setupUploadWarningsListener(websocket);
150
171
  this.setupDevServersStartedListener(websocket);
172
+ this.setupUploadInProgressListener(websocket);
151
173
  }
152
174
  async start() {
153
175
  await this.cliWebSocketServer.start({
@@ -1,7 +1,8 @@
1
- import { LocalDevDeployWebsocketMessage } from '../../../types/LocalDev.js';
1
+ import { LocalDevDeployWebsocketMessage, LocalDevSetAutoUploadWebsocketMessage } from '../../../types/LocalDev.js';
2
2
  import { CLIWebSocketMessage } from '../../CLIWebSocketServer.js';
3
3
  export declare function isUploadWebsocketMessage(message: CLIWebSocketMessage): boolean;
4
4
  export declare function isDeployWebsocketMessage(message: CLIWebSocketMessage): message is LocalDevDeployWebsocketMessage;
5
+ export declare function isSetAutoUploadWebsocketMessage(message: CLIWebSocketMessage): message is LocalDevSetAutoUploadWebsocketMessage;
5
6
  export declare function isViewedWelcomeScreenWebsocketMessage(message: CLIWebSocketMessage): boolean;
6
7
  export declare function isAppInstallSuccessWebsocketMessage(message: CLIWebSocketMessage): boolean;
7
8
  export declare function isAppInstallInitiatedWebsocketMessage(message: CLIWebSocketMessage): boolean;
@@ -5,6 +5,9 @@ export function isUploadWebsocketMessage(message) {
5
5
  export function isDeployWebsocketMessage(message) {
6
6
  return message.type === LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.DEPLOY;
7
7
  }
8
+ export function isSetAutoUploadWebsocketMessage(message) {
9
+ return message.type === LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.SET_AUTO_UPLOAD;
10
+ }
8
11
  export function isViewedWelcomeScreenWebsocketMessage(message) {
9
12
  return (message.type === LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.VIEWED_WELCOME_SCREEN);
10
13
  }
@@ -60,7 +60,7 @@ export async function resolveBuildId(accountId, projectName, buildOption, force)
60
60
  export async function validateBuildForRelease(accountId, projectName, buildId) {
61
61
  try {
62
62
  const { data: build } = await getBuildStatus(accountId, projectName, buildId);
63
- return meetsMinimumPlatformVersion(build.platformVersion, PLATFORM_VERSIONS.v2026_09_BETA);
63
+ return meetsMinimumPlatformVersion(build.platformVersion, PLATFORM_VERSIONS.v2027_03_BETA);
64
64
  }
65
65
  catch (e) {
66
66
  if (isSpecifiedError(e, { statusCode: 404 })) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "8.14.0-beta.0",
3
+ "version": "8.14.0-beta.1",
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",
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "dependencies": {
13
13
  "@hubspot/local-dev-lib": "5.10.3",
14
- "@hubspot/project-parsing-lib": "0.22.1",
14
+ "@hubspot/project-parsing-lib": "0.23.0",
15
15
  "@hubspot/ui-extensions-dev-server": "2.1.2",
16
16
  "@inquirer/prompts": "7.1.0",
17
17
  "@modelcontextprotocol/sdk": "1.29.0",
@@ -25,6 +25,7 @@ export type LocalDevStateConstructorOptions = {
25
25
  initialProjectProfileData: HSProfileVariables;
26
26
  env: Environment;
27
27
  actions: LocalDevActions;
28
+ autoUploadEnabled?: boolean;
28
29
  };
29
30
  export type LocalDevDeployWebsocketMessage = {
30
31
  type: typeof LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.DEPLOY;
@@ -32,6 +33,12 @@ export type LocalDevDeployWebsocketMessage = {
32
33
  force: boolean;
33
34
  };
34
35
  };
36
+ export type LocalDevSetAutoUploadWebsocketMessage = {
37
+ type: typeof LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.SET_AUTO_UPLOAD;
38
+ data: {
39
+ enabled: boolean;
40
+ };
41
+ };
35
42
  export type LocalDevStateListener<K extends keyof LocalDevState> = (value: LocalDevState[K]) => void;
36
43
  export type AppLocalDevData = {
37
44
  id: number;
package/types/Yargs.d.ts CHANGED
@@ -49,6 +49,7 @@ export type ProjectDevArgs = CommonArgs & ConfigArgs & EnvironmentArgs & {
49
49
  testingAccount?: string | number;
50
50
  projectAccount?: string | number;
51
51
  port?: number;
52
+ autoUpload?: boolean;
52
53
  };
53
54
  export type TestingArgs = {
54
55
  qa?: boolean;