mirror of
https://github.com/stack-auth/stack.git
synced 2026-07-20 21:29:36 +08:00
fix(cli): resolve SDK config imports from CLI's bundled copy when project has no SDK installed
Co-Authored-By: mantra <mantra@stack-auth.com>
This commit is contained in:
parent
ce956a0fd2
commit
d33c2cebe4
@ -3,6 +3,31 @@ import * as os from "os";
|
||||
import * as path from "path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { assertConfigPullTarget, buildConfigPushSource, resolveConfigFilePathForPull } from "./config-file.js";
|
||||
import { createConfigFileJiti } from "../lib/config-jiti.js";
|
||||
|
||||
describe("createConfigFileJiti", () => {
|
||||
let tmpDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "hexclave-cli-config-jiti-"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("loads config authoring imports when the project has no SDK installed", async () => {
|
||||
const configPath = path.join(tmpDir, "hexclave.config.ts");
|
||||
fs.writeFileSync(
|
||||
configPath,
|
||||
'import { defineHexclaveConfig } from "@hexclave/js/config";\nexport const config = defineHexclaveConfig({ auth: { allowSignUp: true } });\n',
|
||||
);
|
||||
|
||||
const configModule = await createConfigFileJiti(configPath).import<{ config: { auth: { allowSignUp: boolean } } }>(configPath);
|
||||
|
||||
expect(configModule.config).toEqual({ auth: { allowSignUp: true } });
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveConfigFilePathForPull", () => {
|
||||
let tmpDir: string;
|
||||
|
||||
@ -287,8 +287,8 @@ export function registerConfigCommand(program: Command) {
|
||||
throw new CliError("Config file must have a .js or .ts extension.");
|
||||
}
|
||||
|
||||
const { createJiti } = await import("jiti");
|
||||
const jiti = createJiti(import.meta.url);
|
||||
const { createConfigFileJiti } = await import("../lib/config-jiti.js");
|
||||
const jiti = createConfigFileJiti(filePath);
|
||||
const configModule: { config?: unknown } = await jiti.import(filePath);
|
||||
|
||||
const config = parseConfigOverride(configModule.config);
|
||||
|
||||
@ -453,8 +453,8 @@ function configFileCheck(): CheckSpec {
|
||||
if (!foundPath || !foundRel) return null; // skip — config file is optional
|
||||
|
||||
try {
|
||||
const { createJiti } = await import("jiti");
|
||||
const jiti = createJiti(import.meta.url);
|
||||
const { createConfigFileJiti } = await import("../lib/config-jiti.js");
|
||||
const jiti = createConfigFileJiti(foundPath);
|
||||
const mod = await jiti.import<{ config?: unknown }>(foundPath);
|
||||
const config = mod.config;
|
||||
if (config === undefined) {
|
||||
|
||||
43
packages/cli/src/lib/config-jiti.ts
Normal file
43
packages/cli/src/lib/config-jiti.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { createJiti, type Jiti } from "jiti";
|
||||
|
||||
const CONFIG_IMPORT_SPECIFIERS = [
|
||||
"@hexclave/js/config",
|
||||
"@hexclave/next/config",
|
||||
"@hexclave/react/config",
|
||||
"@hexclave/tanstack-start/config",
|
||||
"@hexclave/template/config",
|
||||
"@stackframe/js",
|
||||
"@stackframe/next",
|
||||
"@stackframe/react",
|
||||
"@stackframe/stack",
|
||||
"@stackframe/template",
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Loads config authoring imports from the project's SDK when available, while
|
||||
* allowing bare CI checkouts to use the CLI's bundled SDK copy. Jiti resolves
|
||||
* imports relative to the config file, so those projects may otherwise fail.
|
||||
*/
|
||||
export function createConfigFileJiti(configFilePath: string): Jiti {
|
||||
const configRequire = createRequire(configFilePath);
|
||||
const unresolvedSpecifiers: string[] = [];
|
||||
|
||||
for (const specifier of CONFIG_IMPORT_SPECIFIERS) {
|
||||
try {
|
||||
configRequire.resolve(specifier);
|
||||
} catch {
|
||||
unresolvedSpecifiers.push(specifier);
|
||||
}
|
||||
}
|
||||
|
||||
const configAliases: Record<string, string> = {};
|
||||
if (unresolvedSpecifiers.length > 0) {
|
||||
const cliConfigEntrypoint = createRequire(import.meta.url).resolve("@hexclave/js/config");
|
||||
for (const specifier of unresolvedSpecifiers) {
|
||||
configAliases[specifier] = cliConfigEntrypoint;
|
||||
}
|
||||
}
|
||||
|
||||
return createJiti(import.meta.url, { alias: configAliases });
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user