@gigadrive/network-config 5.3.0 → 5.4.0

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/dist/index.mjs CHANGED
@@ -905,8 +905,8 @@ var detectContainerProject = Effect3.fn("detectContainerProject")(function* (pro
905
905
  });
906
906
 
907
907
  // src/detection/detect-framework.ts
908
- import { FileSystem as FileSystem12, Path as Path10 } from "@effect/platform";
909
- import { Effect as Effect14 } from "effect";
908
+ import { FileSystem as FileSystem13, Path as Path11 } from "@effect/platform";
909
+ import { Effect as Effect15 } from "effect";
910
910
 
911
911
  // src/detection/detect-package-manager.ts
912
912
  import { FileSystem as FileSystem4, Path as Path4 } from "@effect/platform";
@@ -1001,8 +1001,14 @@ var cakephp = {
1001
1001
  "logs"
1002
1002
  ],
1003
1003
  excludeFiles: ["tests/", "tmp/", "logs/"],
1004
- // config/app.php reads the salt from env; app_local.php is not committed.
1005
- environmentVariables: { SECURITY_SALT: generatedSecret("hex") }
1004
+ environmentVariables: {
1005
+ // The app_local.php that `composer install` copies from the example
1006
+ // reads env('DEBUG', true), which would run every deployment in debug
1007
+ // mode with stack traces in error pages.
1008
+ DEBUG: "false",
1009
+ // config/app.php reads the salt from env; app_local.php is not committed.
1010
+ SECURITY_SALT: generatedSecret("hex")
1011
+ }
1006
1012
  })
1007
1013
  };
1008
1014
 
@@ -1897,6 +1903,157 @@ var phpSites = DOCUMENT_ROOTS.map((documentRoot) => ({
1897
1903
  refineDefaultConfig: (defaults, projectFolder) => refinePhpDocumentRoot(defaults, projectFolder).pipe(Effect10.map((refined) => ({ ...refined, installCommand: "" })))
1898
1904
  }));
1899
1905
 
