@gigadrive/network-config 3.2.0 → 3.3.1

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
@@ -1,6 +1,6 @@
1
1
  // src/detection/detect-framework.ts
2
- import { FileSystem as FileSystem4, Path as Path3 } from "@effect/platform";
3
- import { Effect as Effect6 } from "effect";
2
+ import { FileSystem as FileSystem7, Path as Path5 } from "@effect/platform";
3
+ import { Effect as Effect9 } from "effect";
4
4
 
5
5
  // src/detection/detect-package-manager.ts
6
6
  import { FileSystem, Path } from "@effect/platform";
@@ -220,6 +220,141 @@ var nestjs = {
220
220
  };
221
221
 
222
222
  // src/detection/frameworks/nextjs.ts
223
+ import { FileSystem as FileSystem4, Path as Path3 } from "@effect/platform";
224
+ import { Effect as Effect4 } from "effect";
225
+
226
+ // src/build-output-v3/get-default-path-map.ts
227
+ import { FileSystem as FileSystem3, Path as Path2 } from "@effect/platform";
228
+ import { Effect as Effect3 } from "effect";
229
+ var getDefaultPathMap = Effect3.fn("getDefaultPathMap")(function* (directory) {
230
+ const fs = yield* FileSystem3.FileSystem;
231
+ const pathService = yield* Path2.Path;
232
+ const result = {};
233
+ const exists = yield* fs.exists(directory).pipe(Effect3.catchAll(() => Effect3.succeed(false)));
234
+ if (!exists) {
235
+ return result;
236
+ }
237
+ const MAX_DEPTH = 100;
238
+ const processDirectory = (currentPath, basePath = "", depth = 0) => Effect3.gen(function* () {
239
+ if (depth > MAX_DEPTH) return;
240
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect3.catchAll(() => Effect3.succeed([])));
241
+ for (const name of entries) {
242
+ const fullPath = pathService.join(currentPath, name);
243
+ const relativePath = basePath ? pathService.join(basePath, name) : name;
244
+ const stat = yield* fs.stat(fullPath).pipe(Effect3.catchAll(() => Effect3.succeed(null)));
245
+ if (!stat) continue;
246
+ if (stat.type === "Directory") {
247
+ yield* processDirectory(fullPath, relativePath, depth + 1);
248
+ } else {
249
+ result[fullPath] = relativePath;
250
+ }
251
+ }
252
+ });
253
+ yield* processDirectory(directory);
254
+ return result;
255
+ });
256
+
257
+ // src/detection/frameworks/nextjs.ts
258
+ var isRecord2 = (value) => typeof value === "object" && value !== null;
259
+ var normalizeRelativePath = (value, allowCurrentDirectory = false) => {
260
+ const normalized = value.replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/+$/, "");
261
+ if (!allowCurrentDirectory && (!normalized || normalized === ".") || normalized.startsWith("/") || /^[A-Za-z]:/.test(normalized) || normalized.includes(":") || normalized.split("/").some((segment) => segment === "..")) {
262
+ return void 0;
263
+ }
264
+ return normalized || ".";
265
+ };
266
+ var parseBuildManifest = (content) => {
267
+ try {
268
+ const value = JSON.parse(content);
269
+ if (!isRecord2(value) || value.version !== 1 || value.output !== "standalone" && value.output !== "export" || typeof value.distDir !== "string" || typeof value.repoRootToProject !== "string") {
270
+ return void 0;
271
+ }
272
+ const distDir = normalizeRelativePath(value.distDir);
273
+ const repoRootToProject = normalizeRelativePath(value.repoRootToProject, true);
274
+ return distDir && repoRootToProject ? { version: 1, output: value.output, distDir, repoRootToProject } : void 0;
275
+ } catch {
276
+ return void 0;
277
+ }
278
+ };
279
+ var toPortablePath = (value) => value.replaceAll("\\", "/");
280
+ var createStaticExportConfig = Effect4.fn("nextjs.createStaticExportConfig")(function* (defaults, projectFolder) {
281
+ const pathService = yield* Path3.Path;
282
+ const outputDirectory = pathService.join(projectFolder, "out");
283
+ const files = yield* getDefaultPathMap(outputDirectory);
284
+ const assetPaths = [];
285
+ const assetOverrides = {};
286
+ for (const absolutePath of Object.keys(files)) {
287
+ const projectRelativePath = toPortablePath(pathService.relative(projectFolder, absolutePath));
288
+ const outputRelativePath = toPortablePath(pathService.relative(outputDirectory, absolutePath));
289
+ assetPaths.push(projectRelativePath);
290
+ const routePath = outputRelativePath === "index.html" ? "" : outputRelativePath.endsWith("/index.html") ? outputRelativePath.slice(0, -"/index.html".length) : outputRelativePath;
291
+ assetOverrides[projectRelativePath] = { path: routePath };
292
+ }
293
+ return {
294
+ ...defaults,
295
+ entrypoint: void 0,
296
+ routes: [],
297
+ assetsDir: "out",
298
+ assetsPrefixToStrip: "",
299
+ assetPaths,
300
+ assetOverrides,
301
+ package: void 0
302
+ };
303
+ });
304
+ var createStandaloneConfig = Effect4.fn("nextjs.createStandaloneConfig")(function* (defaults, projectFolder, manifest) {
305
+ const fs = yield* FileSystem4.FileSystem;
306
+ const pathService = yield* Path3.Path;
307
+ const standaloneRoot = pathService.join(projectFolder, manifest.distDir, "standalone");
308
+ const monorepoServer = pathService.join(standaloneRoot, manifest.repoRootToProject, "server.js");
309
+ const rootServer = pathService.join(standaloneRoot, "server.js");
310
+ const monorepoServerExists = yield* fs.exists(monorepoServer).pipe(Effect4.catchAll(() => Effect4.succeed(false)));
311
+ const serverPath = monorepoServerExists ? monorepoServer : rootServer;
312
+ const serverExists = yield* fs.exists(serverPath).pipe(Effect4.catchAll(() => Effect4.succeed(false)));
313
+ if (!serverExists) return defaults;
314
+ const serverDirectory = pathService.dirname(serverPath);
315
+ const entrypoint = toPortablePath(pathService.relative(standaloneRoot, serverPath));
316
+ const publicDirectory = pathService.join(projectFolder, "public");
317
+ const staticDirectory = pathService.join(projectFolder, manifest.distDir, "static");
318
+ const [publicFiles, staticFiles] = yield* Effect4.all([
319
+ getDefaultPathMap(publicDirectory),
320
+ getDefaultPathMap(staticDirectory)
321
+ ]);
322
+ const assetPaths = [];
323
+ const assetOverrides = {};
324
+ const filePathMap = {};
325
+ for (const [absolutePath, relativePath] of Object.entries(publicFiles)) {
326
+ const portableRelativePath = toPortablePath(relativePath);
327
+ const projectRelativePath = toPortablePath(pathService.relative(projectFolder, absolutePath));
328
+ assetPaths.push(projectRelativePath);
329
+ assetOverrides[projectRelativePath] = { path: portableRelativePath };
330
+ filePathMap[absolutePath] = toPortablePath(
331
+ pathService.relative(standaloneRoot, pathService.join(serverDirectory, "public", relativePath))
332
+ );
333
+ }
334
+ for (const [absolutePath, relativePath] of Object.entries(staticFiles)) {
335
+ const portableRelativePath = toPortablePath(relativePath);
336
+ const projectRelativePath = toPortablePath(pathService.relative(projectFolder, absolutePath));
337
+ assetPaths.push(projectRelativePath);
338
+ assetOverrides[projectRelativePath] = { path: `_next/static/${portableRelativePath}` };
339
+ filePathMap[absolutePath] = toPortablePath(
340
+ pathService.relative(standaloneRoot, pathService.join(serverDirectory, manifest.distDir, "static", relativePath))
341
+ );
342
+ }
343
+ return {
344
+ ...defaults,
345
+ entrypoint,
346
+ routes: [{ source: "/*", destination: entrypoint }],
347
+ assetsDir: manifest.distDir,
348
+ assetsPrefixToStrip: "",
349
+ assetPaths,
350
+ assetOverrides,
351
+ package: {
352
+ trace: false,
353
+ rootOverwrite: standaloneRoot,
354
+ filePathMap
355
+ }
356
+ };
357
+ });
223
358
  var nextjs = {
224
359
  slug: "nextjs",
225
360
  name: "Next.js",
@@ -237,10 +372,27 @@ var nextjs = {
237
372
  populateAssetCache: true,
238
373
  routes: [{ source: "/*", destination: ".next/standalone/server.js" }],
239
374
  environmentVariables: { NODE_ENV: "production" }
375
+ }),
376
+ refineDefaultConfig: (defaults, projectFolder) => Effect4.gen(function* () {
377
+ const fs = yield* FileSystem4.FileSystem;
378
+ const manifestContent = yield* fs.readFileString(`${projectFolder}/.gigadrive/nextjs.json`).pipe(Effect4.catchAll(() => Effect4.succeed(void 0)));
379
+ const manifest = manifestContent ? parseBuildManifest(manifestContent) : void 0;
380
+ if (!manifest) return defaults;
381
+ return manifest.output === "export" ? yield* createStaticExportConfig(defaults, projectFolder) : yield* createStandaloneConfig(defaults, projectFolder, manifest);
240
382
  })
