Skip to content

Commit 9233ac7

Browse files
committed
Add dependencies handling
1 parent 3080a84 commit 9233ac7

File tree

5 files changed

+164
-24
lines changed

5 files changed

+164
-24
lines changed

packages/cli-v3/e2e/compile.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ import { escapeImportPath } from "../src/utilities/windows.js";
2121
type CompileOptions = {
2222
outputMetafile?: string;
2323
resolvedConfig: ReadConfigResult;
24+
tempDir: string;
2425
};
2526

2627
export async function compile(options: CompileOptions) {
2728
if (options.resolvedConfig.status === "error") {
2829
throw new Error("cannot resolve config");
2930
}
30-
const { config } = options.resolvedConfig;
31+
32+
const {
33+
tempDir,
34+
resolvedConfig: { config },
35+
} = options;
3136
const configPath =
3237
options.resolvedConfig.status === "file" ? options.resolvedConfig.path : undefined;
3338

@@ -175,7 +180,6 @@ export async function compile(options: CompileOptions) {
175180

176181
// Create a tmp directory to store the build
177182
// const tempDir = await createTempDir();
178-
const tempDir = await mkdir(join(config.projectDir, ".trigger"), { recursive: true });
179183

180184
logger.debug(`Writing compiled files to ${tempDir}`);
181185

@@ -221,13 +225,13 @@ export async function compile(options: CompileOptions) {
221225

222226
// Save the result outputFile to /tmp/dir/worker.js (and make sure to map the sourceMap to the correct location in the file)
223227
await writeFile(
224-
join(tempDir!, "worker.js"),
228+
join(tempDir, "worker.js"),
225229
`${workerOutputFile.text}\n//# sourceMappingURL=worker.js.map`
226230
);
227231
// Save the sourceMapFile to /tmp/dir/worker.js.map
228-
await writeFile(join(tempDir!, "worker.js.map"), workerSourcemapFile.text);
232+
await writeFile(join(tempDir, "worker.js.map"), workerSourcemapFile.text);
229233
// Save the entryPoint outputFile to /tmp/dir/index.js
230-
await writeFile(join(tempDir!, "index.js"), entryPointOutputFile.text);
234+
await writeFile(join(tempDir, "index.js"), entryPointOutputFile.text);
231235

232236
return { metaOutput, entryPointMetaOutput };
233237
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env node
2+
3+
import { join } from "node:path";
4+
5+
import { ReadConfigResult } from "../src/utilities/configFiles.js";
6+
import { writeJSONFile } from "../src/utilities/fileSystem.js";
7+
import { logger } from "../src/utilities/logger.js";
8+
import { JavascriptProject } from "../src/utilities/javascriptProject.js";
9+
import {
10+
copyAdditionalFiles,
11+
resolveDependencies,
12+
resolveRequiredDependencies,
13+
} from "../src/commands/deploy.js";
14+
import terminalLink from "terminal-link";
15+
import { SkipLoggingError } from "../src/cli/common.js";
16+
import { log } from "@clack/prompts";
17+
import { Metafile } from "esbuild";
18+
19+
type HandleDependenciesOptions = {
20+
entryPointMetaOutput: Metafile["outputs"]["out/stdin.js"];
21+
metaOutput: Metafile["outputs"]["out/stdin.js"];
22+
resolvedConfig: ReadConfigResult;
23+
tempDir: string;
24+
};
25+
26+
export async function handleDependencies(options: HandleDependenciesOptions) {
27+
if (options.resolvedConfig.status === "error") {
28+
throw new Error("cannot resolve config");
29+
}
30+
const {
31+
entryPointMetaOutput,
32+
metaOutput,
33+
resolvedConfig: { config },
34+
tempDir,
35+
} = options;
36+
37+
// COPIED FROM compileProject()
38+
logger.debug("Getting the imports for the worker and entryPoint builds", {
39+
workerImports: metaOutput.imports,
40+
entryPointImports: entryPointMetaOutput.imports,
41+
});
42+
43+
// Get all the required dependencies from the metaOutputs and save them to /tmp/dir/package.json
44+
const allImports = [...metaOutput.imports, ...entryPointMetaOutput.imports];
45+
46+
const javascriptProject = new JavascriptProject(config.projectDir);
47+
48+
const dependencies = await resolveRequiredDependencies(allImports, config, javascriptProject);
49+
50+
logger.debug("gatherRequiredDependencies()", { dependencies });
51+
52+
const packageJsonContents = {
53+
name: "trigger-worker",
54+
version: "0.0.0",
55+
description: "",
56+
dependencies,
57+
scripts: {
58+
...javascriptProject.scripts,
59+
},
60+
};
61+
62+
// span.setAttributes({
63+
// ...flattenAttributes(packageJsonContents, "packageJson.contents"),
64+
// });
65+
66+
await writeJSONFile(join(tempDir, "package.json"), packageJsonContents);
67+
68+
const copyResult = await copyAdditionalFiles(config, tempDir);
69+
70+
if (!copyResult.ok) {
71+
// compileSpinner.stop("Project built with warnings");
72+
73+
log.warn(
74+
`No additionalFiles matches for:\n\n${copyResult.noMatches
75+
.map((glob) => `- "${glob}"`)
76+
.join("\n")}\n\nIf this is unexpected you should check your ${terminalLink(
77+
"glob patterns",
78+
"https://github.com/isaacs/node-glob?tab=readme-ov-file#glob-primer"
79+
)} are valid.`
80+
);
81+
}
82+
// } else {
83+
// compileSpinner.stop("Project built successfully");
84+
// }
85+
86+
const resolvingDependenciesResult = await resolveDependencies(
87+
tempDir,
88+
packageJsonContents,
89+
config
90+
);
91+
92+
if (!resolvingDependenciesResult) {
93+
throw new SkipLoggingError("Failed to resolve dependencies");
94+
}
95+
}

packages/cli-v3/e2e/index.test.ts

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import { execa } from "execa";
22
import { readFileSync } from "node:fs";
3-
import { rename, rm } from "node:fs/promises";
3+
import { mkdir, rename, rm } from "node:fs/promises";
44
import { join, resolve } from "node:path";
55

66
import { typecheckProject } from "../src/commands/deploy";
77
import { readConfig, ReadConfigFileResult } from "../src/utilities/configFiles";
88
import { compile } from "./compile";
9-
import { Metafile } from "esbuild";
109
import { Loglevel, LogLevelSchema, PackageManager, PackageManagerSchema } from ".";
1110
import { logger } from "../src/utilities/logger";
11+
import { handleDependencies } from "./handleDependencies";
1212

1313
type TestCase = {
1414
name: string;
1515
skipTypecheck?: boolean;
1616
wantConfigNotFoundError?: boolean;
1717
wantBadConfigError?: boolean;
1818
wantCompilationError?: boolean;
19+
wantDependenciesError?: boolean;
1920
};
2021

2122
const allTestCases: TestCase[] = [
@@ -67,6 +68,7 @@ if (testCases.length > 0) {
6768
wantConfigNotFoundError,
6869
wantBadConfigError,
6970
wantCompilationError,
71+
wantDependenciesError,
7072
}: TestCase) => {
7173
const fixtureDir = resolve(join(process.cwd(), "e2e/fixtures", name));
7274

@@ -148,30 +150,40 @@ if (testCases.length > 0) {
148150
);
149151

150152
describe.skipIf(wantConfigNotFoundError || wantBadConfigError)("with resolved config", () => {
153+
beforeAll(async () => {
154+
global.tempDir = await mkdir(
155+
join((global.resolvedConfig as ReadConfigFileResult).config.projectDir, ".trigger"),
156+
{ recursive: true }
157+
);
158+
});
159+
160+
afterAll(() => {
161+
delete global.tempDir;
162+
delete global.resolvedConfig;
163+
});
164+
151165
test.skipIf(skipTypecheck)("typechecks", async () => {
152-
expect(global.resolvedConfig.status).not.toBe("error");
166+
expect(global.resolvedConfig!.status).not.toBe("error");
153167

154168
await expect(
155169
(async () =>
156170
await typecheckProject((global.resolvedConfig as ReadConfigFileResult).config))()
157171
).resolves.not.toThrowError();
158172
});
159173

160-
let entrypointMetadata: Metafile["outputs"]["out/stdin.js"];
161-
let workerMetadata: Metafile["outputs"]["out/stdin.js"];
162-
163174
test(
164175
wantCompilationError ? "does not compile" : "compiles",
165176
async () => {
166-
expect(global.resolvedConfig.status).not.toBe("error");
177+
expect(global.resolvedConfig!.status).not.toBe("error");
167178

168179
const expectation = expect(
169180
(async () => {
170181
const { entryPointMetaOutput, metaOutput } = await compile({
171-
resolvedConfig: global.resolvedConfig,
182+
resolvedConfig: global.resolvedConfig!,
183+
tempDir: global.tempDir!,
172184
});
173-
entrypointMetadata = entryPointMetaOutput;
174-
workerMetadata = metaOutput;
185+
global.entryPointMetaOutput = entryPointMetaOutput;
186+
global.metaOutput = metaOutput;
175187
})()
176188
);
177189

@@ -185,7 +197,33 @@ if (testCases.length > 0) {
185197
);
186198

187199
describe.skipIf(wantCompilationError)("with successful compilation", () => {
188-
test.todo("dependencies handling");
200+
afterAll(() => {
201+
delete global.entryPointMetaOutput;
202+
delete global.metaOutput;
203+
});
204+
205+
test(
206+
wantDependenciesError ? "does not resolve dependencies" : "resolves dependencies",
207+
async () => {
208+
const expectation = expect(
209+
(async () => {
210+
await handleDependencies({
211+
entryPointMetaOutput: global.entryPointMetaOutput!,
212+
metaOutput: global.metaOutput!,
213+
resolvedConfig: global.resolvedConfig!,
214+
tempDir: global.tempDir!,
215+
});
216+
})()
217+
);
218+
219+
if (wantDependenciesError) {
220+
await expectation.rejects.toThrowError();
221+
} else {
222+
await expectation.resolves.not.toThrowError();
223+
}
224+
},
225+
{ timeout: 60_000 }
226+
);
189227
});
190228
});
191229
}

packages/cli-v3/e2e/vitest.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
import { Metafile } from "esbuild";
2+
13
import { ReadConfigResult } from "../src/utilities/configFiles";
24

35
declare global {
4-
var resolvedConfig: ReadConfigResult;
6+
var resolvedConfig: ReadConfigResult | undefined;
7+
var tempDir: string | undefined;
8+
var metaOutput: Metafile["outputs"]["out/stdin.js"] | undefined;
9+
var entryPointMetaOutput: Metafile["outputs"]["out/stdin.js"] | undefined;
510
}

packages/cli-v3/src/commands/deploy.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,8 +1349,7 @@ async function compileProject(
13491349
const resolvingDependenciesResult = await resolveDependencies(
13501350
tempDir,
13511351
packageJsonContents,
1352-
config,
1353-
options
1352+
config
13541353
);
13551354

13561355
if (!resolvingDependenciesResult) {
@@ -1487,11 +1486,10 @@ async function resolveEnvironmentVariables(
14871486
// in the `.trigger/cache` directory. If the package-lock.json is found, we'll write it to the project directory
14881487
// If the package-lock.json is not found, we will run `npm install --package-lock-only` and then write the package-lock.json
14891488
// to the project directory, and finally we'll write the digest to the `.trigger/cache` directory with the contents of the package-lock.json
1490-
async function resolveDependencies(
1489+
export async function resolveDependencies(
14911490
projectDir: string,
14921491
packageJsonContents: any,
1493-
config: ResolvedConfig,
1494-
options: DeployCommandOptions
1492+
config: ResolvedConfig
14951493
) {
14961494
return await tracer.startActiveSpan("resolveDependencies", async (span) => {
14971495
const resolvingDepsSpinner = spinner();
@@ -1682,7 +1680,7 @@ export async function typecheckProject(config: ResolvedConfig) {
16821680

16831681
// Returns the dependencies that are required by the output that are found in output and the CLI package dependencies
16841682
// Returns the dependency names and the version to use (taken from the CLI deps package.json)
1685-
async function resolveRequiredDependencies(
1683+
export async function resolveRequiredDependencies(
16861684
imports: Metafile["outputs"][string]["imports"],
16871685
config: ResolvedConfig,
16881686
project: JavascriptProject
@@ -1810,7 +1808,7 @@ type AdditionalFilesReturn =
18101808
noMatches: string[];
18111809
};
18121810

1813-
async function copyAdditionalFiles(
1811+
export async function copyAdditionalFiles(
18141812
config: ResolvedConfig,
18151813
tempDir: string
18161814
): Promise<AdditionalFilesReturn> {

0 commit comments

Comments
 (0)