1906
+ // src/detection/frameworks/php-runtime.ts
1907
+ import { FileSystem as FileSystem11, Path as Path9 } from "@effect/platform";
1908
+ import { Effect as Effect11, Option as Option3 } from "effect";
1909
+
1910
+ // src/detection/frameworks/composer-constraint.ts
1911
+ var STABILITY_SUFFIX = /-(?:dev|alpha|beta|a|b|rc|patch|pl|p|stable)\.?\d*$/i;
1912
+ var parseVersion = (text) => {
1913
+ const parts = text.replace(/^v/i, "").replace(STABILITY_SUFFIX, "").split(".");
1914
+ if (parts.length > 4) {
1915
+ return void 0;
1916
+ }
1917
+ const segments = [];
1918
+ let wildcard = false;
1919
+ for (const part of parts) {
1920
+ if (/^[*x]$/i.test(part)) {
1921
+ wildcard = true;
1922
+ } else if (/^\d+$/.test(part) && !wildcard) {
1923
+ segments.push(Number(part));
1924
+ } else {
1925
+ return void 0;
1926
+ }
1927
+ }
1928
+ return { segments, wildcard };
1929
+ };
1930
+ var pad = (segments) => [segments[0] ?? 0, segments[1] ?? 0, segments[2] ?? 0, segments[3] ?? 0];
1931
+ var bump = (segments, position) => pad(segments.slice(0, position).map((segment, index) => index === position - 1 ? segment + 1 : segment));
1932
+ var compare = (a, b) => {
1933
+ for (let index = 0; index < 4; index++) {
1934
+ if (a[index] !== b[index]) {
1935
+ return a[index] - b[index];
1936
+ }
1937
+ }
1938
+ return 0;
1939
+ };
1940
+ var inRange = (version, lower, upper) => compare(version, lower) >= 0 && compare(version, upper) < 0;
1941
+ var allowsAtom = (atom, version) => {
1942
+ const match = /^(\^|~|>=|<=|<>|!=|==|=|>|<)?(.+)$/.exec(atom);
1943
+ const parsed = match ? parseVersion(match[2]) : void 0;
1944
+ if (!match || !parsed) {
1945
+ return void 0;
1946
+ }
1947
+ const operator = match[1];
1948
+ const { segments } = parsed;
1949
+ if (parsed.wildcard) {
1950
+ if (operator !== void 0) {
1951
+ return void 0;
1952
+ }
1953
+ return segments.length === 0 || inRange(version, pad(segments), bump(segments, segments.length));
1954
+ }
1955
+ const target = pad(segments);
1956
+ switch (operator) {
1957
+ case "^": {
1958
+ const position = segments[0] !== 0 || segments.length < 2 ? 1 : segments[1] !== 0 || segments.length < 3 ? 2 : 3;
1959
+ return inRange(version, target, bump(segments, position));
1960
+ }
1961
+ case "~":
1962
+ return inRange(version, target, bump(segments, Math.max(1, segments.length - 1)));
1963
+ case ">=":
1964
+ return compare(version, target) >= 0;
1965
+ case ">":
1966
+ return compare(version, target) > 0;
1967
+ case "<=":
1968
+ return compare(version, target) <= 0;
1969
+ case "<":
1970
+ return compare(version, target) < 0;
1971
+ case "!=":
1972
+ case "<>":
1973
+ return compare(version, target) !== 0;
1974
+ default:
1975
+ return compare(version, target) === 0;
1976
+ }
1977
+ };
1978
+ var allowsHyphenRange = (from, to, version) => {
1979
+ const lower = parseVersion(from);
1980
+ const upper = parseVersion(to);
1981
+ if (!lower || !upper || lower.wildcard || upper.wildcard) {
1982
+ return void 0;
1983
+ }
1984
+ const withinUpper = upper.segments.length >= 3 ? compare(version, pad(upper.segments)) <= 0 : compare(version, bump(upper.segments, upper.segments.length)) < 0;
1985
+ return compare(version, pad(lower.segments)) >= 0 && withinUpper;
1986
+ };
1987
+ var allowsAll = (branch, version) => {
1988
+ const tokens = branch.trim().replace(/([<>=!~^]+)\s+/g, "$1").split(/\s*,\s*|\s+/).filter((token) => token !== "");
1989
+ if (tokens.length === 0) {
1990
+ return void 0;
1991
+ }
1992
+ let allowed = true;
1993
+ for (let index = 0; index < tokens.length; index++) {
1994
+ let result;
1995
+ if (tokens[index + 1] === "-") {
1996
+ const to = tokens[index + 2];
1997
+ result = to === void 0 ? void 0 : allowsHyphenRange(tokens[index], to, version);
1998
+ index += 2;
1999
+ } else {
2000
+ result = allowsAtom(tokens[index], version);
2001
+ }
2002
+ if (result === void 0) {
2003
+ return void 0;
2004
+ }
2005
+ allowed &&= result;
2006
+ }
2007
+ return allowed;
2008
+ };
2009
+ var composerConstraintAllows = (constraint, version) => {
2010
+ const parsed = parseVersion(version);
2011
+ if (!parsed || parsed.wildcard || parsed.segments.length === 0) {
2012
+ return void 0;
2013
+ }
2014
+ const target = pad(parsed.segments);
2015
+ let allowed = false;
2016
+ for (const branch of constraint.replace(/@[a-z]+/gi, "").split(/\|\|?/)) {
2017
+ const result = allowsAll(branch, target);
2018
+ if (result === void 0) {
2019
+ return void 0;
2020
+ }
2021
+ allowed ||= result;
2022
+ }
2023
+ return allowed;
2024
+ };
2025
+
2026
+ // src/detection/frameworks/php-runtime.ts
2027
+ var PHP_RUNTIME_CANDIDATES = [
2028
+ { runtime: "php-84", newestVersion: "8.4.9999" },
2029
+ { runtime: "php-83", newestVersion: "8.3.9999" }
2030
+ ];
2031
+ var phpRuntimeForConstraint = (constraint) => PHP_RUNTIME_CANDIDATES.find(({ newestVersion }) => composerConstraintAllows(constraint, newestVersion) === true)?.runtime;
2032
+ var readPhpConstraint = Effect11.fn("readPhpConstraint")(
2033
+ function* (projectFolder) {
2034
+ const fs = yield* FileSystem11.FileSystem;
2035
+ const pathService = yield* Path9.Path;
2036
+ const content = yield* fs.readFileString(pathService.join(projectFolder, "composer.json"));
2037
+ const manifest = yield* Effect11.try(() => JSON.parse(content));
2038
+ const requires = manifest && typeof manifest === "object" && "require" in manifest ? manifest.require : void 0;
2039
+ const php = requires && typeof requires === "object" && "php" in requires ? requires.php : void 0;
2040
+ return typeof php === "string" ? Option3.some(php) : Option3.none();
2041
+ },
2042
+ Effect11.catchAll(() => Effect11.succeed(Option3.none()))
2043
+ );
2044
+ var refineComposerPhpRuntime = Effect11.fn("refineComposerPhpRuntime")(function* (defaults, projectFolder) {
2045
+ const constraint = yield* readPhpConstraint(projectFolder);
2046
+ const runtime = Option3.getOrUndefined(Option3.flatMapNullable(constraint, phpRuntimeForConstraint));
2047
+ return runtime ? { ...defaults, runtime } : defaults;
2048
+ });
2049
+ var withComposerPhpRuntime = (framework) => ({
2050
+ ...framework,
2051
+ refineDefaultConfig: (defaults, projectFolder) => Effect11.gen(function* () {
2052
+ const refined = framework.refineDefaultConfig ? yield* framework.refineDefaultConfig(defaults, projectFolder) : defaults;
2053
+ return yield* refineComposerPhpRuntime(refined, projectFolder);
2054
+ })
2055
+ });
2056
+
1900
2057
  // src/detection/frameworks/remix.ts
