Skip to content

Commit 750af9e

Browse files
Sujay JayakarConvex, Inc.
Sujay Jayakar
authored and
Convex, Inc.
committed
Fix path encoding for ComponentDefinitionPath (#29794)
GitOrigin-RevId: 511ad4af1b0db0a3ed34f9d32d7c8afafee567ad
1 parent 4540d3a commit 750af9e

File tree

5 files changed

+58
-28
lines changed

5 files changed

+58
-28
lines changed

npm-packages/convex/src/cli/lib/components.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import {
3939
} from "./deployApi/definitionConfig.js";
4040
import { typeCheckFunctionsInMode, TypeCheckMode } from "./typecheck.js";
4141
import { withTmpDir } from "../../bundler/fs.js";
42-
import { ROOT_DEFINITION_FILENAME } from "./components/constants.js";
4342
import { handleDebugBundlePath } from "./debugBundlePath.js";
4443
import chalk from "chalk";
4544
import { StartPushRequest, StartPushResponse } from "./deployApi/startPush.js";
@@ -52,16 +51,36 @@ import {
5251
DeveloperIndexConfig,
5352
} from "./deployApi/finishPush.js";
5453
import { Reporter, Span } from "./tracing.js";
54+
import {
55+
DEFINITION_FILENAME_JS,
56+
DEFINITION_FILENAME_TS,
57+
} from "./components/constants.js";
58+
59+
async function findComponentRootPath(ctx: Context, functionsDir: string) {
60+
// Default to `.ts` but fallback to `.js` if not present.
61+
let componentRootPath = path.resolve(
62+
path.join(functionsDir, DEFINITION_FILENAME_TS),
63+
);
64+
if (!ctx.fs.exists(componentRootPath)) {
65+
componentRootPath = path.resolve(
66+
path.join(functionsDir, DEFINITION_FILENAME_JS),
67+
);
68+
}
69+
return componentRootPath;
70+
}
5571

5672
export async function runCodegen(ctx: Context, options: CodegenOptions) {
5773
// This also ensures the current directory is the project root.
5874
await ensureHasConvexDependency(ctx, "codegen");
5975

6076
const { configPath, projectConfig } = await readProjectConfig(ctx);
6177
const functionsDirectoryPath = functionsDir(configPath, projectConfig);
62-
const componentRootPath = path.resolve(
63-
path.join(functionsDirectoryPath, ROOT_DEFINITION_FILENAME),
78+
79+
const componentRootPath = await findComponentRootPath(
80+
ctx,
81+
functionsDirectoryPath,
6482
);
83+
6584
if (ctx.fs.exists(componentRootPath)) {
6685
const deploymentSelection = deploymentSelectionFromOptions(options);
6786
const credentials = await fetchDeploymentCredentialsProvisionProd(
@@ -106,9 +125,7 @@ export async function runCodegen(ctx: Context, options: CodegenOptions) {
106125
export async function runPush(ctx: Context, options: PushOptions) {
107126
const { configPath, projectConfig } = await readProjectConfig(ctx);
108127
const convexDir = functionsDir(configPath, projectConfig);
109-
const componentRootPath = path.resolve(
110-
path.join(convexDir, ROOT_DEFINITION_FILENAME),
111-
);
128+
const componentRootPath = await findComponentRootPath(ctx, convexDir);
112129
if (ctx.fs.exists(componentRootPath)) {
113130
await runComponentsPush(ctx, options, configPath, projectConfig);
114131
} else {
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
export const ROOT_DEFINITION_FILENAME = "convex.config.ts";
2-
export const DEFINITION_FILENAME = "convex.config.ts";
3-
export const COMPILED_DEFINITION_FILENAME = "convex.config.js";
1+
export const DEFINITION_FILENAME_TS = "convex.config.ts";
2+
export const DEFINITION_FILENAME_JS = "convex.config.js";

npm-packages/convex/src/cli/lib/components/definition/bundle.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,6 @@ export async function bundleDefinitions(
435435
rootComponentDirectory,
436436
directory,
437437
),
438-
origDefinitionPath: toComponentDefinitionPath(
439-
rootComponentDirectory,
440-
directory,
441-
),
442438
definition: {
443439
path: path.relative(directory.path, outputJs.path),
444440
source: outputJs.text,

npm-packages/convex/src/cli/lib/components/definition/directoryStructure.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import path from "path";
22
import { Context } from "../../../../bundler/context.js";
33
import {
4-
COMPILED_DEFINITION_FILENAME,
5-
DEFINITION_FILENAME,
6-
ROOT_DEFINITION_FILENAME,
4+
DEFINITION_FILENAME_JS,
5+
DEFINITION_FILENAME_TS,
76
} from "../constants.js";
87
import { getFunctionsDirectoryPath } from "../../config.js";
98

@@ -19,8 +18,19 @@ import { getFunctionsDirectoryPath } from "../../config.js";
1918
* (e.g. 'convex-waitlist' instead of '../node_modules/convex-waitlist/convex.config.ts')
2019
*/
2120
export type ComponentDirectory = {
21+
/**
22+
* Is this component directory for the root component?
23+
*/
2224
isRoot: boolean;
25+
26+
/**
27+
* Absolute local filesystem path to the component definition's directory.
28+
*/
2329
path: string;
30+
31+
/**
32+
* Absolute local filesystem path to the `convex.config.{ts,js}` file within the component definition.
33+
*/
2434
definitionPath: string;
2535
};
2636

@@ -57,13 +67,11 @@ export function isComponentDirectory(
5767
return { kind: "err", why: `Not a directory` };
5868
}
5969

60-
// Check that we have a definition file.
61-
let filename = isRoot
62-
? ROOT_DEFINITION_FILENAME
63-
: COMPILED_DEFINITION_FILENAME;
70+
// Check that we have a definition file, defaulting to `.ts` but falling back to `.js`.
71+
let filename = DEFINITION_FILENAME_TS;
6472
let definitionPath = path.resolve(path.join(directory, filename));
6573
if (!ctx.fs.exists(definitionPath)) {
66-
filename = isRoot ? ROOT_DEFINITION_FILENAME : DEFINITION_FILENAME;
74+
filename = DEFINITION_FILENAME_JS;
6775
definitionPath = path.resolve(path.join(directory, filename));
6876
}
6977
if (!ctx.fs.exists(definitionPath)) {
@@ -128,15 +136,27 @@ export function toComponentDefinitionPath(
128136
rootComponent: ComponentDirectory,
129137
component: ComponentDirectory,
130138
): ComponentDefinitionPath {
131-
return path.relative(
139+
// First, compute a file system relative path.
140+
const relativePath: string = path.relative(
132141
rootComponent.path,
133142
component.path,
134-
) as ComponentDefinitionPath;
143+
);
144+
145+
// Then, convert it to a ComponentDefinitionPath, which always uses POSIX conventions.
146+
const definitionPath = relativePath.split(path.sep).join(path.posix.sep);
147+
148+
return definitionPath as ComponentDefinitionPath;
135149
}
136150

137151
export function toAbsolutePath(
138152
rootComponent: ComponentDirectory,
139153
componentDefinitionPath: ComponentDefinitionPath,
140154
) {
141-
return path.normalize(path.join(rootComponent.path, componentDefinitionPath));
155+
// Repeat the process from `toComponentDefinitionPath` in reverse: First
156+
// convert to a relative local filesystem path, and then join it to
157+
// the root component's absolute path.
158+
const relativePath = componentDefinitionPath
159+
.split(path.posix.sep)
160+
.join(path.sep);
161+
return path.normalize(path.join(rootComponent.path, relativePath));
142162
}

npm-packages/convex/src/cli/lib/config.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,21 +632,19 @@ interface BundledModuleInfo {
632632
export type ComponentDefinitionSpec = {
633633
/** This path is relative to the app (root component) directory. */
634634
definitionPath: ComponentDefinitionPath;
635-
/** This path is relative to the app (root component) directory. */
636-
origDefinitionPath: ComponentDefinitionPath;
635+
637636
/** Dependencies are paths to the directory of the dependency component definition from the app (root component) directory */
638637
dependencies: ComponentDefinitionPath[];
639638

640639
// All other paths are relative to the directory of the definitionPath above.
641-
642640
definition: Bundle;
643641
schema: Bundle;
644642
functions: Bundle[];
645643
};
646644

647645
export type AppDefinitionSpec = Omit<
648646
ComponentDefinitionSpec,
649-
"definitionPath" | "origDefinitionPath"
647+
"definitionPath"
650648
> & {
651649
// Only app (root) component specs contain an auth bundle.
652650
auth: Bundle | null;

0 commit comments

Comments
 (0)