@gigadrive/network-config 3.0.0 → 3.1.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
@@ -1,6 +1,6 @@
1
1
  // src/detection/detect-framework.ts
2
- import { FileSystem as FileSystem3, Path as Path3 } from "@effect/platform";
3
- import { Effect as Effect4 } from "effect";
2
+ import { FileSystem as FileSystem4, Path as Path3 } from "@effect/platform";
3
+ import { Effect as Effect6 } from "effect";
4
4
 
5
5
  // src/detection/detect-package-manager.ts
6
6
  import { FileSystem, Path } from "@effect/platform";
@@ -157,21 +157,65 @@ var laravel = {
157
157
  };
158
158
 
159
159
  // src/detection/frameworks/nestjs.ts
160
- var nestjs = {
161
- slug: "nestjs",
162
- name: "NestJS",
163
- language: "node",
164
- detectors: [{ matchPackage: "@nestjs/core" }],
165
- priority: 90,
166
- getDefaultConfig: () => ({
160
+ import { FileSystem as FileSystem2 } from "@effect/platform";
161
+ import { Effect as Effect2 } from "effect";
162
+ var isRecord = (value) => typeof value === "object" && value !== null;
163
+ var parseNestCliJson = (content) => {
164
+ try {
165
+ const parsed = JSON.parse(content);
166
+ if (!isRecord(parsed)) return void 0;
167
+ return parsed;
168
+ } catch {
169
+ return void 0;
170
+ }
171
+ };
172
+ var getProjectOutputPath = (config) => {
173
+ if (typeof config.compilerOptions?.outputPath === "string") {
174
+ return config.compilerOptions.outputPath;
175
+ }
176
+ if (typeof config.defaultProject === "string") {
177
+ const outputPath2 = config.projects?.[config.defaultProject]?.compilerOptions?.outputPath;
178
+ if (typeof outputPath2 === "string") return outputPath2;
179
+ }
180
+ const firstProject = Object.values(config.projects ?? {})[0];
181
+ const outputPath = firstProject?.compilerOptions?.outputPath;
182
+ return typeof outputPath === "string" ? outputPath : void 0;
183
+ };
184
+ var normalizeOutputPath = (outputPath) => {
185
+ const normalized = outputPath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
186
+ if (!normalized || normalized === "." || normalized.startsWith("/") || /^[A-Za-z]:/.test(normalized) || normalized.includes(":") || normalized.split("/").some((segment) => segment === "..")) {
187
+ return void 0;
188
+ }
189
+ return normalized;
190
+ };
191
+ var createNestConfig = (outputPath) => {
192
+ const outputDirectory = normalizeOutputPath(outputPath) ?? "dist";
193
+ const entrypoint = `${outputDirectory}/main.js`;
194
+ return {
167
195
  runtime: "node-22",
168
196
  memory: 256,
169
197
  maxDuration: 30,
170
198
  streaming: true,
171
199
  commands: ["nest build"],
172
- entrypoint: "dist/main.js",
173
- routes: [{ source: "/*", destination: "dist/main.js" }],
200
+ entrypoint,
201
+ routes: [{ source: "/*", destination: entrypoint }],
174
202
  environmentVariables: { NODE_ENV: "production" }
203
+ };
204
+ };
205
+ var nestjs = {
206
+ slug: "nestjs",
207
+ name: "NestJS",
208
+ language: "node",
209
+ detectors: [{ matchPackage: "@nestjs/core" }],
210
+ priority: 90,
211
+ getDefaultConfig: () => createNestConfig("dist"),
212
+ refineDefaultConfig: (defaults, projectFolder) => Effect2.gen(function* () {
213
+ const fs = yield* FileSystem2.FileSystem;
214
+ const content = yield* fs.readFileString(`${projectFolder}/nest-cli.json`).pipe(Effect2.catchAll(() => Effect2.succeed(void 0)));
215
+ if (!content) return defaults;
216
+ const nestConfig = parseNestCliJson(content);
217
+ const outputPath = nestConfig ? getProjectOutputPath(nestConfig) : void 0;
218
+ return outputPath ? createNestConfig(outputPath) : defaults;
175
219
  })
176
220
  };
177
221
 
@@ -326,7 +370,7 @@ var FRAMEWORK_DEFINITIONS = [
326
370
  ].sort((a, b) => b.priority - a.priority);
327
371
 
328
372
  // src/detection/generate-config.ts
329
- import { Effect as Effect2 } from "effect";
373
+ import { Effect as Effect3 } from "effect";
330
374
 
331
375
  // src/regions.ts
332
376
  var REGION_DEFINITIONS = [
@@ -366,11 +410,11 @@ var getInstallCommand = (pm) => {
366
410
  return "npm install";
367
411
  }
368
412
  };
369
- var generateConfig = Effect2.fn("generateConfig")(function* (framework, packageManager) {
370
- const defaults = framework.getDefaultConfig(packageManager);
413
+ var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageManager, refinedDefaults) {
414
+ const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
371
415
  const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
372
416
  const commands = [installCmd, ...defaults.commands];
373
- yield* Effect2.logDebug(`Generating config for ${framework.name}`, {
417
+ yield* Effect3.logDebug(`Generating config for ${framework.name}`, {
374
418
  runtime: defaults.runtime,
375
419
  entrypoint: defaults.entrypoint,
376
420
  commands
@@ -382,7 +426,8 @@ var generateConfig = Effect2.fn("generateConfig")(function* (framework, packageM
382
426
  memory: defaults.memory,
383
427
  maxDuration: defaults.maxDuration,
384
428
  streaming: defaults.streaming,
385
- symlinks: defaults.symlinks
429
+ symlinks: defaults.symlinks,
430
+ package: defaults.package
386
431
  }
387
432
  ] : [];
388
433
  const routes = defaults.entrypoint ? defaults.routes.map((route) => ({
@@ -414,8 +459,8 @@ var generateConfig = Effect2.fn("generateConfig")(function* (framework, packageM
414
459
  });
415
460
 
416
461
  // src/detection/read-dependencies.ts
417
- import { FileSystem as FileSystem2, Path as Path2 } from "@effect/platform";
418
- import { Effect as Effect3 } from "effect";
462
+ import { FileSystem as FileSystem3, Path as Path2 } from "@effect/platform";
463
+ import { Effect as Effect5 } from "effect";
419
464
 
420
465
  // src/detection/types.ts
421
466
  import { Schema } from "effect";
@@ -448,25 +493,25 @@ var MANIFEST_CONFIG = {
448
493
  node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
449
494
  php: { file: "composer.json", depKeys: ["require", "require-dev"] }
450
495
  };
451
- var readManifest = Effect3.fn("readManifest")(function* (filePath) {
452
- const fs = yield* FileSystem2.FileSystem;
453
- const exists = yield* fs.exists(filePath).pipe(Effect3.catchAll(() => Effect3.succeed(false)));
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)));
454
499
  if (!exists) {
455
- return yield* Effect3.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
500
+ return yield* Effect5.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
456
501
  }
457
- const content = yield* fs.readFileString(filePath).pipe(Effect3.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
458
- const parsed = yield* Effect3.try({
502
+ const content = yield* fs.readFileString(filePath).pipe(Effect5.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
503
+ const parsed = yield* Effect5.try({
459
504
  try: () => JSON.parse(content),
460
505
  catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
461
506
  });
462
507
  return parsed;
463
508
  });
464
- var readDependencies = Effect3.fn("readDependencies")(function* (projectFolder, language) {
509
+ var readDependencies = Effect5.fn("readDependencies")(function* (projectFolder, language) {
465
510
  const pathService = yield* Path2.Path;
466
511
  const config = MANIFEST_CONFIG[language];
467
512
  const filePath = pathService.join(projectFolder, config.file);
468
513
  const manifest = yield* readManifest(filePath).pipe(
469
- Effect3.catchTag("ManifestNotFoundError", () => Effect3.succeed(null))
514
+ Effect5.catchTag("ManifestNotFoundError", () => Effect5.succeed(null))
470
515
  );
471
516
  if (!manifest) {
472
517
  return /* @__PURE__ */ new Set();
@@ -484,8 +529,8 @@ var readDependencies = Effect3.fn("readDependencies")(function* (projectFolder,
484
529
  });
485
530
 
486
531
  // src/detection/detect-framework.ts
487
- var matchesDetectionItem = Effect4.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
488
- const fs = yield* FileSystem3.FileSystem;
532
+ var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
533
+ const fs = yield* FileSystem4.FileSystem;
489
534
  const pathService = yield* Path3.Path;
490
535
  if (item.matchPackage != null) {
491
536
  const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
@@ -495,12 +540,12 @@ var matchesDetectionItem = Effect4.fn("matchesDetectionItem")(function* (item, p
495
540
  }
496
541
  if (item.path != null) {
497
542
  const filePath = pathService.join(projectFolder, item.path);
498
- const exists = yield* fs.exists(filePath).pipe(Effect4.catchAll(() => Effect4.succeed(false)));
543
+ const exists = yield* fs.exists(filePath).pipe(Effect6.catchAll(() => Effect6.succeed(false)));
499
544
  if (!exists) {
500
545
  return false;
501
546
  }
502
547
  if (item.matchContent != null) {
503
- const content = yield* fs.readFileString(filePath).pipe(Effect4.catchAll(() => Effect4.succeed("")));
548
+ const content = yield* fs.readFileString(filePath).pipe(Effect6.catchAll(() => Effect6.succeed("")));
504
549
  let regexMatch = false;
505
550
  try {
506
551
  regexMatch = new RegExp(item.matchContent).test(content);
@@ -513,7 +558,7 @@ var matchesDetectionItem = Effect4.fn("matchesDetectionItem")(function* (item, p
513
558
  }
514
559
  return true;
515
560
  });
516
- var matchesFramework = Effect4.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
561
+ var matchesFramework = Effect6.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
517
562
  for (const detector of framework.detectors) {
518
563
  const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
519
564
  if (!matches) {
@@ -522,9 +567,9 @@ var matchesFramework = Effect4.fn("matchesFramework")(function* (framework, proj
522
567
  }
523
568
  return true;
524
569
  });
525
- var detectFramework = Effect4.fn("detectFramework")(function* (projectFolder) {
526
- yield* Effect4.logDebug(`Detecting framework in ${projectFolder}`);
527
- const cachedReadDeps = yield* Effect4.cachedFunction((key) => {
570
+ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
571
+ yield* Effect6.logDebug(`Detecting framework in ${projectFolder}`);
572
+ const cachedReadDeps = yield* Effect6.cachedFunction((key) => {
528
573
  const sepIndex = key.lastIndexOf("\0");
529
574
  const folder = key.slice(0, sepIndex);
530
575
  const language = key.slice(sepIndex + 1);
@@ -533,13 +578,16 @@ var detectFramework = Effect4.fn("detectFramework")(function* (projectFolder) {
533
578
  for (const framework of FRAMEWORK_DEFINITIONS) {
534
579
  const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
535
580
  if (matches) {
536
- yield* Effect4.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
537
- const packageManager = yield* detectPackageManager(projectFolder);
538
- const config = yield* generateConfig(framework, packageManager);
581
+ yield* Effect6.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
582
+ const detectedPackageManager = yield* detectPackageManager(projectFolder);
583
+ const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
584
+ const defaults = framework.getDefaultConfig(packageManager);
585
+ const refinedDefaults = framework.refineDefaultConfig ? yield* framework.refineDefaultConfig(defaults, projectFolder) : defaults;
586
+ const config = yield* generateConfig(framework, packageManager, refinedDefaults);
539
587
  return { framework, packageManager, config };
540
588
  }
541
589
  }
542
- return yield* Effect4.fail(
590
+ return yield* Effect6.fail(
543
591
  new FrameworkNotDetectedError({
544
592
  message: `No framework detected in project directory`,
545
593
  directory: projectFolder
@@ -548,9 +596,9 @@ var detectFramework = Effect4.fn("detectFramework")(function* (projectFolder) {
548
596
  });
549
597
 
550
598
  // src/detection/merge-config.ts
551
- import { Effect as Effect5 } from "effect";
552
- var mergeWithFrameworkDefaults = Effect5.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
553
- yield* Effect5.logDebug("Merging user config with framework defaults");
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");
554
602
  const merged = {
555
603
  regions: userConfig.regions,
556
604
  commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
@@ -621,11 +669,11 @@ var filterFunctionsFromAssets = (config) => {
621
669
  };
622
670
 
623
671
  // src/parse-config.ts
624
- import { Effect as Effect11 } from "effect";
672
+ import { Effect as Effect13 } from "effect";
625
673
 
626
674
  // src/services/raw-config-reader.ts
627
- import { FileSystem as FileSystem4, Path as Path4 } from "@effect/platform";
628
- import { Effect as Effect6 } from "effect";
675
+ import { FileSystem as FileSystem5, Path as Path4 } from "@effect/platform";
676
+ import { Effect as Effect8 } from "effect";
629
677
  import { parse as parseYaml } from "yaml";
630
678
  var ALLOWED_CONFIG_NAMES = [
631
679
  "gigadrive.yaml",
@@ -634,34 +682,34 @@ var ALLOWED_CONFIG_NAMES = [
634
682
  "nebula.yml",
635
683
  "nebula.json"
636
684
  ];
637
- var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
638
- effect: Effect6.gen(function* () {
639
- const fs = yield* FileSystem4.FileSystem;
685
+ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
686
+ effect: Effect8.gen(function* () {
687
+ const fs = yield* FileSystem5.FileSystem;
640
688
  const pathService = yield* Path4.Path;
641
- const findConfig = Effect6.fn("RawConfigReader.findConfig")(function* (projectFolder) {
689
+ const findConfig = Effect8.fn("RawConfigReader.findConfig")(function* (projectFolder) {
642
690
  for (const name of ALLOWED_CONFIG_NAMES) {
643
691
  const filePath = pathService.join(projectFolder, name);
644
- const exists = yield* fs.exists(filePath).pipe(Effect6.catchAll(() => Effect6.succeed(false)));
692
+ const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
645
693
  if (exists) {
646
694
  return filePath;
647
695
  }
648
696
  }
649
697
  return null;
650
698
  });
651
- const readRawConfig = Effect6.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
652
- const exists = yield* fs.exists(filePath).pipe(Effect6.catchAll(() => Effect6.succeed(false)));
699
+ const readRawConfig = Effect8.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
700
+ const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
653
701
  if (!exists) {
654
- return yield* Effect6.fail(
702
+ return yield* Effect8.fail(
655
703
  new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
656
704
  );
657
705
  }
658
706
  const fileContents = yield* fs.readFileString(filePath).pipe(
659
- Effect6.mapError(
707
+ Effect8.mapError(
660
708
  () => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
661
709
  )
662
710
  );
663
711
  if (fileContents.length === 0) {
664
- return yield* Effect6.fail(
712
+ return yield* Effect8.fail(
665
713
  new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
666
714
  );
667
715
  }
@@ -676,7 +724,7 @@ var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
676
724
  parsed = parseYaml(fileContents);
677
725
  }
678
726
  } catch (error) {
679
- return yield* Effect6.fail(
727
+ return yield* Effect8.fail(
680
728
  new ConfigFileParseError({
681
729
  message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
682
730
  filePath,
@@ -685,21 +733,21 @@ var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
685
733
  );
686
734
  }
687
735
  if (parsed == null) {
688
- return yield* Effect6.fail(
736
+ return yield* Effect8.fail(
689
737
  new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
690
738
  );
691
739
  }
692
740
  if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
693
- return yield* Effect6.fail(
741
+ return yield* Effect8.fail(
694
742
  new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
695
743
  );
696
744
  }
697
745
  return parsed;
698
746
  });
699
747
  const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
700
- Effect6.map((parsed) => parsed),
701
- Effect6.catchTag("ConfigFileNotFoundError", () => Effect6.succeed(null)),
702
- Effect6.withSpan("RawConfigReader.readConfigFile")
748
+ Effect8.map((parsed) => parsed),
749
+ Effect8.catchTag("ConfigFileNotFoundError", () => Effect8.succeed(null)),
750
+ Effect8.withSpan("RawConfigReader.readConfigFile")
703
751
  );
704
752
  return { findConfig, readRawConfig, readConfigFile };
705
753
  })
@@ -709,17 +757,17 @@ var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
709
757
  // src/services/schema-validator.ts
710
758
  import Ajv from "ajv";
711
759
  import addFormats from "ajv-formats";
712
- import { Effect as Effect7 } from "effect";
713
- var SchemaValidator = class extends Effect7.Service()("SchemaValidator", {
714
- effect: Effect7.gen(function* () {
760
+ import { Effect as Effect9 } from "effect";
761
+ var SchemaValidator = class extends Effect9.Service()("SchemaValidator", {
762
+ effect: Effect9.gen(function* () {
715
763
  const ajv = new Ajv();
716
764
  addFormats(ajv);
717
- const validate = Effect7.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
765
+ const validate = Effect9.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
718
766
  const compiledValidate = ajv.compile(schema);
719
767
  const valid = compiledValidate(config);
720
768
  if (!valid) {
721
769
  const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
722
- return yield* Effect7.fail(
770
+ return yield* Effect9.fail(
723
771
  new ConfigSchemaValidationError({
724
772
  message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
725
773
  filePath,
@@ -734,9 +782,9 @@ var SchemaValidator = class extends Effect7.Service()("SchemaValidator", {
734
782
  };
735
783
 
736
784
  // src/services/v4-config-parser.ts
737
- import { FileSystem as FileSystem5, Path as Path5 } from "@effect/platform";
785
+ import { FileSystem as FileSystem6, Path as Path5 } from "@effect/platform";
738
786
  import { getFilesForPattern } from "@gigadrive/build-utils";
739
- import { Effect as Effect8 } from "effect";
787
+ import { Effect as Effect10 } from "effect";
740
788
  import { minimatch } from "minimatch";
741
789
  import safeRegex from "safe-regex2";
742
790
  var MAX_ASSET_DEPTH = 100;
@@ -749,6 +797,10 @@ var DEFAULT_FUNCTION_SETTINGS = {
749
797
  excludeFiles: void 0,
750
798
  includeFiles: void 0
751
799
  };
800
+ var toArray = (value) => {
801
+ if (value == null) return void 0;
802
+ return Array.isArray(value) ? value : [value];
803
+ };
752
804
  var matchesPattern = (path2, pattern) => {
753
805
  if (minimatch(path2, pattern)) return true;
754
806
  try {
@@ -788,7 +840,7 @@ var mapRoute = (route) => ({
788
840
  negativeRequirements: route.missing,
789
841
  status: route.statusCode
790
842
  });
791
- var parseEntrypoints = Effect8.fn("parseEntrypoints")(function* (config, projectFolder) {
843
+ var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projectFolder) {
792
844
  const entrypoints = [];
793
845
  if (config.functions == null) return entrypoints;
794
846
  for (const [fnPath, func] of Object.entries(config.functions)) {
@@ -799,7 +851,7 @@ var parseEntrypoints = Effect8.fn("parseEntrypoints")(function* (config, project
799
851
  functionPath: fnPath
800
852
  });
801
853
  }
802
- const matchedFiles = yield* Effect8.tryPromise({
854
+ const matchedFiles = yield* Effect10.tryPromise({
803
855
  try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
804
856
  catch: (error) => new FunctionConfigError({
805
857
  message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
@@ -816,20 +868,24 @@ var parseEntrypoints = Effect8.fn("parseEntrypoints")(function* (config, project
816
868
  maxDuration: settings.max_duration ?? 30,
817
869
  schedule: func.schedule,
818
870
  symlinks: func.symlinks,
819
- streaming: settings.runtime == null || settings.runtime.startsWith("node-") || settings.runtime.startsWith("bun-")
871
+ streaming: settings.runtime == null || settings.runtime.startsWith("node-") || settings.runtime.startsWith("bun-"),
872
+ package: settings.includeFiles != null || settings.excludeFiles != null ? {
873
+ includeFiles: toArray(settings.includeFiles),
874
+ excludeFiles: toArray(settings.excludeFiles)
875
+ } : void 0
820
876
  });
821
877
  }
822
878
  }
823
879
  return entrypoints;
824
880
  });
825
- var collectAssets = Effect8.fn("collectAssets")(function* (config, projectFolder) {
881
+ var collectAssets = Effect10.fn("collectAssets")(function* (config, projectFolder) {
826
882
  if (config.assets == null) return [];
827
- const fs = yield* FileSystem5.FileSystem;
883
+ const fs = yield* FileSystem6.FileSystem;
828
884
  const pathService = yield* Path5.Path;
829
885
  const assetsPath = pathService.join(projectFolder, config.assets);
830
- const assetsExist = yield* fs.exists(assetsPath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
886
+ const assetsExist = yield* fs.exists(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(false)));
831
887
  if (!assetsExist) return [];
832
- const stat = yield* fs.stat(assetsPath).pipe(Effect8.catchAll(() => Effect8.succeed(null)));
888
+ const stat = yield* fs.stat(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
833
889
  if (!stat || stat.type !== "Directory") return [];
834
890
  const allFiles = yield* collectFilesRecursively(assetsPath);
835
891
  const assets = [];
@@ -840,18 +896,18 @@ var collectAssets = Effect8.fn("collectAssets")(function* (config, projectFolder
840
896
  }
841
897
  return assets;
842
898
  });
843
- var collectFilesRecursively = Effect8.fn("collectFilesRecursively")(
899
+ var collectFilesRecursively = Effect10.fn("collectFilesRecursively")(
844
900
  function* (basePath, relativePath = "", depth = 0) {
845
901
  if (depth > MAX_ASSET_DEPTH) return [];
846
- const fs = yield* FileSystem5.FileSystem;
902
+ const fs = yield* FileSystem6.FileSystem;
847
903
  const pathSvc = yield* Path5.Path;
848
904
  const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
849
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect8.catchAll(() => Effect8.succeed([])));
905
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect10.catchAll(() => Effect10.succeed([])));
850
906
  const result = [];
851
907
  for (const name of entries) {
852
908
  const fullPath = pathSvc.join(currentPath, name);
853
909
  const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
854
- const stat = yield* fs.stat(fullPath).pipe(Effect8.catchAll(() => Effect8.succeed(null)));
910
+ const stat = yield* fs.stat(fullPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
855
911
  if (!stat) continue;
856
912
  if (stat.type === "Directory") {
857
913
  const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
@@ -863,16 +919,16 @@ var collectFilesRecursively = Effect8.fn("collectFilesRecursively")(
863
919
  return result;
864
920
  }
865
921
  );
866
- var V4ConfigParser = class extends Effect8.Service()("V4ConfigParser", {
922
+ var V4ConfigParser = class extends Effect10.Service()("V4ConfigParser", {
867
923
  accessors: true,
868
- effect: Effect8.succeed({
924
+ effect: Effect10.succeed({
869
925
  /**
870
926
  * Parses a ConfigV4 into a NormalizedConfig.
871
927
  *
872
928
  * @param config - The raw V4 config object
873
929
  * @param projectFolder - Absolute path to the project root
874
930
  */
875
- parse: Effect8.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
931
+ parse: Effect10.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
876
932
  const entrypoints = yield* parseEntrypoints(config, projectFolder);
877
933
  const assets = yield* collectAssets(config, projectFolder);
878
934
  return {
@@ -899,7 +955,7 @@ var V4ConfigParser = class extends Effect8.Service()("V4ConfigParser", {
899
955
  import { Path as Path7 } from "@effect/platform";
900
956
  import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
901
957
  import { deepMerge } from "@gigadrive/commons";
902
- import { Effect as Effect10 } from "effect";
958
+ import { Effect as Effect12 } from "effect";
903
959
 
904
960
  // src/build-output-v3/determine-repo-root.ts
905
961
  import path from "path";
@@ -935,24 +991,24 @@ var determineRepoRoot = (projectFolder, config) => {
935
991
  };
936
992
 
937
993
  // src/build-output-v3/get-default-path-map.ts
938
- import { FileSystem as FileSystem6, Path as Path6 } from "@effect/platform";
939
- import { Effect as Effect9 } from "effect";
940
- var getDefaultPathMap = Effect9.fn("getDefaultPathMap")(function* (directory) {
941
- const fs = yield* FileSystem6.FileSystem;
994
+ import { FileSystem as FileSystem7, Path as Path6 } from "@effect/platform";
995
+ import { Effect as Effect11 } from "effect";
996
+ var getDefaultPathMap = Effect11.fn("getDefaultPathMap")(function* (directory) {
997
+ const fs = yield* FileSystem7.FileSystem;
942
998
  const pathService = yield* Path6.Path;
943
999
  const result = {};
944
- const exists = yield* fs.exists(directory).pipe(Effect9.catchAll(() => Effect9.succeed(false)));
1000
+ const exists = yield* fs.exists(directory).pipe(Effect11.catchAll(() => Effect11.succeed(false)));
945
1001
  if (!exists) {
946
1002
  return result;
947
1003
  }
948
1004
  const MAX_DEPTH = 100;
949
- const processDirectory = (currentPath, basePath = "", depth = 0) => Effect9.gen(function* () {
1005
+ const processDirectory = (currentPath, basePath = "", depth = 0) => Effect11.gen(function* () {
950
1006
  if (depth > MAX_DEPTH) return;
951
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect9.catchAll(() => Effect9.succeed([])));
1007
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect11.catchAll(() => Effect11.succeed([])));
952
1008
  for (const name of entries) {
953
1009
  const fullPath = pathService.join(currentPath, name);
954
1010
  const relativePath = basePath ? pathService.join(basePath, name) : name;
955
- const stat = yield* fs.stat(fullPath).pipe(Effect9.catchAll(() => Effect9.succeed(null)));
1011
+ const stat = yield* fs.stat(fullPath).pipe(Effect11.catchAll(() => Effect11.succeed(null)));
956
1012
  if (!stat) continue;
957
1013
  if (stat.type === "Directory") {
958
1014
  yield* processDirectory(fullPath, relativePath, depth + 1);
@@ -1026,11 +1082,11 @@ var translateVercelRuntime = (runtime) => {
1026
1082
  var CONFIG_PATH = ".vercel/output/config.json";
1027
1083
  var FUNCTIONS_FOLDER = ".vercel/output/functions";
1028
1084
  var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
1029
- var VercelBuildOutputParser = class extends Effect10.Service()("VercelBuildOutputParser", {
1030
- effect: Effect10.gen(function* () {
1085
+ var VercelBuildOutputParser = class extends Effect12.Service()("VercelBuildOutputParser", {
1086
+ effect: Effect12.gen(function* () {
1031
1087
  const rawConfigReader = yield* RawConfigReader;
1032
1088
  const pathService = yield* Path7.Path;
1033
- const parse = Effect10.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1089
+ const parse = Effect12.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1034
1090
  const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
1035
1091
  if (!config || typeof config.version !== "number" || config.version < 3) {
1036
1092
  return parseResult;
@@ -1041,8 +1097,8 @@ var VercelBuildOutputParser = class extends Effect10.Service()("VercelBuildOutpu
1041
1097
  merged.regions = [...new Set(merged.regions)];
1042
1098
  return merged;
1043
1099
  });
1044
- const loadFunctions = Effect10.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1045
- const functionConfigs = yield* Effect10.tryPromise({
1100
+ const loadFunctions = Effect12.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1101
+ const functionConfigs = yield* Effect12.tryPromise({
1046
1102
  try: () => getFilesForPattern2(FUNCTION_CONFIGS_PATTERN, projectFolder),
1047
1103
  catch: (error) => new ConfigFileParseError({
1048
1104
  message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
@@ -1496,7 +1552,7 @@ var schema_default = {
1496
1552
  };
1497
1553
 
1498
1554
  // src/parse-config.ts
1499
- var parseConfigRaw = Effect11.fn("parseConfigRaw")(function* (filePath, projectFolder) {
1555
+ var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectFolder) {
1500
1556
  const rawReader = yield* RawConfigReader;
1501
1557
  const validator = yield* SchemaValidator;
1502
1558
  const v4Parser = yield* V4ConfigParser;
@@ -1507,7 +1563,7 @@ var parseConfigRaw = Effect11.fn("parseConfigRaw")(function* (filePath, projectF
1507
1563
  };
1508
1564
  const schema = schemaMap[version];
1509
1565
  if (!schema) {
1510
- return yield* Effect11.fail(
1566
+ return yield* Effect13.fail(
1511
1567
  new ConfigVersionError({
1512
1568
  message: `Config file at ${filePath} has an unsupported version: ${version}`,
1513
1569
  filePath,
@@ -1518,11 +1574,11 @@ var parseConfigRaw = Effect11.fn("parseConfigRaw")(function* (filePath, projectF
1518
1574
  yield* validator.validate(parsed, schema, filePath);
1519
1575
  return yield* v4Parser.parse(parsed, projectFolder);
1520
1576
  });
1521
- var parseConfig = Effect11.fn("parseConfig")(function* (filePath, projectFolder) {
1577
+ var parseConfig = Effect13.fn("parseConfig")(function* (filePath, projectFolder) {
1522
1578
  const parseResult = yield* parseConfigRaw(filePath, projectFolder);
1523
1579
  return yield* postProcessConfig(parseResult, projectFolder);
1524
1580
  });
1525
- var postProcessConfig = Effect11.fn("postProcessConfig")(function* (config, projectFolder) {
1581
+ var postProcessConfig = Effect13.fn("postProcessConfig")(function* (config, projectFolder) {
1526
1582
  const vercelParser = yield* VercelBuildOutputParser;
1527
1583
  let result = yield* vercelParser.parse(config, projectFolder);
1528
1584
  if (result.entrypoints.length === 0 && (result.assets?.paths?.length || 0) === 0 && result.routes.length === 0) {