@gigadrive/network-config 4.4.0 → 4.6.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,3 +1,63 @@
1
+ // src/asset-manifest.ts
2
+ import { Schema as Schema2 } from "effect";
3
+
4
+ // src/manifest-schema.ts
5
+ import { Option, Schema } from "effect";
6
+ var HTTP_HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
7
+ var HTTP_HEADER_VALUE = /^[\t\x20-\x7e\x80-\xff]*$/;
8
+ var URL_PATHNAME_FORBIDDEN_CHARACTER = /[\x00-\x1f\x7f?#\\]/;
9
+ var isUrlDotSegment = (segment) => {
10
+ const decodedDots = segment.replace(/%2e/gi, ".");
11
+ return decodedDots === "." || decodedDots === "..";
12
+ };
13
+ var isPortableRelativePath = (value, allowCurrentDirectory = false) => {
14
+ const normalized = value.replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/+$/, "");
15
+ return (allowCurrentDirectory || normalized !== "" && normalized !== ".") && !normalized.startsWith("/") && !/^[A-Za-z]:/.test(normalized) && !normalized.includes(":") && !normalized.split("/").includes("..");
16
+ };
17
+ var PortableRelativePathSchema = Schema.String.pipe(Schema.filter((value) => isPortableRelativePath(value)));
18
+ var RepositoryRelativePathSchema = Schema.String.pipe(
19
+ Schema.filter((value) => isPortableRelativePath(value, true))
20
+ );
21
+ var UrlPathnameSchema = Schema.String.pipe(
22
+ Schema.filter(
23
+ (value) => value.startsWith("/") && !URL_PATHNAME_FORBIDDEN_CHARACTER.test(value) && !value.split("/").some(isUrlDotSegment)
24
+ )
25
+ );
26
+ var HttpHeaderValueSchema = Schema.String.pipe(Schema.pattern(HTTP_HEADER_VALUE));
27
+ var HttpHeadersSchema = Schema.mutable(
28
+ Schema.Record({
29
+ key: Schema.String,
30
+ value: Schema.Union(HttpHeaderValueSchema, Schema.mutable(Schema.Array(HttpHeaderValueSchema)))
31
+ })
32
+ ).pipe(Schema.filter((headers) => Object.keys(headers).every((name) => HTTP_HEADER_NAME.test(name))));
33
+ var HttpSingleValueHeadersSchema = Schema.mutable(
34
+ Schema.Record({ key: Schema.String, value: HttpHeaderValueSchema })
35
+ ).pipe(Schema.filter((headers) => Object.keys(headers).every((name) => HTTP_HEADER_NAME.test(name))));
36
+ var decodeUnknown = (schema, value) => Schema.decodeUnknownOption(schema, { onExcessProperty: "preserve" })(value).pipe(Option.getOrUndefined);
37
+ var decodeJson = (schema, content) => decodeUnknown(Schema.parseJson(schema), content);
38
+
39
+ // src/asset-manifest.ts
40
+ var StaticAssetHeadersSchema = HttpHeadersSchema;
41
+ var StaticAssetManifestEntrySchema = Schema2.mutable(
42
+ Schema2.Struct({
43
+ source: PortableRelativePathSchema,
44
+ path: UrlPathnameSchema,
45
+ status: Schema2.optional(Schema2.Int.pipe(Schema2.between(100, 599))),
46
+ headers: Schema2.optional(StaticAssetHeadersSchema),
47
+ immutable: Schema2.optional(Schema2.Boolean)
48
+ })
49
+ );
50
+ var StaticAssetManifestV1Schema = Schema2.mutable(
51
+ Schema2.Struct({
52
+ version: Schema2.Literal(1),
53
+ assets: Schema2.mutable(Schema2.Array(StaticAssetManifestEntrySchema))
54
+ })
55
+ ).pipe(Schema2.filter(({ assets }) => new Set(assets.map(({ path: path2 }) => path2)).size === assets.length));
56
+ var parseStaticAssetManifest = (content) => decodeJson(StaticAssetManifestV1Schema, content);
57
+
58
+ // src/define-config.ts
59
+ var defineConfig = (config) => config;
60
+
1
61
  // src/detection/detect-framework.ts
2
62
  import { FileSystem as FileSystem8, Path as Path6 } from "@effect/platform";
3
63
  import { Effect as Effect10 } from "effect";
@@ -335,54 +395,189 @@ var getDefaultPathMap = Effect4.fn("getDefaultPathMap")(function* (directory) {
335
395
  return result;
336
396
  });
337
397
 
398
+ // src/nextjs-constants.ts
399
+ var MAXIMUM_ENTRY_PAGE_PATHS = 50;
400
+
338
401
  // src/nextjs-manifest.ts