1901
2058
  var remix = {
1902
2059
  slug: "remix",
@@ -2045,10 +2202,10 @@ var FRAMEWORK_DEFINITIONS = [
2045
2202
  ...phpComposerProjects,
2046
2203
  ...phpSites,
2047
2204
  vite
2048
- ].sort((a, b) => b.priority - a.priority);
2205
+ ].map((framework) => framework.language === "php" ? withComposerPhpRuntime(framework) : framework).sort((a, b) => b.priority - a.priority);
2049
2206
 
2050
2207
  // src/detection/generate-config.ts
2051
- import { Effect as Effect11 } from "effect";
2208
+ import { Effect as Effect12 } from "effect";
2052
2209
  var getInstallCommand = (pm) => {
2053
2210
  switch (pm) {
2054
2211
  case "bun":
@@ -2069,11 +2226,11 @@ var isPrivatePhpProjectFile = (projectPath) => {
2069
2226
  const segments = projectPath.split("/").filter((segment) => segment !== "" && segment !== ".");
2070
2227
  return segments.some((segment) => segment.startsWith(".")) || segments[0] === "vendor" || segments[0] === "node_modules" || segments.length === 1 && COMPOSER_ROOT_FILES.has(segments[0] ?? "");
2071
2228
  };
2072
- var generateConfig = Effect11.fn("generateConfig")(function* (framework, packageManager, projectFolder, refinedDefaults) {
2229
+ var generateConfig = Effect12.fn("generateConfig")(function* (framework, packageManager, projectFolder, refinedDefaults) {
2073
2230
  const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
2074
2231
  const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
2075
2232
  const commands = installCmd ? [installCmd, ...defaults.commands] : [...defaults.commands];
2076
- yield* Effect11.logDebug(`Generating config for ${framework.name}`, {
2233
+ yield* Effect12.logDebug(`Generating config for ${framework.name}`, {
2077
2234
  runtime: defaults.runtime,
2078
2235
  entrypoint: defaults.entrypoint,
2079
2236
  commands
@@ -2139,8 +2296,8 @@ var generateConfig = Effect11.fn("generateConfig")(function* (framework, package
2139
2296
  });
2140
2297
 
2141
2298
  // src/detection/read-dependencies.ts
2142
- import { FileSystem as FileSystem11, Path as Path9 } from "@effect/platform";
2143
- import { Effect as Effect13 } from "effect";
2299
+ import { FileSystem as FileSystem12, Path as Path10 } from "@effect/platform";
2300
+ import { Effect as Effect14 } from "effect";
2144
2301
 
2145
2302
  // src/detection/types.ts
2146
2303
  import { Schema as Schema5 } from "effect";
@@ -2173,25 +2330,25 @@ var MANIFEST_CONFIG = {
2173
2330
  node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
2174
2331
  php: { file: "composer.json", depKeys: ["require", "require-dev"] }
2175
2332
  };
2176
- var readManifest = Effect13.fn("readManifest")(function* (filePath) {
2177
- const fs = yield* FileSystem11.FileSystem;
2178
- const exists = yield* fs.exists(filePath).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
2333
+ var readManifest = Effect14.fn("readManifest")(function* (filePath) {
2334
+ const fs = yield* FileSystem12.FileSystem;
2335
+ const exists = yield* fs.exists(filePath).pipe(Effect14.catchAll(() => Effect14.succeed(false)));
2179
2336
  if (!exists) {
2180
- return yield* Effect13.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
2337
+ return yield* Effect14.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
2181
2338
  }
2182
- const content = yield* fs.readFileString(filePath).pipe(Effect13.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
2183
- const parsed = yield* Effect13.try({
2339
+ const content = yield* fs.readFileString(filePath).pipe(Effect14.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
2340
+ const parsed = yield* Effect14.try({
2184
2341
  try: () => JSON.parse(content),
2185
2342
  catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
2186
2343
  });
2187
2344
  return parsed;
2188
2345
  });
2189
- var readDependencies = Effect13.fn("readDependencies")(function* (projectFolder, language) {
2190
- const pathService = yield* Path9.Path;
2346
+ var readDependencies = Effect14.fn("readDependencies")(function* (projectFolder, language) {
2347
+ const pathService = yield* Path10.Path;
2191
2348
  const config = MANIFEST_CONFIG[language];
2192
2349
  const filePath = pathService.join(projectFolder, config.file);
2193
2350
  const manifest = yield* readManifest(filePath).pipe(
2194
- Effect13.catchTag("ManifestNotFoundError", () => Effect13.succeed(null))
2351
+ Effect14.catchTag("ManifestNotFoundError", () => Effect14.succeed(null))
2195
2352
  );
2196
2353
  if (!manifest) {
2197
2354
  return /* @__PURE__ */ new Set();
@@ -2209,9 +2366,9 @@ var readDependencies = Effect13.fn("readDependencies")(function* (projectFolder,
2209
2366
  });
2210
2367
 
2211
2368
  // src/detection/detect-framework.ts
2212
- var matchesDetectionItem = Effect14.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
2213
- const fs = yield* FileSystem12.FileSystem;
2214
- const pathService = yield* Path10.Path;
2369
+ var matchesDetectionItem = Effect15.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
2370
+ const fs = yield* FileSystem13.FileSystem;
2371
+ const pathService = yield* Path11.Path;
2215
2372
  if (item.matchPackage != null) {
2216
2373
  const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
2217
2374
  if (!deps.has(item.matchPackage)) {
@@ -2220,12 +2377,12 @@ var matchesDetectionItem = Effect14.fn("matchesDetectionItem")(function* (item,
2220
2377
  }
2221
2378
  if (item.path != null) {
2222
2379
  const filePath = pathService.join(projectFolder, item.path);
2223
- const exists = yield* fs.exists(filePath).pipe(Effect14.catchAll(() => Effect14.succeed(false)));
2380
+ const exists = yield* fs.exists(filePath).pipe(Effect15.catchAll(() => Effect15.succeed(false)));
2224
2381
  if (!exists) {
2225
2382
  return false;
2226
2383
  }
2227
2384
  if (item.matchContent != null) {
2228
- const content = yield* fs.readFileString(filePath).pipe(Effect14.catchAll(() => Effect14.succeed("")));
2385
+ const content = yield* fs.readFileString(filePath).pipe(Effect15.catchAll(() => Effect15.succeed("")));
2229
2386
  let regexMatch = false;
2230
2387
  try {
2231
2388
  regexMatch = new RegExp(item.matchContent).test(content);
@@ -2238,7 +2395,7 @@ var matchesDetectionItem = Effect14.fn("matchesDetectionItem")(function* (item,
2238
2395
  }
2239
2396
  return true;
2240
2397
  });
2241
- var matchesFramework = Effect14.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
2398
+ var matchesFramework = Effect15.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
2242
2399
  for (const detector of framework.detectors) {
2243
2400
  const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
2244
2401
  if (!matches) {
@@ -2247,9 +2404,9 @@ var matchesFramework = Effect14.fn("matchesFramework")(function* (framework, pro
2247
2404
  }
2248
2405
  return true;
2249
2406
  });
2250
- var detectFramework = Effect14.fn("detectFramework")(function* (projectFolder) {
2251
- yield* Effect14.logDebug(`Detecting framework in ${projectFolder}`);
2252
- const cachedReadDeps = yield* Effect14.cachedFunction((key) => {
2407
+ var detectFramework = Effect15.fn("detectFramework")(function* (projectFolder) {
2408
+ yield* Effect15.logDebug(`Detecting framework in ${projectFolder}`);
2409
+ const cachedReadDeps = yield* Effect15.cachedFunction((key) => {
2253
2410
  const sepIndex = key.lastIndexOf("\0");
2254
2411
  const folder = key.slice(0, sepIndex);
2255
2412
  const language = key.slice(sepIndex + 1);
@@ -2258,7 +2415,7 @@ var detectFramework = Effect14.fn("detectFramework")(function* (projectFolder) {
2258
2415
  for (const framework of FRAMEWORK_DEFINITIONS) {
2259
2416
  const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
2260
2417
  if (matches) {
2261
- yield* Effect14.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
2418
+ yield* Effect15.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
2262
2419
  const detectedPackageManager = yield* detectPackageManager(projectFolder);
2263
2420
  const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
2264
2421
  const defaults = framework.getDefaultConfig(packageManager);
@@ -2267,7 +2424,7 @@ var detectFramework = Effect14.fn("detectFramework")(function* (projectFolder) {
2267
2424
  return { framework, packageManager, config };
2268
2425
  }
2269
2426
  }
2270
- return yield* Effect14.fail(
2427
+ return yield* Effect15.fail(
2271
2428
  new FrameworkNotDetectedError({
2272
2429
  message: `No framework detected in project directory`,
2273
2430
  directory: projectFolder
@@ -2276,9 +2433,9 @@ var detectFramework = Effect14.fn("detectFramework")(function* (projectFolder) {
2276
2433
  });
2277
2434
 
2278
2435
  // src/detection/merge-config.ts
2279
- import { Effect as Effect15 } from "effect";
2280
- var mergeWithFrameworkDefaults = Effect15.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
2281
- yield* Effect15.logDebug("Merging user config with framework defaults");
2436
+ import { Effect as Effect16 } from "effect";
2437
+ var mergeWithFrameworkDefaults = Effect16.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
2438
+ yield* Effect16.logDebug("Merging user config with framework defaults");
2282
2439
  const userHasAssets = (userConfig.assets?.paths?.length ?? 0) > 0 || (userConfig.assets?.prefixes?.length ?? 0) > 0 || (userConfig.assets?.manifests?.length ?? 0) > 0;
2283
2440
  const isContainer = (entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME;
2284
2441
  const userFileFunctions = userConfig.entrypoints.filter((entrypoint) => !isContainer(entrypoint));
@@ -2319,23 +2476,23 @@ var filterFunctionsFromAssets = (config) => {
2319
2476
  };
2320
2477
 
2321
2478
  // src/parse-config.ts
2322
- import { Effect as Effect21 } from "effect";
2479
+ import { Effect as Effect22 } from "effect";
2323
2480
 
2324
2481
  // src/services/raw-config-reader.ts
2325
- import { FileSystem as FileSystem13, Path as Path11 } from "@effect/platform";
2326
- import { Effect as Effect17 } from "effect";
2482
+ import { FileSystem as FileSystem14, Path as Path12 } from "@effect/platform";
2483
+ import { Effect as Effect18 } from "effect";
2327
2484
  import { parse as parseYaml2 } from "yaml";
2328
2485
 
2329
2486
  // src/services/config-module-loader.ts
2330
- import { Effect as Effect16 } from "effect";
2487
+ import { Effect as Effect17 } from "effect";
2331
2488
  import { createJiti } from "jiti";
2332
2489
  var MISSING_DEFAULT_EXPORT = /* @__PURE__ */ Symbol("MissingDefaultExport");
2333
2490
  var STRICT_DEFAULT_EXPORT_EXTENSIONS = [".ts", ".mts", ".mjs"];
2334
- var ConfigModuleLoader = class extends Effect16.Service()("ConfigModuleLoader", {
2335
- effect: Effect16.gen(function* () {
2336
- const loadConfigModule = Effect16.fn("ConfigModuleLoader.loadConfigModule")(function* (filePath) {
2491
+ var ConfigModuleLoader = class extends Effect17.Service()("ConfigModuleLoader", {
2492
+ effect: Effect17.gen(function* () {
2493
+ const loadConfigModule = Effect17.fn("ConfigModuleLoader.loadConfigModule")(function* (filePath) {
2337
2494
  const extension = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
2338
- const mod = yield* Effect16.tryPromise({
2495
+ const mod = yield* Effect17.tryPromise({
2339
2496
  try: async () => {
2340
2497
  const jiti = createJiti(filePath, { fsCache: false, interopDefault: true, moduleCache: false });
2341
2498
  const namespace = await jiti.import(filePath);
@@ -2354,7 +2511,7 @@ var ConfigModuleLoader = class extends Effect16.Service()("ConfigModuleLoader",
2354
2511
  })
2355
2512
  });
2356
2513
  if (mod === MISSING_DEFAULT_EXPORT) {
2357
- return yield* Effect16.fail(
2514
+ return yield* Effect17.fail(
2358
2515
  new ConfigModuleLoadError({
2359
2516
  message: `Config module at ${filePath} does not have a default export. Export the config object as the default export (or via module.exports for CommonJS files), optionally wrapped in defineConfig.`,
2360
2517
  filePath
@@ -2362,7 +2519,7 @@ var ConfigModuleLoader = class extends Effect16.Service()("ConfigModuleLoader",
2362
2519
  );
2363
2520
  }
2364
2521
  if (typeof mod === "function") {
2365
- return yield* Effect16.fail(
2522
+ return yield* Effect17.fail(
2366
2523
  new ConfigModuleLoadError({
2367
2524
  message: `Config module at ${filePath} default-exports a function; config factories are not supported. Export a config object instead (optionally wrapped in defineConfig).`,
2368
2525
  filePath
@@ -2370,7 +2527,7 @@ var ConfigModuleLoader = class extends Effect16.Service()("ConfigModuleLoader",
2370
2527
  );
2371
2528
  }
2372
2529
  if (typeof mod !== "object" || mod === null || Array.isArray(mod)) {
2373
- return yield* Effect16.fail(
2530
+ return yield* Effect17.fail(
2374
2531
  new ConfigModuleLoadError({
2375
2532
  message: `Config module at ${filePath} must default-export a config object.`,
2376
2533
  filePath
@@ -2400,36 +2557,36 @@ var ALLOWED_CONFIG_NAMES = [
2400
2557
  "nebula.json"
2401
2558
  ];
2402
2559
  var MODULE_EXTENSIONS = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
2403
- var RawConfigReader = class extends Effect17.Service()("RawConfigReader", {
2560
+ var RawConfigReader = class extends Effect18.Service()("RawConfigReader", {
2404
2561
  dependencies: [ConfigModuleLoader.Default],
2405
- effect: Effect17.gen(function* () {
2406
- const fs = yield* FileSystem13.FileSystem;
2407
- const pathService = yield* Path11.Path;
2562
+ effect: Effect18.gen(function* () {
2563
+ const fs = yield* FileSystem14.FileSystem;
2564
+ const pathService = yield* Path12.Path;
2408
2565
  const moduleLoader = yield* ConfigModuleLoader;
2409
- const findConfig = Effect17.fn("RawConfigReader.findConfig")(function* (projectFolder) {
2566
+ const findConfig = Effect18.fn("RawConfigReader.findConfig")(function* (projectFolder) {
2410
2567
  for (const name of ALLOWED_CONFIG_NAMES) {
2411
2568
  const filePath = pathService.join(projectFolder, name);
2412
- const exists = yield* fs.exists(filePath).pipe(Effect17.catchAll(() => Effect17.succeed(false)));
2569
+ const exists = yield* fs.exists(filePath).pipe(Effect18.catchAll(() => Effect18.succeed(false)));
2413
2570
  if (exists) {
2414
2571
  return filePath;
2415
2572
  }
2416
2573
  }
2417
2574
  return null;
2418
2575
  });
2419
- const readRawConfig = Effect17.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
2420
- const exists = yield* fs.exists(filePath).pipe(Effect17.catchAll(() => Effect17.succeed(false)));
2576
+ const readRawConfig = Effect18.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
2577
+ const exists = yield* fs.exists(filePath).pipe(Effect18.catchAll(() => Effect18.succeed(false)));
2421
2578
  if (!exists) {
2422
- return yield* Effect17.fail(
2579
+ return yield* Effect18.fail(
2423
2580
  new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
2424
2581
  );
2425
2582
  }
2426
2583
  const fileContents = yield* fs.readFileString(filePath).pipe(
2427
- Effect17.mapError(
2584
+ Effect18.mapError(
2428
2585
  () => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
2429
2586
  )
2430
2587
  );
2431
2588
  if (fileContents.length === 0) {
2432
- return yield* Effect17.fail(
2589
+ return yield* Effect18.fail(
2433
2590
  new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
2434
2591
  );
2435
2592
  }
@@ -2445,7 +2602,7 @@ var RawConfigReader = class extends Effect17.Service()("RawConfigReader", {
2445
2602
  parsed = parseYaml2(fileContents);
2446
2603
  }
2447
2604
  } catch (error) {
2448
- return yield* Effect17.fail(
2605
+ return yield* Effect18.fail(
2449
2606
  new ConfigFileParseError({
2450
2607
  message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
2451
2608
  filePath,
@@ -2455,21 +2612,21 @@ var RawConfigReader = class extends Effect17.Service()("RawConfigReader", {
2455
2612
  }
2456
2613
  }
2457
2614
  if (parsed == null) {
2458
- return yield* Effect17.fail(
2615
+ return yield* Effect18.fail(
2459
2616
  new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
2460
2617
  );
2461
2618
  }
2462
2619
  if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
2463
- return yield* Effect17.fail(
2620
+ return yield* Effect18.fail(
2464
2621
  new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
2465
2622
  );
2466
2623
  }
2467
2624
  return parsed;
2468
2625
  });
2469
2626
  const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
2470
- Effect17.map((parsed) => parsed),
2471
- Effect17.catchTag("ConfigFileNotFoundError", () => Effect17.succeed(null)),
2472
- Effect17.withSpan("RawConfigReader.readConfigFile")
2627
+ Effect18.map((parsed) => parsed),
2628
+ Effect18.catchTag("ConfigFileNotFoundError", () => Effect18.succeed(null)),
2629
+ Effect18.withSpan("RawConfigReader.readConfigFile")
2473
2630
  );
2474
2631
  return { findConfig, readRawConfig, readConfigFile };
2475
2632
  })
@@ -2479,17 +2636,17 @@ var RawConfigReader = class extends Effect17.Service()("RawConfigReader", {
2479
2636
  // src/services/schema-validator.ts
2480
2637
  import Ajv from "ajv";
2481
2638
  import addFormats from "ajv-formats";
2482
- import { Effect as Effect18 } from "effect";
2483
- var SchemaValidator = class extends Effect18.Service()("SchemaValidator", {
2484
- effect: Effect18.gen(function* () {
2639
+ import { Effect as Effect19 } from "effect";
2640
+ var SchemaValidator = class extends Effect19.Service()("SchemaValidator", {
2641
+ effect: Effect19.gen(function* () {
2485
2642
  const ajv = new Ajv();
2486
2643
  addFormats(ajv);
2487
- const validate = Effect18.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
2644
+ const validate = Effect19.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
2488
2645
  const compiledValidate = ajv.compile(schema);
2489
2646
  const valid = compiledValidate(config);
2490
2647
  if (!valid) {
2491
2648
  const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
2492
- return yield* Effect18.fail(
2649
+ return yield* Effect19.fail(
2493
2650
  new ConfigSchemaValidationError({
2494
2651
  message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
2495
2652
  filePath,
@@ -2545,7 +2702,7 @@ var getFilesForPattern = async (pattern, projectFolder, excludeFiles = []) => {
2545
2702
  };
2546
2703
 
2547
2704
  // src/services/v4-config-parser.ts
2548
- import { Effect as Effect19 } from "effect";
2705
+ import { Effect as Effect20 } from "effect";
2549
2706
  import { minimatch as minimatch2 } from "minimatch";
2550
2707
  import { posix as posix2 } from "path";
2551
2708
  import safeRegex from "safe-regex2";
@@ -2696,7 +2853,7 @@ var mapRoute = (route, entrypoints) => ({
2696
2853
  negativeRequirements: route.missing,
2697
2854
  status: route.statusCode
2698
2855
  });
2699
- var parseEntrypoints = Effect19.fn("parseEntrypoints")(function* (config, projectFolder) {
2856
+ var parseEntrypoints = Effect20.fn("parseEntrypoints")(function* (config, projectFolder) {
2700
2857
  const entrypoints = [];
2701
2858
  const dockerFunctions = [];
2702
2859
  if (config.functions == null) return { entrypoints, dockerFunctions };
@@ -2707,7 +2864,7 @@ var parseEntrypoints = Effect19.fn("parseEntrypoints")(function* (config, projec
2707
2864
  functionPath: fnPath
2708
2865
  });
2709
2866
  }
2710
- const matchedFiles = yield* Effect19.tryPromise({
2867
+ const matchedFiles = yield* Effect20.tryPromise({
2711
2868
  try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
2712
2869
  catch: (error) => new FunctionConfigError({
2713
2870
  message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
@@ -2782,13 +2939,13 @@ var parseEntrypoints = Effect19.fn("parseEntrypoints")(function* (config, projec
2782
2939
  }
2783
2940
  return { entrypoints, dockerFunctions };
2784
2941
  });
2785
- var collectAssets = Effect19.fn("collectAssets")(function* (config, projectFolder) {
2942
+ var collectAssets = Effect20.fn("collectAssets")(function* (config, projectFolder) {
2786
2943
  if (config.assets == null) return [];
2787
2944
  const assetNames = yield* collectAssetFiles(projectFolder, config.assets);
2788
2945
  return assetNames.filter((assetName) => getFunctionSettings(`${config.assets}/${assetName}`, config) == null).map((assetName) => `${config.assets}/${assetName}`);
2789
2946
  });
2790
2947
  var reservedRuntimePorts = (entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME ? [] : entrypoint.runtime.startsWith("php-") ? [8080, 9e3] : [8080];
2791
- var parseContainers = Effect19.fn("parseContainers")(function* (config, projectFolder, fileEntrypoints, dockerFunctions) {
2948
+ var parseContainers = Effect20.fn("parseContainers")(function* (config, projectFolder, fileEntrypoints, dockerFunctions) {
2792
2949
  const warnings = [];
2793
2950
  let containers = {};
2794
2951
  if (config.compose != null) {
@@ -2821,16 +2978,16 @@ var parseContainers = Effect19.fn("parseContainers")(function* (config, projectF
2821
2978
  }
2822
2979
  return { ...result, warnings };
2823
2980
  });
2824
- var V4ConfigParser = class extends Effect19.Service()("V4ConfigParser", {
2981
+ var V4ConfigParser = class extends Effect20.Service()("V4ConfigParser", {
2825
2982
  accessors: true,
2826
- effect: Effect19.succeed({
2983
+ effect: Effect20.succeed({
2827
2984
  /**
2828
2985
  * Parses a ConfigV4 into a NormalizedConfig.
2829
2986
  *
2830
2987
  * @param config - The raw V4 config object
2831
2988
  * @param projectFolder - Absolute path to the project root
2832
2989
  */
2833
- parse: Effect19.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
2990
+ parse: Effect20.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
2834
2991
  const { entrypoints: fileEntrypoints, dockerFunctions } = yield* parseEntrypoints(config, projectFolder);
2835
2992
  const containers = yield* parseContainers(config, projectFolder, fileEntrypoints, dockerFunctions);
2836
2993
  const entrypoints = [...fileEntrypoints, ...containers.entrypoints];
@@ -2872,7 +3029,7 @@ var V4ConfigParser = class extends Effect19.Service()("V4ConfigParser", {
2872
3029
  };
2873
3030
 
2874
3031
  // src/services/vercel-build-output-parser.ts
2875
- import { Path as Path12 } from "@effect/platform";
3032
+ import { Path as Path13 } from "@effect/platform";
2876
3033
 
2877
3034
  // ../commons/src/deep-merge.ts
2878
3035
  var deepMerge = (target, ...partials) => {
@@ -2901,7 +3058,7 @@ var deepMerge = (target, ...partials) => {
2901
3058
  };
2902
3059
 
2903
3060
  // src/services/vercel-build-output-parser.ts
2904
- import { Effect as Effect20 } from "effect";
3061
+ import { Effect as Effect21 } from "effect";
2905
3062
 
2906
3063
  // src/build-output-v3/determine-repo-root.ts
2907
3064
  import path from "path";
@@ -2997,11 +3154,11 @@ var translateVercelRuntime = (runtime) => {
2997
3154
  var CONFIG_PATH = ".vercel/output/config.json";
2998
3155
  var FUNCTIONS_FOLDER = ".vercel/output/functions";
2999
3156
  var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
3000
- var VercelBuildOutputParser = class extends Effect20.Service()("VercelBuildOutputParser", {
3001
- effect: Effect20.gen(function* () {
3157
+ var VercelBuildOutputParser = class extends Effect21.Service()("VercelBuildOutputParser", {
3158
+ effect: Effect21.gen(function* () {
3002
3159
  const rawConfigReader = yield* RawConfigReader;
3003
- const pathService = yield* Path12.Path;
3004
- const parse = Effect20.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
3160
+ const pathService = yield* Path13.Path;
3161
+ const parse = Effect21.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
3005
3162
  const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
3006
3163
  if (!config || typeof config.version !== "number" || config.version < 3) {
3007
3164
  return parseResult;
@@ -3013,8 +3170,8 @@ var VercelBuildOutputParser = class extends Effect20.Service()("VercelBuildOutpu
3013
3170
  merged.regions = [...new Set(merged.regions)];
3014
3171
  return merged;
3015
3172
  });
3016
- const loadFunctions = Effect20.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
3017
- const functionConfigs = yield* Effect20.tryPromise({
3173
+ const loadFunctions = Effect21.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
3174
+ const functionConfigs = yield* Effect21.tryPromise({
3018
3175
  try: () => getFilesForPattern(FUNCTION_CONFIGS_PATTERN, projectFolder),
3019
3176
  catch: (error) => new ConfigFileParseError({
3020
3177
  message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
@@ -3931,7 +4088,7 @@ var schema_default = {
3931
4088
  };
3932
4089
 
3933
4090
  // src/parse-config.ts
3934
- var parseConfigRaw = Effect21.fn("parseConfigRaw")(function* (filePath, projectFolder) {
4091
+ var parseConfigRaw = Effect22.fn("parseConfigRaw")(function* (filePath, projectFolder) {
3935
4092
  const rawReader = yield* RawConfigReader;
3936
4093
  const validator = yield* SchemaValidator;
3937
4094
  const v4Parser = yield* V4ConfigParser;
@@ -3942,7 +4099,7 @@ var parseConfigRaw = Effect21.fn("parseConfigRaw")(function* (filePath, projectF
3942
4099
  };
3943
4100
  const schema = schemaMap[version];
3944
4101
  if (!schema) {
3945
- return yield* Effect21.fail(
4102
+ return yield* Effect22.fail(
3946
4103
  new ConfigVersionError({
3947
4104
  message: `Config file at ${filePath} has an unsupported version: ${version}`,
3948
4105
  filePath,
@@ -3953,11 +4110,11 @@ var parseConfigRaw = Effect21.fn("parseConfigRaw")(function* (filePath, projectF
3953
4110
  yield* validator.validate(parsed, schema, filePath);
3954
4111
  return yield* v4Parser.parse(parsed, projectFolder);
3955
4112
  });
3956
- var parseConfig = Effect21.fn("parseConfig")(function* (filePath, projectFolder) {
4113
+ var parseConfig = Effect22.fn("parseConfig")(function* (filePath, projectFolder) {
3957
4114
  const parseResult = yield* parseConfigRaw(filePath, projectFolder);
3958
4115
  return yield* postProcessConfig(parseResult, projectFolder);
3959
4116
  });
3960
- var postProcessConfig = Effect21.fn("postProcessConfig")(function* (config, projectFolder) {
4117
+ var postProcessConfig = Effect22.fn("postProcessConfig")(function* (config, projectFolder) {
3961
4118
  const vercelParser = yield* VercelBuildOutputParser;
3962
4119
  let result = yield* vercelParser.parse(config, projectFolder);
3963
4120
  const hasAssets = (result.assets?.paths?.length ?? 0) > 0 || (result.assets?.prefixes?.length ?? 0) > 0 || (result.assets?.manifests?.length ?? 0) > 0;