241
383
  };
242
384
 
243
385
  // src/detection/frameworks/nuxt.ts
386
+ import { FileSystem as FileSystem5 } from "@effect/platform";
387
+ import { Effect as Effect5 } from "effect";
388
+ var isVercelBuildOutputV3 = (content) => {
389
+ try {
390
+ const config = JSON.parse(content);
391
+ return typeof config === "object" && config !== null && "version" in config && typeof config.version === "number" && config.version >= 3;
392
+ } catch {
393
+ return false;
394
+ }
395
+ };
244
396
  var nuxt = {
245
397
  slug: "nuxt",
246
398
  name: "Nuxt",
@@ -258,6 +410,20 @@ var nuxt = {
258
410
  populateAssetCache: true,
259
411
  routes: [{ source: "/*", destination: ".output/server/index.mjs" }],
260
412
  environmentVariables: { NODE_ENV: "production", NITRO_PRESET: "node-server" }
413
+ }),
414
+ refineDefaultConfig: (defaults, projectFolder) => Effect5.gen(function* () {
415
+ const fs = yield* FileSystem5.FileSystem;
416
+ const buildOutputConfig = yield* fs.readFileString(`${projectFolder}/.vercel/output/config.json`).pipe(Effect5.catchAll(() => Effect5.succeed(void 0)));
417
+ if (!buildOutputConfig || !isVercelBuildOutputV3(buildOutputConfig)) {
418
+ return defaults;
419
+ }
420
+ return {
421
+ ...defaults,
422
+ entrypoint: void 0,
423
+ assetsDir: ".vercel/output/static",
424
+ routes: [],
425
+ environmentVariables: { ...defaults.environmentVariables, NITRO_PRESET: "vercel" }
426
+ };
261
427
  })