339
- var isRecord3 = (value) => typeof value === "object" && value !== null;
340
- var isPortableRelativePath = (value, allowCurrentDirectory = false) => {
341
- if (typeof value !== "string") return false;
342
- const normalized = value.replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/+$/, "");
343
- return (allowCurrentDirectory || normalized !== "" && normalized !== ".") && !normalized.startsWith("/") && !/^[A-Za-z]:/.test(normalized) && !normalized.includes(":") && !normalized.split("/").some((segment) => segment === "..");
344
- };
345
- var isStringRecord = (value) => isRecord3(value) && Object.values(value).every((item) => typeof item === "string");
346
- var isJsonValue = (value) => {
347
- if (value === null || typeof value === "string" || typeof value === "boolean") return true;
348
- if (typeof value === "number") return Number.isFinite(value);
349
- if (Array.isArray(value)) return value.every(isJsonValue);
350
- return isRecord3(value) && Object.values(value).every(isJsonValue);
351
- };
352
- var isPrerenderOutput = (value) => isRecord3(value) && value.type === "PRERENDER" && typeof value.id === "string" && typeof value.pathname === "string" && typeof value.parentOutputId === "string" && typeof value.groupId === "number" && isRecord3(value.config) && (value.fallback === void 0 || isRecord3(value.fallback) && (value.fallback.filePath === void 0 || isPortableRelativePath(value.fallback.filePath)));
353
- var isStaticAssetPrefix = (value) => isRecord3(value) && isPortableRelativePath(value.sourceDir) && isPortableRelativePath(value.urlPrefix) && typeof value.immutable === "boolean";
354
- var isServerDescriptor = (value) => isRecord3(value) && (value.maxDuration === void 0 || typeof value.maxDuration === "number") && (value.preferredRegion === void 0 || typeof value.preferredRegion === "string" || Array.isArray(value.preferredRegion) && value.preferredRegion.every((region) => typeof region === "string")) && (value.env === void 0 || isStringRecord(value.env));
355
- var isImagePolicy = (value) => isRecord3(value) && Array.isArray(value.localPatterns) && Array.isArray(value.remotePatterns) && value.remotePatterns.every((pattern) => isRecord3(pattern) && typeof pattern.hostname === "string") && Array.isArray(value.widths) && value.widths.every((item) => typeof item === "number" && Number.isInteger(item) && item > 0) && Array.isArray(value.heights) && value.heights.every((item) => typeof item === "number" && Number.isInteger(item) && item > 0) && Array.isArray(value.qualities) && value.qualities.every((item) => typeof item === "number" && item >= 1 && item <= 100) && Array.isArray(value.formats) && value.formats.every((item) => ["image/avif", "image/webp", "image/jpeg", "image/png"].includes(String(item))) && typeof value.minimumCacheTTL === "number" && typeof value.dangerouslyAllowSVG === "boolean" && typeof value.contentSecurityPolicy === "string" && (value.contentDispositionType === "inline" || value.contentDispositionType === "attachment") && typeof value.maximumRedirects === "number" && typeof value.maximumResponseBody === "number" && isRecord3(value.variants);
356
- var parseGigadriveNextBuildManifest = (content) => {
357
- try {
358
- const value = JSON.parse(content);
359
- if (!isRecord3(value)) return void 0;
360
- if (value.version === 1) {
361
- if (value.output !== "standalone" && value.output !== "export" || !isPortableRelativePath(value.distDir) || !isPortableRelativePath(value.repoRootToProject, true) || typeof value.nextVersion !== "string" || typeof value.buildId !== "string") {
362
- return void 0;
363
- }
364
- return value;
365
- }
366
- if (value.version === 2) {
367
- if (!isPortableRelativePath(value.distDir) || !isPortableRelativePath(value.repoRootToProject, true) || typeof value.nextVersion !== "string" || typeof value.buildId !== "string") {
368
- return void 0;
369
- }
370
- if (value.mode === "export") {
371
- return value;
372
- }
373
- if (value.mode === "standalone-v2") {
374
- if (!isServerDescriptor(value.server) || !isRecord3(value.config) || typeof value.config.basePath !== "string" || typeof value.config.trailingSlash !== "boolean" || typeof value.config.cacheComponents !== "boolean" || value.config.images !== void 0 && !isImagePolicy(value.config.images) || !isRecord3(value.routing) || !isJsonValue(value.routing) || !isRecord3(value.outputs) || !Array.isArray(value.outputs.prerenders) || !value.outputs.prerenders.every(isPrerenderOutput) || !Array.isArray(value.outputs.staticAssets) || !value.outputs.staticAssets.every(isStaticAssetPrefix)) {
375
- return void 0;
376
- }
377
- return value;
378
- }
379
- return void 0;
380
- }
381
- return void 0;
382
- } catch {
383
- return void 0;
384
- }
385
- };
402
+ import { Schema as Schema3 } from "effect";
403
+ var StringArraySchema = Schema3.mutable(Schema3.Array(Schema3.String));
404
+ var StringRecordSchema = Schema3.mutable(Schema3.Record({ key: Schema3.String, value: Schema3.String }));
405
+ var JsonValueSchema = Schema3.suspend(
406
+ () => Schema3.Union(
407
+ Schema3.Null,
408
+ Schema3.Boolean,
409
+ Schema3.Number,
410
+ Schema3.String,
411
+ Schema3.mutable(Schema3.Array(JsonValueSchema)),
412
+ Schema3.mutable(Schema3.Record({ key: Schema3.String, value: JsonValueSchema }))
413
+ )
414
+ );
415
+ var ImageLocalPatternSchema = Schema3.mutable(
416
+ Schema3.Struct({
417
+ pathname: Schema3.optional(Schema3.String),
418
+ search: Schema3.optional(Schema3.String)
419
+ })
420
+ );
421
+ var ImageRemotePatternSchema = Schema3.mutable(
422
+ Schema3.Struct({
423
+ protocol: Schema3.optional(Schema3.Literal("http", "https")),
424
+ hostname: Schema3.String,
425
+ port: Schema3.optional(Schema3.String),
426
+ pathname: Schema3.optional(Schema3.String),
427
+ search: Schema3.optional(Schema3.String)
428
+ })
429
+ );
430
+ var ImageVariantSchema = Schema3.mutable(
431
+ Schema3.Struct({
432
+ width: Schema3.optional(Schema3.Number),
433
+ height: Schema3.optional(Schema3.Number),
434
+ quality: Schema3.optional(Schema3.Number),
435
+ format: Schema3.optional(Schema3.Literal("image/avif", "image/webp", "image/jpeg", "image/png")),
436
+ fit: Schema3.optional(Schema3.Literal("contain", "cover", "fill", "inside", "outside"))
437
+ })
438
+ );
439
+ var PositiveIntSchema = Schema3.Int.pipe(Schema3.greaterThan(0));
440
+ var ImagePolicySchema = Schema3.mutable(
441
+ Schema3.Struct({
442
+ localPatterns: Schema3.mutable(Schema3.Array(ImageLocalPatternSchema)),
443
+ remotePatterns: Schema3.mutable(Schema3.Array(ImageRemotePatternSchema)),
444
+ widths: Schema3.mutable(Schema3.Array(PositiveIntSchema)),
445
+ heights: Schema3.mutable(Schema3.Array(PositiveIntSchema)),
446
+ qualities: Schema3.mutable(Schema3.Array(Schema3.Number.pipe(Schema3.between(1, 100)))),
447
+ formats: Schema3.mutable(Schema3.Array(Schema3.Literal("image/avif", "image/webp", "image/jpeg", "image/png"))),
448
+ minimumCacheTTL: Schema3.Number,
449
+ dangerouslyAllowSVG: Schema3.Boolean,
450
+ contentSecurityPolicy: Schema3.String,
451
+ contentDispositionType: Schema3.Literal("inline", "attachment"),
452
+ maximumRedirects: Schema3.Number,
453
+ maximumResponseBody: Schema3.Number,
454
+ variants: Schema3.mutable(Schema3.Record({ key: Schema3.String, value: ImageVariantSchema }))
455
+ })
456
+ );
457
+ var GigadriveNextPrerenderOutputSchema = Schema3.mutable(
458
+ Schema3.Struct({
459
+ id: Schema3.String,
460
+ type: Schema3.Literal("PRERENDER"),
461
+ pathname: 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(
468
+ Schema3.Struct({
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)
475
+ })
476
+ )
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
+ );
490
+ var GigadriveNextStaticAssetPrefixSchema = Schema3.mutable(
491
+ Schema3.Struct({
492
+ sourceDir: PortableRelativePathSchema,
493
+ urlPrefix: PortableRelativePathSchema,
494
+ immutable: Schema3.Boolean
495
+ })
496
+ );
497
+ var GigadriveNextServerDescriptorSchema = Schema3.mutable(
498
+ Schema3.Struct({
499
+ maxDuration: Schema3.optional(Schema3.Number),
500
+ preferredRegion: Schema3.optional(Schema3.Union(Schema3.String, StringArraySchema)),
501
+ env: Schema3.optional(StringRecordSchema)
502
+ })
503
+ );
504
+ var PrerenderArraySchema = Schema3.mutable(Schema3.Array(GigadriveNextPrerenderOutputSchema));
505
+ var StaticAssetArraySchema = Schema3.mutable(Schema3.Array(GigadriveNextStaticAssetPrefixSchema));
506
+ var JsonValueArraySchema = Schema3.mutable(Schema3.Array(JsonValueSchema));
507
+ var GigadriveNextBuildManifestV1Schema = Schema3.mutable(
508
+ Schema3.Struct({
509
+ version: Schema3.Literal(1),
510
+ output: Schema3.Literal("standalone", "export"),
511
+ distDir: PortableRelativePathSchema,
512
+ repoRootToProject: RepositoryRelativePathSchema,
513
+ nextVersion: Schema3.String,
514
+ buildId: Schema3.String
515
+ })
516
+ );
517
+ var GigadriveNextBuildManifestV2ExportSchema = Schema3.mutable(
518
+ Schema3.Struct({
519
+ version: Schema3.Literal(2),
520
+ mode: Schema3.Literal("export"),
521
+ distDir: PortableRelativePathSchema,
522
+ repoRootToProject: RepositoryRelativePathSchema,
523
+ nextVersion: Schema3.String,
524
+ buildId: Schema3.String
525
+ })
526
+ );
527
+ var GigadriveNextBuildManifestV2StandaloneSchema = Schema3.mutable(
528
+ Schema3.Struct({
529
+ version: Schema3.Literal(2),
530
+ mode: Schema3.Literal("standalone-v2"),
531
+ distDir: PortableRelativePathSchema,
532
+ repoRootToProject: RepositoryRelativePathSchema,
533
+ nextVersion: Schema3.String,
534
+ buildId: Schema3.String,
535
+ server: GigadriveNextServerDescriptorSchema,
536
+ config: Schema3.mutable(
537
+ Schema3.Struct({
538
+ basePath: Schema3.String,
539
+ trailingSlash: Schema3.Boolean,
540
+ cacheComponents: Schema3.Boolean,
541
+ i18n: Schema3.optional(JsonValueSchema),
542
+ images: Schema3.optional(ImagePolicySchema)
543
+ })
544
+ ),
545
+ routing: Schema3.mutable(
546
+ Schema3.Struct({
547
+ beforeMiddleware: JsonValueArraySchema,
548
+ beforeFiles: JsonValueArraySchema,
549
+ afterFiles: JsonValueArraySchema,
550
+ dynamicRoutes: JsonValueArraySchema,
551
+ onMatch: JsonValueArraySchema,
552
+ fallback: JsonValueArraySchema,
553
+ shouldNormalizeNextData: Schema3.Boolean,
554
+ rsc: JsonValueSchema
555
+ })
556
+ ),
557
+ outputs: Schema3.mutable(
558
+ Schema3.Struct({
559
+ prerenders: PrerenderArraySchema,
560
+ prerenderManifest: Schema3.optional(PortableRelativePathSchema),
561
+ assetManifest: Schema3.optional(PortableRelativePathSchema),
562
+ entryPagePaths: Schema3.optional(Schema3.mutable(Schema3.Array(UrlPathnameSchema))),
563
+ staticAssets: StaticAssetArraySchema
564
+ })
565
+ )
566
+ })
567
+ );
568
+ var GigadriveNextBuildManifestSchema = Schema3.Union(
569
+ GigadriveNextBuildManifestV1Schema,
570
+ GigadriveNextBuildManifestV2ExportSchema,
571
+ GigadriveNextBuildManifestV2StandaloneSchema
572
+ );
573
+ var GigadriveNextPrerenderManifestV1Schema = Schema3.mutable(
574
+ Schema3.Struct({
575
+ version: Schema3.Literal(1),
576
+ prerenders: PrerenderArraySchema
577
+ })
578
+ );
579
+ var parseGigadriveNextBuildManifest = (content) => decodeJson(GigadriveNextBuildManifestSchema, content);
580
+ var parseGigadriveNextPrerenderManifest = (content) => decodeJson(GigadriveNextPrerenderManifestV1Schema, content);
386
581
 
387
582
  // src/regions.ts
388
583
  var REGION_DEFINITIONS = [
@@ -408,7 +603,6 @@ var AVAILABLE_REGIONS = [...REGION_DEFINITIONS];
408
603
 
409
604
  // src/detection/frameworks/nextjs.ts
410
605
  var toPortablePath = (value) => value.replaceAll("\\", "/");
411
- var MAXIMUM_ENTRY_PAGE_PATHS = 50;
412
606
  var STANDALONE_SERVER_MEMORY_MB = 1024;
413
607
  var resolveStandaloneServer = Effect5.fn("nextjs.resolveStandaloneServer")(function* (projectFolder, distDir, repoRootToProject) {
414
608
  const fs = yield* FileSystem5.FileSystem;
@@ -513,9 +707,11 @@ var createStandaloneV2Config = Effect5.fn("nextjs.createStandaloneV2Config")(fun
513
707
  immutable: staticAsset.immutable,
514
708
  populateCache: true
515
709
  }));
516
- const entryPagePaths = [
710
+ const assetManifests = manifest.outputs.assetManifest ? [{ source: manifest.outputs.assetManifest }] : void 0;
711
+ const { entryPagePaths: manifestEntryPagePaths, ...manifestOutputs } = manifest.outputs;
712
+ const entryPagePaths = manifestEntryPagePaths?.slice(0, MAXIMUM_ENTRY_PAGE_PATHS) ?? [
517
713
  ...new Set(
518
- manifest.outputs.prerenders.filter((output) => !output.fallback?.postponedState).map((output) => output.pathname).filter((pathname) => pathname.startsWith("/") && !pathname.includes("["))
714
+ manifest.outputs.prerenders.filter((output) => output.fallback?.postponedState === void 0).map((output) => output.pathname).filter((pathname) => pathname.startsWith("/") && !pathname.includes("["))
519
715
  )
520
716
  ].sort((left, right) => left.split("/").length - right.split("/").length || left.localeCompare(right)).slice(0, MAXIMUM_ENTRY_PAGE_PATHS);
521
717
  const singleEntrypoint = {
@@ -544,10 +740,9 @@ var createStandaloneV2Config = Effect5.fn("nextjs.createStandaloneV2Config")(fun
544
740
  server: manifest.server,
545
741
  config: manifest.config,
546
742
  routing: manifest.routing,
547
- // The prerender table is deliberately not forwarded: the standalone server
548
- // serves build-time prerenders from its own bundle, so the platform only
549
- // needs the warming sample below.
550
- outputs: { prerenders: [], staticAssets: manifest.outputs.staticAssets },
743
+ // Keep high-cardinality output metadata in portable sidecars rather than
744
+ // expanding it into normalized deployment configuration.
745
+ outputs: { ...manifestOutputs, prerenders: [] },
551
746
  entryPagePaths,
552
747
  type: "nextjs",
553
748
  schemaVersion: 2
@@ -559,6 +754,7 @@ var createStandaloneV2Config = Effect5.fn("nextjs.createStandaloneV2Config")(fun
559
754
  assetPaths,
560
755
  assetOverrides,
561
756
  assetPrefixes,
757
+ assetManifests,
562
758
  assetsDir: manifest.distDir,
563
759
  assetsPrefixToStrip: "",
564
760
  populateAssetCache: true,
@@ -820,12 +1016,13 @@ var generateConfig = Effect7.fn("generateConfig")(function* (framework, packageM
820
1016
  errors: [],
821
1017
  ...defaults.normalizedConfig
822
1018
  };
823
- if (defaults.assetsDir || defaults.assetPaths || defaults.assetPrefixes) {
1019
+ if (defaults.assetsDir || defaults.assetPaths || defaults.assetPrefixes || defaults.assetManifests) {
824
1020
  config.assets = {
825
1021
  paths: defaults.assetPaths ? [...defaults.assetPaths] : [],
826
1022
  prefixToStrip: defaults.assetsPrefixToStrip ?? (defaults.assetsDir ? defaults.assetsDir + "/" : ""),
827
1023
  overrides: defaults.assetOverrides ? { ...defaults.assetOverrides } : void 0,
828
1024
  prefixes: defaults.assetPrefixes ? defaults.assetPrefixes.map((prefix) => ({ ...prefix })) : void 0,
1025
+ manifests: defaults.assetManifests ? defaults.assetManifests.map((manifest) => ({ ...manifest })) : void 0,
829
1026
  dynamicRoutes: true,
830
1027
  populateCache: defaults.populateAssetCache ?? false
831
1028
  };
@@ -838,27 +1035,27 @@ import { FileSystem as FileSystem7, Path as Path5 } from "@effect/platform";
838
1035
  import { Effect as Effect9 } from "effect";
839
1036
 
840
1037
  // src/detection/types.ts
841
- import { Schema } from "effect";
842
- var ManifestNotFoundError = class extends Schema.TaggedError()("ManifestNotFoundError", {
843
- message: Schema.String,
844
- filePath: Schema.String
1038
+ import { Schema as Schema4 } from "effect";
1039
+ var ManifestNotFoundError = class extends Schema4.TaggedError()("ManifestNotFoundError", {
1040
+ message: Schema4.String,
1041
+ filePath: Schema4.String
845
1042
  }) {
846
1043
  };
847
- var ManifestReadError = class extends Schema.TaggedError()("ManifestReadError", {
848
- message: Schema.String,
849
- filePath: Schema.String
1044
+ var ManifestReadError = class extends Schema4.TaggedError()("ManifestReadError", {
1045
+ message: Schema4.String,
1046
+ filePath: Schema4.String
850
1047
  }) {
851
1048
  };
852
- var ManifestParseError = class extends Schema.TaggedError()("ManifestParseError", {
853
- message: Schema.String,
854
- filePath: Schema.String
1049
+ var ManifestParseError = class extends Schema4.TaggedError()("ManifestParseError", {
1050
+ message: Schema4.String,
1051
+ filePath: Schema4.String
855
1052
  }) {
856
1053
  };
857
- var FrameworkNotDetectedError = class extends Schema.TaggedError()(
1054
+ var FrameworkNotDetectedError = class extends Schema4.TaggedError()(
858
1055
  "FrameworkNotDetectedError",
859
1056
  {
860
- message: Schema.String,
861
- directory: Schema.String
1057
+ message: Schema4.String,
1058
+ directory: Schema4.String
862
1059
  }
863
1060
  ) {
864
1061
  };
@@ -974,12 +1171,13 @@ var detectFramework = Effect10.fn("detectFramework")(function* (projectFolder) {
974
1171
  import { Effect as Effect11 } from "effect";
975
1172
  var mergeWithFrameworkDefaults = Effect11.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
976
1173
  yield* Effect11.logDebug("Merging user config with framework defaults");
1174
+ const userHasAssets = (userConfig.assets?.paths?.length ?? 0) > 0 || (userConfig.assets?.prefixes?.length ?? 0) > 0 || (userConfig.assets?.manifests?.length ?? 0) > 0;
977
1175
  const merged = {
978
1176
  regions: userConfig.regions,
979
1177
  commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
980
1178
  entrypoints: userConfig.entrypoints.length > 0 ? userConfig.entrypoints : frameworkConfig.entrypoints,
981
1179
  routes: userConfig.routes.length > 0 ? userConfig.routes : frameworkConfig.routes,
982
- assets: userConfig.assets?.paths && userConfig.assets.paths.length > 0 ? userConfig.assets : frameworkConfig.assets,
1180
+ assets: userHasAssets ? userConfig.assets : frameworkConfig.assets,
983
1181
  environmentVariables: {
984
1182
  ...frameworkConfig.environmentVariables,
985
1183
  ...userConfig.environmentVariables
@@ -994,41 +1192,47 @@ var mergeWithFrameworkDefaults = Effect11.fn("mergeWithFrameworkDefaults")(funct
994
1192
  });
995
1193
 
996
1194
  // src/errors.ts
997
- import { Schema as Schema2 } from "effect";
998
- var ConfigFileNotFoundError = class extends Schema2.TaggedError()("ConfigFileNotFoundError", {
999
- message: Schema2.String,
1000
- filePath: Schema2.String
1195
+ import { Schema as Schema5 } from "effect";
1196
+ var ConfigFileNotFoundError = class extends Schema5.TaggedError()("ConfigFileNotFoundError", {
1197
+ message: Schema5.String,
1198
+ filePath: Schema5.String
1199
+ }) {
1200
+ };
1201
+ var ConfigFileEmptyError = class extends Schema5.TaggedError()("ConfigFileEmptyError", {
1202
+ message: Schema5.String,
1203
+ filePath: Schema5.String
1001
1204
  }) {
1002
1205
  };
1003
- var ConfigFileEmptyError = class extends Schema2.TaggedError()("ConfigFileEmptyError", {
1004
- message: Schema2.String,
1005
- filePath: Schema2.String
1206
+ var ConfigFileParseError = class extends Schema5.TaggedError()("ConfigFileParseError", {
1207
+ message: Schema5.String,
1208
+ filePath: Schema5.String,
1209
+ cause: Schema5.optional(Schema5.String)
1006
1210
  }) {
1007
1211
  };
1008
- var ConfigFileParseError = class extends Schema2.TaggedError()("ConfigFileParseError", {
1009
- message: Schema2.String,
1010
- filePath: Schema2.String,
1011
- cause: Schema2.optional(Schema2.String)
1212
+ var ConfigModuleLoadError = class extends Schema5.TaggedError()("ConfigModuleLoadError", {
1213
+ message: Schema5.String,
1214
+ filePath: Schema5.String,
1215
+ cause: Schema5.optional(Schema5.String)
1012
1216
  }) {
1013
1217
  };
1014
- var ConfigVersionError = class extends Schema2.TaggedError()("ConfigVersionError", {
1015
- message: Schema2.String,
1016
- filePath: Schema2.String,
1017
- version: Schema2.optional(Schema2.Number)
1218
+ var ConfigVersionError = class extends Schema5.TaggedError()("ConfigVersionError", {
1219
+ message: Schema5.String,
1220
+ filePath: Schema5.String,
1221
+ version: Schema5.optional(Schema5.Number)
1018
1222
  }) {
1019
1223
  };
1020
- var ConfigSchemaValidationError = class extends Schema2.TaggedError()(
1224
+ var ConfigSchemaValidationError = class extends Schema5.TaggedError()(
1021
1225
  "ConfigSchemaValidationError",
1022
1226
  {
1023
- message: Schema2.String,
1024
- filePath: Schema2.String,
1025
- validationErrors: Schema2.Array(Schema2.String)
1227
+ message: Schema5.String,
1228
+ filePath: Schema5.String,
1229
+ validationErrors: Schema5.Array(Schema5.String)
1026
1230
  }
1027
1231
  ) {
1028
1232
  };
1029
- var FunctionConfigError = class extends Schema2.TaggedError()("FunctionConfigError", {
1030
- message: Schema2.String,
1031
- functionPath: Schema2.String
1233
+ var FunctionConfigError = class extends Schema5.TaggedError()("FunctionConfigError", {
1234
+ message: Schema5.String,
1235
+ functionPath: Schema5.String
1032
1236
  }) {
1033
1237
  };
1034
1238
 
@@ -1048,85 +1252,157 @@ var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
1048
1252
  var MAX_FUNCTION_DURATION_SECONDS = 28800;
1049
1253
 
1050
1254
  // src/parse-config.ts
1051
- import { Effect as Effect16 } from "effect";
1255
+ import { Effect as Effect17 } from "effect";
1052
1256
 
1053
1257
  // src/services/raw-config-reader.ts
1054
1258
  import { FileSystem as FileSystem9, Path as Path7 } from "@effect/platform";
1055
- import { Effect as Effect12 } from "effect";
1259
+ import { Effect as Effect13 } from "effect";
1056
1260
  import { parse as parseYaml } from "yaml";
1261
+
1262
+ // src/services/config-module-loader.ts
1263
+ import { Effect as Effect12 } from "effect";
1264
+ import { createJiti } from "jiti";
1265
+ var MISSING_DEFAULT_EXPORT = /* @__PURE__ */ Symbol("MissingDefaultExport");
1266
+ var STRICT_DEFAULT_EXPORT_EXTENSIONS = [".ts", ".mts", ".mjs"];
1267
+ var ConfigModuleLoader = class extends Effect12.Service()("ConfigModuleLoader", {
1268
+ effect: Effect12.gen(function* () {
1269
+ const loadConfigModule = Effect12.fn("ConfigModuleLoader.loadConfigModule")(function* (filePath) {
1270
+ const extension = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
1271
+ const mod = yield* Effect12.tryPromise({
1272
+ try: async () => {
1273
+ const jiti = createJiti(filePath, { fsCache: false, interopDefault: true, moduleCache: false });
1274
+ const namespace = await jiti.import(filePath);
1275
+ if (typeof namespace === "object" && namespace !== null && "default" in namespace) {
1276
+ return namespace.default;
1277
+ }
1278
+ if (!STRICT_DEFAULT_EXPORT_EXTENSIONS.includes(extension)) {
1279
+ return namespace.default ?? MISSING_DEFAULT_EXPORT;
1280
+ }
1281
+ return MISSING_DEFAULT_EXPORT;
1282
+ },
1283
+ catch: (error) => new ConfigModuleLoadError({
1284
+ message: `Failed to load config module at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
1285
+ filePath,
1286
+ cause: error instanceof Error ? error.message : void 0
1287
+ })
1288
+ });
1289
+ if (mod === MISSING_DEFAULT_EXPORT) {
1290
+ return yield* Effect12.fail(
1291
+ new ConfigModuleLoadError({
1292
+ 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.`,
1293
+ filePath
1294
+ })
1295
+ );
1296
+ }
1297
+ if (typeof mod === "function") {
1298
+ return yield* Effect12.fail(
1299
+ new ConfigModuleLoadError({
1300
+ message: `Config module at ${filePath} default-exports a function; config factories are not supported. Export a config object instead (optionally wrapped in defineConfig).`,
1301
+ filePath
1302
+ })
1303
+ );
1304
+ }
1305
+ if (typeof mod !== "object" || mod === null || Array.isArray(mod)) {
1306
+ return yield* Effect12.fail(
1307
+ new ConfigModuleLoadError({
1308
+ message: `Config module at ${filePath} must default-export a config object.`,
1309
+ filePath
1310
+ })
1311
+ );
1312
+ }
1313
+ return mod;
1314
+ });
1315
+ return { loadConfigModule };
1316
+ })
1317
+ }) {
1318
+ };
1319
+
1320
+ // src/services/raw-config-reader.ts
1057
1321
  var ALLOWED_CONFIG_NAMES = [
1322
+ "gigadrive.ts",
1323
+ "gigadrive.mts",
1324
+ "gigadrive.cts",
1325
+ "gigadrive.js",
1326
+ "gigadrive.mjs",
1327
+ "gigadrive.cjs",
1058
1328
  "gigadrive.yaml",
1059
1329
  "gigadrive.yml",
1330
+ "gigadrive.json",
1060
1331
  "nebula.yaml",
1061
1332
  "nebula.yml",
1062
1333
  "nebula.json"
1063
1334
  ];
1064
- var RawConfigReader = class extends Effect12.Service()("RawConfigReader", {
1065
- effect: Effect12.gen(function* () {
1335
+ var MODULE_EXTENSIONS = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
1336
+ var RawConfigReader = class extends Effect13.Service()("RawConfigReader", {
1337
+ dependencies: [ConfigModuleLoader.Default],
1338
+ effect: Effect13.gen(function* () {
1066
1339
  const fs = yield* FileSystem9.FileSystem;
1067
1340
  const pathService = yield* Path7.Path;
1068
- const findConfig = Effect12.fn("RawConfigReader.findConfig")(function* (projectFolder) {
1341
+ const moduleLoader = yield* ConfigModuleLoader;
1342
+ const findConfig = Effect13.fn("RawConfigReader.findConfig")(function* (projectFolder) {
1069
1343
  for (const name of ALLOWED_CONFIG_NAMES) {
1070
1344
  const filePath = pathService.join(projectFolder, name);
1071
- const exists = yield* fs.exists(filePath).pipe(Effect12.catchAll(() => Effect12.succeed(false)));
1345
+ const exists = yield* fs.exists(filePath).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
1072
1346
  if (exists) {
1073
1347
  return filePath;
1074
1348
  }
1075
1349
  }
1076
1350
  return null;
1077
1351
  });
1078
- const readRawConfig = Effect12.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
1079
- const exists = yield* fs.exists(filePath).pipe(Effect12.catchAll(() => Effect12.succeed(false)));
1352
+ const readRawConfig = Effect13.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
1353
+ const exists = yield* fs.exists(filePath).pipe(Effect13.catchAll(() => Effect13.succeed(false)));
1080
1354
  if (!exists) {
1081
- return yield* Effect12.fail(
1355
+ return yield* Effect13.fail(
1082
1356
  new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
1083
1357
  );
1084
1358
  }
1085
1359
  const fileContents = yield* fs.readFileString(filePath).pipe(
1086
- Effect12.mapError(
1360
+ Effect13.mapError(
1087
1361
  () => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
1088
1362
  )
1089
1363
  );
1090
1364
  if (fileContents.length === 0) {
1091
- return yield* Effect12.fail(
1365
+ return yield* Effect13.fail(
1092
1366
  new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
1093
1367
  );
1094
1368
  }
1095
1369
  const fileExtension = pathService.extname(filePath).toLowerCase();
1096
1370
  let parsed;
1097
- try {
1098
- if (fileExtension === ".json") {
1099
- parsed = JSON.parse(fileContents);
1100
- } else if ([".yml", ".yaml"].includes(fileExtension)) {
1101
- parsed = parseYaml(fileContents);
1102
- } else {
1103
- parsed = parseYaml(fileContents);
1371
+ if (MODULE_EXTENSIONS.includes(fileExtension)) {
1372
+ parsed = yield* moduleLoader.loadConfigModule(filePath);
1373
+ } else {
1374
+ try {
1375
+ if (fileExtension === ".json") {
1376
+ parsed = JSON.parse(fileContents);
1377
+ } else {
1378
+ parsed = parseYaml(fileContents);
1379
+ }
1380
+ } catch (error) {
1381
+ return yield* Effect13.fail(
1382
+ new ConfigFileParseError({
1383
+ message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
1384
+ filePath,
1385
+ cause: error instanceof Error ? error.message : void 0
1386
+ })
1387
+ );
1104
1388
  }
1105
- } catch (error) {
1106
- return yield* Effect12.fail(
1107
- new ConfigFileParseError({
1108
- message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
1109
- filePath,
1110
- cause: error instanceof Error ? error.message : void 0
1111
- })
1112
- );
1113
1389
  }
1114
1390
  if (parsed == null) {
1115
- return yield* Effect12.fail(
1391
+ return yield* Effect13.fail(
1116
1392
  new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
1117
1393
  );
1118
1394
  }
1119
1395
  if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
1120
- return yield* Effect12.fail(
1396
+ return yield* Effect13.fail(
1121
1397
  new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
1122
1398
  );
1123
1399
  }
1124
1400
  return parsed;
1125
1401
  });
1126
1402
  const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
1127
- Effect12.map((parsed) => parsed),
1128
- Effect12.catchTag("ConfigFileNotFoundError", () => Effect12.succeed(null)),
1129
- Effect12.withSpan("RawConfigReader.readConfigFile")
1403
+ Effect13.map((parsed) => parsed),
1404
+ Effect13.catchTag("ConfigFileNotFoundError", () => Effect13.succeed(null)),
1405
+ Effect13.withSpan("RawConfigReader.readConfigFile")
1130
1406
  );
1131
1407
  return { findConfig, readRawConfig, readConfigFile };
1132
1408
  })
@@ -1136,17 +1412,17 @@ var RawConfigReader = class extends Effect12.Service()("RawConfigReader", {
1136
1412
  // src/services/schema-validator.ts
1137
1413
  import Ajv from "ajv";
1138
1414
  import addFormats from "ajv-formats";
1139
- import { Effect as Effect13 } from "effect";
1140
- var SchemaValidator = class extends Effect13.Service()("SchemaValidator", {
1141
- effect: Effect13.gen(function* () {
1415
+ import { Effect as Effect14 } from "effect";
1416
+ var SchemaValidator = class extends Effect14.Service()("SchemaValidator", {
1417
+ effect: Effect14.gen(function* () {
1142
1418
  const ajv = new Ajv();
1143
1419
  addFormats(ajv);
1144
- const validate = Effect13.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
1420
+ const validate = Effect14.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
1145
1421
  const compiledValidate = ajv.compile(schema);
1146
1422
  const valid = compiledValidate(config);
1147
1423
  if (!valid) {
1148
1424
  const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
1149
- return yield* Effect13.fail(
1425
+ return yield* Effect14.fail(
1150
1426
  new ConfigSchemaValidationError({
1151
1427
  message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
1152
1428
  filePath,
@@ -1163,7 +1439,7 @@ var SchemaValidator = class extends Effect13.Service()("SchemaValidator", {
1163
1439
  // src/services/v4-config-parser.ts
1164
1440
  import { FileSystem as FileSystem10, Path as Path8 } from "@effect/platform";
1165
1441
  import { getFilesForPattern } from "@gigadrive/build-utils";
1166
- import { Effect as Effect14 } from "effect";
1442
+ import { Effect as Effect15 } from "effect";
1167
1443
  import { minimatch } from "minimatch";
1168
1444
  import safeRegex from "safe-regex2";
1169
1445
  var MAX_ASSET_DEPTH = 100;
@@ -1269,7 +1545,7 @@ var mapRoute = (route, entrypoints) => ({
1269
1545
  negativeRequirements: route.missing,
1270
1546
  status: route.statusCode
1271
1547
  });
1272
- var parseEntrypoints = Effect14.fn("parseEntrypoints")(function* (config, projectFolder) {
1548
+ var parseEntrypoints = Effect15.fn("parseEntrypoints")(function* (config, projectFolder) {
1273
1549
  const entrypoints = [];
1274
1550
  if (config.functions == null) return entrypoints;
1275
1551
  for (const [fnPath, func] of Object.entries(config.functions)) {
@@ -1279,7 +1555,7 @@ var parseEntrypoints = Effect14.fn("parseEntrypoints")(function* (config, projec
1279
1555
  functionPath: fnPath
1280
1556
  });
1281
1557
  }
1282
- const matchedFiles = yield* Effect14.tryPromise({
1558
+ const matchedFiles = yield* Effect15.tryPromise({
1283
1559
  try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
1284
1560
  catch: (error) => new FunctionConfigError({
1285
1561
  message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
@@ -1315,14 +1591,14 @@ var parseEntrypoints = Effect14.fn("parseEntrypoints")(function* (config, projec
1315
1591
  }
1316
1592
  return entrypoints;
1317
1593
  });
1318
- var collectAssets = Effect14.fn("collectAssets")(function* (config, projectFolder) {
1594
+ var collectAssets = Effect15.fn("collectAssets")(function* (config, projectFolder) {
1319
1595
  if (config.assets == null) return [];
1320
1596
  const fs = yield* FileSystem10.FileSystem;
1321
1597
  const pathService = yield* Path8.Path;
1322
1598
  const assetsPath = pathService.join(projectFolder, config.assets);
1323
- const assetsExist = yield* fs.exists(assetsPath).pipe(Effect14.catchAll(() => Effect14.succeed(false)));
1599
+ const assetsExist = yield* fs.exists(assetsPath).pipe(Effect15.catchAll(() => Effect15.succeed(false)));
1324
1600
  if (!assetsExist) return [];
1325
- const stat = yield* fs.stat(assetsPath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1601
+ const stat = yield* fs.stat(assetsPath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1326
1602
  if (!stat || stat.type !== "Directory") return [];
1327
1603
  const allFiles = yield* collectFilesRecursively(assetsPath);
1328
1604
  const assets = [];
@@ -1333,18 +1609,18 @@ var collectAssets = Effect14.fn("collectAssets")(function* (config, projectFolde
1333
1609
  }
1334
1610
  return assets;
1335
1611
  });
1336
- var collectFilesRecursively = Effect14.fn("collectFilesRecursively")(
1612
+ var collectFilesRecursively = Effect15.fn("collectFilesRecursively")(
1337
1613
  function* (basePath, relativePath = "", depth = 0) {
1338
1614
  if (depth > MAX_ASSET_DEPTH) return [];
1339
1615
  const fs = yield* FileSystem10.FileSystem;
1340
1616
  const pathSvc = yield* Path8.Path;
1341
1617
  const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
1342
- const entries = yield* fs.readDirectory(currentPath).pipe(Effect14.catchAll(() => Effect14.succeed([])));
1618
+ const entries = yield* fs.readDirectory(currentPath).pipe(Effect15.catchAll(() => Effect15.succeed([])));
1343
1619
  const result = [];
1344
1620
  for (const name of entries) {
1345
1621
  const fullPath = pathSvc.join(currentPath, name);
1346
1622
  const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
1347
- const stat = yield* fs.stat(fullPath).pipe(Effect14.catchAll(() => Effect14.succeed(null)));
1623
+ const stat = yield* fs.stat(fullPath).pipe(Effect15.catchAll(() => Effect15.succeed(null)));
1348
1624
  if (!stat) continue;
1349
1625
  if (stat.type === "Directory") {
1350
1626
  const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
@@ -1356,16 +1632,16 @@ var collectFilesRecursively = Effect14.fn("collectFilesRecursively")(
1356
1632
  return result;
1357
1633
  }
1358
1634
  );
1359
- var V4ConfigParser = class extends Effect14.Service()("V4ConfigParser", {
1635
+ var V4ConfigParser = class extends Effect15.Service()("V4ConfigParser", {
1360
1636
  accessors: true,
1361
- effect: Effect14.succeed({
1637
+ effect: Effect15.succeed({
1362
1638
  /**
1363
1639
  * Parses a ConfigV4 into a NormalizedConfig.
1364
1640
  *
1365
1641
  * @param config - The raw V4 config object
1366
1642
  * @param projectFolder - Absolute path to the project root
1367
1643
  */
1368
- parse: Effect14.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
1644
+ parse: Effect15.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
1369
1645
  const entrypoints = yield* parseEntrypoints(config, projectFolder);
1370
1646
  const assets = yield* collectAssets(config, projectFolder);
1371
1647
  return {
@@ -1394,7 +1670,7 @@ var V4ConfigParser = class extends Effect14.Service()("V4ConfigParser", {
1394
1670
  import { Path as Path9 } from "@effect/platform";
1395
1671
  import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
1396
1672
  import { deepMerge } from "@gigadrive/commons";
1397
- import { Effect as Effect15 } from "effect";
1673
+ import { Effect as Effect16 } from "effect";
1398
1674
 
1399
1675
  // src/build-output-v3/determine-repo-root.ts
1400
1676
  import path from "path";
@@ -1490,11 +1766,11 @@ var translateVercelRuntime = (runtime) => {
1490
1766
  var CONFIG_PATH = ".vercel/output/config.json";
1491
1767
  var FUNCTIONS_FOLDER = ".vercel/output/functions";
1492
1768
  var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
1493
- var VercelBuildOutputParser = class extends Effect15.Service()("VercelBuildOutputParser", {
1494
- effect: Effect15.gen(function* () {
1769
+ var VercelBuildOutputParser = class extends Effect16.Service()("VercelBuildOutputParser", {
1770
+ effect: Effect16.gen(function* () {
1495
1771
  const rawConfigReader = yield* RawConfigReader;
1496
1772
  const pathService = yield* Path9.Path;
1497
- const parse = Effect15.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1773
+ const parse = Effect16.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
1498
1774
  const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
1499
1775
  if (!config || typeof config.version !== "number" || config.version < 3) {
1500
1776
  return parseResult;
@@ -1506,8 +1782,8 @@ var VercelBuildOutputParser = class extends Effect15.Service()("VercelBuildOutpu
1506
1782
  merged.regions = [...new Set(merged.regions)];
1507
1783
  return merged;
1508
1784
  });
1509
- const loadFunctions = Effect15.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1510
- const functionConfigs = yield* Effect15.tryPromise({
1785
+ const loadFunctions = Effect16.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
1786
+ const functionConfigs = yield* Effect16.tryPromise({
1511
1787
  try: () => getFilesForPattern2(FUNCTION_CONFIGS_PATTERN, projectFolder),
1512
1788
  catch: (error) => new ConfigFileParseError({
1513
1789
  message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
@@ -2106,7 +2382,7 @@ var schema_default = {
2106
2382
  };
2107
2383
 
2108
2384
  // src/parse-config.ts
2109
- var parseConfigRaw = Effect16.fn("parseConfigRaw")(function* (filePath, projectFolder) {
2385
+ var parseConfigRaw = Effect17.fn("parseConfigRaw")(function* (filePath, projectFolder) {
2110
2386
  const rawReader = yield* RawConfigReader;
2111
2387
  const validator = yield* SchemaValidator;
2112
2388
  const v4Parser = yield* V4ConfigParser;
@@ -2117,7 +2393,7 @@ var parseConfigRaw = Effect16.fn("parseConfigRaw")(function* (filePath, projectF
2117
2393
  };
2118
2394
  const schema = schemaMap[version];
2119
2395
  if (!schema) {
2120
- return yield* Effect16.fail(
2396
+ return yield* Effect17.fail(
2121
2397
  new ConfigVersionError({
2122
2398
  message: `Config file at ${filePath} has an unsupported version: ${version}`,
2123
2399
  filePath,
@@ -2128,18 +2404,19 @@ var parseConfigRaw = Effect16.fn("parseConfigRaw")(function* (filePath, projectF
2128
2404
  yield* validator.validate(parsed, schema, filePath);
2129
2405
  return yield* v4Parser.parse(parsed, projectFolder);
2130
2406
  });
2131
- var parseConfig = Effect16.fn("parseConfig")(function* (filePath, projectFolder) {
2407
+ var parseConfig = Effect17.fn("parseConfig")(function* (filePath, projectFolder) {
2132
2408
  const parseResult = yield* parseConfigRaw(filePath, projectFolder);
2133
2409
  return yield* postProcessConfig(parseResult, projectFolder);
2134
2410
  });
2135
- var postProcessConfig = Effect16.fn("postProcessConfig")(function* (config, projectFolder) {
2411
+ var postProcessConfig = Effect17.fn("postProcessConfig")(function* (config, projectFolder) {
2136
2412
  const vercelParser = yield* VercelBuildOutputParser;
2137
2413
  let result = yield* vercelParser.parse(config, projectFolder);
2138
- if (result.entrypoints.length === 0 && (result.assets?.paths?.length || 0) === 0 && result.routes.length === 0) {
2414
+ const hasAssets = (result.assets?.paths?.length ?? 0) > 0 || (result.assets?.prefixes?.length ?? 0) > 0 || (result.assets?.manifests?.length ?? 0) > 0;
2415
+ if (result.entrypoints.length === 0 && !hasAssets && result.routes.length === 0) {
2139
2416
  result.errors.push(
2140
2417
  "The current project config does not resolve to any functions, assets or routes and can not be deployed."
2141
2418
  );
2142
- } else if (result.entrypoints.length === 0 && (result.assets?.paths?.length || 0) === 0) {
2419
+ } else if (result.entrypoints.length === 0 && !hasAssets) {
2143
2420
  result.warnings.push("The current project does not have any functions or assets to deploy.");
2144
2421
  }
2145
2422
  result = filterFunctionsFromAssets(result);
@@ -2161,7 +2438,12 @@ var AVAILABLE_RUNTIMES = [...RUNTIME_DEFINITIONS];
2161
2438
 
2162
2439
  // src/services/index.ts
2163
2440
  import { Layer } from "effect";
2164
- var BaseLayers = Layer.mergeAll(RawConfigReader.Default, SchemaValidator.Default, V4ConfigParser.Default);
2441
+ var BaseLayers = Layer.mergeAll(
2442
+ ConfigModuleLoader.Default,
2443
+ RawConfigReader.Default,
2444
+ SchemaValidator.Default,
2445
+ V4ConfigParser.Default
2446
+ );
2165
2447
  var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(Layer.provideMerge(BaseLayers));
2166
2448
  export {
2167
2449
  ALLOWED_CONFIG_NAMES,
@@ -2170,12 +2452,22 @@ export {
2170
2452
  ConfigFileEmptyError,
2171
2453
  ConfigFileNotFoundError,
2172
2454
  ConfigFileParseError,
2455
+ ConfigModuleLoadError,
2456
+ ConfigModuleLoader,
2173
2457
  ConfigSchemaValidationError,
2174
2458
  ConfigVersionError,
2175
2459
  DEFAULT_FUNCTION_DURATION_SECONDS,
2176
2460
  FRAMEWORK_DEFINITIONS,
2177
2461
  FrameworkNotDetectedError,
2178
2462
  FunctionConfigError,
2463
+ GigadriveNextBuildManifestSchema,
2464
+ GigadriveNextBuildManifestV1Schema,
2465
+ GigadriveNextBuildManifestV2ExportSchema,
2466
+ GigadriveNextBuildManifestV2StandaloneSchema,
2467
+ GigadriveNextPrerenderManifestV1Schema,
2468
+ GigadriveNextPrerenderOutputSchema,
2469
+ GigadriveNextServerDescriptorSchema,
2470
+ GigadriveNextStaticAssetPrefixSchema,
2179
2471
  MAX_FUNCTION_DURATION_SECONDS,
2180
2472
  ManifestNotFoundError,
2181
2473
  ManifestParseError,
@@ -2183,8 +2475,12 @@ export {
2183
2475
  NetworkConfigLive,
2184
2476
  RawConfigReader,
2185
2477
  SchemaValidator,
2478
+ StaticAssetHeadersSchema,
2479
+ StaticAssetManifestEntrySchema,
2480
+ StaticAssetManifestV1Schema,
2186
2481
  V4ConfigParser,
2187
2482
  VercelBuildOutputParser,
2483
+ defineConfig,
2188
2484
  detectFramework,
2189
2485
  detectPackageManager,
2190
2486
  filterFunctionsFromAssets,
@@ -2194,6 +2490,8 @@ export {
2194
2490
  parseConfig,
2195
2491
  parseConfigRaw,
2196
2492
  parseGigadriveNextBuildManifest,
2493
+ parseGigadriveNextPrerenderManifest,
2494
+ parseStaticAssetManifest,
2197
2495
  postProcessConfig,
2198
2496
  readDependencies
2199
2497
  };