@gigadrive/network-config 4.5.0 → 4.6.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
@@ -55,6 +55,9 @@ var StaticAssetManifestV1Schema = Schema2.mutable(
55
55
  ).pipe(Schema2.filter(({ assets }) => new Set(assets.map(({ path: path2 }) => path2)).size === assets.length));
56
56
  var parseStaticAssetManifest = (content) => decodeJson(StaticAssetManifestV1Schema, content);
57
57
 
58
+ // src/define-config.ts
59
+ var defineConfig = (config) => config;
60
+
58
61
  // src/detection/detect-framework.ts
59
62
  import { FileSystem as FileSystem8, Path as Path6 } from "@effect/platform";
60
63
  import { Effect as Effect10 } from "effect";
@@ -451,38 +454,60 @@ var ImagePolicySchema = Schema3.mutable(
451
454
  variants: Schema3.mutable(Schema3.Record({ key: Schema3.String, value: ImageVariantSchema }))
452
455
  })
453
456
  );
454
- var GigadriveNextPrerenderOutputSchema = Schema3.mutable(
455
- Schema3.Struct({
456
- id: Schema3.String,
457
- type: Schema3.Literal("PRERENDER"),
458
- pathname: UrlPathnameSchema,
459
- parentOutputId: Schema3.String,
460
- groupId: Schema3.Number,
461
- pprChain: Schema3.optional(Schema3.mutable(Schema3.Struct({ headers: HttpSingleValueHeadersSchema }))),
462
- parentFallbackMode: Schema3.optional(JsonValueSchema),
463
- fallback: Schema3.optional(
464
- Schema3.mutable(
465
- Schema3.Struct({
466
- filePath: Schema3.optional(PortableRelativePathSchema),
467
- initialStatus: Schema3.optional(Schema3.Int.pipe(Schema3.between(100, 599))),
468
- initialHeaders: Schema3.optional(HttpHeadersSchema),
469
- initialExpiration: Schema3.optional(Schema3.Number),
470
- initialRevalidate: Schema3.optional(Schema3.Union(Schema3.Number, Schema3.Literal(false))),
471
- postponedState: Schema3.optional(Schema3.String)
472
- })
473
- )
474
- ),
475
- config: Schema3.mutable(
457
+ var GigadriveNextPrerenderOutputFields = {
458
+ id: Schema3.String,
459
+ type: Schema3.Literal("PRERENDER"),
460
+ pathname: UrlPathnameSchema,
461
+ route: Schema3.optional(UrlPathnameSchema),
462
+ parentOutputId: Schema3.String,
463
+ groupId: Schema3.Number,
464
+ pprChain: Schema3.optional(Schema3.mutable(Schema3.Struct({ headers: HttpSingleValueHeadersSchema }))),
465
+ parentFallbackMode: Schema3.optional(JsonValueSchema),
466
+ fallback: Schema3.optional(
467
+ Schema3.mutable(
476
468
  Schema3.Struct({
477
- allowQuery: Schema3.optional(StringArraySchema),
478
- allowHeader: Schema3.optional(StringArraySchema),
479
- bypassFor: Schema3.optional(Schema3.mutable(Schema3.Array(JsonValueSchema))),
480
- renderingMode: Schema3.optional(Schema3.String),
481
- partialFallback: Schema3.optional(Schema3.Boolean),
482
- bypassToken: Schema3.optional(Schema3.String)
469
+ filePath: Schema3.optional(PortableRelativePathSchema),
470
+ initialStatus: Schema3.optional(Schema3.Int.pipe(Schema3.between(100, 599))),
471
+ initialHeaders: Schema3.optional(HttpHeadersSchema),
472
+ initialExpiration: Schema3.optional(Schema3.Number),
473
+ initialRevalidate: Schema3.optional(Schema3.Union(Schema3.Number, Schema3.Literal(false))),
474
+ postponedState: Schema3.optional(Schema3.String)
483
475
  })
484
476
  )
485
- })
477
+ ),
478
+ config: Schema3.mutable(
479
+ Schema3.Struct({
480
+ allowQuery: Schema3.optional(StringArraySchema),
481
+ allowHeader: Schema3.optional(StringArraySchema),
482
+ bypassFor: Schema3.optional(Schema3.mutable(Schema3.Array(JsonValueSchema))),
483
+ renderingMode: Schema3.optional(Schema3.String),
484
+ partialFallback: Schema3.optional(Schema3.Boolean),
485
+ bypassToken: Schema3.optional(Schema3.String)
486
+ })
487
+ )
488
+ };
489
+ var GigadriveNextPrerenderClassificationSchema = Schema3.Struct({
490
+ routeType: Schema3.Literal("route", "fallback", "shell", "page"),
491
+ response: Schema3.Literal("empty", "initial", "complete"),
492
+ compute: Schema3.Literal("blocking", "resuming", "static"),
493
+ htmlSize: Schema3.optional(Schema3.Number)
494
+ });
495
+ var GigadriveNextPrerenderWithoutClassificationSchema = Schema3.Struct({
496
+ routeType: Schema3.optional(Schema3.Never),
497
+ response: Schema3.optional(Schema3.Never),
498
+ compute: Schema3.optional(Schema3.Never),
499
+ htmlSize: Schema3.optional(Schema3.Never)
500
+ });
501
+ var GigadriveNextPrerenderOutputSchema = Schema3.Union(
502
+ Schema3.mutable(
503
+ Schema3.Struct({ ...GigadriveNextPrerenderOutputFields, ...GigadriveNextPrerenderClassificationSchema.fields })
504
+ ),
505
+ Schema3.mutable(
506
+ Schema3.Struct({
507
+ ...GigadriveNextPrerenderOutputFields,
508
+ ...GigadriveNextPrerenderWithoutClassificationSchema.fields
509
+ })
510
+ )
486
511
  );
487
512
  var GigadriveNextStaticAssetPrefixSchema = Schema3.mutable(
488
513
  Schema3.Struct({
@@ -491,6 +516,43 @@ var GigadriveNextStaticAssetPrefixSchema = Schema3.mutable(
491
516
  immutable: Schema3.Boolean
492
517
  })
493
518
  );
519
+ var GigadriveNextRouteConditionSchema = Schema3.Union(
520
+ Schema3.mutable(
521
+ Schema3.Struct({
522
+ type: Schema3.Literal("header", "cookie", "query"),
523
+ key: Schema3.String,
524
+ value: Schema3.optional(Schema3.String)
525
+ })
526
+ ),
527
+ Schema3.mutable(
528
+ Schema3.Struct({
529
+ type: Schema3.Literal("host"),
530
+ value: Schema3.String
531
+ })
532
+ )
533
+ );
534
+ var GigadriveNextMiddlewareMatcherSchema = Schema3.mutable(
535
+ Schema3.Struct({
536
+ source: Schema3.String,
537
+ sourceRegex: Schema3.String,
538
+ has: Schema3.optional(Schema3.mutable(Schema3.Array(GigadriveNextRouteConditionSchema))),
539
+ missing: Schema3.optional(Schema3.mutable(Schema3.Array(GigadriveNextRouteConditionSchema)))
540
+ })
541
+ );
542
+ var GigadriveNextMiddlewareDescriptorSchema = Schema3.Union(
543
+ Schema3.mutable(
544
+ Schema3.Struct({
545
+ present: Schema3.Literal(true),
546
+ matchers: Schema3.mutable(Schema3.Array(GigadriveNextMiddlewareMatcherSchema))
547
+ })
548
+ ),
549
+ Schema3.mutable(
550
+ Schema3.Struct({
551
+ present: Schema3.Literal(false),
552
+ matchers: Schema3.mutable(Schema3.Tuple())
553
+ })
554
+ )
555
+ );
494
556
  var GigadriveNextServerDescriptorSchema = Schema3.mutable(
495
557
  Schema3.Struct({
496
558
  maxDuration: Schema3.optional(Schema3.Number),
@@ -501,6 +563,9 @@ var GigadriveNextServerDescriptorSchema = Schema3.mutable(
501
563
  var PrerenderArraySchema = Schema3.mutable(Schema3.Array(GigadriveNextPrerenderOutputSchema));
502
564
  var StaticAssetArraySchema = Schema3.mutable(Schema3.Array(GigadriveNextStaticAssetPrefixSchema));
503
565
  var JsonValueArraySchema = Schema3.mutable(Schema3.Array(JsonValueSchema));
566
+ var GigadriveNextPrerenderSeedMethodsSchema = Schema3.mutable(
567
+ Schema3.Tuple(Schema3.Literal("GET"), Schema3.Literal("HEAD"))
568
+ );
504
569
  var GigadriveNextBuildManifestV1Schema = Schema3.mutable(
505
570
  Schema3.Struct({
506
571
  version: Schema3.Literal(1),
@@ -557,7 +622,8 @@ var GigadriveNextBuildManifestV2StandaloneSchema = Schema3.mutable(
557
622
  prerenderManifest: Schema3.optional(PortableRelativePathSchema),
558
623
  assetManifest: Schema3.optional(PortableRelativePathSchema),
559
624
  entryPagePaths: Schema3.optional(Schema3.mutable(Schema3.Array(UrlPathnameSchema))),
560
- staticAssets: StaticAssetArraySchema
625
+ staticAssets: StaticAssetArraySchema,
626
+ middleware: Schema3.optional(GigadriveNextMiddlewareDescriptorSchema)
561
627
  })
562
628
  )
563
629
  })
@@ -570,6 +636,7 @@ var GigadriveNextBuildManifestSchema = Schema3.Union(
570
636
  var GigadriveNextPrerenderManifestV1Schema = Schema3.mutable(
571
637
  Schema3.Struct({
572
638
  version: Schema3.Literal(1),
639
+ seedMethods: Schema3.optional(GigadriveNextPrerenderSeedMethodsSchema),
573
640
  prerenders: PrerenderArraySchema
574
641
  })
575
642
  );
@@ -1206,6 +1273,12 @@ var ConfigFileParseError = class extends Schema5.TaggedError()("ConfigFileParseE
1206
1273
  cause: Schema5.optional(Schema5.String)
1207
1274
  }) {
1208
1275
  };
1276
+ var ConfigModuleLoadError = class extends Schema5.TaggedError()("ConfigModuleLoadError", {
1277
+ message: Schema5.String,
1278
+ filePath: Schema5.String,
1279
+ cause: Schema5.optional(Schema5.String)
1280
+ }) {
1281
+ };
1209
1282
  var ConfigVersionError = class extends Schema5.TaggedError()("ConfigVersionError", {
1210
1283
  message: Schema5.String,
1211
1284
  filePath: Schema5.String,
@@ -1243,85 +1316,157 @@ var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
1243
1316
  var MAX_FUNCTION_DURATION_SECONDS = 28800;
1244
1317
 
1245
1318
  // src/parse-config.ts
1246
- import { Effect as Effect16 } from "effect";
1319
+ import { Effect as Effect17 } from "effect";
1247
1320
 
1248
1321
  // src/services/raw-config-reader.ts
1249
1322
  import { FileSystem as FileSystem9, Path as Path7 } from "@effect/platform";
1250
- import { Effect as Effect12 } from "effect";
1323
+ import { Effect as Effect13 } from "effect";
1251
1324
  import { parse as parseYaml } from "yaml";
1325
+
1326
+ // src/services/config-module-loader.ts
1327
+ import { Effect as Effect12 } from "effect";
1328
+ import { createJiti } from "jiti";
1329
+ var MISSING_DEFAULT_EXPORT = /* @__PURE__ */ Symbol("MissingDefaultExport");
1330
+ var STRICT_DEFAULT_EXPORT_EXTENSIONS = [".ts", ".mts", ".mjs"];
1331
+ var ConfigModuleLoader = class extends Effect12.Service()("ConfigModuleLoader", {
1332
+ effect: Effect12.gen(function* () {
1333
+ const loadConfigModule = Effect12.fn("ConfigModuleLoader.loadConfigModule")(function* (filePath) {
1334
+ const extension = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
1335
+ const mod = yield* Effect12.tryPromise({
1336
+ try: async () => {
1337
+ const jiti = createJiti(filePath, { fsCache: false, interopDefault: true, moduleCache: false });
1338
+ const namespace = await jiti.import(filePath);
1339
+ if (typeof namespace === "object" && namespace !== null && "default" in namespace) {
1340
+ return namespace.default;
1341
+ }
1342
+ if (!STRICT_DEFAULT_EXPORT_EXTENSIONS.includes(extension)) {
1343
+ return namespace.default ?? MISSING_DEFAULT_EXPORT;
1344
+ }
1345
+ return MISSING_DEFAULT_EXPORT;
1346
+ },
1347
+ catch: (error) => new ConfigModuleLoadError({
1348
+ message: `Failed to load config module at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
1349
+ filePath,
1350
+ cause: error instanceof Error ? error.message : void 0
1351
+ })
1352
+ });
1353
+ if (mod === MISSING_DEFAULT_EXPORT) {
1354
+ return yield* Effect12.fail(
1355
+ new ConfigModuleLoadError({
1356
+ message: `Config module at ${filePath} does not have a default export. Export the config object as the default export (or via module.exports for CommonJS files), optionally wrapped in defineConfig.`,
1357
+ filePath
1358
+ })
1359
+ );
1360
+ }
1361
+ if (typeof mod === "function") {
1362
+ return yield* Effect12.fail(
1363
+ new ConfigModuleLoadError({
1364
+ message: `Config module at ${filePath} default-exports a function; config factories are not supported. Export a config object instead (optionally wrapped in defineConfig).`,
1365
+ filePath
1366
+ })
1367
+ );
1368
+ }
1369
+ if (typeof mod !== "object" || mod === null || Array.isArray(mod)) {
1370
+ return yield* Effect12.fail(
1371
+ new ConfigModuleLoadError({
1372
+ message: `Config module at ${filePath} must default-export a config object.`,
1373
+ filePath
1374
+ })
1375
+ );
1376
+ }
1377
+ return mod;
1378
+ });
1379
+ return { loadConfigModule };
1380
+ })
1381
+ }) {
1382
+ };
1383
+
1384
+ // src/services/raw-config-reader.ts
1252
1385
  var ALLOWED_CONFIG_NAMES = [
1386
+ "gigadrive.ts",
1387
+ "gigadrive.mts",
1388
+ "gigadrive.cts",
1389
+ "gigadrive.js",
1390
+ "gigadrive.mjs",
1391
+ "gigadrive.cjs",
1253
1392
  "gigadrive.yaml",
1254
1393
  "gigadrive.yml",
1394
+ "gigadrive.json",
1255
1395
  "nebula.yaml",
1256
1396
  "nebula.yml",
1257
1397
  "nebula.json"
1258
1398
  ];
1259
- var RawConfigReader = class extends Effect12.Service()("RawConfigReader", {
1260
- effect: Effect12.gen(function* () {
1399
+ var MODULE_EXTENSIONS = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
1400
+ var RawConfigReader = class extends Effect13.Service()("RawConfigReader", {
1401
+ dependencies: [ConfigModuleLoader.Default],
1402
+ effect: Effect13.gen(function* () {
1261
1403
  const fs = yield* FileSystem9.FileSystem;
1262
1404
  const pathService = yield* Path7.Path;
1263
- const findConfig = Effect12.fn("RawConfigReader.findConfig")(function* (projectFolder) {
1405
+ const moduleLoader = yield* ConfigModuleLoader;
1406
+ const findConfig = Effect13.fn("RawConfigReader.findConfig")(function* (projectFolder) {
1264
1407
  for (const name of ALLOWED_CONFIG_NAMES) {
1265
1408
  const filePath = pathService.join(projectFolder, name);
1266
- const exists = yield* fs.exists(filePath).pipe(Effect12.catchAll(() => Effect12.succeed(false)));
1409
+ const exists = yield* fs.exists(filePath).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
1267
1410
  if (exists) {
1268
1411
  return filePath;
1269
1412
  }
1270
1413
  }
1271
1414
  return null;
1272
1415
  });
1273
- const readRawConfig = Effect12.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
1274
- const exists = yield* fs.exists(filePath).pipe(Effect12.catchAll(() => Effect12.succeed(false)));
1416
+ const readRawConfig = Effect13.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
1417
+ const exists = yield* fs.exists(filePath).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
1275
1418
  if (!exists) {
1276
- return yield* Effect12.fail(
1419
+ return yield* Effect13.fail(
1277
1420
  new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
1278
1421
  );
1279
1422
  }
1280
1423
  const fileContents = yield* fs.readFileString(filePath).pipe(
1281
- Effect12.mapError(
1424
+ Effect13.mapError(
1282
1425
  () => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
1283
1426
  )
1284
1427
  );
1285
1428
  if (fileContents.length === 0) {
1286
- return yield* Effect12.fail(
1429
+ return yield* Effect13.fail(
1287
1430
  new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
1288
1431
  );
1289
1432
  }
1290
1433
  const fileExtension = pathService.extname(filePath).toLowerCase();
1291
1434
  let parsed;
1292
- try {
1293
- if (fileExtension === ".json") {
1294
- parsed = JSON.parse(fileContents);
1295
- } else if ([".yml", ".yaml"].includes(fileExtension)) {
1296
- parsed = parseYaml(fileContents);
1297
- } else {
1298
- parsed = parseYaml(fileContents);
1435
+ if (MODULE_EXTENSIONS.includes(fileExtension)) {
1436
+ parsed = yield* moduleLoader.loadConfigModule(filePath);
1437
+ } else {
1438
+ try {
1439
+ if (fileExtension === ".json") {
1440
+ parsed = JSON.parse(fileContents);
1441
+ } else {
1442
+ parsed = parseYaml(fileContents);
1443
+ }
1444
+ } catch (error) {
1445
+ return yield* Effect13.fail(
1446
+ new ConfigFileParseError({
1447
+ message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
1448
+ filePath,
1449
+ cause: error instanceof Error ? error.message : void 0
1450
+ })
1451
+ );
1299
1452
  }
1300
- } catch (error) {
1301
- return yield* Effect12.fail(
1302
- new ConfigFileParseError({
1303
- message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
1304
- filePath,
1305
- cause: error instanceof Error ? error.message : void 0
1306
- })
1307
- );
1308
1453
  }
1309
1454
  if (parsed == null) {
1310
- return yield* Effect12.fail(
1455
+ return yield* Effect13.fail(
1311
1456
  new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
1312
1457
  );
1313
1458
  }
1314
1459
  if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
1315
- return yield* Effect12.fail(
1460
+ return yield* Effect13.fail(
1316
1461
  new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
1317
1462
  );
1318
1463
  }
1319
1464
  return parsed;
1320
1465
  });
1321
1466
  const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
1322
- Effect12.map((parsed) => parsed),
1323
- Effect12.catchTag("ConfigFileNotFoundError", () => Effect12.succeed(null)),
1324
- Effect12.withSpan("RawConfigReader.readConfigFile")
1467
+ Effect13.map((parsed) => parsed),
1468
+ Effect13.catchTag("ConfigFileNotFoundError", () => Effect13.succeed(null)),
1469
+ Effect13.withSpan("RawConfigReader.readConfigFile")
1325
1470
  );
1326
1471
  return { findConfig, readRawConfig, readConfigFile };
1327
1472
  })
@@ -1331,17 +1476,17 @@ var RawConfigReader = class extends Effect12.Service()("RawConfigReader", {
1331
1476
  // src/services/schema-validator.ts
1332
1477
  import Ajv from "ajv";
1333
1478
  import addFormats from "ajv-formats";
1334
- import { Effect as Effect13 } from "effect";
1335
- var SchemaValidator = class extends Effect13.Service()("SchemaValidator", {
1336
- effect: Effect13.gen(function* () {
1479
+ import { Effect as Effect14 } from "effect";
1480
+ var SchemaValidator = class extends Effect14.Service()("SchemaValidator", {
1481
+ effect: Effect14.gen(function* () {
1337
1482
  const ajv = new Ajv();
1338
1483
  addFormats(ajv);
1339
- const validate = Effect13.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
1484
+ const validate = Effect14.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
1340
1485
  const compiledValidate = ajv.compile(schema);
1341
1486
  const valid = compiledValidate(config);
1342
1487
  if (!valid) {
1343
1488
  const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
1344
- return yield* Effect13.fail(
1489
+ return yield* Effect14.fail(
1345
1490
  new ConfigSchemaValidationError({
1346
1491
  message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
1347
1492
  filePath,
@@ -1357,9 +1502,51 @@ var SchemaValidator = class extends Effect13.Service()("SchemaValidator", {
1357
1502
 
1358
1503
  // src/services/v4-config-parser.ts
1359
1504
  import { FileSystem as FileSystem10, Path as Path8 } from "@effect/platform";
1360
- import { getFilesForPattern } from "@gigadrive/build-utils";
1361
- import { Effect as Effect14 } from "effect";
1505
+
1506
+ // ../build-utils/src/get-files-for-pattern.ts
1362
1507
  import { minimatch } from "minimatch";
1508
+ import { readdir } from "fs/promises";
1509
+ var getFilesForPattern = async (pattern, projectFolder, excludeFiles = []) => {
1510
+ const files = [];
1511
+ const filesInFolder = await readdir(projectFolder, { recursive: true });
1512
+ const exactFiles = new Set(filesInFolder.filter((file) => typeof file === "string"));
1513
+ let regex = null;
1514
+ if (!exactFiles.has(pattern)) {
1515
+ try {
1516
+ regex = new RegExp(`^(?:${pattern})$`);
1517
+ } catch {
1518
+ }
1519
+ }
1520
+ const finalExclusions = Array.isArray(excludeFiles) ? excludeFiles : [excludeFiles];
1521
+ for (const file of filesInFolder) {
1522
+ if (typeof file !== "string") {
1523
+ continue;
1524
+ }
1525
+ if (finalExclusions.some((excludeFile) => {
1526
+ if (minimatch(file, excludeFile)) {
1527
+ return true;
1528
+ }
1529
+ if (!exactFiles.has(excludeFile)) {
1530
+ try {
1531
+ return new RegExp(`^(?:${excludeFile})$`).test(file);
1532
+ } catch {
1533
+ return false;
1534
+ }
1535
+ }
1536
+ return false;
1537
+ })) {
1538
+ continue;
1539
+ }
1540
+ if (minimatch(file, pattern) || regex != null && regex.test(file)) {
1541
+ files.push(file);
1542
+ }
1543
+ }
1544
+ return files;
1545
+ };
1546
+
1547
+ // src/services/v4-config-parser.ts
1548
+ import { Effect as Effect15 } from "effect";
1549
+ import { minimatch as minimatch2 } from "minimatch";
1363
1550
  import safeRegex from "safe-regex2";
1364
1551
  var MAX_ASSET_DEPTH = 100;
1365
1552
  var DISALLOWED_ASSET_EXTENSIONS = [".htaccess", ".htpasswd"];
@@ -1424,7 +1611,7 @@ var destinationMatchesEntrypoint = (destination, entrypointPath) => {
1424
1611
  return new RegExp(`^${pattern}$`).test(entrypointPath);
1425
1612
  };
1426
1613
  var matchesPattern = (path2, pattern) => {
1427
- if (minimatch(path2, pattern)) return true;
1614
+ if (minimatch2(path2, pattern)) return true;
1428
1615
  try {
1429
1616
  if (safeRegex(pattern)) {
1430
1617
  return new RegExp(pattern).test(path2);
@@ -1464,7 +1651,7 @@ var mapRoute = (route, entrypoints) => ({
1464
1651
  negativeRequirements: route.missing,
1465
1652
  status: route.statusCode
1466
1653
  });
1467
- var parseEntrypoints = Effect14.fn("parseEntrypoints")(function* (config, projectFolder) {
1654
+ var parseEntrypoints = Effect15.fn("parseEntrypoints")(function* (config, projectFolder) {
1468
1655
  const entrypoints = [];
1469
1656
  if (config.functions == null) return entrypoints;
1470
1657
  for (const [fnPath, func] of Object.entries(config.functions)) {
@@ -1474,7 +1661,7 @@ var parseEntrypoints = Effect14.fn("parseEntrypoints")(function* (config, projec
1474
1661
  functionPath: fnPath
1475
1662
  });
1476
1663
  }
1477
- const matchedFiles = yield* Effect14.tryPromise({
1664
+ const matchedFiles = yield* Effect15.tryPromise({
1478
1665
  try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
1479
1666
  catch: (error) => new FunctionConfigError({
1480
1667
  message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
@@ -1510,14 +1697,14 @@ var parseEntrypoints = Effect14.fn("parseEntrypoints")(function* (config, projec
1510
1697
  }
1511
1698
  return entrypoints;
1512
1699
  });
1513
- var collectAssets = Effect14.fn("collectAssets")(function* (config, projectFolder) {
1700
+ var collectAssets = Effect15.fn("collectAssets")(function* (config, projectFolder) {
1514
1701
  if (config.assets == null) return [];
1515
1702
  const fs = yield* FileSystem10.FileSystem;
1516
1703
  const pathService = yield* Path8.Path;
1517
1704
  const assetsPath = pathService.join(projectFolder, config.assets);
1518
- const assetsExist = yield* fs.exists(assetsPath).pipe(Effect14.catchAll(() => Effect14.succeed(false)));
1705
+ const assetsExist = yield* fs.exists(assetsPath).pipe(Effect15.catchAll(() => Effect15.succeed(false)));
1519
1706
  if (!assetsExist) return [];
1520
- const stat = yield* fs.stat(assetsPath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1707
+ const stat = yield* fs.stat(assetsPath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1521
1708
  if (!stat || stat.type !== "Directory") return [];
1522
1709
  const allFiles = yield* collectFilesRecursively(assetsPath);
1523
1710
  const assets = [];
@@ -1528,18 +1715,18 @@ var collectAssets = Effect14.fn("collectAssets")(function* (config, projectFolde
1528
1715
  }
1529
1716
  return assets;
1530
1717
  });
1531
- var collectFilesRecursively = Effect14.fn("collectFilesRecursively")(
1718
+ var collectFilesRecursively = Effect15.fn("collectFilesRecursively")(
1532
1719
  function* (basePath, relativePath = "", depth = 0) {
1533
1720
  if (depth > MAX_ASSET_DEPTH) return [];
1534
1721
  const fs = yield* FileSystem10.FileSystem;
1535
1722
  const pathSvc = yield* Path8.Path;
1536
1723
  const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
1537
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect14.catchAll(() => Effect14.succeed([])));
1724
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect15.catchAll(() => Effect15.succeed([])));
1538
1725
  const result = [];
1539
1726
  for (const name of entries) {
1540
1727
  const fullPath = pathSvc.join(currentPath, name);
1541
1728
  const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
1542
- const stat = yield* fs.stat(fullPath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1729
+ const stat = yield* fs.stat(fullPath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1543
1730
  if (!stat) continue;
1544
1731
  if (stat.type === "Directory") {
1545
1732
  const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
@@ -1551,16 +1738,16 @@ var collectFilesRecursively = Effect14.fn("collectFilesRecursively")(
1551
1738
  return result;
1552
1739
  }
1553
1740
  );
1554
- var V4ConfigParser = class extends Effect14.Service()("V4ConfigParser", {
1741
+ var V4ConfigParser = class extends Effect15.Service()("V4ConfigParser", {
1555
1742
  accessors: true,
1556
- effect: Effect14.succeed({
1743
+ effect: Effect15.succeed({
1557
1744
  /**
1558
1745
  * Parses a ConfigV4 into a NormalizedConfig.
1559
1746
  *
1560
1747
  * @param config - The raw V4 config object
1561
1748
  * @param projectFolder - Absolute path to the project root
1562
1749
  */
1563
- parse: Effect14.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
1750
+ parse: Effect15.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
1564
1751
  const entrypoints = yield* parseEntrypoints(config, projectFolder);
1565
1752
  const assets = yield* collectAssets(config, projectFolder);
1566
1753
  return {
@@ -1587,9 +1774,35 @@ var V4ConfigParser = class extends Effect14.Service()("V4ConfigParser", {
1587
1774
 
1588
1775
  // src/services/vercel-build-output-parser.ts
1589
1776
  import { Path as Path9 } from "@effect/platform";
1590
- import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
1591
- import { deepMerge } from "@gigadrive/commons";
1592
- import { Effect as Effect15 } from "effect";
1777
+
1778
+ // ../commons/src/deep-merge.ts
1779
+ var deepMerge = (target, ...partials) => {
1780
+ const isObject = (item) => item !== null && typeof item === "object";
1781
+ if (!isObject(target)) {
1782
+ return target;
1783
+ }
1784
+ for (const partial of partials) {
1785
+ if (!isObject(partial)) {
1786
+ continue;
1787
+ }
1788
+ Object.keys(partial).forEach((key) => {
1789
+ if (key === "__proto__" || key === "constructor") return;
1790
+ const targetValue = target[key];
1791
+ const sourceValue = partial[key];
1792
+ if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
1793
+ targetValue.push(...sourceValue);
1794
+ } else if (isObject(targetValue) && isObject(sourceValue)) {
1795
+ deepMerge(targetValue, sourceValue);
1796
+ } else {
1797
+ target[key] = sourceValue;
1798
+ }
1799
+ });
1800
+ }
1801
+ return target;
1802
+ };
1803
+
1804
+ // src/services/vercel-build-output-parser.ts
1805
+ import { Effect as Effect16 } from "effect";
1593
1806
 
1594
1807
  // src/build-output-v3/determine-repo-root.ts
1595
1808
  import path from "path";
@@ -1685,11 +1898,11 @@ var translateVercelRuntime = (runtime) => {
1685
1898
  var CONFIG_PATH = ".vercel/output/config.json";
1686
1899
  var FUNCTIONS_FOLDER = ".vercel/output/functions";
1687
1900
  var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
1688
- var VercelBuildOutputParser = class extends Effect15.Service()("VercelBuildOutputParser", {
1689
- effect: Effect15.gen(function* () {
1901
+ var VercelBuildOutputParser = class extends Effect16.Service()("VercelBuildOutputParser", {
1902
+ effect: Effect16.gen(function* () {
1690
1903
  const rawConfigReader = yield* RawConfigReader;
1691
1904
  const pathService = yield* Path9.Path;
1692
- const parse = Effect15.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1905
+ const parse = Effect16.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1693
1906
  const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
1694
1907
  if (!config || typeof config.version !== "number" || config.version < 3) {
1695
1908
  return parseResult;
@@ -1701,9 +1914,9 @@ var VercelBuildOutputParser = class extends Effect15.Service()("VercelBuildOutpu
1701
1914
  merged.regions = [...new Set(merged.regions)];
1702
1915
  return merged;
1703
1916
  });
1704
- const loadFunctions = Effect15.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1705
- const functionConfigs = yield* Effect15.tryPromise({
1706
- try: () => getFilesForPattern2(FUNCTION_CONFIGS_PATTERN, projectFolder),
1917
+ const loadFunctions = Effect16.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1918
+ const functionConfigs = yield* Effect16.tryPromise({
1919
+ try: () => getFilesForPattern(FUNCTION_CONFIGS_PATTERN, projectFolder),
1707
1920
  catch: (error) => new ConfigFileParseError({
1708
1921
  message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
1709
1922
  filePath: projectFolder
@@ -2301,7 +2514,7 @@ var schema_default = {
2301
2514
  };
2302
2515
 
2303
2516
  // src/parse-config.ts
2304
- var parseConfigRaw = Effect16.fn("parseConfigRaw")(function* (filePath, projectFolder) {
2517
+ var parseConfigRaw = Effect17.fn("parseConfigRaw")(function* (filePath, projectFolder) {
2305
2518
  const rawReader = yield* RawConfigReader;
2306
2519
  const validator = yield* SchemaValidator;
2307
2520
  const v4Parser = yield* V4ConfigParser;
@@ -2312,7 +2525,7 @@ var parseConfigRaw = Effect16.fn("parseConfigRaw")(function* (filePath, projectF
2312
2525
  };
2313
2526
  const schema = schemaMap[version];
2314
2527
  if (!schema) {
2315
- return yield* Effect16.fail(
2528
+ return yield* Effect17.fail(
2316
2529
  new ConfigVersionError({
2317
2530
  message: `Config file at ${filePath} has an unsupported version: ${version}`,
2318
2531
  filePath,
@@ -2323,11 +2536,11 @@ var parseConfigRaw = Effect16.fn("parseConfigRaw")(function* (filePath, projectF
2323
2536
  yield* validator.validate(parsed, schema, filePath);
2324
2537
  return yield* v4Parser.parse(parsed, projectFolder);
2325
2538
  });
2326
- var parseConfig = Effect16.fn("parseConfig")(function* (filePath, projectFolder) {
2539
+ var parseConfig = Effect17.fn("parseConfig")(function* (filePath, projectFolder) {
2327
2540
  const parseResult = yield* parseConfigRaw(filePath, projectFolder);
2328
2541
  return yield* postProcessConfig(parseResult, projectFolder);
2329
2542
  });
2330
- var postProcessConfig = Effect16.fn("postProcessConfig")(function* (config, projectFolder) {
2543
+ var postProcessConfig = Effect17.fn("postProcessConfig")(function* (config, projectFolder) {
2331
2544
  const vercelParser = yield* VercelBuildOutputParser;
2332
2545
  let result = yield* vercelParser.parse(config, projectFolder);
2333
2546
  const hasAssets = (result.assets?.paths?.length ?? 0) > 0 || (result.assets?.prefixes?.length ?? 0) > 0 || (result.assets?.manifests?.length ?? 0) > 0;
@@ -2357,7 +2570,12 @@ var AVAILABLE_RUNTIMES = [...RUNTIME_DEFINITIONS];
2357
2570
 
2358
2571
  // src/services/index.ts
2359
2572
  import { Layer } from "effect";
2360
- var BaseLayers = Layer.mergeAll(RawConfigReader.Default, SchemaValidator.Default, V4ConfigParser.Default);
2573
+ var BaseLayers = Layer.mergeAll(
2574
+ ConfigModuleLoader.Default,
2575
+ RawConfigReader.Default,
2576
+ SchemaValidator.Default,
2577
+ V4ConfigParser.Default
2578
+ );
2361
2579
  var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(Layer.provideMerge(BaseLayers));
2362
2580
  export {
2363
2581
  ALLOWED_CONFIG_NAMES,
@@ -2366,6 +2584,8 @@ export {
2366
2584
  ConfigFileEmptyError,
2367
2585
  ConfigFileNotFoundError,
2368
2586
  ConfigFileParseError,
2587
+ ConfigModuleLoadError,
2588
+ ConfigModuleLoader,
2369
2589
  ConfigSchemaValidationError,
2370
2590
  ConfigVersionError,
2371
2591
  DEFAULT_FUNCTION_DURATION_SECONDS,
@@ -2376,8 +2596,12 @@ export {
2376
2596
  GigadriveNextBuildManifestV1Schema,
2377
2597
  GigadriveNextBuildManifestV2ExportSchema,
2378
2598
  GigadriveNextBuildManifestV2StandaloneSchema,
2599
+ GigadriveNextMiddlewareDescriptorSchema,
2600
+ GigadriveNextMiddlewareMatcherSchema,
2379
2601
  GigadriveNextPrerenderManifestV1Schema,
2380
2602
  GigadriveNextPrerenderOutputSchema,
2603
+ GigadriveNextPrerenderSeedMethodsSchema,
2604
+ GigadriveNextRouteConditionSchema,
2381
2605
  GigadriveNextServerDescriptorSchema,
2382
2606
  GigadriveNextStaticAssetPrefixSchema,
2383
2607
  MAX_FUNCTION_DURATION_SECONDS,
@@ -2392,6 +2616,7 @@ export {
2392
2616
  StaticAssetManifestV1Schema,
2393
2617
  V4ConfigParser,
2394
2618
  VercelBuildOutputParser,
2619
+ defineConfig,
2395
2620
  detectFramework,
2396
2621
  detectPackageManager,
2397
2622
  filterFunctionsFromAssets,