@hubspot/cli 8.1.3-experimental.0 → 8.1.4-experimental.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.
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import archiver from 'archiver';
|
|
2
|
-
import { WorkspaceMapping, FileDependencyMapping
|
|
3
|
-
export type FileDepArchiveEntry = {
|
|
4
|
-
archivePath: string;
|
|
5
|
-
protocol: LocalDependencyProtocol;
|
|
6
|
-
};
|
|
2
|
+
import { WorkspaceMapping, FileDependencyMapping } from '@hubspot/project-parsing-lib/workspaces';
|
|
7
3
|
/**
|
|
8
4
|
* Result of archiving workspaces and file dependencies
|
|
9
5
|
*/
|
|
10
6
|
export type WorkspaceArchiveResult = {
|
|
11
7
|
packageWorkspaces: Map<string, string[]>;
|
|
12
|
-
packageFileDeps: Map<string, Map<string,
|
|
8
|
+
packageFileDeps: Map<string, Map<string, string>>;
|
|
13
9
|
};
|
|
14
10
|
/**
|
|
15
11
|
* Generates a short hash of the input string for use in workspace paths.
|
|
@@ -28,14 +24,10 @@ export declare function shortHash(input: string): string;
|
|
|
28
24
|
export declare function toPosixPath(p: string): string;
|
|
29
25
|
/**
|
|
30
26
|
* Determines the archive path for an external workspace or file: dependency.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* For tarballs, produces `_workspaces/<basename-no-ext>-<hash>/<original-basename>`,
|
|
34
|
-
* so the rewritten package.json reference still ends in the original filename.
|
|
35
|
-
*
|
|
36
|
-
* The hash prevents collisions between different paths with the same basename.
|
|
27
|
+
* Produces `_workspaces/<basename>-<hash>` with no subdirectory.
|
|
28
|
+
* The hash prevents collisions between different directories with the same basename.
|
|
37
29
|
*/
|
|
38
|
-
export declare function computeExternalArchivePath(absolutePath: string
|
|
30
|
+
export declare function computeExternalArchivePath(absolutePath: string): string;
|
|
39
31
|
/**
|
|
40
32
|
* Updates package.json files in the archive to reflect new workspace and file: dependency paths.
|
|
41
33
|
*
|
|
@@ -46,7 +38,7 @@ export declare function computeExternalArchivePath(absolutePath: string, kind?:
|
|
|
46
38
|
* Only external file: dependencies appear in packageFileDeps; internal ones
|
|
47
39
|
* keep their original file: references and are left untouched.
|
|
48
40
|
*/
|
|
49
|
-
export declare function updatePackageJsonInArchive(archive: archiver.Archiver, srcDir: string, packageWorkspaces: Map<string, string[]>, packageFileDeps: Map<string, Map<string,
|
|
41
|
+
export declare function updatePackageJsonInArchive(archive: archiver.Archiver, srcDir: string, packageWorkspaces: Map<string, string[]>, packageFileDeps: Map<string, Map<string, string>>): Promise<void>;
|
|
50
42
|
export declare function rewriteLockfileForExternalDeps(lockfileContent: Record<string, unknown>, pathMappings: Array<{
|
|
51
43
|
oldPath: string;
|
|
52
44
|
newPath: string;
|
|
@@ -27,35 +27,14 @@ export function toPosixPath(p) {
|
|
|
27
27
|
}
|
|
28
28
|
return p.replaceAll(path.sep, path.posix.sep);
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Strips the longest matching tarball extension (.tar.gz, .tgz, .tar)
|
|
32
|
-
* from a file basename. Returns the input unchanged if no extension matches.
|
|
33
|
-
*/
|
|
34
|
-
function stripTarballExtension(basename) {
|
|
35
|
-
const lower = basename.toLowerCase();
|
|
36
|
-
for (const ext of ['.tar.gz', '.tgz', '.tar']) {
|
|
37
|
-
if (lower.endsWith(ext)) {
|
|
38
|
-
return basename.slice(0, basename.length - ext.length);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return basename;
|
|
42
|
-
}
|
|
43
30
|
/**
|
|
44
31
|
* Determines the archive path for an external workspace or file: dependency.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* For tarballs, produces `_workspaces/<basename-no-ext>-<hash>/<original-basename>`,
|
|
48
|
-
* so the rewritten package.json reference still ends in the original filename.
|
|
49
|
-
*
|
|
50
|
-
* The hash prevents collisions between different paths with the same basename.
|
|
32
|
+
* Produces `_workspaces/<basename>-<hash>` with no subdirectory.
|
|
33
|
+
* The hash prevents collisions between different directories with the same basename.
|
|
51
34
|
*/
|
|
52
|
-
export function computeExternalArchivePath(absolutePath
|
|
35
|
+
export function computeExternalArchivePath(absolutePath) {
|
|
53
36
|
const resolved = path.resolve(absolutePath);
|
|
54
37
|
const name = path.basename(resolved);
|
|
55
|
-
if (kind === 'tarball') {
|
|
56
|
-
const nameNoExt = stripTarballExtension(name);
|
|
57
|
-
return path.posix.join('_workspaces', `${nameNoExt}-${shortHash(resolved)}`, name);
|
|
58
|
-
}
|
|
59
38
|
return path.posix.join('_workspaces', `${name}-${shortHash(resolved)}`);
|
|
60
39
|
}
|
|
61
40
|
/**
|
|
@@ -142,25 +121,25 @@ async function archiveWorkspaceDirectories(archive, srcDir, workspaceMappings) {
|
|
|
142
121
|
return { externalArchivePaths, packageWorkspaceEntries };
|
|
143
122
|
}
|
|
144
123
|
/**
|
|
145
|
-
* Archives file:
|
|
124
|
+
* Archives file: dependencies and returns mapping information.
|
|
146
125
|
*
|
|
147
|
-
* Internal dependencies (inside srcDir) are skipped — their original
|
|
148
|
-
* references in package.json remain valid after upload.
|
|
126
|
+
* Internal file: dependencies (inside srcDir) are skipped — their original
|
|
127
|
+
* `file:` references in package.json remain valid after upload.
|
|
149
128
|
*
|
|
150
|
-
* External
|
|
151
|
-
*
|
|
152
|
-
* `_workspaces/<name-no-ext>-<hash>/<original-basename>` so the rewritten
|
|
153
|
-
* reference still ends in the original filename.
|
|
129
|
+
* External file: dependencies are archived to `_workspaces/<name>-<hash>`
|
|
130
|
+
* and tracked in the returned map so package.json can be rewritten.
|
|
154
131
|
*/
|
|
155
132
|
async function archiveFileDependencies(archive, srcDir, fileDependencyMappings, externalArchivePaths) {
|
|
156
133
|
const packageFileDeps = new Map();
|
|
157
134
|
const toArchive = [];
|
|
158
135
|
for (const mapping of fileDependencyMappings) {
|
|
159
|
-
const { packageName, localPath, sourcePackageJsonPath
|
|
136
|
+
const { packageName, localPath, sourcePackageJsonPath } = mapping;
|
|
160
137
|
if (isInsideSrcDir(localPath, srcDir)) {
|
|
138
|
+
// Internal: original file: reference stays unchanged, nothing to do
|
|
161
139
|
continue;
|
|
162
140
|
}
|
|
163
|
-
|
|
141
|
+
// External: archive to _workspaces/<name>-<hash>
|
|
142
|
+
const archivePath = computeExternalArchivePath(localPath);
|
|
164
143
|
const resolvedPath = path.resolve(localPath);
|
|
165
144
|
if (!packageFileDeps.has(sourcePackageJsonPath)) {
|
|
166
145
|
packageFileDeps.set(sourcePackageJsonPath, new Map());
|
|
@@ -169,27 +148,23 @@ async function archiveFileDependencies(archive, srcDir, fileDependencyMappings,
|
|
|
169
148
|
const relativeArchivePath = toPosixPath(path.relative(relPkgJsonDir, archivePath));
|
|
170
149
|
packageFileDeps
|
|
171
150
|
.get(sourcePackageJsonPath)
|
|
172
|
-
.set(packageName,
|
|
151
|
+
.set(packageName, relativeArchivePath);
|
|
152
|
+
// Only archive each unique path once
|
|
173
153
|
if (!externalArchivePaths.has(resolvedPath)) {
|
|
174
154
|
externalArchivePaths.set(resolvedPath, archivePath);
|
|
175
|
-
toArchive.push({ localPath, archivePath, packageName
|
|
155
|
+
toArchive.push({ localPath, archivePath, packageName });
|
|
176
156
|
}
|
|
177
157
|
}
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
// getPackableFiles only applies to directory deps; tarballs are a single file.
|
|
181
|
-
const directoriesWithPackableFiles = await Promise.all(directoryItems.map(async (item) => ({
|
|
158
|
+
// Fetch packable files in parallel (I/O optimization)
|
|
159
|
+
const withPackableFiles = await Promise.all(toArchive.map(async (item) => ({
|
|
182
160
|
...item,
|
|
183
161
|
packableFiles: await getPackableFiles(item.localPath),
|
|
184
162
|
})));
|
|
185
|
-
|
|
163
|
+
// Archive directories sequentially (archiver requires sequential operations)
|
|
164
|
+
for (const { localPath, archivePath, packageName, packableFiles, } of withPackableFiles) {
|
|
186
165
|
uiLogger.log(lib.projectUpload.handleProjectUpload.fileDependencyIncluded(packageName, localPath, archivePath));
|
|
187
166
|
archive.directory(localPath, archivePath, createWorkspaceFileFilter(packableFiles));
|
|
188
167
|
}
|
|
189
|
-
for (const { localPath, archivePath, packageName } of tarballItems) {
|
|
190
|
-
uiLogger.log(lib.projectUpload.handleProjectUpload.fileDependencyIncluded(packageName, localPath, archivePath));
|
|
191
|
-
archive.file(localPath, { name: archivePath });
|
|
192
|
-
}
|
|
193
168
|
return packageFileDeps;
|
|
194
169
|
}
|
|
195
170
|
/**
|
|
@@ -238,18 +213,14 @@ export async function updatePackageJsonInArchive(archive, srcDir, packageWorkspa
|
|
|
238
213
|
uiLogger.debug(lib.projectUpload.handleProjectUpload.updatingPackageJsonWorkspaces(relativePackageJsonPath));
|
|
239
214
|
uiLogger.debug(lib.projectUpload.handleProjectUpload.updatedWorkspaces(workspaceEntries.join(', ')));
|
|
240
215
|
}
|
|
241
|
-
// Update external file:
|
|
242
|
-
// The protocol prefix (file: vs link:) is preserved from the original spec.
|
|
216
|
+
// Update external file: dependencies; internal ones are left untouched
|
|
243
217
|
const fileDeps = packageFileDeps.get(packageJsonPath);
|
|
244
218
|
if (fileDeps && fileDeps.size > 0 && packageJson.dependencies) {
|
|
245
|
-
for (const [packageName,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
(current.startsWith('file:') || current.startsWith('link:'))) {
|
|
249
|
-
const newValue = `${protocol}:${archivePath}`;
|
|
250
|
-
packageJson.dependencies[packageName] = newValue;
|
|
219
|
+
for (const [packageName, archivePath] of fileDeps.entries()) {
|
|
220
|
+
if (packageJson.dependencies[packageName]?.startsWith('file:')) {
|
|
221
|
+
packageJson.dependencies[packageName] = `file:${archivePath}`;
|
|
251
222
|
modified = true;
|
|
252
|
-
uiLogger.debug(lib.projectUpload.handleProjectUpload.updatedFileDependency(packageName,
|
|
223
|
+
uiLogger.debug(lib.projectUpload.handleProjectUpload.updatedFileDependency(packageName, archivePath));
|
|
253
224
|
}
|
|
254
225
|
}
|
|
255
226
|
}
|
|
@@ -277,24 +248,11 @@ export function rewriteLockfileForExternalDeps(lockfileContent, pathMappings) {
|
|
|
277
248
|
typeof value === 'object' &&
|
|
278
249
|
value !== null) {
|
|
279
250
|
const entry = value;
|
|
280
|
-
if (typeof entry.resolved
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const filePrefix = 'file:';
|
|
286
|
-
const isFileUrl = resolved.startsWith(filePrefix);
|
|
287
|
-
const resolvedPath = isFileUrl
|
|
288
|
-
? resolved.slice(filePrefix.length)
|
|
289
|
-
: resolved;
|
|
290
|
-
const mapping = pathMappings.find(m => m.oldPath === resolvedPath);
|
|
291
|
-
if (mapping) {
|
|
292
|
-
newPackages[key] = {
|
|
293
|
-
...entry,
|
|
294
|
-
resolved: isFileUrl
|
|
295
|
-
? `${filePrefix}${mapping.newPath}`
|
|
296
|
-
: mapping.newPath,
|
|
297
|
-
};
|
|
251
|
+
if (entry.link === true && typeof entry.resolved === 'string') {
|
|
252
|
+
const mapping = pathMappings.find(m => m.oldPath === entry.resolved);
|
|
253
|
+
if (mapping) {
|
|
254
|
+
newPackages[key] = { ...entry, resolved: mapping.newPath };
|
|
255
|
+
}
|
|
298
256
|
}
|
|
299
257
|
}
|
|
300
258
|
}
|
|
@@ -24,10 +24,12 @@ export async function runCommandInDir(directory, command) {
|
|
|
24
24
|
}
|
|
25
25
|
finalCommand = addFlag(finalCommand, 'disable-usage-tracking', true);
|
|
26
26
|
}
|
|
27
|
+
const resolvedDir = path.resolve(directory);
|
|
27
28
|
return execAsync(finalCommand, {
|
|
28
|
-
cwd:
|
|
29
|
+
cwd: resolvedDir,
|
|
29
30
|
env: {
|
|
30
31
|
...process.env,
|
|
32
|
+
INIT_CWD: resolvedDir,
|
|
31
33
|
},
|
|
32
34
|
});
|
|
33
35
|
}
|
|
@@ -3,6 +3,7 @@ export function setupHubSpotConfig(absoluteCurrentWorkingDirectory) {
|
|
|
3
3
|
if (!absoluteCurrentWorkingDirectory) {
|
|
4
4
|
return;
|
|
5
5
|
}
|
|
6
|
+
process.env.INIT_CWD = absoluteCurrentWorkingDirectory;
|
|
6
7
|
const configPath = getLocalConfigFilePathIfExists(absoluteCurrentWorkingDirectory);
|
|
7
8
|
if (configPath) {
|
|
8
9
|
process.env.HUBSPOT_CONFIG_PATH = configPath;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.4-experimental.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",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@hubspot/local-dev-lib": "5.7.1",
|
|
14
|
-
"@hubspot/project-parsing-lib": "0.
|
|
14
|
+
"@hubspot/project-parsing-lib": "0.16.0",
|
|
15
15
|
"@hubspot/serverless-dev-runtime": "7.0.7",
|
|
16
16
|
"@hubspot/ui-extensions-dev-server": "2.0.7",
|
|
17
17
|
"@inquirer/prompts": "7.1.0",
|