@hubspot/cli 8.2.1-experimental.0 → 8.2.1-experimental.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.
- package/commands/cms/function/server.js +14 -7
- package/commands/cms/theme/preview.js +8 -1
- package/commands/getStarted.js +15 -20
- package/commands/project/add.js +7 -6
- package/commands/project/appInstallStatus.js +7 -3
- package/commands/project/create.js +9 -6
- package/commands/project/deploy.js +13 -11
- package/commands/project/dev/index.js +9 -7
- package/commands/project/dev/unifiedFlow.js +8 -0
- package/commands/project/download.js +3 -3
- package/commands/project/info.js +7 -4
- package/commands/project/installApp.js +8 -3
- package/commands/project/installDeps.js +6 -5
- package/commands/project/lint.js +16 -9
- package/commands/project/listBuilds.d.ts +3 -2
- package/commands/project/listBuilds.js +40 -13
- package/commands/project/migrate.js +14 -12
- package/commands/project/open.js +15 -7
- package/commands/project/profile/add.js +8 -4
- package/commands/project/profile/delete.js +8 -4
- package/commands/project/release/create.js +4 -6
- package/commands/project/release/info.js +3 -3
- package/commands/project/release/list.js +3 -3
- package/commands/project/updateDeps.js +6 -5
- package/commands/project/upload.js +26 -15
- package/commands/project/validate.js +14 -97
- package/commands/project/watch.js +8 -11
- package/commands/project.js +1 -1
- package/lang/en.d.ts +19 -18
- package/lang/en.js +23 -20
- package/lib/app/migrate.js +5 -7
- package/lib/cms/serverlessDevRuntime.d.ts +1 -0
- package/lib/cms/serverlessDevRuntime.js +72 -0
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +2 -0
- package/lib/dependencyManagement.js +3 -10
- package/lib/doctor/DiagnosticInfoBuilder.d.ts +2 -2
- package/lib/doctor/DiagnosticInfoBuilder.js +8 -8
- package/lib/doctor/Doctor.js +7 -9
- package/lib/errors/ProjectErrors.d.ts +0 -6
- package/lib/errors/ProjectErrors.js +0 -12
- package/lib/errors/ProjectValidationError.d.ts +2 -1
- package/lib/errors/ProjectValidationError.js +3 -1
- package/lib/getStartedV2Actions.js +14 -18
- package/lib/jsonOutput.d.ts +86 -0
- package/lib/jsonOutput.js +77 -0
- package/lib/npm/packageJson.js +1 -1
- package/lib/projects/ProjectLogsManager.js +1 -4
- package/lib/projects/config.d.ts +6 -5
- package/lib/projects/config.js +7 -38
- package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
- package/lib/projects/localDev/LocalDevLogger.js +18 -0
- package/lib/projects/localDev/LocalDevProcess.d.ts +11 -1
- package/lib/projects/localDev/LocalDevProcess.js +91 -9
- package/lib/projects/localDev/LocalDevState.d.ts +7 -1
- package/lib/projects/localDev/LocalDevState.js +19 -1
- package/lib/projects/localDev/LocalDevWatcher.js +1 -1
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +1 -0
- package/lib/projects/localDev/LocalDevWebsocketServer.js +23 -1
- package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +2 -1
- package/lib/projects/localDev/localDevWebsocketServerUtils.js +3 -0
- package/lib/projects/projectProfiles.d.ts +2 -2
- package/lib/projects/projectProfiles.js +0 -3
- package/lib/projects/release.js +1 -1
- package/lib/projects/uieLinting.js +0 -3
- package/lib/projects/validate.d.ts +9 -0
- package/lib/projects/validate.js +96 -0
- package/lib/theme/migrate.js +1 -4
- package/mcp-server/tools/project/GetBuildLogsTool.js +2 -3
- package/mcp-server/tools/project/GetBuildStatusTool.js +2 -3
- package/mcp-server/tools/project/UploadProjectTools.js +3 -5
- package/package.json +11 -10
- package/types/LocalDev.d.ts +7 -0
- package/types/Projects.d.ts +1 -5
- package/types/Yargs.d.ts +1 -0
|
@@ -4,18 +4,6 @@ export class ProjectNestingError extends Error {
|
|
|
4
4
|
this.name = 'ProjectNestingError';
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
export class ProjectConfigNotFoundError extends Error {
|
|
8
|
-
constructor(message) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.name = 'ProjectConfigNotFoundError';
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export class ProjectValidationError extends Error {
|
|
14
|
-
constructor(message) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.name = 'ProjectValidationError';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
7
|
export class ProjectUploadError extends Error {
|
|
20
8
|
constructor(message, cause) {
|
|
21
9
|
super(message, { cause });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { ProjectConfigValidationError } from '@hubspot/project-parsing-lib/projects';
|
|
1
2
|
export default class ProjectValidationError extends Error {
|
|
2
3
|
constructor(message: string, options?: ErrorOptions);
|
|
3
4
|
}
|
|
4
|
-
export declare function isProjectValidationError(err: unknown): err is ProjectValidationError;
|
|
5
|
+
export declare function isProjectValidationError(err: unknown): err is ProjectValidationError | ProjectConfigValidationError;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ProjectConfigValidationError } from '@hubspot/project-parsing-lib/projects';
|
|
1
2
|
export default class ProjectValidationError extends Error {
|
|
2
3
|
constructor(message, options) {
|
|
3
4
|
super(message, options);
|
|
@@ -5,5 +6,6 @@ export default class ProjectValidationError extends Error {
|
|
|
5
6
|
}
|
|
6
7
|
}
|
|
7
8
|
export function isProjectValidationError(err) {
|
|
8
|
-
return err instanceof ProjectValidationError
|
|
9
|
+
return (err instanceof ProjectValidationError ||
|
|
10
|
+
err instanceof ProjectConfigValidationError);
|
|
9
11
|
}
|
|
@@ -11,8 +11,8 @@ import { translate, } from '@hubspot/project-parsing-lib/translate';
|
|
|
11
11
|
import { commands, lib } from '../lang/en.js';
|
|
12
12
|
import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
|
|
13
13
|
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_CONFIG_FILE, } from '../lib/constants.js';
|
|
14
|
-
import { ProjectNestingError,
|
|
15
|
-
import { getProjectConfig,
|
|
14
|
+
import { ProjectNestingError, ProjectUploadError, ProjectBuildDeployError, } from './errors/ProjectErrors.js';
|
|
15
|
+
import { getProjectConfig, writeProjectConfig, } from '../lib/projects/config.js';
|
|
16
16
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
17
17
|
import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
|
|
18
18
|
import { handleProjectUpload } from '../lib/projects/upload.js';
|
|
@@ -29,11 +29,17 @@ export async function createProjectAction({ projectName, projectDest, }) {
|
|
|
29
29
|
: 'Invalid project directory');
|
|
30
30
|
}
|
|
31
31
|
const projectDestAbsolute = path.resolve(getCwd(), projectDest);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
existingProjectDir
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
try {
|
|
33
|
+
const { projectDir: existingProjectDir } = getProjectConfig(projectDestAbsolute);
|
|
34
|
+
if (projectDestAbsolute.startsWith(existingProjectDir)) {
|
|
35
|
+
throw new ProjectNestingError(commands.project.create.errors.cannotNestProjects(existingProjectDir));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error instanceof ProjectNestingError) {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
// Not in a project directory, which is the expected case
|
|
37
43
|
}
|
|
38
44
|
try {
|
|
39
45
|
await cloneGithubRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, projectDestAbsolute, {
|
|
@@ -88,17 +94,7 @@ async function buildProjectMetadata(projectDir, projectConfig, accountId) {
|
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
export async function uploadAndDeployAction({ accountId, projectDest, }) {
|
|
91
|
-
const { projectConfig, projectDir } =
|
|
92
|
-
if (!projectConfig || !projectDir) {
|
|
93
|
-
throw new ProjectConfigNotFoundError(commands.getStarted.errors.configFileNotFound);
|
|
94
|
-
}
|
|
95
|
-
try {
|
|
96
|
-
validateProjectConfig(projectConfig, projectDir);
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
-
throw new ProjectValidationError(message);
|
|
101
|
-
}
|
|
97
|
+
const { projectConfig, projectDir } = getProjectConfig(projectDest);
|
|
102
98
|
const env = getConfigAccountEnvironment(accountId);
|
|
103
99
|
try {
|
|
104
100
|
const { result, uploadError } = await handleProjectUpload({
|
package/lib/jsonOutput.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { HubSpotConfigAccount } from '@hubspot/local-dev-lib/types/Accounts';
|
|
3
|
+
import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
2
4
|
import { Release } from '../api/releases.js';
|
|
3
5
|
declare const ReleaseComponentSchema: z.ZodObject<{
|
|
4
6
|
buildType: z.ZodString;
|
|
@@ -35,6 +37,74 @@ export declare const ReleaseListSchema: z.ZodObject<{
|
|
|
35
37
|
}, z.core.$strip>;
|
|
36
38
|
}, z.core.$strip>>;
|
|
37
39
|
}, z.core.$strip>;
|
|
40
|
+
declare const BuildSubbuildStatusSchema: z.ZodObject<{
|
|
41
|
+
buildName: z.ZodString;
|
|
42
|
+
buildType: z.ZodString;
|
|
43
|
+
status: z.ZodString;
|
|
44
|
+
errorMessage: z.ZodOptional<z.ZodString>;
|
|
45
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
46
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
47
|
+
rootPath: z.ZodOptional<z.ZodString>;
|
|
48
|
+
id: z.ZodOptional<z.ZodString>;
|
|
49
|
+
visible: z.ZodOptional<z.ZodBoolean>;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
export declare const BuildSchema: z.ZodObject<{
|
|
52
|
+
buildId: z.ZodNumber;
|
|
53
|
+
status: z.ZodString;
|
|
54
|
+
isDeployed: z.ZodBoolean;
|
|
55
|
+
isAutoDeployEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
56
|
+
deployableState: z.ZodOptional<z.ZodString>;
|
|
57
|
+
platformVersion: z.ZodOptional<z.ZodString>;
|
|
58
|
+
uploadMessage: z.ZodOptional<z.ZodString>;
|
|
59
|
+
enqueuedAt: z.ZodOptional<z.ZodString>;
|
|
60
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
61
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
62
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
63
|
+
subbuildStatuses: z.ZodArray<z.ZodObject<{
|
|
64
|
+
buildName: z.ZodString;
|
|
65
|
+
buildType: z.ZodString;
|
|
66
|
+
status: z.ZodString;
|
|
67
|
+
errorMessage: z.ZodOptional<z.ZodString>;
|
|
68
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
69
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
70
|
+
rootPath: z.ZodOptional<z.ZodString>;
|
|
71
|
+
id: z.ZodOptional<z.ZodString>;
|
|
72
|
+
visible: z.ZodOptional<z.ZodBoolean>;
|
|
73
|
+
}, z.core.$strip>>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
export declare const ProjectBuildsListSchema: z.ZodObject<{
|
|
76
|
+
projectName: z.ZodString;
|
|
77
|
+
deployedBuildId: z.ZodOptional<z.ZodNumber>;
|
|
78
|
+
results: z.ZodArray<z.ZodObject<{
|
|
79
|
+
buildId: z.ZodNumber;
|
|
80
|
+
status: z.ZodString;
|
|
81
|
+
isDeployed: z.ZodBoolean;
|
|
82
|
+
isAutoDeployEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
83
|
+
deployableState: z.ZodOptional<z.ZodString>;
|
|
84
|
+
platformVersion: z.ZodOptional<z.ZodString>;
|
|
85
|
+
uploadMessage: z.ZodOptional<z.ZodString>;
|
|
86
|
+
enqueuedAt: z.ZodOptional<z.ZodString>;
|
|
87
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
88
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
89
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
90
|
+
subbuildStatuses: z.ZodArray<z.ZodObject<{
|
|
91
|
+
buildName: z.ZodString;
|
|
92
|
+
buildType: z.ZodString;
|
|
93
|
+
status: z.ZodString;
|
|
94
|
+
errorMessage: z.ZodOptional<z.ZodString>;
|
|
95
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
96
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
97
|
+
rootPath: z.ZodOptional<z.ZodString>;
|
|
98
|
+
id: z.ZodOptional<z.ZodString>;
|
|
99
|
+
visible: z.ZodOptional<z.ZodBoolean>;
|
|
100
|
+
}, z.core.$strip>>;
|
|
101
|
+
}, z.core.$strip>>;
|
|
102
|
+
paging: z.ZodOptional<z.ZodObject<{
|
|
103
|
+
next: z.ZodObject<{
|
|
104
|
+
after: z.ZodString;
|
|
105
|
+
}, z.core.$strip>;
|
|
106
|
+
}, z.core.$strip>>;
|
|
107
|
+
}, z.core.$strip>;
|
|
38
108
|
export declare const ProjectInfoSchema: z.ZodObject<{
|
|
39
109
|
projectName: z.ZodString;
|
|
40
110
|
platformVersion: z.ZodString;
|
|
@@ -58,7 +128,17 @@ declare const PreviewSchema: z.ZodObject<{
|
|
|
58
128
|
releaseTag: z.ZodOptional<z.ZodString>;
|
|
59
129
|
succeeded: z.ZodBoolean;
|
|
60
130
|
}, z.core.$strip>;
|
|
131
|
+
declare const TargetAccountSchema: z.ZodObject<{
|
|
132
|
+
accountId: z.ZodNumber;
|
|
133
|
+
accountName: z.ZodOptional<z.ZodString>;
|
|
134
|
+
accountType: z.ZodOptional<z.ZodString>;
|
|
135
|
+
}, z.core.$strip>;
|
|
61
136
|
export declare const UploadSchema: z.ZodObject<{
|
|
137
|
+
targetAccount: z.ZodOptional<z.ZodObject<{
|
|
138
|
+
accountId: z.ZodNumber;
|
|
139
|
+
accountName: z.ZodOptional<z.ZodString>;
|
|
140
|
+
accountType: z.ZodOptional<z.ZodString>;
|
|
141
|
+
}, z.core.$strip>>;
|
|
62
142
|
buildId: z.ZodOptional<z.ZodNumber>;
|
|
63
143
|
deployId: z.ZodOptional<z.ZodNumber>;
|
|
64
144
|
preview: z.ZodOptional<z.ZodObject<{
|
|
@@ -98,12 +178,18 @@ export declare const CreateTestAccountSchema: z.ZodObject<{
|
|
|
98
178
|
export type ReleaseComponentJsonOutput = z.infer<typeof ReleaseComponentSchema>;
|
|
99
179
|
export type ReleaseJsonOutput = z.infer<typeof ReleaseSchema>;
|
|
100
180
|
export type ReleaseListJsonOutput = z.infer<typeof ReleaseListSchema>;
|
|
181
|
+
export type BuildSubbuildStatusJsonOutput = z.infer<typeof BuildSubbuildStatusSchema>;
|
|
182
|
+
export type BuildJsonOutput = z.infer<typeof BuildSchema>;
|
|
183
|
+
export type ProjectBuildsListJsonOutput = z.infer<typeof ProjectBuildsListSchema>;
|
|
101
184
|
export type ProjectInfoJsonOutput = z.infer<typeof ProjectInfoSchema>;
|
|
102
185
|
export type PreviewJsonOutput = z.infer<typeof PreviewSchema>;
|
|
186
|
+
export type TargetAccountJsonOutput = z.infer<typeof TargetAccountSchema>;
|
|
103
187
|
export type UploadJsonOutput = z.infer<typeof UploadSchema>;
|
|
104
188
|
export type DeployJsonOutput = z.infer<typeof DeploySchema>;
|
|
105
189
|
export type InstallStatusJsonOutput = z.infer<typeof InstallStatusSchema>;
|
|
106
190
|
export type InstallAppJsonOutput = z.infer<typeof InstallAppSchema>;
|
|
107
191
|
export type CreateTestAccountJsonOutput = z.infer<typeof CreateTestAccountSchema>;
|
|
192
|
+
export declare function mapAccountToTargetAccount(accountId: number, account?: HubSpotConfigAccount | null): TargetAccountJsonOutput;
|
|
193
|
+
export declare function mapBuildToJsonOutput(build: Build, deployedBuildId?: number): BuildJsonOutput;
|
|
108
194
|
export declare function mapReleaseToJsonOutput(release: Release): ReleaseJsonOutput;
|
|
109
195
|
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(),
|
|
@@ -43,7 +80,13 @@ const PreviewSchema = z.object({
|
|
|
43
80
|
releaseTag: z.string().optional(),
|
|
44
81
|
succeeded: z.boolean(),
|
|
45
82
|
});
|
|
83
|
+
const TargetAccountSchema = z.object({
|
|
84
|
+
accountId: z.number(),
|
|
85
|
+
accountName: z.string().optional(),
|
|
86
|
+
accountType: z.string().optional(),
|
|
87
|
+
});
|
|
46
88
|
export const UploadSchema = z.object({
|
|
89
|
+
targetAccount: TargetAccountSchema.optional(),
|
|
47
90
|
buildId: z.number().optional(),
|
|
48
91
|
deployId: z.number().optional(),
|
|
49
92
|
preview: PreviewSchema.optional(),
|
|
@@ -78,6 +121,40 @@ export const CreateTestAccountSchema = z.object({
|
|
|
78
121
|
accountId: z.number().optional(),
|
|
79
122
|
personalAccessKey: z.string().optional(),
|
|
80
123
|
});
|
|
124
|
+
export function mapAccountToTargetAccount(accountId, account) {
|
|
125
|
+
return {
|
|
126
|
+
accountId,
|
|
127
|
+
accountName: account?.name,
|
|
128
|
+
accountType: account?.accountType,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export function mapBuildToJsonOutput(build, deployedBuildId) {
|
|
132
|
+
const { buildId, status, isAutoDeployEnabled, deployableState, platformVersion, uploadMessage, enqueuedAt, startedAt, finishedAt, createdAt, subbuildStatuses, } = build;
|
|
133
|
+
return {
|
|
134
|
+
buildId,
|
|
135
|
+
status,
|
|
136
|
+
isDeployed: buildId === deployedBuildId,
|
|
137
|
+
isAutoDeployEnabled,
|
|
138
|
+
deployableState,
|
|
139
|
+
platformVersion,
|
|
140
|
+
uploadMessage,
|
|
141
|
+
enqueuedAt,
|
|
142
|
+
startedAt,
|
|
143
|
+
finishedAt,
|
|
144
|
+
createdAt,
|
|
145
|
+
subbuildStatuses: subbuildStatuses.map(subbuild => ({
|
|
146
|
+
buildName: subbuild.buildName,
|
|
147
|
+
buildType: subbuild.buildType,
|
|
148
|
+
status: subbuild.status,
|
|
149
|
+
errorMessage: subbuild.errorMessage,
|
|
150
|
+
startedAt: subbuild.startedAt,
|
|
151
|
+
finishedAt: subbuild.finishedAt,
|
|
152
|
+
rootPath: subbuild.rootPath,
|
|
153
|
+
id: subbuild.id,
|
|
154
|
+
visible: subbuild.visible,
|
|
155
|
+
})),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
81
158
|
export function mapReleaseToJsonOutput(release) {
|
|
82
159
|
const { releaseTag, buildId, createdAt, components } = release;
|
|
83
160
|
return {
|
package/lib/npm/packageJson.js
CHANGED
|
@@ -92,7 +92,7 @@ const findAllPackageJsonFilesInDirectoryCached = async (directory) => {
|
|
|
92
92
|
* @returns Array of absolute paths to package.json files in the project
|
|
93
93
|
*/
|
|
94
94
|
export async function findAllPackageJsonFilesInProjectCached() {
|
|
95
|
-
const projectConfig =
|
|
95
|
+
const projectConfig = getProjectConfig();
|
|
96
96
|
const { projectDir } = projectConfig;
|
|
97
97
|
if (!projectDir) {
|
|
98
98
|
return [];
|
|
@@ -34,10 +34,7 @@ class _ProjectLogsManager {
|
|
|
34
34
|
this.functions = [];
|
|
35
35
|
}
|
|
36
36
|
async init(accountId) {
|
|
37
|
-
const { projectConfig } =
|
|
38
|
-
if (!projectConfig || !projectConfig.name) {
|
|
39
|
-
throw new Error(commands.project.logs.errors.noProjectConfig);
|
|
40
|
-
}
|
|
37
|
+
const { projectConfig } = getProjectConfig();
|
|
41
38
|
this.projectConfig = projectConfig;
|
|
42
39
|
this.projectName = projectConfig.name;
|
|
43
40
|
this.accountId = accountId;
|
package/lib/projects/config.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { ProjectConfig } from '
|
|
1
|
+
import type { ProjectConfig } from '@hubspot/project-parsing-lib/projects';
|
|
2
|
+
export { ProjectConfigValidationError } from '@hubspot/project-parsing-lib/projects';
|
|
3
|
+
export type { ProjectConfig } from '@hubspot/project-parsing-lib/projects';
|
|
2
4
|
export declare function writeProjectConfig(configPath: string, config: ProjectConfig): boolean;
|
|
3
5
|
export declare function getIsInProject(dir?: string): boolean;
|
|
4
6
|
export interface LoadedProjectConfig {
|
|
5
|
-
projectDir: string
|
|
6
|
-
projectConfig: ProjectConfig
|
|
7
|
+
projectDir: string;
|
|
8
|
+
projectConfig: ProjectConfig;
|
|
7
9
|
}
|
|
8
|
-
export declare function getProjectConfig(dir?: string):
|
|
9
|
-
export declare function validateProjectConfig(projectConfig: ProjectConfig | null, projectDir: string | null): asserts projectConfig is ProjectConfig;
|
|
10
|
+
export declare function getProjectConfig(dir?: string): LoadedProjectConfig;
|
package/lib/projects/config.js
CHANGED
|
@@ -2,10 +2,11 @@ import fs from 'fs-extra';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import findup from 'findup-sync';
|
|
4
4
|
import { getAbsoluteFilePath, getCwd } from '@hubspot/local-dev-lib/path';
|
|
5
|
+
import { parseProjectConfig, ProjectConfigValidationError, } from '@hubspot/project-parsing-lib/projects';
|
|
5
6
|
import { PROJECT_CONFIG_FILE } from '../constants.js';
|
|
6
7
|
import { lib } from '../../lang/en.js';
|
|
7
8
|
import { uiLogger } from '../ui/logger.js';
|
|
8
|
-
|
|
9
|
+
export { ProjectConfigValidationError } from '@hubspot/project-parsing-lib/projects';
|
|
9
10
|
export function writeProjectConfig(configPath, config) {
|
|
10
11
|
try {
|
|
11
12
|
fs.ensureFileSync(configPath);
|
|
@@ -30,44 +31,12 @@ function getProjectConfigPath(dir) {
|
|
|
30
31
|
});
|
|
31
32
|
return configPath;
|
|
32
33
|
}
|
|
33
|
-
export
|
|
34
|
+
export function getProjectConfig(dir) {
|
|
34
35
|
const configPath = getProjectConfigPath(dir);
|
|
35
36
|
if (!configPath) {
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const config = fs.readFileSync(configPath);
|
|
40
|
-
const projectConfig = JSON.parse(config.toString());
|
|
41
|
-
return {
|
|
42
|
-
projectDir: path.dirname(configPath),
|
|
43
|
-
projectConfig,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
catch (e) {
|
|
47
|
-
uiLogger.error(lib.projects.getProjectConfig.error);
|
|
48
|
-
return { projectConfig: null, projectDir: null };
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
export function validateProjectConfig(projectConfig, projectDir) {
|
|
52
|
-
if (!projectConfig || !projectDir) {
|
|
53
|
-
throw new ProjectValidationError(lib.projects.validateProjectConfig.configNotFound);
|
|
54
|
-
}
|
|
55
|
-
const missingFields = [];
|
|
56
|
-
if (!projectConfig.name) {
|
|
57
|
-
missingFields.push('name');
|
|
58
|
-
}
|
|
59
|
-
if (!projectConfig.srcDir) {
|
|
60
|
-
missingFields.push('srcDir');
|
|
61
|
-
}
|
|
62
|
-
if (missingFields.length > 0) {
|
|
63
|
-
throw new ProjectValidationError(lib.projects.validateProjectConfig.configMissingFields(missingFields));
|
|
64
|
-
}
|
|
65
|
-
const resolvedPath = path.resolve(projectDir, projectConfig.srcDir);
|
|
66
|
-
if (!resolvedPath.startsWith(projectDir)) {
|
|
67
|
-
const projectConfigFile = path.relative('.', path.join(projectDir, PROJECT_CONFIG_FILE));
|
|
68
|
-
throw new ProjectValidationError(lib.projects.validateProjectConfig.srcOutsideProjectDir(projectConfigFile, projectConfig.srcDir));
|
|
69
|
-
}
|
|
70
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
71
|
-
throw new ProjectValidationError(lib.projects.validateProjectConfig.srcDirNotFound(projectConfig.srcDir, projectDir));
|
|
37
|
+
throw new ProjectConfigValidationError(lib.projects.validateProjectConfig.configNotFound);
|
|
72
38
|
}
|
|
39
|
+
const projectDir = path.dirname(configPath);
|
|
40
|
+
const projectConfig = parseProjectConfig(projectDir);
|
|
41
|
+
return { projectDir, projectConfig };
|
|
73
42
|
}
|
|
@@ -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();
|
|
@@ -83,17 +108,17 @@ class LocalDevProcess {
|
|
|
83
108
|
}
|
|
84
109
|
}
|
|
85
110
|
async projectConfigValidForUpload() {
|
|
86
|
-
|
|
87
|
-
|
|
111
|
+
let projectConfig;
|
|
112
|
+
try {
|
|
113
|
+
({ projectConfig } = getProjectConfig());
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
88
116
|
return false;
|
|
89
117
|
}
|
|
90
|
-
Object.keys(projectConfig).
|
|
118
|
+
return Object.keys(projectConfig).every(key => {
|
|
91
119
|
const field = key;
|
|
92
|
-
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
120
|
+
return projectConfig[field] === this.state.projectConfig[field];
|
|
95
121
|
});
|
|
96
|
-
return true;
|
|
97
122
|
}
|
|
98
123
|
async getIntermediateRepresentation(projectNodesAtLastDeploy) {
|
|
99
124
|
const { intermediateRepresentation } = await translateForLocalDev({
|
|
@@ -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.
|
|
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;
|