veryfront 0.1.129 → 0.1.130
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.
- package/esm/cli/commands/config/command-help.d.ts +3 -0
- package/esm/cli/commands/config/command-help.d.ts.map +1 -0
- package/esm/cli/commands/config/command-help.js +13 -0
- package/esm/cli/commands/config/handler.d.ts +5 -0
- package/esm/cli/commands/config/handler.d.ts.map +1 -0
- package/esm/cli/commands/config/handler.js +70 -0
- package/esm/cli/commands/open/command-help.d.ts +3 -0
- package/esm/cli/commands/open/command-help.d.ts.map +1 -0
- package/esm/cli/commands/open/command-help.js +17 -0
- package/esm/cli/commands/open/command.d.ts +14 -0
- package/esm/cli/commands/open/command.d.ts.map +1 -0
- package/esm/cli/commands/open/command.js +22 -0
- package/esm/cli/commands/open/handler.d.ts +3 -0
- package/esm/cli/commands/open/handler.d.ts.map +1 -0
- package/esm/cli/commands/open/handler.js +29 -0
- package/esm/cli/help/command-definitions.d.ts.map +1 -1
- package/esm/cli/help/command-definitions.js +4 -0
- package/esm/cli/router.d.ts.map +1 -1
- package/esm/cli/router.js +4 -0
- package/esm/deno.js +1 -1
- package/esm/src/platform/compat/framework-source-resolver.d.ts +8 -0
- package/esm/src/platform/compat/framework-source-resolver.d.ts.map +1 -1
- package/esm/src/platform/compat/framework-source-resolver.js +77 -1
- package/esm/src/transforms/esm/import-parser.d.ts.map +1 -1
- package/esm/src/transforms/esm/import-parser.js +6 -0
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.d.ts +1 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.js +10 -66
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/cli/commands/config/command-help.ts +15 -0
- package/src/cli/commands/config/handler.ts +90 -0
- package/src/cli/commands/open/command-help.ts +19 -0
- package/src/cli/commands/open/command.ts +28 -0
- package/src/cli/commands/open/handler.ts +38 -0
- package/src/cli/help/command-definitions.ts +4 -0
- package/src/cli/router.ts +4 -0
- package/src/deno.js +1 -1
- package/src/src/platform/compat/framework-source-resolver.ts +101 -1
- package/src/src/transforms/esm/import-parser.ts +12 -0
- package/src/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.ts +10 -69
- package/src/src/utils/version-constant.ts +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/config/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,UAAU,EAAE,WAYxB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const configHelp = {
|
|
2
|
+
name: "config",
|
|
3
|
+
category: "project",
|
|
4
|
+
description: "Show effective project configuration",
|
|
5
|
+
usage: "veryfront config [options]",
|
|
6
|
+
options: [
|
|
7
|
+
{ flag: "--json", description: "Output as JSON" },
|
|
8
|
+
],
|
|
9
|
+
examples: [
|
|
10
|
+
"veryfront config",
|
|
11
|
+
"veryfront config --json",
|
|
12
|
+
],
|
|
13
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ParsedArgs } from "../../shared/types.js";
|
|
2
|
+
export declare function detectConfigSource(projectDir: string): Promise<string | null>;
|
|
3
|
+
export declare function getEnvOverrides(): string[];
|
|
4
|
+
export declare function handleConfigCommand(_args: ParsedArgs): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/config/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAexD,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAexB;AAED,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAM1C;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA+C1E"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { cliLogger } from "../../utils/index.js";
|
|
2
|
+
import { getEnv } from "../../../src/platform/index.js";
|
|
3
|
+
import { createSuccessEnvelope, isJsonMode, outputJson } from "../../shared/json-output.js";
|
|
4
|
+
import { bold, dim } from "../../ui/colors.js";
|
|
5
|
+
const ENV_OVERRIDES = {
|
|
6
|
+
projectSlug: "VERYFRONT_PROJECT_SLUG",
|
|
7
|
+
apiBaseUrl: "VERYFRONT_API_BASE_URL",
|
|
8
|
+
apiToken: "VERYFRONT_API_TOKEN",
|
|
9
|
+
nodeEnv: "NODE_ENV",
|
|
10
|
+
veryfrontEnv: "VERYFRONT_ENV",
|
|
11
|
+
debug: "VERYFRONT_DEBUG",
|
|
12
|
+
};
|
|
13
|
+
export async function detectConfigSource(projectDir) {
|
|
14
|
+
const { createFileSystem } = await import("../../../src/platform/index.js");
|
|
15
|
+
const { join } = await import("../../../src/platform/compat/path/index.js");
|
|
16
|
+
const fs = createFileSystem();
|
|
17
|
+
for (const name of [
|
|
18
|
+
"veryfront.config.ts",
|
|
19
|
+
"veryfront.config.js",
|
|
20
|
+
"veryfront.json",
|
|
21
|
+
]) {
|
|
22
|
+
if (await fs.exists(join(projectDir, name)))
|
|
23
|
+
return name;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
export function getEnvOverrides() {
|
|
28
|
+
const overrides = [];
|
|
29
|
+
for (const [field, envVar] of Object.entries(ENV_OVERRIDES)) {
|
|
30
|
+
if (getEnv(envVar))
|
|
31
|
+
overrides.push(`${field} (${envVar})`);
|
|
32
|
+
}
|
|
33
|
+
return overrides;
|
|
34
|
+
}
|
|
35
|
+
export async function handleConfigCommand(_args) {
|
|
36
|
+
const { getEnvironmentConfig } = await import("../../../src/config/index.js");
|
|
37
|
+
const { cwd } = await import("../../../src/platform/index.js");
|
|
38
|
+
const config = getEnvironmentConfig();
|
|
39
|
+
const projectDir = cwd();
|
|
40
|
+
const configSource = await detectConfigSource(projectDir);
|
|
41
|
+
const envOverrides = getEnvOverrides();
|
|
42
|
+
const configData = {
|
|
43
|
+
projectSlug: config.projectSlug ?? null,
|
|
44
|
+
nodeEnv: config.nodeEnv,
|
|
45
|
+
veryfrontEnv: config.veryfrontEnv || null,
|
|
46
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
47
|
+
debug: config.debug,
|
|
48
|
+
ci: config.ci,
|
|
49
|
+
hasApiToken: !!config.apiToken,
|
|
50
|
+
configSource,
|
|
51
|
+
envOverrides,
|
|
52
|
+
};
|
|
53
|
+
if (isJsonMode()) {
|
|
54
|
+
await outputJson(createSuccessEnvelope("config", configData));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
cliLogger.info(`\n ${bold("Project Configuration")}\n`);
|
|
58
|
+
cliLogger.info(` ${dim("Project slug:")} ${configData.projectSlug ?? "(not set)"}`);
|
|
59
|
+
cliLogger.info(` ${dim("Environment:")} ${configData.nodeEnv}`);
|
|
60
|
+
cliLogger.info(` ${dim("VF Environment:")} ${configData.veryfrontEnv ?? "(not set)"}`);
|
|
61
|
+
cliLogger.info(` ${dim("API endpoint:")} ${configData.apiBaseUrl}`);
|
|
62
|
+
cliLogger.info(` ${dim("Debug:")} ${configData.debug}`);
|
|
63
|
+
cliLogger.info(` ${dim("CI:")} ${configData.ci}`);
|
|
64
|
+
cliLogger.info(` ${dim("Authenticated:")} ${configData.hasApiToken ? "yes" : "no"}`);
|
|
65
|
+
cliLogger.info(` ${dim("Config file:")} ${configData.configSource ?? "(none)"}`);
|
|
66
|
+
if (envOverrides.length > 0) {
|
|
67
|
+
cliLogger.info(` ${dim("Env overrides:")} ${envOverrides.join(", ")}`);
|
|
68
|
+
}
|
|
69
|
+
cliLogger.info("");
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-help.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/open/command-help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,QAAQ,EAAE,WAgBtB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const openHelp = {
|
|
2
|
+
name: "open",
|
|
3
|
+
category: "project",
|
|
4
|
+
description: "Open project URLs in the browser",
|
|
5
|
+
usage: "veryfront open [options]",
|
|
6
|
+
options: [
|
|
7
|
+
{ flag: "--env <name>", description: "Open a specific environment URL" },
|
|
8
|
+
{ flag: "--studio", description: "Open Veryfront Studio" },
|
|
9
|
+
{ flag: "--json", description: "Output URL as JSON instead of opening" },
|
|
10
|
+
],
|
|
11
|
+
examples: [
|
|
12
|
+
"veryfront open",
|
|
13
|
+
"veryfront open --env staging",
|
|
14
|
+
"veryfront open --studio",
|
|
15
|
+
"veryfront open --json",
|
|
16
|
+
],
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const OpenArgsSchema: z.ZodObject<{
|
|
3
|
+
env: z.ZodOptional<z.ZodString>;
|
|
4
|
+
studio: z.ZodDefault<z.ZodBoolean>;
|
|
5
|
+
projectSlug: z.ZodOptional<z.ZodString>;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export type OpenOptions = z.infer<typeof OpenArgsSchema>;
|
|
8
|
+
export declare const parseOpenArgs: (args: import("../../shared/types.js").ParsedArgs) => import("../../shared/args.js").SafeParseResult<{
|
|
9
|
+
studio: boolean;
|
|
10
|
+
env?: string | undefined;
|
|
11
|
+
projectSlug?: string | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function buildUrl(projectSlug: string, options: OpenOptions): string;
|
|
14
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/open/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,cAAc;;;;iBAIzB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEzD,eAAO,MAAM,aAAa;;;;EAIxB,CAAC;AAIH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAQ1E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createArgParser } from "../../shared/args.js";
|
|
3
|
+
export const OpenArgsSchema = z.object({
|
|
4
|
+
env: z.string().optional(),
|
|
5
|
+
studio: z.boolean().default(false),
|
|
6
|
+
projectSlug: z.string().optional(),
|
|
7
|
+
});
|
|
8
|
+
export const parseOpenArgs = createArgParser(OpenArgsSchema, {
|
|
9
|
+
env: { keys: ["env"], type: "string" },
|
|
10
|
+
studio: { keys: ["studio"], type: "boolean" },
|
|
11
|
+
projectSlug: { keys: ["project-slug", "project", "p"], type: "string" },
|
|
12
|
+
});
|
|
13
|
+
const DASHBOARD_BASE = "https://veryfront.com";
|
|
14
|
+
export function buildUrl(projectSlug, options) {
|
|
15
|
+
if (options.studio) {
|
|
16
|
+
return `${DASHBOARD_BASE}/studio/${projectSlug}`;
|
|
17
|
+
}
|
|
18
|
+
if (options.env) {
|
|
19
|
+
return `${DASHBOARD_BASE}/projects/${projectSlug}/environments/${options.env}`;
|
|
20
|
+
}
|
|
21
|
+
return `${DASHBOARD_BASE}/projects/${projectSlug}`;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/open/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAMxD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BvE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { parseArgsOrThrow } from "../../shared/args.js";
|
|
2
|
+
import { cliLogger, exitProcess } from "../../utils/index.js";
|
|
3
|
+
import { createSuccessEnvelope, isJsonMode, outputJson } from "../../shared/json-output.js";
|
|
4
|
+
import { buildUrl, parseOpenArgs } from "./command.js";
|
|
5
|
+
export async function handleOpenCommand(args) {
|
|
6
|
+
const opts = parseArgsOrThrow(parseOpenArgs, "open", args);
|
|
7
|
+
let projectSlug = opts.projectSlug;
|
|
8
|
+
if (!projectSlug) {
|
|
9
|
+
const { cwd } = await import("../../../src/platform/index.js");
|
|
10
|
+
const { getEnvironmentConfig } = await import("../../../src/config/index.js");
|
|
11
|
+
const { readConfigFile } = await import("../../shared/config.js");
|
|
12
|
+
projectSlug = getEnvironmentConfig().projectSlug ??
|
|
13
|
+
(await readConfigFile(cwd()))?.projectSlug ??
|
|
14
|
+
undefined;
|
|
15
|
+
}
|
|
16
|
+
if (!projectSlug) {
|
|
17
|
+
cliLogger.error("No project found. Run from a project directory or use --project-slug");
|
|
18
|
+
exitProcess(1);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const url = buildUrl(projectSlug, opts);
|
|
22
|
+
if (isJsonMode()) {
|
|
23
|
+
await outputJson(createSuccessEnvelope("open", { url }));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const { openBrowser } = await import("../../auth/browser.js");
|
|
27
|
+
await openBrowser(url);
|
|
28
|
+
console.log(` Opening ${url}`);
|
|
29
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-definitions.d.ts","sourceRoot":"","sources":["../../../src/cli/help/command-definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"command-definitions.d.ts","sourceRoot":"","sources":["../../../src/cli/help/command-definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAyClD;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,eAuCtB,CAAC"}
|
|
@@ -39,6 +39,8 @@ import { schemaHelp } from "../commands/schema/command-help.js";
|
|
|
39
39
|
import { testHelp } from "../commands/test/command-help.js";
|
|
40
40
|
import { lintHelp } from "../commands/lint/command-help.js";
|
|
41
41
|
import { skillsHelp } from "../commands/skills/command-help.js";
|
|
42
|
+
import { configHelp } from "../commands/config/command-help.js";
|
|
43
|
+
import { openHelp } from "../commands/open/command-help.js";
|
|
42
44
|
import { completionsHelp } from "../commands/completions/command-help.js";
|
|
43
45
|
/**
|
|
44
46
|
* Central registry of all command help definitions.
|
|
@@ -80,5 +82,7 @@ export const COMMANDS = {
|
|
|
80
82
|
test: testHelp,
|
|
81
83
|
lint: lintHelp,
|
|
82
84
|
skills: skillsHelp,
|
|
85
|
+
config: configHelp,
|
|
86
|
+
open: openHelp,
|
|
83
87
|
completions: completionsHelp,
|
|
84
88
|
};
|
package/esm/cli/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/cli/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/cli/router.ts"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAmEpD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA0FlE"}
|
package/esm/cli/router.js
CHANGED
|
@@ -38,6 +38,8 @@ import { handleSchemaCommand } from "./commands/schema/handler.js";
|
|
|
38
38
|
import { handleTestCommand } from "./commands/test/handler.js";
|
|
39
39
|
import { handleLintCommand } from "./commands/lint/handler.js";
|
|
40
40
|
import { handleSkillsCommand } from "./commands/skills/handler.js";
|
|
41
|
+
import { handleConfigCommand } from "./commands/config/handler.js";
|
|
42
|
+
import { handleOpenCommand } from "./commands/open/handler.js";
|
|
41
43
|
import { handleCompletionsCommand } from "./commands/completions/handler.js";
|
|
42
44
|
import { login, logout, whoami } from "./auth/index.js";
|
|
43
45
|
import { parseLoginMethod } from "./auth/utils.js";
|
|
@@ -95,6 +97,8 @@ const commands = {
|
|
|
95
97
|
"test": handleTestCommand,
|
|
96
98
|
"lint": handleLintCommand,
|
|
97
99
|
"skills": handleSkillsCommand,
|
|
100
|
+
"config": handleConfigCommand,
|
|
101
|
+
"open": handleOpenCommand,
|
|
98
102
|
"completions": handleCompletionsCommand,
|
|
99
103
|
};
|
|
100
104
|
/**
|
package/esm/deno.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FileInfo } from "../adapters/base.js";
|
|
2
2
|
export declare const FRAMEWORK_ROOT: string;
|
|
3
|
+
export declare const FRAMEWORK_SRC_DIR: string;
|
|
3
4
|
export declare const FRAMEWORK_EMBEDDED_SRC_DIR: string;
|
|
4
5
|
export declare const DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS: readonly [".tsx.src", ".ts.src", ".jsx.src", ".js.src", ".mdx.src", ".md.src", ".tsx", ".ts", ".jsx", ".js", ".mdx", ".md"];
|
|
5
6
|
export interface FrameworkSourceFileSystem {
|
|
@@ -15,6 +16,13 @@ export interface ResolveFrameworkSourcePathOptions {
|
|
|
15
16
|
extensions?: readonly string[];
|
|
16
17
|
includeIndexFallback?: boolean;
|
|
17
18
|
}
|
|
19
|
+
export interface ResolveRelativeFrameworkSourceImportOptions {
|
|
20
|
+
fileSystem?: FrameworkSourceFileSystem;
|
|
21
|
+
exists?: (path: string) => Promise<boolean>;
|
|
22
|
+
extensions?: readonly string[];
|
|
23
|
+
}
|
|
18
24
|
export declare function getFrameworkSourceLookupDirs(extraLookupDirs?: string[]): string[];
|
|
25
|
+
export declare function isFrameworkSourcePath(path: string): boolean;
|
|
19
26
|
export declare function resolveFrameworkSourcePath(relativePathWithoutExt: string, options?: ResolveFrameworkSourcePathOptions): Promise<FrameworkSourceLookupResult | null>;
|
|
27
|
+
export declare function resolveRelativeFrameworkSourceImport(specifier: string, fromSourcePath: string, options?: ResolveRelativeFrameworkSourceImportOptions): Promise<string | null>;
|
|
20
28
|
//# sourceMappingURL=framework-source-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framework-source-resolver.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/framework-source-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,eAAO,MAAM,cAAc,QAA4C,CAAC;AACxE,eAAO,MAAM,0BAA0B,QAAgD,CAAC;AAExF,eAAO,MAAM,mCAAmC,6HAatC,CAAC;AAEX,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iCAAiC;IAChD,UAAU,CAAC,EAAE,yBAAyB,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,4BAA4B,CAAC,eAAe,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAarF;AAED,wBAAsB,0BAA0B,CAC9C,sBAAsB,EAAE,MAAM,EAC9B,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CA+B7C"}
|
|
1
|
+
{"version":3,"file":"framework-source-resolver.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/framework-source-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,eAAO,MAAM,cAAc,QAA4C,CAAC;AACxE,eAAO,MAAM,iBAAiB,QAA8B,CAAC;AAC7D,eAAO,MAAM,0BAA0B,QAAgD,CAAC;AAExF,eAAO,MAAM,mCAAmC,6HAatC,CAAC;AAEX,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iCAAiC;IAChD,UAAU,CAAC,EAAE,yBAAyB,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,2CAA2C;IAC1D,UAAU,CAAC,EAAE,yBAAyB,CAAC;IACvC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,wBAAgB,4BAA4B,CAAC,eAAe,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAarF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG3D;AAuCD,wBAAsB,0BAA0B,CAC9C,sBAAsB,EAAE,MAAM,EAC9B,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CA+B7C;AAED,wBAAsB,oCAAoC,CACxD,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,2CAAgD,GACxD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6CxB"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { join } from "./path/index.js";
|
|
2
2
|
import { createFileSystem } from "./fs.js";
|
|
3
|
-
import { getFrameworkRootFromMeta } from "./vfs-paths.js";
|
|
3
|
+
import { getFrameworkRoot, getFrameworkRootFromMeta } from "./vfs-paths.js";
|
|
4
4
|
export const FRAMEWORK_ROOT = getFrameworkRootFromMeta(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
|
|
5
|
+
export const FRAMEWORK_SRC_DIR = join(FRAMEWORK_ROOT, "src");
|
|
5
6
|
export const FRAMEWORK_EMBEDDED_SRC_DIR = join(FRAMEWORK_ROOT, "dist", "framework-src");
|
|
6
7
|
export const DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS = [
|
|
7
8
|
".tsx.src",
|
|
@@ -31,6 +32,40 @@ export function getFrameworkSourceLookupDirs(extraLookupDirs = []) {
|
|
|
31
32
|
return true;
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
export function isFrameworkSourcePath(path) {
|
|
36
|
+
return path.startsWith(`${FRAMEWORK_SRC_DIR}/`) ||
|
|
37
|
+
path.startsWith(`${FRAMEWORK_EMBEDDED_SRC_DIR}/`);
|
|
38
|
+
}
|
|
39
|
+
function expandFrameworkCandidatePaths(candidatePath) {
|
|
40
|
+
const candidates = [candidatePath];
|
|
41
|
+
const candidateRoot = getFrameworkRoot(candidatePath);
|
|
42
|
+
const candidateSrcDir = candidateRoot ? join(candidateRoot, "src") : FRAMEWORK_SRC_DIR;
|
|
43
|
+
const candidateEmbeddedDir = candidateRoot
|
|
44
|
+
? join(candidateRoot, "dist", "framework-src")
|
|
45
|
+
: FRAMEWORK_EMBEDDED_SRC_DIR;
|
|
46
|
+
if (candidatePath.startsWith(`${candidateSrcDir}/`)) {
|
|
47
|
+
const relativePath = candidatePath.slice(candidateSrcDir.length + 1);
|
|
48
|
+
candidates.push(join(candidateEmbeddedDir, relativePath));
|
|
49
|
+
}
|
|
50
|
+
return [...new Set(candidates)];
|
|
51
|
+
}
|
|
52
|
+
async function findExistingFrameworkCandidate(candidatePath, options = {}) {
|
|
53
|
+
const fs = options.fileSystem ?? createFileSystem();
|
|
54
|
+
const exists = options.exists ?? (async (path) => {
|
|
55
|
+
try {
|
|
56
|
+
const stat = await fs.stat(path);
|
|
57
|
+
return stat.isFile;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
for (const candidate of expandFrameworkCandidatePaths(candidatePath)) {
|
|
64
|
+
if (await exists(candidate))
|
|
65
|
+
return candidate;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
34
69
|
export async function resolveFrameworkSourcePath(relativePathWithoutExt, options = {}) {
|
|
35
70
|
const fs = options.fileSystem ?? createFileSystem();
|
|
36
71
|
const lookupDirs = getFrameworkSourceLookupDirs(options.extraLookupDirs);
|
|
@@ -60,3 +95,44 @@ export async function resolveFrameworkSourcePath(relativePathWithoutExt, options
|
|
|
60
95
|
}
|
|
61
96
|
return null;
|
|
62
97
|
}
|
|
98
|
+
export async function resolveRelativeFrameworkSourceImport(specifier, fromSourcePath, options = {}) {
|
|
99
|
+
const extensions = options.extensions ?? DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS;
|
|
100
|
+
const fromDir = fromSourcePath.substring(0, fromSourcePath.lastIndexOf("/"));
|
|
101
|
+
const parts = fromDir.split("/").filter(Boolean);
|
|
102
|
+
const importParts = specifier.split("/").filter(Boolean);
|
|
103
|
+
for (const part of importParts) {
|
|
104
|
+
if (part === "..") {
|
|
105
|
+
parts.pop();
|
|
106
|
+
}
|
|
107
|
+
else if (part !== ".") {
|
|
108
|
+
parts.push(part);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const basePath = "/" + parts.join("/");
|
|
112
|
+
if (/\.(tsx?|jsx?|mjs)$/.test(specifier)) {
|
|
113
|
+
const explicitCandidates = [basePath, `${basePath}.src`];
|
|
114
|
+
if (basePath.endsWith(".js") || basePath.endsWith(".mjs")) {
|
|
115
|
+
const stem = basePath.replace(/\.(?:m?js)$/, "");
|
|
116
|
+
for (const ext of [".ts", ".tsx", ".jsx", ".js", ".mjs"]) {
|
|
117
|
+
explicitCandidates.push(`${stem}${ext}.src`, `${stem}${ext}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const candidate of explicitCandidates) {
|
|
121
|
+
const resolved = await findExistingFrameworkCandidate(candidate, options);
|
|
122
|
+
if (resolved)
|
|
123
|
+
return resolved;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
for (const ext of extensions) {
|
|
128
|
+
const candidate = await findExistingFrameworkCandidate(basePath + ext, options);
|
|
129
|
+
if (candidate)
|
|
130
|
+
return candidate;
|
|
131
|
+
}
|
|
132
|
+
for (const ext of extensions) {
|
|
133
|
+
const candidate = await findExistingFrameworkCandidate(join(basePath, "index" + ext), options);
|
|
134
|
+
if (candidate)
|
|
135
|
+
return candidate;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-parser.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/import-parser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-parser.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/import-parser.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAKtE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,uBAAuB;IAC/B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAKD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,uBAAuB,CAAC,CAiFlC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getEsbuild } from "../../platform/compat/esbuild.js";
|
|
2
2
|
import { join } from "../../platform/compat/path/index.js";
|
|
3
3
|
import { createFileSystem } from "../../platform/compat/fs.js";
|
|
4
|
+
import { isFrameworkSourcePath, resolveRelativeFrameworkSourceImport, } from "../../platform/compat/framework-source-resolver.js";
|
|
4
5
|
import { isCrossProjectImport, parseCrossProjectImport } from "./path-resolver.js";
|
|
5
6
|
import { parseImports } from "./lexer.js";
|
|
6
7
|
import { getLoaderFromPath } from "./transform-utils.js";
|
|
@@ -94,6 +95,11 @@ async function checkFileExists(path, adapter) {
|
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
async function resolveLocalImportPath(fromFile, importSpecifier, adapter) {
|
|
98
|
+
if (isFrameworkSourcePath(fromFile)) {
|
|
99
|
+
const resolvedFrameworkImport = await resolveRelativeFrameworkSourceImport(importSpecifier, fromFile);
|
|
100
|
+
if (resolvedFrameworkImport)
|
|
101
|
+
return resolvedFrameworkImport;
|
|
102
|
+
}
|
|
97
103
|
const fromDir = fromFile.substring(0, fromFile.lastIndexOf("/"));
|
|
98
104
|
const basePath = resolveRelative(fromDir, importSpecifier);
|
|
99
105
|
if (adapter?.fs.resolveFile) {
|
|
@@ -32,5 +32,5 @@ export declare function resolveVeryfrontSourcePath(specifier: string, existsFn?:
|
|
|
32
32
|
* Handles both regular source files (.tsx, .ts) and embedded sources (.tsx.src, .ts.src)
|
|
33
33
|
* for compiled binaries.
|
|
34
34
|
*/
|
|
35
|
-
export declare function resolveRelativeFrameworkImport(specifier: string, fromSourcePath: string,
|
|
35
|
+
export declare function resolveRelativeFrameworkImport(specifier: string, fromSourcePath: string, fs: ReturnType<typeof createFileSystem>, existsFn?: (path: string) => Promise<boolean>): Promise<string | null>;
|
|
36
36
|
//# sourceMappingURL=path-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-resolver.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAU,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"path-resolver.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAU,MAAM,mCAAmC,CAAC;AAa7E,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAU,GACpD,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmBzD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EACvC,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAU,GACpD,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA6DzD;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAU,GACpD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkExB;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EACvC,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAU,GACpD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASxB"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { exists } from "../../../../platform/compat/fs.js";
|
|
8
8
|
import { join } from "../../../../platform/compat/path/index.js";
|
|
9
9
|
import { rendererLogger as logger } from "../../../../utils/index.js";
|
|
10
|
+
import { resolveRelativeFrameworkSourceImport } from "../../../../platform/compat/framework-source-resolver.js";
|
|
10
11
|
import { resolveInternalModuleTarget } from "../../../veryfront-module-urls.js";
|
|
11
12
|
import { EMBEDDED_SRC_DIR, EXTENSIONS, FRAMEWORK_LOOKUPS, FRAMEWORK_ROOT, LOG_PREFIX, } from "./constants.js";
|
|
12
13
|
export async function tryReadWithExtensions(fs, basePath, existsFn = exists) {
|
|
@@ -168,70 +169,13 @@ export async function resolveVeryfrontSourcePath(specifier, existsFn = exists) {
|
|
|
168
169
|
* Handles both regular source files (.tsx, .ts) and embedded sources (.tsx.src, .ts.src)
|
|
169
170
|
* for compiled binaries.
|
|
170
171
|
*/
|
|
171
|
-
export async function resolveRelativeFrameworkImport(specifier, fromSourcePath,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
parts.push(part);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
const basePath = "/" + parts.join("/");
|
|
184
|
-
// If specifier already has extension (e.g., ./Head.tsx), we need to try:
|
|
185
|
-
// 1. The exact path (basePath)
|
|
186
|
-
// 2. The path with .src suffix (basePath.src) for embedded sources
|
|
187
|
-
// 3. For transpiled .js/.mjs imports, fall back to sibling TS/TSX/JSX sources
|
|
188
|
-
if (/\.(tsx?|jsx?|mjs)$/.test(specifier)) {
|
|
189
|
-
const explicitCandidates = [basePath, `${basePath}.src`];
|
|
190
|
-
// esbuild rewrites TS/TSX relative imports to .js in transformed output.
|
|
191
|
-
// When the original source only exists as .ts/.tsx (or embedded .src),
|
|
192
|
-
// probe those sibling source extensions before giving up.
|
|
193
|
-
if (basePath.endsWith(".js") || basePath.endsWith(".mjs")) {
|
|
194
|
-
const stem = basePath.replace(/\.(?:m?js)$/, "");
|
|
195
|
-
for (const ext of [".ts", ".tsx", ".jsx", ".js", ".mjs"]) {
|
|
196
|
-
explicitCandidates.push(`${stem}${ext}.src`, `${stem}${ext}`);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
for (const candidate of explicitCandidates) {
|
|
200
|
-
try {
|
|
201
|
-
if (await existsFn(candidate))
|
|
202
|
-
return candidate;
|
|
203
|
-
}
|
|
204
|
-
catch (_) {
|
|
205
|
-
/* expected: file may not exist at this path */
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
// No extension provided - try all extensions (including .src for embedded sources)
|
|
211
|
-
const allExtensions = [
|
|
212
|
-
...EXTENSIONS.map((ext) => ext + ".src"),
|
|
213
|
-
...EXTENSIONS,
|
|
214
|
-
];
|
|
215
|
-
for (const ext of allExtensions) {
|
|
216
|
-
const pathWithExt = basePath + ext;
|
|
217
|
-
try {
|
|
218
|
-
if (await existsFn(pathWithExt))
|
|
219
|
-
return pathWithExt;
|
|
220
|
-
}
|
|
221
|
-
catch (_) {
|
|
222
|
-
/* expected: file may not exist at this path */
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
// Try index file
|
|
226
|
-
for (const ext of allExtensions) {
|
|
227
|
-
const indexPath = join(basePath, "index" + ext);
|
|
228
|
-
try {
|
|
229
|
-
if (await existsFn(indexPath))
|
|
230
|
-
return indexPath;
|
|
231
|
-
}
|
|
232
|
-
catch (_) {
|
|
233
|
-
/* expected: file may not exist at this path */
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return null;
|
|
172
|
+
export async function resolveRelativeFrameworkImport(specifier, fromSourcePath, fs, existsFn = exists) {
|
|
173
|
+
return await resolveRelativeFrameworkSourceImport(specifier, fromSourcePath, {
|
|
174
|
+
fileSystem: fs,
|
|
175
|
+
exists: existsFn,
|
|
176
|
+
extensions: [
|
|
177
|
+
...EXTENSIONS.map((ext) => `${ext}.src`),
|
|
178
|
+
...EXTENSIONS,
|
|
179
|
+
],
|
|
180
|
+
});
|
|
237
181
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.130";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CommandHelp } from "../../help/types.js";
|
|
2
|
+
|
|
3
|
+
export const configHelp: CommandHelp = {
|
|
4
|
+
name: "config",
|
|
5
|
+
category: "project",
|
|
6
|
+
description: "Show effective project configuration",
|
|
7
|
+
usage: "veryfront config [options]",
|
|
8
|
+
options: [
|
|
9
|
+
{ flag: "--json", description: "Output as JSON" },
|
|
10
|
+
],
|
|
11
|
+
examples: [
|
|
12
|
+
"veryfront config",
|
|
13
|
+
"veryfront config --json",
|
|
14
|
+
],
|
|
15
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { ParsedArgs } from "../../shared/types.js";
|
|
2
|
+
import { cliLogger } from "../../utils/index.js";
|
|
3
|
+
import { getEnv } from "../../../src/platform/index.js";
|
|
4
|
+
import { createSuccessEnvelope, isJsonMode, outputJson } from "../../shared/json-output.js";
|
|
5
|
+
import { bold, dim } from "../../ui/colors.js";
|
|
6
|
+
|
|
7
|
+
const ENV_OVERRIDES: Record<string, string> = {
|
|
8
|
+
projectSlug: "VERYFRONT_PROJECT_SLUG",
|
|
9
|
+
apiBaseUrl: "VERYFRONT_API_BASE_URL",
|
|
10
|
+
apiToken: "VERYFRONT_API_TOKEN",
|
|
11
|
+
nodeEnv: "NODE_ENV",
|
|
12
|
+
veryfrontEnv: "VERYFRONT_ENV",
|
|
13
|
+
debug: "VERYFRONT_DEBUG",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function detectConfigSource(
|
|
17
|
+
projectDir: string,
|
|
18
|
+
): Promise<string | null> {
|
|
19
|
+
const { createFileSystem } = await import("../../../src/platform/index.js");
|
|
20
|
+
const { join } = await import("../../../src/platform/compat/path/index.js");
|
|
21
|
+
const fs = createFileSystem();
|
|
22
|
+
|
|
23
|
+
for (
|
|
24
|
+
const name of [
|
|
25
|
+
"veryfront.config.ts",
|
|
26
|
+
"veryfront.config.js",
|
|
27
|
+
"veryfront.json",
|
|
28
|
+
]
|
|
29
|
+
) {
|
|
30
|
+
if (await fs.exists(join(projectDir, name))) return name;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getEnvOverrides(): string[] {
|
|
36
|
+
const overrides: string[] = [];
|
|
37
|
+
for (const [field, envVar] of Object.entries(ENV_OVERRIDES)) {
|
|
38
|
+
if (getEnv(envVar)) overrides.push(`${field} (${envVar})`);
|
|
39
|
+
}
|
|
40
|
+
return overrides;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function handleConfigCommand(_args: ParsedArgs): Promise<void> {
|
|
44
|
+
const { getEnvironmentConfig } = await import("../../../src/config/index.js");
|
|
45
|
+
const { cwd } = await import("../../../src/platform/index.js");
|
|
46
|
+
const config = getEnvironmentConfig();
|
|
47
|
+
|
|
48
|
+
const projectDir = cwd();
|
|
49
|
+
const configSource = await detectConfigSource(projectDir);
|
|
50
|
+
const envOverrides = getEnvOverrides();
|
|
51
|
+
|
|
52
|
+
const configData = {
|
|
53
|
+
projectSlug: config.projectSlug ?? null,
|
|
54
|
+
nodeEnv: config.nodeEnv,
|
|
55
|
+
veryfrontEnv: config.veryfrontEnv || null,
|
|
56
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
57
|
+
debug: config.debug,
|
|
58
|
+
ci: config.ci,
|
|
59
|
+
hasApiToken: !!config.apiToken,
|
|
60
|
+
configSource,
|
|
61
|
+
envOverrides,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (isJsonMode()) {
|
|
65
|
+
await outputJson(createSuccessEnvelope("config", configData));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
cliLogger.info(`\n ${bold("Project Configuration")}\n`);
|
|
70
|
+
cliLogger.info(
|
|
71
|
+
` ${dim("Project slug:")} ${configData.projectSlug ?? "(not set)"}`,
|
|
72
|
+
);
|
|
73
|
+
cliLogger.info(` ${dim("Environment:")} ${configData.nodeEnv}`);
|
|
74
|
+
cliLogger.info(
|
|
75
|
+
` ${dim("VF Environment:")} ${configData.veryfrontEnv ?? "(not set)"}`,
|
|
76
|
+
);
|
|
77
|
+
cliLogger.info(` ${dim("API endpoint:")} ${configData.apiBaseUrl}`);
|
|
78
|
+
cliLogger.info(` ${dim("Debug:")} ${configData.debug}`);
|
|
79
|
+
cliLogger.info(` ${dim("CI:")} ${configData.ci}`);
|
|
80
|
+
cliLogger.info(
|
|
81
|
+
` ${dim("Authenticated:")} ${configData.hasApiToken ? "yes" : "no"}`,
|
|
82
|
+
);
|
|
83
|
+
cliLogger.info(
|
|
84
|
+
` ${dim("Config file:")} ${configData.configSource ?? "(none)"}`,
|
|
85
|
+
);
|
|
86
|
+
if (envOverrides.length > 0) {
|
|
87
|
+
cliLogger.info(` ${dim("Env overrides:")} ${envOverrides.join(", ")}`);
|
|
88
|
+
}
|
|
89
|
+
cliLogger.info("");
|
|
90
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CommandHelp } from "../../help/types.js";
|
|
2
|
+
|
|
3
|
+
export const openHelp: CommandHelp = {
|
|
4
|
+
name: "open",
|
|
5
|
+
category: "project",
|
|
6
|
+
description: "Open project URLs in the browser",
|
|
7
|
+
usage: "veryfront open [options]",
|
|
8
|
+
options: [
|
|
9
|
+
{ flag: "--env <name>", description: "Open a specific environment URL" },
|
|
10
|
+
{ flag: "--studio", description: "Open Veryfront Studio" },
|
|
11
|
+
{ flag: "--json", description: "Output URL as JSON instead of opening" },
|
|
12
|
+
],
|
|
13
|
+
examples: [
|
|
14
|
+
"veryfront open",
|
|
15
|
+
"veryfront open --env staging",
|
|
16
|
+
"veryfront open --studio",
|
|
17
|
+
"veryfront open --json",
|
|
18
|
+
],
|
|
19
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createArgParser } from "../../shared/args.js";
|
|
3
|
+
|
|
4
|
+
export const OpenArgsSchema = z.object({
|
|
5
|
+
env: z.string().optional(),
|
|
6
|
+
studio: z.boolean().default(false),
|
|
7
|
+
projectSlug: z.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export type OpenOptions = z.infer<typeof OpenArgsSchema>;
|
|
11
|
+
|
|
12
|
+
export const parseOpenArgs = createArgParser(OpenArgsSchema, {
|
|
13
|
+
env: { keys: ["env"], type: "string" },
|
|
14
|
+
studio: { keys: ["studio"], type: "boolean" },
|
|
15
|
+
projectSlug: { keys: ["project-slug", "project", "p"], type: "string" },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const DASHBOARD_BASE = "https://veryfront.com";
|
|
19
|
+
|
|
20
|
+
export function buildUrl(projectSlug: string, options: OpenOptions): string {
|
|
21
|
+
if (options.studio) {
|
|
22
|
+
return `${DASHBOARD_BASE}/studio/${projectSlug}`;
|
|
23
|
+
}
|
|
24
|
+
if (options.env) {
|
|
25
|
+
return `${DASHBOARD_BASE}/projects/${projectSlug}/environments/${options.env}`;
|
|
26
|
+
}
|
|
27
|
+
return `${DASHBOARD_BASE}/projects/${projectSlug}`;
|
|
28
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ParsedArgs } from "../../shared/types.js";
|
|
2
|
+
import { parseArgsOrThrow } from "../../shared/args.js";
|
|
3
|
+
import { cliLogger, exitProcess } from "../../utils/index.js";
|
|
4
|
+
import { createSuccessEnvelope, isJsonMode, outputJson } from "../../shared/json-output.js";
|
|
5
|
+
import { buildUrl, parseOpenArgs } from "./command.js";
|
|
6
|
+
|
|
7
|
+
export async function handleOpenCommand(args: ParsedArgs): Promise<void> {
|
|
8
|
+
const opts = parseArgsOrThrow(parseOpenArgs, "open", args);
|
|
9
|
+
|
|
10
|
+
let projectSlug = opts.projectSlug;
|
|
11
|
+
if (!projectSlug) {
|
|
12
|
+
const { cwd } = await import("../../../src/platform/index.js");
|
|
13
|
+
const { getEnvironmentConfig } = await import("../../../src/config/index.js");
|
|
14
|
+
const { readConfigFile } = await import("../../shared/config.js");
|
|
15
|
+
projectSlug = getEnvironmentConfig().projectSlug ??
|
|
16
|
+
(await readConfigFile(cwd()))?.projectSlug ??
|
|
17
|
+
undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!projectSlug) {
|
|
21
|
+
cliLogger.error(
|
|
22
|
+
"No project found. Run from a project directory or use --project-slug",
|
|
23
|
+
);
|
|
24
|
+
exitProcess(1);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const url = buildUrl(projectSlug, opts);
|
|
29
|
+
|
|
30
|
+
if (isJsonMode()) {
|
|
31
|
+
await outputJson(createSuccessEnvelope("open", { url }));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { openBrowser } = await import("../../auth/browser.js");
|
|
36
|
+
await openBrowser(url);
|
|
37
|
+
console.log(` Opening ${url}`);
|
|
38
|
+
}
|
|
@@ -42,6 +42,8 @@ import { schemaHelp } from "../commands/schema/command-help.js";
|
|
|
42
42
|
import { testHelp } from "../commands/test/command-help.js";
|
|
43
43
|
import { lintHelp } from "../commands/lint/command-help.js";
|
|
44
44
|
import { skillsHelp } from "../commands/skills/command-help.js";
|
|
45
|
+
import { configHelp } from "../commands/config/command-help.js";
|
|
46
|
+
import { openHelp } from "../commands/open/command-help.js";
|
|
45
47
|
import { completionsHelp } from "../commands/completions/command-help.js";
|
|
46
48
|
|
|
47
49
|
/**
|
|
@@ -84,5 +86,7 @@ export const COMMANDS: CommandRegistry = {
|
|
|
84
86
|
test: testHelp,
|
|
85
87
|
lint: lintHelp,
|
|
86
88
|
skills: skillsHelp,
|
|
89
|
+
config: configHelp,
|
|
90
|
+
open: openHelp,
|
|
87
91
|
completions: completionsHelp,
|
|
88
92
|
};
|
package/src/cli/router.ts
CHANGED
|
@@ -40,6 +40,8 @@ import { handleSchemaCommand } from "./commands/schema/handler.js";
|
|
|
40
40
|
import { handleTestCommand } from "./commands/test/handler.js";
|
|
41
41
|
import { handleLintCommand } from "./commands/lint/handler.js";
|
|
42
42
|
import { handleSkillsCommand } from "./commands/skills/handler.js";
|
|
43
|
+
import { handleConfigCommand } from "./commands/config/handler.js";
|
|
44
|
+
import { handleOpenCommand } from "./commands/open/handler.js";
|
|
43
45
|
import { handleCompletionsCommand } from "./commands/completions/handler.js";
|
|
44
46
|
import { login, logout, whoami } from "./auth/index.js";
|
|
45
47
|
import { parseLoginMethod } from "./auth/utils.js";
|
|
@@ -105,6 +107,8 @@ const commands: Record<string, (args: ParsedArgs) => Promise<void>> = {
|
|
|
105
107
|
"test": handleTestCommand,
|
|
106
108
|
"lint": handleLintCommand,
|
|
107
109
|
"skills": handleSkillsCommand,
|
|
110
|
+
"config": handleConfigCommand,
|
|
111
|
+
"open": handleOpenCommand,
|
|
108
112
|
"completions": handleCompletionsCommand,
|
|
109
113
|
};
|
|
110
114
|
|
package/src/deno.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { join } from "./path/index.js";
|
|
2
2
|
import type { FileInfo } from "../adapters/base.js";
|
|
3
3
|
import { createFileSystem } from "./fs.js";
|
|
4
|
-
import { getFrameworkRootFromMeta } from "./vfs-paths.js";
|
|
4
|
+
import { getFrameworkRoot, getFrameworkRootFromMeta } from "./vfs-paths.js";
|
|
5
5
|
|
|
6
6
|
export const FRAMEWORK_ROOT = getFrameworkRootFromMeta(import.meta.url);
|
|
7
|
+
export const FRAMEWORK_SRC_DIR = join(FRAMEWORK_ROOT, "src");
|
|
7
8
|
export const FRAMEWORK_EMBEDDED_SRC_DIR = join(FRAMEWORK_ROOT, "dist", "framework-src");
|
|
8
9
|
|
|
9
10
|
export const DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS = [
|
|
@@ -37,6 +38,12 @@ export interface ResolveFrameworkSourcePathOptions {
|
|
|
37
38
|
includeIndexFallback?: boolean;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
export interface ResolveRelativeFrameworkSourceImportOptions {
|
|
42
|
+
fileSystem?: FrameworkSourceFileSystem;
|
|
43
|
+
exists?: (path: string) => Promise<boolean>;
|
|
44
|
+
extensions?: readonly string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
40
47
|
export function getFrameworkSourceLookupDirs(extraLookupDirs: string[] = []): string[] {
|
|
41
48
|
const seen = new Set<string>();
|
|
42
49
|
const ordered = [
|
|
@@ -52,6 +59,48 @@ export function getFrameworkSourceLookupDirs(extraLookupDirs: string[] = []): st
|
|
|
52
59
|
});
|
|
53
60
|
}
|
|
54
61
|
|
|
62
|
+
export function isFrameworkSourcePath(path: string): boolean {
|
|
63
|
+
return path.startsWith(`${FRAMEWORK_SRC_DIR}/`) ||
|
|
64
|
+
path.startsWith(`${FRAMEWORK_EMBEDDED_SRC_DIR}/`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function expandFrameworkCandidatePaths(candidatePath: string): string[] {
|
|
68
|
+
const candidates = [candidatePath];
|
|
69
|
+
const candidateRoot = getFrameworkRoot(candidatePath);
|
|
70
|
+
const candidateSrcDir = candidateRoot ? join(candidateRoot, "src") : FRAMEWORK_SRC_DIR;
|
|
71
|
+
const candidateEmbeddedDir = candidateRoot
|
|
72
|
+
? join(candidateRoot, "dist", "framework-src")
|
|
73
|
+
: FRAMEWORK_EMBEDDED_SRC_DIR;
|
|
74
|
+
|
|
75
|
+
if (candidatePath.startsWith(`${candidateSrcDir}/`)) {
|
|
76
|
+
const relativePath = candidatePath.slice(candidateSrcDir.length + 1);
|
|
77
|
+
candidates.push(join(candidateEmbeddedDir, relativePath));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return [...new Set(candidates)];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function findExistingFrameworkCandidate(
|
|
84
|
+
candidatePath: string,
|
|
85
|
+
options: ResolveRelativeFrameworkSourceImportOptions = {},
|
|
86
|
+
): Promise<string | null> {
|
|
87
|
+
const fs = options.fileSystem ?? createFileSystem();
|
|
88
|
+
const exists = options.exists ?? (async (path: string) => {
|
|
89
|
+
try {
|
|
90
|
+
const stat = await fs.stat(path);
|
|
91
|
+
return stat.isFile;
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
for (const candidate of expandFrameworkCandidatePaths(candidatePath)) {
|
|
98
|
+
if (await exists(candidate)) return candidate;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
55
104
|
export async function resolveFrameworkSourcePath(
|
|
56
105
|
relativePathWithoutExt: string,
|
|
57
106
|
options: ResolveFrameworkSourcePathOptions = {},
|
|
@@ -87,3 +136,54 @@ export async function resolveFrameworkSourcePath(
|
|
|
87
136
|
|
|
88
137
|
return null;
|
|
89
138
|
}
|
|
139
|
+
|
|
140
|
+
export async function resolveRelativeFrameworkSourceImport(
|
|
141
|
+
specifier: string,
|
|
142
|
+
fromSourcePath: string,
|
|
143
|
+
options: ResolveRelativeFrameworkSourceImportOptions = {},
|
|
144
|
+
): Promise<string | null> {
|
|
145
|
+
const extensions = options.extensions ?? DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS;
|
|
146
|
+
const fromDir = fromSourcePath.substring(0, fromSourcePath.lastIndexOf("/"));
|
|
147
|
+
const parts = fromDir.split("/").filter(Boolean);
|
|
148
|
+
const importParts = specifier.split("/").filter(Boolean);
|
|
149
|
+
|
|
150
|
+
for (const part of importParts) {
|
|
151
|
+
if (part === "..") {
|
|
152
|
+
parts.pop();
|
|
153
|
+
} else if (part !== ".") {
|
|
154
|
+
parts.push(part);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const basePath = "/" + parts.join("/");
|
|
159
|
+
|
|
160
|
+
if (/\.(tsx?|jsx?|mjs)$/.test(specifier)) {
|
|
161
|
+
const explicitCandidates = [basePath, `${basePath}.src`];
|
|
162
|
+
|
|
163
|
+
if (basePath.endsWith(".js") || basePath.endsWith(".mjs")) {
|
|
164
|
+
const stem = basePath.replace(/\.(?:m?js)$/, "");
|
|
165
|
+
for (const ext of [".ts", ".tsx", ".jsx", ".js", ".mjs"]) {
|
|
166
|
+
explicitCandidates.push(`${stem}${ext}.src`, `${stem}${ext}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const candidate of explicitCandidates) {
|
|
171
|
+
const resolved = await findExistingFrameworkCandidate(candidate, options);
|
|
172
|
+
if (resolved) return resolved;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
for (const ext of extensions) {
|
|
179
|
+
const candidate = await findExistingFrameworkCandidate(basePath + ext, options);
|
|
180
|
+
if (candidate) return candidate;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
for (const ext of extensions) {
|
|
184
|
+
const candidate = await findExistingFrameworkCandidate(join(basePath, "index" + ext), options);
|
|
185
|
+
if (candidate) return candidate;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { getEsbuild } from "../../platform/compat/esbuild.js";
|
|
2
2
|
import { join } from "../../platform/compat/path/index.js";
|
|
3
3
|
import { createFileSystem } from "../../platform/compat/fs.js";
|
|
4
|
+
import {
|
|
5
|
+
isFrameworkSourcePath,
|
|
6
|
+
resolveRelativeFrameworkSourceImport,
|
|
7
|
+
} from "../../platform/compat/framework-source-resolver.js";
|
|
4
8
|
import type { RuntimeAdapter } from "../../platform/adapters/base.js";
|
|
5
9
|
import { isCrossProjectImport, parseCrossProjectImport } from "./path-resolver.js";
|
|
6
10
|
import { parseImports } from "./lexer.js";
|
|
@@ -138,6 +142,14 @@ async function resolveLocalImportPath(
|
|
|
138
142
|
importSpecifier: string,
|
|
139
143
|
adapter?: RuntimeAdapter,
|
|
140
144
|
): Promise<string | null> {
|
|
145
|
+
if (isFrameworkSourcePath(fromFile)) {
|
|
146
|
+
const resolvedFrameworkImport = await resolveRelativeFrameworkSourceImport(
|
|
147
|
+
importSpecifier,
|
|
148
|
+
fromFile,
|
|
149
|
+
);
|
|
150
|
+
if (resolvedFrameworkImport) return resolvedFrameworkImport;
|
|
151
|
+
}
|
|
152
|
+
|
|
141
153
|
const fromDir = fromFile.substring(0, fromFile.lastIndexOf("/"));
|
|
142
154
|
const basePath = resolveRelative(fromDir, importSpecifier);
|
|
143
155
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { createFileSystem, exists } from "../../../../platform/compat/fs.js";
|
|
9
9
|
import { join } from "../../../../platform/compat/path/index.js";
|
|
10
10
|
import { rendererLogger as logger } from "../../../../utils/index.js";
|
|
11
|
+
import { resolveRelativeFrameworkSourceImport } from "../../../../platform/compat/framework-source-resolver.js";
|
|
11
12
|
import { resolveInternalModuleTarget } from "../../../veryfront-module-urls.js";
|
|
12
13
|
import {
|
|
13
14
|
EMBEDDED_SRC_DIR,
|
|
@@ -201,75 +202,15 @@ export async function resolveVeryfrontSourcePath(
|
|
|
201
202
|
export async function resolveRelativeFrameworkImport(
|
|
202
203
|
specifier: string,
|
|
203
204
|
fromSourcePath: string,
|
|
204
|
-
|
|
205
|
+
fs: ReturnType<typeof createFileSystem>,
|
|
205
206
|
existsFn: (path: string) => Promise<boolean> = exists,
|
|
206
207
|
): Promise<string | null> {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
parts.push(part);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const basePath = "/" + parts.join("/");
|
|
220
|
-
|
|
221
|
-
// If specifier already has extension (e.g., ./Head.tsx), we need to try:
|
|
222
|
-
// 1. The exact path (basePath)
|
|
223
|
-
// 2. The path with .src suffix (basePath.src) for embedded sources
|
|
224
|
-
// 3. For transpiled .js/.mjs imports, fall back to sibling TS/TSX/JSX sources
|
|
225
|
-
if (/\.(tsx?|jsx?|mjs)$/.test(specifier)) {
|
|
226
|
-
const explicitCandidates = [basePath, `${basePath}.src`];
|
|
227
|
-
|
|
228
|
-
// esbuild rewrites TS/TSX relative imports to .js in transformed output.
|
|
229
|
-
// When the original source only exists as .ts/.tsx (or embedded .src),
|
|
230
|
-
// probe those sibling source extensions before giving up.
|
|
231
|
-
if (basePath.endsWith(".js") || basePath.endsWith(".mjs")) {
|
|
232
|
-
const stem = basePath.replace(/\.(?:m?js)$/, "");
|
|
233
|
-
for (const ext of [".ts", ".tsx", ".jsx", ".js", ".mjs"]) {
|
|
234
|
-
explicitCandidates.push(`${stem}${ext}.src`, `${stem}${ext}`);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
for (const candidate of explicitCandidates) {
|
|
239
|
-
try {
|
|
240
|
-
if (await existsFn(candidate)) return candidate;
|
|
241
|
-
} catch (_) {
|
|
242
|
-
/* expected: file may not exist at this path */
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// No extension provided - try all extensions (including .src for embedded sources)
|
|
250
|
-
const allExtensions = [
|
|
251
|
-
...EXTENSIONS.map((ext) => ext + ".src"),
|
|
252
|
-
...EXTENSIONS,
|
|
253
|
-
];
|
|
254
|
-
|
|
255
|
-
for (const ext of allExtensions) {
|
|
256
|
-
const pathWithExt = basePath + ext;
|
|
257
|
-
try {
|
|
258
|
-
if (await existsFn(pathWithExt)) return pathWithExt;
|
|
259
|
-
} catch (_) {
|
|
260
|
-
/* expected: file may not exist at this path */
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Try index file
|
|
265
|
-
for (const ext of allExtensions) {
|
|
266
|
-
const indexPath = join(basePath, "index" + ext);
|
|
267
|
-
try {
|
|
268
|
-
if (await existsFn(indexPath)) return indexPath;
|
|
269
|
-
} catch (_) {
|
|
270
|
-
/* expected: file may not exist at this path */
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return null;
|
|
208
|
+
return await resolveRelativeFrameworkSourceImport(specifier, fromSourcePath, {
|
|
209
|
+
fileSystem: fs,
|
|
210
|
+
exists: existsFn,
|
|
211
|
+
extensions: [
|
|
212
|
+
...EXTENSIONS.map((ext) => `${ext}.src`),
|
|
213
|
+
...EXTENSIONS,
|
|
214
|
+
],
|
|
215
|
+
});
|
|
275
216
|
}
|