@gigadrive/network-config 3.2.0 → 3.3.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 FileSystem4, Path as Path3 } from "@effect/platform";
3
- import { Effect as Effect6 } from "effect";
2
+ import { FileSystem as FileSystem6, Path as Path5 } from "@effect/platform";
3
+ import { Effect as Effect8 } 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,6 +372,13 @@ 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
 
@@ -370,7 +512,7 @@ var FRAMEWORK_DEFINITIONS = [
370
512
  ].sort((a, b) => b.priority - a.priority);
371
513
 
372
514
  // src/detection/generate-config.ts
373
- import { Effect as Effect3 } from "effect";
515
+ import { Effect as Effect5 } from "effect";
374
516
 
375
517
  // src/regions.ts
376
518
  var REGION_DEFINITIONS = [
@@ -410,11 +552,11 @@ var getInstallCommand = (pm) => {
410
552
  return "npm install";
411
553
  }
412
554
  };
413
- var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageManager, refinedDefaults) {
555
+ var generateConfig = Effect5.fn("generateConfig")(function* (framework, packageManager, refinedDefaults) {
414
556
  const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
415
557
  const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
416
558
  const commands = [installCmd, ...defaults.commands];
417
- yield* Effect3.logDebug(`Generating config for ${framework.name}`, {
559
+ yield* Effect5.logDebug(`Generating config for ${framework.name}`, {
418
560
  runtime: defaults.runtime,
419
561
  entrypoint: defaults.entrypoint,
420
562
  commands
@@ -447,10 +589,11 @@ var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageM
447
589
  warnings: [`Auto-detected framework: ${framework.name}. Create a gigadrive.yaml to customize.`],
448
590
  errors: []
449
591
  };
450
- if (defaults.assetsDir) {
592
+ if (defaults.assetsDir || defaults.assetPaths) {
451
593
  config.assets = {
452
- paths: [],
453
- prefixToStrip: defaults.assetsDir + "/",
594
+ paths: defaults.assetPaths ? [...defaults.assetPaths] : [],
595
+ prefixToStrip: defaults.assetsPrefixToStrip ?? (defaults.assetsDir ? defaults.assetsDir + "/" : ""),
596
+ overrides: defaults.assetOverrides ? { ...defaults.assetOverrides } : void 0,
454
597
  dynamicRoutes: true,
455
598
  populateCache: defaults.populateAssetCache ?? false
456
599
  };
@@ -459,8 +602,8 @@ var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageM
459
602
  });
460
603
 
461
604
  // src/detection/read-dependencies.ts
462
- import { FileSystem as FileSystem3, Path as Path2 } from "@effect/platform";
463
- import { Effect as Effect5 } from "effect";
605
+ import { FileSystem as FileSystem5, Path as Path4 } from "@effect/platform";
606
+ import { Effect as Effect7 } from "effect";
464
607
 
465
608
  // src/detection/types.ts
466
609
  import { Schema } from "effect";
@@ -493,25 +636,25 @@ var MANIFEST_CONFIG = {
493
636
  node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
494
637
  php: { file: "composer.json", depKeys: ["require", "require-dev"] }
495
638
  };
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)));
639
+ var readManifest = Effect7.fn("readManifest")(function* (filePath) {
640
+ const fs = yield* FileSystem5.FileSystem;
641
+ const exists = yield* fs.exists(filePath).pipe(Effect7.catchAll(() => Effect7.succeed(false)));
499
642
  if (!exists) {
500
- return yield* Effect5.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
643
+ return yield* Effect7.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
501
644
  }
502
- const content = yield* fs.readFileString(filePath).pipe(Effect5.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
503
- const parsed = yield* Effect5.try({
645
+ const content = yield* fs.readFileString(filePath).pipe(Effect7.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
646
+ const parsed = yield* Effect7.try({
504
647
  try: () => JSON.parse(content),
505
648
  catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
506
649
  });
507
650
  return parsed;
508
651
  });
509
- var readDependencies = Effect5.fn("readDependencies")(function* (projectFolder, language) {
510
- const pathService = yield* Path2.Path;
652
+ var readDependencies = Effect7.fn("readDependencies")(function* (projectFolder, language) {
653
+ const pathService = yield* Path4.Path;
511
654
  const config = MANIFEST_CONFIG[language];
512
655
  const filePath = pathService.join(projectFolder, config.file);
513
656
  const manifest = yield* readManifest(filePath).pipe(
514
- Effect5.catchTag("ManifestNotFoundError", () => Effect5.succeed(null))
657
+ Effect7.catchTag("ManifestNotFoundError", () => Effect7.succeed(null))
515
658
  );
516
659
  if (!manifest) {
517
660
  return /* @__PURE__ */ new Set();
@@ -529,9 +672,9 @@ var readDependencies = Effect5.fn("readDependencies")(function* (projectFolder,
529
672
  });
530
673
 
531
674
  // 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;
675
+ var matchesDetectionItem = Effect8.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
676
+ const fs = yield* FileSystem6.FileSystem;
677
+ const pathService = yield* Path5.Path;
535
678
  if (item.matchPackage != null) {
536
679
  const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
537
680
  if (!deps.has(item.matchPackage)) {
@@ -540,12 +683,12 @@ var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, p
540
683
  }
541
684
  if (item.path != null) {
542
685
  const filePath = pathService.join(projectFolder, item.path);
543
- const exists = yield* fs.exists(filePath).pipe(Effect6.catchAll(() => Effect6.succeed(false)));
686
+ const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
544
687
  if (!exists) {
545
688
  return false;
546
689
  }
547
690
  if (item.matchContent != null) {
548
- const content = yield* fs.readFileString(filePath).pipe(Effect6.catchAll(() => Effect6.succeed("")));
691
+ const content = yield* fs.readFileString(filePath).pipe(Effect8.catchAll(() => Effect8.succeed("")));
549
692
  let regexMatch = false;
550
693
  try {
551
694
  regexMatch = new RegExp(item.matchContent).test(content);
@@ -558,7 +701,7 @@ var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, p
558
701
  }
559
702
  return true;
560
703
  });
561
- var matchesFramework = Effect6.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
704
+ var matchesFramework = Effect8.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
562
705
  for (const detector of framework.detectors) {
563
706
  const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
564
707
  if (!matches) {
@@ -567,9 +710,9 @@ var matchesFramework = Effect6.fn("matchesFramework")(function* (framework, proj
567
710
  }
568
711
  return true;
569
712
  });
570
- var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
571
- yield* Effect6.logDebug(`Detecting framework in ${projectFolder}`);
572
- const cachedReadDeps = yield* Effect6.cachedFunction((key) => {
713
+ var detectFramework = Effect8.fn("detectFramework")(function* (projectFolder) {
714
+ yield* Effect8.logDebug(`Detecting framework in ${projectFolder}`);
715
+ const cachedReadDeps = yield* Effect8.cachedFunction((key) => {
573
716
  const sepIndex = key.lastIndexOf("\0");
574
717
  const folder = key.slice(0, sepIndex);
575
718
  const language = key.slice(sepIndex + 1);
@@ -578,7 +721,7 @@ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
578
721
  for (const framework of FRAMEWORK_DEFINITIONS) {
579
722
  const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
580
723
  if (matches) {
581
- yield* Effect6.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
724
+ yield* Effect8.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
582
725
  const detectedPackageManager = yield* detectPackageManager(projectFolder);
583
726
  const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
584
727
  const defaults = framework.getDefaultConfig(packageManager);
@@ -587,7 +730,7 @@ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
587
730
  return { framework, packageManager, config };
588
731
  }
589
732
  }
590
- return yield* Effect6.fail(
733
+ return yield* Effect8.fail(
591
734
  new FrameworkNotDetectedError({
592
735
  message: `No framework detected in project directory`,
593
736
  directory: projectFolder
@@ -596,9 +739,9 @@ var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
596
739
  });
597
740
 
598
741
  // 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");
742
+ import { Effect as Effect9 } from "effect";
743
+ var mergeWithFrameworkDefaults = Effect9.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
744
+ yield* Effect9.logDebug("Merging user config with framework defaults");
602
745
  const merged = {
603
746
  regions: userConfig.regions,
604
747
  commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
@@ -673,11 +816,11 @@ var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
673
816
  var MAX_FUNCTION_DURATION_SECONDS = 28800;
674
817
 
675
818
  // src/parse-config.ts
676
- import { Effect as Effect13 } from "effect";
819
+ import { Effect as Effect14 } from "effect";
677
820
 
678
821
  // src/services/raw-config-reader.ts
679
- import { FileSystem as FileSystem5, Path as Path4 } from "@effect/platform";
680
- import { Effect as Effect8 } from "effect";
822
+ import { FileSystem as FileSystem7, Path as Path6 } from "@effect/platform";
823
+ import { Effect as Effect10 } from "effect";
681
824
  import { parse as parseYaml } from "yaml";
682
825
  var ALLOWED_CONFIG_NAMES = [
683
826
  "gigadrive.yaml",
@@ -686,34 +829,34 @@ var ALLOWED_CONFIG_NAMES = [
686
829
  "nebula.yml",
687
830
  "nebula.json"
688
831
  ];
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) {
832
+ var RawConfigReader = class extends Effect10.Service()("RawConfigReader", {
833
+ effect: Effect10.gen(function* () {
834
+ const fs = yield* FileSystem7.FileSystem;
835
+ const pathService = yield* Path6.Path;
836
+ const findConfig = Effect10.fn("RawConfigReader.findConfig")(function* (projectFolder) {
694
837
  for (const name of ALLOWED_CONFIG_NAMES) {
695
838
  const filePath = pathService.join(projectFolder, name);
696
- const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
839
+ const exists = yield* fs.exists(filePath).pipe(Effect10.catchAll(() => Effect10.succeed(false)));
697
840
  if (exists) {
698
841
  return filePath;
699
842
  }
700
843
  }
701
844
  return null;
702
845
  });
703
- const readRawConfig = Effect8.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
704
- const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
846
+ const readRawConfig = Effect10.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
847
+ const exists = yield* fs.exists(filePath).pipe(Effect10.catchAll(() => Effect10.succeed(false)));
705
848
  if (!exists) {
706
- return yield* Effect8.fail(
849
+ return yield* Effect10.fail(
707
850
  new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
708
851
  );
709
852
  }
710
853
  const fileContents = yield* fs.readFileString(filePath).pipe(
711
- Effect8.mapError(
854
+ Effect10.mapError(
712
855
  () => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
713
856
  )
714
857
  );
715
858
  if (fileContents.length === 0) {
716
- return yield* Effect8.fail(
859
+ return yield* Effect10.fail(
717
860
  new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
718
861
  );
719
862
  }
@@ -728,7 +871,7 @@ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
728
871
  parsed = parseYaml(fileContents);
729
872
  }
730
873
  } catch (error) {
731
- return yield* Effect8.fail(
874
+ return yield* Effect10.fail(
732
875
  new ConfigFileParseError({
733
876
  message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
734
877
  filePath,
@@ -737,21 +880,21 @@ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
737
880
  );
738
881
  }
739
882
  if (parsed == null) {
740
- return yield* Effect8.fail(
883
+ return yield* Effect10.fail(
741
884
  new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
742
885
  );
743
886
  }
744
887
  if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
745
- return yield* Effect8.fail(
888
+ return yield* Effect10.fail(
746
889
  new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
747
890
  );
748
891
  }
749
892
  return parsed;
750
893
  });
751
894
  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")
895
+ Effect10.map((parsed) => parsed),
896
+ Effect10.catchTag("ConfigFileNotFoundError", () => Effect10.succeed(null)),
897
+ Effect10.withSpan("RawConfigReader.readConfigFile")
755
898
  );
756
899
  return { findConfig, readRawConfig, readConfigFile };
757
900
  })
@@ -761,17 +904,17 @@ var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
761
904
  // src/services/schema-validator.ts
762
905
  import Ajv from "ajv";
763
906
  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* () {
907
+ import { Effect as Effect11 } from "effect";
908
+ var SchemaValidator = class extends Effect11.Service()("SchemaValidator", {
909
+ effect: Effect11.gen(function* () {
767
910
  const ajv = new Ajv();
768
911
  addFormats(ajv);
769
- const validate = Effect9.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
912
+ const validate = Effect11.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
770
913
  const compiledValidate = ajv.compile(schema);
771
914
  const valid = compiledValidate(config);
772
915
  if (!valid) {
773
916
  const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
774
- return yield* Effect9.fail(
917
+ return yield* Effect11.fail(
775
918
  new ConfigSchemaValidationError({
776
919
  message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
777
920
  filePath,
@@ -786,9 +929,9 @@ var SchemaValidator = class extends Effect9.Service()("SchemaValidator", {
786
929
  };
787
930
 
788
931
  // src/services/v4-config-parser.ts
789
- import { FileSystem as FileSystem6, Path as Path5 } from "@effect/platform";
932
+ import { FileSystem as FileSystem8, Path as Path7 } from "@effect/platform";
790
933
  import { getFilesForPattern } from "@gigadrive/build-utils";
791
- import { Effect as Effect10 } from "effect";
934
+ import { Effect as Effect12 } from "effect";
792
935
  import { minimatch } from "minimatch";
793
936
  import safeRegex from "safe-regex2";
794
937
  var MAX_ASSET_DEPTH = 100;
@@ -859,7 +1002,7 @@ var mapRoute = (route, entrypoints) => ({
859
1002
  negativeRequirements: route.missing,
860
1003
  status: route.statusCode
861
1004
  });
862
- var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projectFolder) {
1005
+ var parseEntrypoints = Effect12.fn("parseEntrypoints")(function* (config, projectFolder) {
863
1006
  const entrypoints = [];
864
1007
  if (config.functions == null) return entrypoints;
865
1008
  for (const [fnPath, func] of Object.entries(config.functions)) {
@@ -869,7 +1012,7 @@ var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projec
869
1012
  functionPath: fnPath
870
1013
  });
871
1014
  }
872
- const matchedFiles = yield* Effect10.tryPromise({
1015
+ const matchedFiles = yield* Effect12.tryPromise({
873
1016
  try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
874
1017
  catch: (error) => new FunctionConfigError({
875
1018
  message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
@@ -905,14 +1048,14 @@ var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projec
905
1048
  }
906
1049
  return entrypoints;
907
1050
  });
908
- var collectAssets = Effect10.fn("collectAssets")(function* (config, projectFolder) {
1051
+ var collectAssets = Effect12.fn("collectAssets")(function* (config, projectFolder) {
909
1052
  if (config.assets == null) return [];
910
- const fs = yield* FileSystem6.FileSystem;
911
- const pathService = yield* Path5.Path;
1053
+ const fs = yield* FileSystem8.FileSystem;
1054
+ const pathService = yield* Path7.Path;
912
1055
  const assetsPath = pathService.join(projectFolder, config.assets);
913
- const assetsExist = yield* fs.exists(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(false)));
1056
+ const assetsExist = yield* fs.exists(assetsPath).pipe(Effect12.catchAll(() => Effect12.succeed(false)));
914
1057
  if (!assetsExist) return [];
915
- const stat = yield* fs.stat(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
1058
+ const stat = yield* fs.stat(assetsPath).pipe(Effect12.catchAll(() => Effect12.succeed(null)));
916
1059
  if (!stat || stat.type !== "Directory") return [];
917
1060
  const allFiles = yield* collectFilesRecursively(assetsPath);
918
1061
  const assets = [];
@@ -923,18 +1066,18 @@ var collectAssets = Effect10.fn("collectAssets")(function* (config, projectFolde
923
1066
  }
924
1067
  return assets;
925
1068
  });
926
- var collectFilesRecursively = Effect10.fn("collectFilesRecursively")(
1069
+ var collectFilesRecursively = Effect12.fn("collectFilesRecursively")(
927
1070
  function* (basePath, relativePath = "", depth = 0) {
928
1071
  if (depth > MAX_ASSET_DEPTH) return [];
929
- const fs = yield* FileSystem6.FileSystem;
930
- const pathSvc = yield* Path5.Path;
1072
+ const fs = yield* FileSystem8.FileSystem;
1073
+ const pathSvc = yield* Path7.Path;
931
1074
  const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
932
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect10.catchAll(() => Effect10.succeed([])));
1075
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect12.catchAll(() => Effect12.succeed([])));
933
1076
  const result = [];
934
1077
  for (const name of entries) {
935
1078
  const fullPath = pathSvc.join(currentPath, name);
936
1079
  const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
937
- const stat = yield* fs.stat(fullPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
1080
+ const stat = yield* fs.stat(fullPath).pipe(Effect12.catchAll(() => Effect12.succeed(null)));
938
1081
  if (!stat) continue;
939
1082
  if (stat.type === "Directory") {
940
1083
  const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
@@ -946,16 +1089,16 @@ var collectFilesRecursively = Effect10.fn("collectFilesRecursively")(
946
1089
  return result;
947
1090
  }
948
1091
  );
949
- var V4ConfigParser = class extends Effect10.Service()("V4ConfigParser", {
1092
+ var V4ConfigParser = class extends Effect12.Service()("V4ConfigParser", {
950
1093
  accessors: true,
951
- effect: Effect10.succeed({
1094
+ effect: Effect12.succeed({
952
1095
  /**
953
1096
  * Parses a ConfigV4 into a NormalizedConfig.
954
1097
  *
955
1098
  * @param config - The raw V4 config object
956
1099
  * @param projectFolder - Absolute path to the project root
957
1100
  */
958
- parse: Effect10.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
1101
+ parse: Effect12.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
959
1102
  const entrypoints = yield* parseEntrypoints(config, projectFolder);
960
1103
  const assets = yield* collectAssets(config, projectFolder);
961
1104
  return {
@@ -979,10 +1122,10 @@ var V4ConfigParser = class extends Effect10.Service()("V4ConfigParser", {
979
1122
  };
980
1123
 
981
1124
  // src/services/vercel-build-output-parser.ts
982
- import { Path as Path7 } from "@effect/platform";
1125
+ import { Path as Path8 } from "@effect/platform";
983
1126
  import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
984
1127
  import { deepMerge } from "@gigadrive/commons";
985
- import { Effect as Effect12 } from "effect";
1128
+ import { Effect as Effect13 } from "effect";
986
1129
 
987
1130
  // src/build-output-v3/determine-repo-root.ts
988
1131
  import path from "path";
@@ -1017,37 +1160,6 @@ var determineRepoRoot = (projectFolder, config) => {
1017
1160
  return projectFolder;
1018
1161
  };
1019
1162
 
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
1163
  // src/build-output-v3/get-monorepo-files.ts
1052
1164
  function getMonorepoFiles(directory, filePathMaps) {
1053
1165
  const result = [];
@@ -1109,11 +1221,11 @@ var translateVercelRuntime = (runtime) => {
1109
1221
  var CONFIG_PATH = ".vercel/output/config.json";
1110
1222
  var FUNCTIONS_FOLDER = ".vercel/output/functions";
1111
1223
  var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
1112
- var VercelBuildOutputParser = class extends Effect12.Service()("VercelBuildOutputParser", {
1113
- effect: Effect12.gen(function* () {
1224
+ var VercelBuildOutputParser = class extends Effect13.Service()("VercelBuildOutputParser", {
1225
+ effect: Effect13.gen(function* () {
1114
1226
  const rawConfigReader = yield* RawConfigReader;
1115
- const pathService = yield* Path7.Path;
1116
- const parse = Effect12.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1227
+ const pathService = yield* Path8.Path;
1228
+ const parse = Effect13.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1117
1229
  const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
1118
1230
  if (!config || typeof config.version !== "number" || config.version < 3) {
1119
1231
  return parseResult;
@@ -1124,8 +1236,8 @@ var VercelBuildOutputParser = class extends Effect12.Service()("VercelBuildOutpu
1124
1236
  merged.regions = [...new Set(merged.regions)];
1125
1237
  return merged;
1126
1238
  });
1127
- const loadFunctions = Effect12.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1128
- const functionConfigs = yield* Effect12.tryPromise({
1239
+ const loadFunctions = Effect13.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1240
+ const functionConfigs = yield* Effect13.tryPromise({
1129
1241
  try: () => getFilesForPattern2(FUNCTION_CONFIGS_PATTERN, projectFolder),
1130
1242
  catch: (error) => new ConfigFileParseError({
1131
1243
  message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
@@ -1581,7 +1693,7 @@ var schema_default = {
1581
1693
  };
1582
1694
 
1583
1695
  // src/parse-config.ts
1584
- var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectFolder) {
1696
+ var parseConfigRaw = Effect14.fn("parseConfigRaw")(function* (filePath, projectFolder) {
1585
1697
  const rawReader = yield* RawConfigReader;
1586
1698
  const validator = yield* SchemaValidator;
1587
1699
  const v4Parser = yield* V4ConfigParser;
@@ -1592,7 +1704,7 @@ var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectF
1592
1704
  };
1593
1705
  const schema = schemaMap[version];
1594
1706
  if (!schema) {
1595
- return yield* Effect13.fail(
1707
+ return yield* Effect14.fail(
1596
1708
  new ConfigVersionError({
1597
1709
  message: `Config file at ${filePath} has an unsupported version: ${version}`,
1598
1710
  filePath,
@@ -1603,11 +1715,11 @@ var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectF
1603
1715
  yield* validator.validate(parsed, schema, filePath);
1604
1716
  return yield* v4Parser.parse(parsed, projectFolder);
1605
1717
  });
1606
- var parseConfig = Effect13.fn("parseConfig")(function* (filePath, projectFolder) {
1718
+ var parseConfig = Effect14.fn("parseConfig")(function* (filePath, projectFolder) {
1607
1719
  const parseResult = yield* parseConfigRaw(filePath, projectFolder);
1608
1720
  return yield* postProcessConfig(parseResult, projectFolder);
1609
1721
  });
1610
- var postProcessConfig = Effect13.fn("postProcessConfig")(function* (config, projectFolder) {
1722
+ var postProcessConfig = Effect14.fn("postProcessConfig")(function* (config, projectFolder) {
1611
1723
  const vercelParser = yield* VercelBuildOutputParser;
1612
1724
  let result = yield* vercelParser.parse(config, projectFolder);
1613
1725
  if (result.entrypoints.length === 0 && (result.assets?.paths?.length || 0) === 0 && result.routes.length === 0) {