262
428
  };
263
429
 
@@ -370,7 +536,7 @@ var FRAMEWORK_DEFINITIONS = [
370
536
  ].sort((a, b) => b.priority - a.priority);
371
537
 
372
538
  // src/detection/generate-config.ts
373
- import { Effect as Effect3 } from "effect";
539
+ import { Effect as Effect6 } from "effect";
374
540
 
375
541
  // src/regions.ts
376
542
  var REGION_DEFINITIONS = [
@@ -410,11 +576,11 @@ var getInstallCommand = (pm) => {
410
576
  return "npm install";
411
577
  }
412
578
  };
413
- var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageManager, refinedDefaults) {
579
+ var generateConfig = Effect6.fn("generateConfig")(function* (framework, packageManager, refinedDefaults) {
414
580
  const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
415
581
  const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
416
582
  const commands = [installCmd, ...defaults.commands];
417
- yield* Effect3.logDebug(`Generating config for ${framework.name}`, {
583
+ yield* Effect6.logDebug(`Generating config for ${framework.name}`, {
418
584
  runtime: defaults.runtime,
419
585
  entrypoint: defaults.entrypoint,
420
586
  commands
@@ -447,10 +613,11 @@ var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageM
447
613
  warnings: [`Auto-detected framework: ${framework.name}. Create a gigadrive.yaml to customize.`],
448
614
  errors: []
449
615
  };
450
- if (defaults.assetsDir) {
616
+ if (defaults.assetsDir || defaults.assetPaths) {
451
617
  config.assets = {
452
- paths: [],
453
- prefixToStrip: defaults.assetsDir + "/",
618
+ paths: defaults.assetPaths ? [...defaults.assetPaths] : [],
619
+ prefixToStrip: defaults.assetsPrefixToStrip ?? (defaults.assetsDir ? defaults.assetsDir + "/" : ""),
620
+ overrides: defaults.assetOverrides ? { ...defaults.assetOverrides } : void 0,
454
621
  dynamicRoutes: true,
455
622
  populateCache: defaults.populateAssetCache ?? false
456
623
  };
@@ -459,8 +626,8 @@ var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageM
459
626
  });
460
627
 
461
628
  // src/detection/read-dependencies.ts
462
- import { FileSystem as FileSystem3, Path as Path2 } from "@effect/platform";
463
- import { Effect as Effect5 } from "effect";
629
+ import { FileSystem as FileSystem6, Path as Path4 } from "@effect/platform";
630
+ import { Effect as Effect8 } from "effect";
464
631
 
465
632
  // src/detection/types.ts
466
633
  import { Schema } from "effect";
@@ -493,25 +660,25 @@ var MANIFEST_CONFIG = {
493
660
  node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
494
661
  php: { file: "composer.json", depKeys: ["require", "require-dev"] }
495
662
  };
496
- var readManifest = Effect5.fn("readManifest")(function* (filePath) {
497
- const fs = yield* FileSystem3.FileSystem;
498
- const exists = yield* fs.exists(filePath).pipe(Effect5.catchAll(() => Effect5.succeed(false)));
663
+ var readManifest = Effect8.fn("readManifest")(function* (filePath) {
664
+ const fs = yield* FileSystem6.FileSystem;
665
+ const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
499
666
  if (!exists) {
500
- return yield* Effect5.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
667
+ return yield* Effect8.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
501
668
  }
502
- const content = yield* fs.readFileString(filePath).pipe(Effect5.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
503
- const parsed = yield* Effect5.try({
669
+ const content = yield* fs.readFileString(filePath).pipe(Effect8.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
670
+ const parsed = yield* Effect8.try({
504
671
  try: () => JSON.parse(content),
505
672
  catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
506
673
  });
507
674
  return parsed;
508
675
  });
509
- var readDependencies = Effect5.fn("readDependencies")(function* (projectFolder, language) {
510
- const pathService = yield* Path2.Path;
676
+ var readDependencies = Effect8.fn("readDependencies")(function* (projectFolder, language) {
677
+ const pathService = yield* Path4.Path;
511
678
  const config = MANIFEST_CONFIG[language];
512
679
  const filePath = pathService.join(projectFolder, config.file);
513
680
  const manifest = yield* readManifest(filePath).pipe(
514
- Effect5.catchTag("ManifestNotFoundError", () => Effect5.succeed(null))
681
+ Effect8.catchTag("ManifestNotFoundError", () => Effect8.succeed(null))
515
682
  );
516
683
  if (!manifest) {
517
684
  return /* @__PURE__ */ new Set();
@@ -529,9 +696,9 @@ var readDependencies = Effect5.fn("readDependencies")(function* (projectFolder,
529
696
  });
530
697
 
531
698
  // src/detection/detect-framework.ts
532
- var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
533
- const fs = yield* FileSystem4.FileSystem;
534
- const pathService = yield* Path3.Path;
699
+ var matchesDetectionItem = Effect9.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
700
+ const fs = yield* FileSystem7.FileSystem;
701
+ const pathService = yield* Path5.Path;
535
702
  if (item.matchPackage != null) {
536
703
  const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
537
704
  if (!deps.has(item.matchPackage)) {
@@ -540,12 +707,12 @@ var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, p
540
707
  }
541
708
  if (item.path != null) {
542
709
  const filePath = pathService.join(projectFolder, item.path);
543
- const exists = yield* fs.exists(filePath).pipe(Effect6.catchAll(() => Effect6.succeed(false)));
710
+ const exists = yield* fs.exists(filePath).pipe(Effect9.catchAll(() => Effect9.succeed(false)));
544
711
  if (!exists) {
545
712
  return false;
546
713
  }
547
714
  if (item.matchContent != null) {
548
- const content = yield* fs.readFileString(filePath).pipe(Effect6.catchAll(() => Effect6.succeed("")));
715
+ const content = yield* fs.readFileString(filePath).pipe(Effect9.catchAll(() => Effect9.succeed("")));
549
716
  let regexMatch = false;
550
717
  try {
551
718
  regexMatch = new RegExp(item.matchContent).test(content);
@@ -558,7 +725,7 @@ var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, p
558
725
  }
559
726
  return true;
560
727
  });
561
- var matchesFramework = Effect6.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
728
+ var matchesFramework = Effect9.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
562
729
  for (const detector of framework.detectors) {
563
730
  const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
564
731
  if (!matches) {
@@ -567,9 +734,9 @@ var matchesFramework = Effect6.fn("matchesFramework")(function* (framework, proj
567
734
  }
568
735
  return true;
569
736
  });
570
- var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
571
- yield* Effect6.logDebug(`Detecting framework in ${projectFolder}`);
572
- const cachedReadDeps = yield* Effect6.cachedFunction((key) => {
737
+ var detectFramework = Effect9.fn("detectFramework")(function* (projectFolder) {
738
+ yield* Effect9.logDebug(`Detecting framework in ${projectFolder}`);
739
+ const cachedReadDeps = yield* Effect9.cachedFunction((key) => {
573
740
  const sepIndex = key.lastIndexOf("\0");
574
741
  const folder = key.slice(0, sepIndex);
575
742
  const language = key.slice(sepIndex + 1);
@@ -578,7 +745,7 @@ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
578
745
  for (const framework of FRAMEWORK_DEFINITIONS) {
579
746
  const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
580
747
  if (matches) {
581
- yield* Effect6.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
748
+ yield* Effect9.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
582
749
  const detectedPackageManager = yield* detectPackageManager(projectFolder);
583
750
  const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
584
751
  const defaults = framework.getDefaultConfig(packageManager);
@@ -587,7 +754,7 @@ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
587
754
  return { framework, packageManager, config };
588
755
  }
589
756
  }
590
- return yield* Effect6.fail(
757
+ return yield* Effect9.fail(
591
758
  new FrameworkNotDetectedError({
592
759
  message: `No framework detected in project directory`,
593
760
  directory: projectFolder
@@ -596,9 +763,9 @@ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
596
763
  });
597
764
 
598
765
  // src/detection/merge-config.ts
599
- import { Effect as Effect7 } from "effect";
600
- var mergeWithFrameworkDefaults = Effect7.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
601
- yield* Effect7.logDebug("Merging user config with framework defaults");
766
+ import { Effect as Effect10 } from "effect";
767
+ var mergeWithFrameworkDefaults = Effect10.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
768
+ yield* Effect10.logDebug("Merging user config with framework defaults");
602
769
  const merged = {
603
770
  regions: userConfig.regions,
604
771
  commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
@@ -673,11 +840,11 @@ var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
673
840
  var MAX_FUNCTION_DURATION_SECONDS = 28800;
674
841
 
675
842
  // src/parse-config.ts
676
- import { Effect as Effect13 } from "effect";
843
+ import { Effect as Effect15 } from "effect";
677
844
 
678
845
  // src/services/raw-config-reader.ts
679
- import { FileSystem as FileSystem5, Path as Path4 } from "@effect/platform";
680
- import { Effect as Effect8 } from "effect";
846
+ import { FileSystem as FileSystem8, Path as Path6 } from "@effect/platform";
847
+ import { Effect as Effect11 } from "effect";
681
848
  import { parse as parseYaml } from "yaml";
682
849
  var ALLOWED_CONFIG_NAMES = [
683
850
  "gigadrive.yaml",
@@ -686,34 +853,34 @@ var ALLOWED_CONFIG_NAMES = [
686
853
  "nebula.yml",
687
854
  "nebula.json"
688
855
  ];
689
- var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
690
- effect: Effect8.gen(function* () {
691
- const fs = yield* FileSystem5.FileSystem;
692
- const pathService = yield* Path4.Path;
693
- const findConfig = Effect8.fn("RawConfigReader.findConfig")(function* (projectFolder) {
856
+ var RawConfigReader = class extends Effect11.Service()("RawConfigReader", {
857
+ effect: Effect11.gen(function* () {
858
+ const fs = yield* FileSystem8.FileSystem;
859
+ const pathService = yield* Path6.Path;
860
+ const findConfig = Effect11.fn("RawConfigReader.findConfig")(function* (projectFolder) {
694
861
  for (const name of ALLOWED_CONFIG_NAMES) {
695
862
  const filePath = pathService.join(projectFolder, name);
696
- const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
863
+ const exists = yield* fs.exists(filePath).pipe(Effect11.catchAll(() => Effect11.succeed(false)));
697
864
  if (exists) {
698
865
  return filePath;
699
866
  }
700
867
  }
701
868
  return null;
702
869
  });
703
- const readRawConfig = Effect8.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
704
- const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
870
+ const readRawConfig = Effect11.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
871
+ const exists = yield* fs.exists(filePath).pipe(Effect11.catchAll(() => Effect11.succeed(false)));
705
872
  if (!exists) {
706
- return yield* Effect8.fail(
873
+ return yield* Effect11.fail(
707
874
  new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
708
875
  );
709
876
  }
710
877
  const fileContents = yield* fs.readFileString(filePath).pipe(
711
- Effect8.mapError(
878
+ Effect11.mapError(
712
879
  () => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
713
880
  )
714
881
  );
715
882
  if (fileContents.length === 0) {
716
- return yield* Effect8.fail(
883
+ return yield* Effect11.fail(
717
884
  new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
718
885
  );
719
886
  }
@@ -728,7 +895,7 @@ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
728
895
  parsed = parseYaml(fileContents);
729
896
  }
730
897
  } catch (error) {
731
- return yield* Effect8.fail(
898
+ return yield* Effect11.fail(
732
899
  new ConfigFileParseError({
733
900
  message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
734
901
  filePath,
@@ -737,21 +904,21 @@ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
737
904
  );
738
905
  }
739
906
  if (parsed == null) {
740
- return yield* Effect8.fail(
907
+ return yield* Effect11.fail(
741
908
  new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
742
909
  );
743
910
  }
744
911
  if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
745
- return yield* Effect8.fail(
912
+ return yield* Effect11.fail(
746
913
  new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
747
914
  );
748
915
  }
749
916
  return parsed;
750
917
  });
751
918
  const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
752
- Effect8.map((parsed) => parsed),
753
- Effect8.catchTag("ConfigFileNotFoundError", () => Effect8.succeed(null)),
754
- Effect8.withSpan("RawConfigReader.readConfigFile")
919
+ Effect11.map((parsed) => parsed),
920
+ Effect11.catchTag("ConfigFileNotFoundError", () => Effect11.succeed(null)),
921
+ Effect11.withSpan("RawConfigReader.readConfigFile")
755
922
  );
756
923
  return { findConfig, readRawConfig, readConfigFile };
757
924
  })
@@ -761,17 +928,17 @@ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
761
928
  // src/services/schema-validator.ts
762
929
  import Ajv from "ajv";
763
930
  import addFormats from "ajv-formats";
764
- import { Effect as Effect9 } from "effect";
765
- var SchemaValidator = class extends Effect9.Service()("SchemaValidator", {
766
- effect: Effect9.gen(function* () {
931
+ import { Effect as Effect12 } from "effect";
932
+ var SchemaValidator = class extends Effect12.Service()("SchemaValidator", {
933
+ effect: Effect12.gen(function* () {
767
934
  const ajv = new Ajv();
768
935
  addFormats(ajv);
769
- const validate = Effect9.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
936
+ const validate = Effect12.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
770
937
  const compiledValidate = ajv.compile(schema);
771
938
  const valid = compiledValidate(config);
772
939
  if (!valid) {
773
940
  const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
774
- return yield* Effect9.fail(
941
+ return yield* Effect12.fail(
775
942
  new ConfigSchemaValidationError({
776
943
  message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
777
944
  filePath,
@@ -786,9 +953,9 @@ var SchemaValidator = class extends Effect9.Service()("SchemaValidator", {
786
953
  };
787
954
 
788
955
  // src/services/v4-config-parser.ts
789
- import { FileSystem as FileSystem6, Path as Path5 } from "@effect/platform";
956
+ import { FileSystem as FileSystem9, Path as Path7 } from "@effect/platform";
790
957
  import { getFilesForPattern } from "@gigadrive/build-utils";
791
- import { Effect as Effect10 } from "effect";
958
+ import { Effect as Effect13 } from "effect";
792
959
  import { minimatch } from "minimatch";
793
960
  import safeRegex from "safe-regex2";
794
961
  var MAX_ASSET_DEPTH = 100;
@@ -859,7 +1026,7 @@ var mapRoute = (route, entrypoints) => ({
859
1026
  negativeRequirements: route.missing,
860
1027
  status: route.statusCode
861
1028
  });
862
- var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projectFolder) {
1029
+ var parseEntrypoints = Effect13.fn("parseEntrypoints")(function* (config, projectFolder) {
863
1030
  const entrypoints = [];
864
1031
  if (config.functions == null) return entrypoints;
865
1032
  for (const [fnPath, func] of Object.entries(config.functions)) {
@@ -869,7 +1036,7 @@ var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projec
869
1036
  functionPath: fnPath
870
1037
  });
871
1038
  }
872
- const matchedFiles = yield* Effect10.tryPromise({
1039
+ const matchedFiles = yield* Effect13.tryPromise({
873
1040
  try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
874
1041
  catch: (error) => new FunctionConfigError({
875
1042
  message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
@@ -905,14 +1072,14 @@ var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projec
905
1072
  }
906
1073
  return entrypoints;
907
1074
  });
908
- var collectAssets = Effect10.fn("collectAssets")(function* (config, projectFolder) {
1075
+ var collectAssets = Effect13.fn("collectAssets")(function* (config, projectFolder) {
909
1076
  if (config.assets == null) return [];
910
- const fs = yield* FileSystem6.FileSystem;
911
- const pathService = yield* Path5.Path;
1077
+ const fs = yield* FileSystem9.FileSystem;
1078
+ const pathService = yield* Path7.Path;
912
1079
  const assetsPath = pathService.join(projectFolder, config.assets);
913
- const assetsExist = yield* fs.exists(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(false)));
1080
+ const assetsExist = yield* fs.exists(assetsPath).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
914
1081
  if (!assetsExist) return [];
915
- const stat = yield* fs.stat(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
1082
+ const stat = yield* fs.stat(assetsPath).pipe(Effect13.catchAll(() => Effect13.succeed(null)));
916
1083
  if (!stat || stat.type !== "Directory") return [];
917
1084
  const allFiles = yield* collectFilesRecursively(assetsPath);
918
1085
  const assets = [];
@@ -923,18 +1090,18 @@ var collectAssets = Effect10.fn("collectAssets")(function* (config, projectFolde
923
1090
  }
924
1091
  return assets;
925
1092
  });
926
- var collectFilesRecursively = Effect10.fn("collectFilesRecursively")(
1093
+ var collectFilesRecursively = Effect13.fn("collectFilesRecursively")(
927
1094
  function* (basePath, relativePath = "", depth = 0) {
928
1095
  if (depth > MAX_ASSET_DEPTH) return [];
929
- const fs = yield* FileSystem6.FileSystem;
930
- const pathSvc = yield* Path5.Path;
1096
+ const fs = yield* FileSystem9.FileSystem;
1097
+ const pathSvc = yield* Path7.Path;
931
1098
  const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
932
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect10.catchAll(() => Effect10.succeed([])));
1099
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect13.catchAll(() => Effect13.succeed([])));
933
1100
  const result = [];
934
1101
  for (const name of entries) {
935
1102
  const fullPath = pathSvc.join(currentPath, name);
936
1103
  const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
937
- const stat = yield* fs.stat(fullPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
1104
+ const stat = yield* fs.stat(fullPath).pipe(Effect13.catchAll(() => Effect13.succeed(null)));
938
1105
  if (!stat) continue;
939
1106
  if (stat.type === "Directory") {
940
1107
  const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
@@ -946,16 +1113,16 @@ var collectFilesRecursively = Effect10.fn("collectFilesRecursively")(
946
1113
  return result;
947
1114
  }
948
1115
  );
949
- var V4ConfigParser = class extends Effect10.Service()("V4ConfigParser", {
1116
+ var V4ConfigParser = class extends Effect13.Service()("V4ConfigParser", {
950
1117
  accessors: true,
951
- effect: Effect10.succeed({
1118
+ effect: Effect13.succeed({
952
1119
  /**
953
1120
  * Parses a ConfigV4 into a NormalizedConfig.
954
1121
  *
955
1122
  * @param config - The raw V4 config object
956
1123
  * @param projectFolder - Absolute path to the project root
957
1124
  */
958
- parse: Effect10.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
1125
+ parse: Effect13.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
959
1126
  const entrypoints = yield* parseEntrypoints(config, projectFolder);
960
1127
  const assets = yield* collectAssets(config, projectFolder);
961
1128
  return {
@@ -979,10 +1146,10 @@ var V4ConfigParser = class extends Effect10.Service()("V4ConfigParser", {
979
1146
  };
980
1147
 
981
1148
  // src/services/vercel-build-output-parser.ts
982
- import { Path as Path7 } from "@effect/platform";
1149
+ import { Path as Path8 } from "@effect/platform";
983
1150
  import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
984
1151
  import { deepMerge } from "@gigadrive/commons";
985
- import { Effect as Effect12 } from "effect";
1152
+ import { Effect as Effect14 } from "effect";
986
1153
 
987
1154
  // src/build-output-v3/determine-repo-root.ts
988
1155
  import path from "path";
@@ -1017,37 +1184,6 @@ var determineRepoRoot = (projectFolder, config) => {
1017
1184
  return projectFolder;
1018
1185
  };
1019
1186
 
1020
- // src/build-output-v3/get-default-path-map.ts
1021
- import { FileSystem as FileSystem7, Path as Path6 } from "@effect/platform";
1022
- import { Effect as Effect11 } from "effect";
1023
- var getDefaultPathMap = Effect11.fn("getDefaultPathMap")(function* (directory) {
1024
- const fs = yield* FileSystem7.FileSystem;
1025
- const pathService = yield* Path6.Path;
1026
- const result = {};
1027
- const exists = yield* fs.exists(directory).pipe(Effect11.catchAll(() => Effect11.succeed(false)));
1028
- if (!exists) {
1029
- return result;
1030
- }
1031
- const MAX_DEPTH = 100;
1032
- const processDirectory = (currentPath, basePath = "", depth = 0) => Effect11.gen(function* () {
1033
- if (depth > MAX_DEPTH) return;
1034
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect11.catchAll(() => Effect11.succeed([])));
1035
- for (const name of entries) {
1036
- const fullPath = pathService.join(currentPath, name);
1037
- const relativePath = basePath ? pathService.join(basePath, name) : name;
1038
- const stat = yield* fs.stat(fullPath).pipe(Effect11.catchAll(() => Effect11.succeed(null)));
1039
- if (!stat) continue;
1040
- if (stat.type === "Directory") {
1041
- yield* processDirectory(fullPath, relativePath, depth + 1);
1042
- } else {
1043
- result[fullPath] = relativePath;
1044
- }
1045
- }
1046
- });
1047
- yield* processDirectory(directory);
1048
- return result;
1049
- });
1050
-
1051
1187
  // src/build-output-v3/get-monorepo-files.ts
1052
1188
  function getMonorepoFiles(directory, filePathMaps) {
1053
1189
  const result = [];
@@ -1109,11 +1245,11 @@ var translateVercelRuntime = (runtime) => {
1109
1245
  var CONFIG_PATH = ".vercel/output/config.json";
1110
1246
  var FUNCTIONS_FOLDER = ".vercel/output/functions";
1111
1247
  var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
1112
- var VercelBuildOutputParser = class extends Effect12.Service()("VercelBuildOutputParser", {
1113
- effect: Effect12.gen(function* () {
1248
+ var VercelBuildOutputParser = class extends Effect14.Service()("VercelBuildOutputParser", {
1249
+ effect: Effect14.gen(function* () {
1114
1250
  const rawConfigReader = yield* RawConfigReader;
1115
- const pathService = yield* Path7.Path;
1116
- const parse = Effect12.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1251
+ const pathService = yield* Path8.Path;
1252
+ const parse = Effect14.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1117
1253
  const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
1118
1254
  if (!config || typeof config.version !== "number" || config.version < 3) {
1119
1255
  return parseResult;
@@ -1124,8 +1260,8 @@ var VercelBuildOutputParser = class extends Effect12.Service()("VercelBuildOutpu
1124
1260
  merged.regions = [...new Set(merged.regions)];
1125
1261
  return merged;
1126
1262
  });
1127
- const loadFunctions = Effect12.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1128
- const functionConfigs = yield* Effect12.tryPromise({
1263
+ const loadFunctions = Effect14.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1264
+ const functionConfigs = yield* Effect14.tryPromise({
1129
1265
  try: () => getFilesForPattern2(FUNCTION_CONFIGS_PATTERN, projectFolder),
1130
1266
  catch: (error) => new ConfigFileParseError({
1131
1267
  message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
@@ -1581,7 +1717,7 @@ var schema_default = {
1581
1717
  };
1582
1718
 
1583
1719
  // src/parse-config.ts
1584
- var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectFolder) {
1720
+ var parseConfigRaw = Effect15.fn("parseConfigRaw")(function* (filePath, projectFolder) {
1585
1721
  const rawReader = yield* RawConfigReader;
1586
1722
  const validator = yield* SchemaValidator;
1587
1723
  const v4Parser = yield* V4ConfigParser;
@@ -1592,7 +1728,7 @@ var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectF
1592
1728
  };
1593
1729
  const schema = schemaMap[version];
1594
1730
  if (!schema) {
1595
- return yield* Effect13.fail(
1731
+ return yield* Effect15.fail(
1596
1732
  new ConfigVersionError({
1597
1733
  message: `Config file at ${filePath} has an unsupported version: ${version}`,
1598
1734
  filePath,
@@ -1603,11 +1739,11 @@ var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectF
1603
1739
  yield* validator.validate(parsed, schema, filePath);
1604
1740
  return yield* v4Parser.parse(parsed, projectFolder);
1605
1741
  });
1606
- var parseConfig = Effect13.fn("parseConfig")(function* (filePath, projectFolder) {
1742
+ var parseConfig = Effect15.fn("parseConfig")(function* (filePath, projectFolder) {
1607
1743
  const parseResult = yield* parseConfigRaw(filePath, projectFolder);
1608
1744
  return yield* postProcessConfig(parseResult, projectFolder);
1609
1745
  });
1610
- var postProcessConfig = Effect13.fn("postProcessConfig")(function* (config, projectFolder) {
1746
+ var postProcessConfig = Effect15.fn("postProcessConfig")(function* (config, projectFolder) {
1611
1747
  const vercelParser = yield* VercelBuildOutputParser;
1612
1748
  let result = yield* vercelParser.parse(config, projectFolder);
1613
1749
  if (result.entrypoints.length === 0 && (result.assets?.paths?.length || 0) === 0 && result.routes.length === 0) {