-
Notifications
You must be signed in to change notification settings - Fork 288
feat: enhance file resolution logic for Convex #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
de8f2d8
2bb6d21
6514726
20c665f
75fb94e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -297,10 +297,26 @@ export async function bundleSchema( | |
dir: string, | ||
extraConditions: string[], | ||
) { | ||
let target = path.resolve(dir, "schema.ts"); | ||
if (!ctx.fs.exists(target)) { | ||
target = path.resolve(dir, "schema.js"); | ||
const candidates = [ | ||
"schema.ts", | ||
"schema.mjs", | ||
"schema.cjs", | ||
"schema.js", | ||
]; | ||
|
||
let target = ""; | ||
for (const filename of candidates) { | ||
const candidatePath = path.resolve(dir, filename); | ||
if (ctx.fs.exists(candidatePath)) { | ||
target = candidatePath; | ||
break; | ||
} | ||
} | ||
|
||
if (!target) { | ||
return []; | ||
} | ||
|
||
const result = await bundle( | ||
ctx, | ||
dir, | ||
|
@@ -314,21 +330,30 @@ export async function bundleSchema( | |
} | ||
|
||
export async function bundleAuthConfig(ctx: Context, dir: string) { | ||
const authConfigPath = path.resolve(dir, "auth.config.js"); | ||
const authConfigTsPath = path.resolve(dir, "auth.config.ts"); | ||
if (ctx.fs.exists(authConfigPath) && ctx.fs.exists(authConfigTsPath)) { | ||
const candidates = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. auth.config.ts doesn't exist in components so there's no need to change this |
||
"auth.config.ts", | ||
"auth.config.mjs", | ||
"auth.config.cjs", | ||
"auth.config.js" | ||
]; | ||
|
||
const existingPaths = candidates | ||
.map(filename => path.resolve(dir, filename)) | ||
.filter(filepath => ctx.fs.exists(filepath)); | ||
|
||
if (existingPaths.length > 1) { | ||
return await ctx.crash({ | ||
exitCode: 1, | ||
errorType: "invalid filesystem data", | ||
printedMessage: `Found both ${authConfigPath} and ${authConfigTsPath}, choose one.`, | ||
printedMessage: `Found multiple auth config files: ${existingPaths.join(", ")}, choose one.`, | ||
thomasballinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
} | ||
const chosenPath = ctx.fs.exists(authConfigTsPath) | ||
? authConfigTsPath | ||
: authConfigPath; | ||
if (!ctx.fs.exists(chosenPath)) { | ||
|
||
if (existingPaths.length === 0) { | ||
return []; | ||
} | ||
|
||
const chosenPath = existingPaths[0]; | ||
const result = await bundle(ctx, dir, [chosenPath], true, "browser"); | ||
return result.modules; | ||
} | ||
|
@@ -419,10 +444,10 @@ export async function entryPoints( | |
logVerbose(ctx, chalk.yellow(`Skipping dotfile ${fpath}`)); | ||
} else if (base.startsWith("#")) { | ||
logVerbose(ctx, chalk.yellow(`Skipping likely emacs tempfile ${fpath}`)); | ||
} else if (base === "schema.ts" || base === "schema.js") { | ||
} else if (base === "schema.mjs" || base === "schema.cjs" || base === "schema.js" || base === "schema.ts") { | ||
logVerbose(ctx, chalk.yellow(`Skipping ${fpath}`)); | ||
} else if ((base.match(/\./g) || []).length > 1) { | ||
// `auth.config.ts` and `convex.config.ts` are important not to bundle. | ||
// `auth.config.*` and `convex.config.*` files are important not to bundle. | ||
// `*.test.ts` `*.spec.ts` are common in developer code. | ||
logVerbose( | ||
ctx, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,19 +54,27 @@ import { Reporter, Span } from "./tracing.js"; | |
import { | ||
DEFINITION_FILENAME_JS, | ||
DEFINITION_FILENAME_TS, | ||
DEFINITION_FILENAME_MJS, | ||
DEFINITION_FILENAME_CJS, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the component changes I do not want to make without understanding the use cases. The spec for components isn't well-defined yet but I wouldn't want to make what's accepted anyy more broad than necessary without specifics use cases There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a response in #126 :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do not want the CJS one. I don't know that we really need a .mjs extension either, but if this is a difficult limitation for a packaging tool we can add .mjs if we also add a component that works like this to make sure we don't regress the behavior. If you'd like to use packem to build convex components, would you consider adding the ability to produce .js files for ESM-only builds of a package with
|
||
} from "./components/constants.js"; | ||
import { DeploymentSelection } from "./deploymentSelection.js"; | ||
async function findComponentRootPath(ctx: Context, functionsDir: string) { | ||
// Default to `.ts` but fallback to `.js` if not present. | ||
let componentRootPath = path.resolve( | ||
path.join(functionsDir, DEFINITION_FILENAME_TS), | ||
); | ||
if (!ctx.fs.exists(componentRootPath)) { | ||
componentRootPath = path.resolve( | ||
path.join(functionsDir, DEFINITION_FILENAME_JS), | ||
); | ||
const candidates = [ | ||
DEFINITION_FILENAME_MJS, | ||
DEFINITION_FILENAME_CJS, | ||
DEFINITION_FILENAME_JS, | ||
DEFINITION_FILENAME_TS, | ||
]; | ||
|
||
for (const filename of candidates) { | ||
const componentRootPath = path.resolve(path.join(functionsDir, filename)); | ||
if (ctx.fs.exists(componentRootPath)) { | ||
return componentRootPath; | ||
} | ||
} | ||
return componentRootPath; | ||
|
||
// Default fallback to .ts for backward compatibility | ||
return path.resolve(path.join(functionsDir, DEFINITION_FILENAME_TS)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a behavior change, previously the default was the JS path |
||
} | ||
|
||
export async function runCodegen( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
export const DEFINITION_FILENAME_TS = "convex.config.ts"; | ||
export const DEFINITION_FILENAME_JS = "convex.config.js"; | ||
export const DEFINITION_FILENAME_MJS = "convex.config.mjs"; | ||
export const DEFINITION_FILENAME_CJS = "convex.config.cjs"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,7 +53,7 @@ function componentPlugin({ | |
name: `convex-${mode === "discover" ? "discover-components" : "bundle-components"}`, | ||
async setup(build) { | ||
// This regex can't be really precise since developers could import | ||
// "convex.config", "convex.config.js", "convex.config.ts", etc. | ||
// "convex.config", "convex.config.mjs", "convex.config.cjs", "convex.config.js", "convex.config.ts", etc. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above, throughout the PR remove .cjs |
||
build.onResolve({ filter: /.*convex.config.*/ }, async (args) => { | ||
verbose && logMessage(ctx, "esbuild resolving import:", args); | ||
if (args.namespace !== "file") { | ||
|
@@ -83,12 +83,14 @@ function componentPlugin({ | |
|
||
const candidates = [args.path]; | ||
const ext = path.extname(args.path); | ||
if (ext === ".js") { | ||
candidates.push(args.path.slice(0, -".js".length) + ".ts"); | ||
|
||
if (ext === ".mjs" || ext === ".cjs" || ext === ".js") { | ||
candidates.push(args.path.slice(0, -ext.length) + ".ts"); | ||
} | ||
if (ext !== ".js" && ext !== ".ts") { | ||
candidates.push(args.path + ".js"); | ||
candidates.push(args.path + ".ts"); | ||
|
||
// If no extension or unrecognized extension, try all in priority order | ||
if (!ext || ![".mjs", ".cjs", ".js", ".ts"].includes(ext)) { | ||
candidates.push(args.path + ".mjs", args.path + ".cjs", args.path + ".js", args.path + ".ts"); | ||
} | ||
let resolvedPath = undefined; | ||
for (const candidate of candidates) { | ||
|
@@ -497,11 +499,14 @@ export async function bundleImplementations( | |
rootComponentDirectory.path, | ||
directory.path, | ||
); | ||
// Check for schema files in priority order: .mjs, .cjs, .js, .ts | ||
const schemaCandidates = ["schema.mjs", "schema.cjs", "schema.js", "schema.ts"]; | ||
const schemaExists = schemaCandidates.some(filename => | ||
ctx.fs.exists(path.resolve(resolvedPath, filename)) | ||
); | ||
|
||
let schema; | ||
if (ctx.fs.exists(path.resolve(resolvedPath, "schema.ts"))) { | ||
schema = | ||
(await bundleSchema(ctx, resolvedPath, extraConditions))[0] || null; | ||
} else if (ctx.fs.exists(path.resolve(resolvedPath, "schema.js"))) { | ||
if (schemaExists) { | ||
schema = | ||
(await bundleSchema(ctx, resolvedPath, extraConditions))[0] || null; | ||
} else { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would love to hear if people are using these extensions and why, but if this is helpful we can make this change. I'd guess the various TypeScript extensions would be more important? .mts, .cts, etc than .js, since most users use TypeScript? But I haven't heard requests for either
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didnt see a lot of developer using .mts and .cts for typescript files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine if we remove .cjs, we never want to bundle a commonjs schema.