@gigadrive/network-config 3.0.1 → 3.1.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.d.mts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +1221 -829
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +192 -109
- package/dist/index.mjs.map +1 -1
- package/dist/v4/schema.json +4 -0
- package/package.json +4 -4
- package/src/v4/schema.json +4 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/detection/detect-framework.ts
|
|
2
|
-
import { FileSystem as
|
|
3
|
-
import { Effect as
|
|
2
|
+
import { FileSystem as FileSystem4, Path as Path3 } from "@effect/platform";
|
|
3
|
+
import { Effect as Effect6 } from "effect";
|
|
4
4
|
|
|
5
5
|
// src/detection/detect-package-manager.ts
|
|
6
6
|
import { FileSystem, Path } from "@effect/platform";
|
|
@@ -157,21 +157,65 @@ var laravel = {
|
|
|
157
157
|
};
|
|
158
158
|
|
|
159
159
|
// src/detection/frameworks/nestjs.ts
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
160
|
+
import { FileSystem as FileSystem2 } from "@effect/platform";
|
|
161
|
+
import { Effect as Effect2 } from "effect";
|
|
162
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
163
|
+
var parseNestCliJson = (content) => {
|
|
164
|
+
try {
|
|
165
|
+
const parsed = JSON.parse(content);
|
|
166
|
+
if (!isRecord(parsed)) return void 0;
|
|
167
|
+
return parsed;
|
|
168
|
+
} catch {
|
|
169
|
+
return void 0;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
var getProjectOutputPath = (config) => {
|
|
173
|
+
if (typeof config.compilerOptions?.outputPath === "string") {
|
|
174
|
+
return config.compilerOptions.outputPath;
|
|
175
|
+
}
|
|
176
|
+
if (typeof config.defaultProject === "string") {
|
|
177
|
+
const outputPath2 = config.projects?.[config.defaultProject]?.compilerOptions?.outputPath;
|
|
178
|
+
if (typeof outputPath2 === "string") return outputPath2;
|
|
179
|
+
}
|
|
180
|
+
const firstProject = Object.values(config.projects ?? {})[0];
|
|
181
|
+
const outputPath = firstProject?.compilerOptions?.outputPath;
|
|
182
|
+
return typeof outputPath === "string" ? outputPath : void 0;
|
|
183
|
+
};
|
|
184
|
+
var normalizeOutputPath = (outputPath) => {
|
|
185
|
+
const normalized = outputPath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
186
|
+
if (!normalized || normalized === "." || normalized.startsWith("/") || /^[A-Za-z]:/.test(normalized) || normalized.includes(":") || normalized.split("/").some((segment) => segment === "..")) {
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
return normalized;
|
|
190
|
+
};
|
|
191
|
+
var createNestConfig = (outputPath) => {
|
|
192
|
+
const outputDirectory = normalizeOutputPath(outputPath) ?? "dist";
|
|
193
|
+
const entrypoint = `${outputDirectory}/main.js`;
|
|
194
|
+
return {
|
|
167
195
|
runtime: "node-22",
|
|
168
196
|
memory: 256,
|
|
169
197
|
maxDuration: 30,
|
|
170
198
|
streaming: true,
|
|
171
199
|
commands: ["nest build"],
|
|
172
|
-
entrypoint
|
|
173
|
-
routes: [{ source: "/*", destination:
|
|
200
|
+
entrypoint,
|
|
201
|
+
routes: [{ source: "/*", destination: entrypoint }],
|
|
174
202
|
environmentVariables: { NODE_ENV: "production" }
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
var nestjs = {
|
|
206
|
+
slug: "nestjs",
|
|
207
|
+
name: "NestJS",
|
|
208
|
+
language: "node",
|
|
209
|
+
detectors: [{ matchPackage: "@nestjs/core" }],
|
|
210
|
+
priority: 90,
|
|
211
|
+
getDefaultConfig: () => createNestConfig("dist"),
|
|
212
|
+
refineDefaultConfig: (defaults, projectFolder) => Effect2.gen(function* () {
|
|
213
|
+
const fs = yield* FileSystem2.FileSystem;
|
|
214
|
+
const content = yield* fs.readFileString(`${projectFolder}/nest-cli.json`).pipe(Effect2.catchAll(() => Effect2.succeed(void 0)));
|
|
215
|
+
if (!content) return defaults;
|
|
216
|
+
const nestConfig = parseNestCliJson(content);
|
|
217
|
+
const outputPath = nestConfig ? getProjectOutputPath(nestConfig) : void 0;
|
|
218
|
+
return outputPath ? createNestConfig(outputPath) : defaults;
|
|
175
219
|
})
|
|
176
220
|
};
|
|
177
221
|
|
|
@@ -326,7 +370,7 @@ var FRAMEWORK_DEFINITIONS = [
|
|
|
326
370
|
].sort((a, b) => b.priority - a.priority);
|
|
327
371
|
|
|
328
372
|
// src/detection/generate-config.ts
|
|
329
|
-
import { Effect as
|
|
373
|
+
import { Effect as Effect3 } from "effect";
|
|
330
374
|
|
|
331
375
|
// src/regions.ts
|
|
332
376
|
var REGION_DEFINITIONS = [
|
|
@@ -366,11 +410,11 @@ var getInstallCommand = (pm) => {
|
|
|
366
410
|
return "npm install";
|
|
367
411
|
}
|
|
368
412
|
};
|
|
369
|
-
var generateConfig =
|
|
370
|
-
const defaults = framework.getDefaultConfig(packageManager);
|
|
413
|
+
var generateConfig = Effect3.fn("generateConfig")(function* (framework, packageManager, refinedDefaults) {
|
|
414
|
+
const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
|
|
371
415
|
const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
|
|
372
416
|
const commands = [installCmd, ...defaults.commands];
|
|
373
|
-
yield*
|
|
417
|
+
yield* Effect3.logDebug(`Generating config for ${framework.name}`, {
|
|
374
418
|
runtime: defaults.runtime,
|
|
375
419
|
entrypoint: defaults.entrypoint,
|
|
376
420
|
commands
|
|
@@ -382,7 +426,8 @@ var generateConfig = Effect2.fn("generateConfig")(function* (framework, packageM
|
|
|
382
426
|
memory: defaults.memory,
|
|
383
427
|
maxDuration: defaults.maxDuration,
|
|
384
428
|
streaming: defaults.streaming,
|
|
385
|
-
symlinks: defaults.symlinks
|
|
429
|
+
symlinks: defaults.symlinks,
|
|
430
|
+
package: defaults.package
|
|
386
431
|
}
|
|
387
432
|
] : [];
|
|
388
433
|
const routes = defaults.entrypoint ? defaults.routes.map((route) => ({
|
|
@@ -414,8 +459,8 @@ var generateConfig = Effect2.fn("generateConfig")(function* (framework, packageM
|
|
|
414
459
|
});
|
|
415
460
|
|
|
416
461
|
// src/detection/read-dependencies.ts
|
|
417
|
-
import { FileSystem as
|
|
418
|
-
import { Effect as
|
|
462
|
+
import { FileSystem as FileSystem3, Path as Path2 } from "@effect/platform";
|
|
463
|
+
import { Effect as Effect5 } from "effect";
|
|
419
464
|
|
|
420
465
|
// src/detection/types.ts
|
|
421
466
|
import { Schema } from "effect";
|
|
@@ -448,25 +493,25 @@ var MANIFEST_CONFIG = {
|
|
|
448
493
|
node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
|
|
449
494
|
php: { file: "composer.json", depKeys: ["require", "require-dev"] }
|
|
450
495
|
};
|
|
451
|
-
var readManifest =
|
|
452
|
-
const fs = yield*
|
|
453
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
496
|
+
var readManifest = Effect5.fn("readManifest")(function* (filePath) {
|
|
497
|
+
const fs = yield* FileSystem3.FileSystem;
|
|
498
|
+
const exists = yield* fs.exists(filePath).pipe(Effect5.catchAll(() => Effect5.succeed(false)));
|
|
454
499
|
if (!exists) {
|
|
455
|
-
return yield*
|
|
500
|
+
return yield* Effect5.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
|
|
456
501
|
}
|
|
457
|
-
const content = yield* fs.readFileString(filePath).pipe(
|
|
458
|
-
const parsed = yield*
|
|
502
|
+
const content = yield* fs.readFileString(filePath).pipe(Effect5.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
|
|
503
|
+
const parsed = yield* Effect5.try({
|
|
459
504
|
try: () => JSON.parse(content),
|
|
460
505
|
catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
|
|
461
506
|
});
|
|
462
507
|
return parsed;
|
|
463
508
|
});
|
|
464
|
-
var readDependencies =
|
|
509
|
+
var readDependencies = Effect5.fn("readDependencies")(function* (projectFolder, language) {
|
|
465
510
|
const pathService = yield* Path2.Path;
|
|
466
511
|
const config = MANIFEST_CONFIG[language];
|
|
467
512
|
const filePath = pathService.join(projectFolder, config.file);
|
|
468
513
|
const manifest = yield* readManifest(filePath).pipe(
|
|
469
|
-
|
|
514
|
+
Effect5.catchTag("ManifestNotFoundError", () => Effect5.succeed(null))
|
|
470
515
|
);
|
|
471
516
|
if (!manifest) {
|
|
472
517
|
return /* @__PURE__ */ new Set();
|
|
@@ -484,8 +529,8 @@ var readDependencies = Effect3.fn("readDependencies")(function* (projectFolder,
|
|
|
484
529
|
});
|
|
485
530
|
|
|
486
531
|
// src/detection/detect-framework.ts
|
|
487
|
-
var matchesDetectionItem =
|
|
488
|
-
const fs = yield*
|
|
532
|
+
var matchesDetectionItem = Effect6.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
|
|
533
|
+
const fs = yield* FileSystem4.FileSystem;
|
|
489
534
|
const pathService = yield* Path3.Path;
|
|
490
535
|
if (item.matchPackage != null) {
|
|
491
536
|
const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
|
|
@@ -495,12 +540,12 @@ var matchesDetectionItem = Effect4.fn("matchesDetectionItem")(function* (item, p
|
|
|
495
540
|
}
|
|
496
541
|
if (item.path != null) {
|
|
497
542
|
const filePath = pathService.join(projectFolder, item.path);
|
|
498
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
543
|
+
const exists = yield* fs.exists(filePath).pipe(Effect6.catchAll(() => Effect6.succeed(false)));
|
|
499
544
|
if (!exists) {
|
|
500
545
|
return false;
|
|
501
546
|
}
|
|
502
547
|
if (item.matchContent != null) {
|
|
503
|
-
const content = yield* fs.readFileString(filePath).pipe(
|
|
548
|
+
const content = yield* fs.readFileString(filePath).pipe(Effect6.catchAll(() => Effect6.succeed("")));
|
|
504
549
|
let regexMatch = false;
|
|
505
550
|
try {
|
|
506
551
|
regexMatch = new RegExp(item.matchContent).test(content);
|
|
@@ -513,7 +558,7 @@ var matchesDetectionItem = Effect4.fn("matchesDetectionItem")(function* (item, p
|
|
|
513
558
|
}
|
|
514
559
|
return true;
|
|
515
560
|
});
|
|
516
|
-
var matchesFramework =
|
|
561
|
+
var matchesFramework = Effect6.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
|
|
517
562
|
for (const detector of framework.detectors) {
|
|
518
563
|
const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
|
|
519
564
|
if (!matches) {
|
|
@@ -522,9 +567,9 @@ var matchesFramework = Effect4.fn("matchesFramework")(function* (framework, proj
|
|
|
522
567
|
}
|
|
523
568
|
return true;
|
|
524
569
|
});
|
|
525
|
-
var detectFramework =
|
|
526
|
-
yield*
|
|
527
|
-
const cachedReadDeps = yield*
|
|
570
|
+
var detectFramework = Effect6.fn("detectFramework")(function* (projectFolder) {
|
|
571
|
+
yield* Effect6.logDebug(`Detecting framework in ${projectFolder}`);
|
|
572
|
+
const cachedReadDeps = yield* Effect6.cachedFunction((key) => {
|
|
528
573
|
const sepIndex = key.lastIndexOf("\0");
|
|
529
574
|
const folder = key.slice(0, sepIndex);
|
|
530
575
|
const language = key.slice(sepIndex + 1);
|
|
@@ -533,13 +578,16 @@ var detectFramework = Effect4.fn("detectFramework")(function* (projectFolder) {
|
|
|
533
578
|
for (const framework of FRAMEWORK_DEFINITIONS) {
|
|
534
579
|
const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
|
|
535
580
|
if (matches) {
|
|
536
|
-
yield*
|
|
537
|
-
const
|
|
538
|
-
const
|
|
581
|
+
yield* Effect6.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
|
|
582
|
+
const detectedPackageManager = yield* detectPackageManager(projectFolder);
|
|
583
|
+
const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
|
|
584
|
+
const defaults = framework.getDefaultConfig(packageManager);
|
|
585
|
+
const refinedDefaults = framework.refineDefaultConfig ? yield* framework.refineDefaultConfig(defaults, projectFolder) : defaults;
|
|
586
|
+
const config = yield* generateConfig(framework, packageManager, refinedDefaults);
|
|
539
587
|
return { framework, packageManager, config };
|
|
540
588
|
}
|
|
541
589
|
}
|
|
542
|
-
return yield*
|
|
590
|
+
return yield* Effect6.fail(
|
|
543
591
|
new FrameworkNotDetectedError({
|
|
544
592
|
message: `No framework detected in project directory`,
|
|
545
593
|
directory: projectFolder
|
|
@@ -548,9 +596,9 @@ var detectFramework = Effect4.fn("detectFramework")(function* (projectFolder) {
|
|
|
548
596
|
});
|
|
549
597
|
|
|
550
598
|
// src/detection/merge-config.ts
|
|
551
|
-
import { Effect as
|
|
552
|
-
var mergeWithFrameworkDefaults =
|
|
553
|
-
yield*
|
|
599
|
+
import { Effect as Effect7 } from "effect";
|
|
600
|
+
var mergeWithFrameworkDefaults = Effect7.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
|
|
601
|
+
yield* Effect7.logDebug("Merging user config with framework defaults");
|
|
554
602
|
const merged = {
|
|
555
603
|
regions: userConfig.regions,
|
|
556
604
|
commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
|
|
@@ -621,11 +669,11 @@ var filterFunctionsFromAssets = (config) => {
|
|
|
621
669
|
};
|
|
622
670
|
|
|
623
671
|
// src/parse-config.ts
|
|
624
|
-
import { Effect as
|
|
672
|
+
import { Effect as Effect13 } from "effect";
|
|
625
673
|
|
|
626
674
|
// src/services/raw-config-reader.ts
|
|
627
|
-
import { FileSystem as
|
|
628
|
-
import { Effect as
|
|
675
|
+
import { FileSystem as FileSystem5, Path as Path4 } from "@effect/platform";
|
|
676
|
+
import { Effect as Effect8 } from "effect";
|
|
629
677
|
import { parse as parseYaml } from "yaml";
|
|
630
678
|
var ALLOWED_CONFIG_NAMES = [
|
|
631
679
|
"gigadrive.yaml",
|
|
@@ -634,34 +682,34 @@ var ALLOWED_CONFIG_NAMES = [
|
|
|
634
682
|
"nebula.yml",
|
|
635
683
|
"nebula.json"
|
|
636
684
|
];
|
|
637
|
-
var RawConfigReader = class extends
|
|
638
|
-
effect:
|
|
639
|
-
const fs = yield*
|
|
685
|
+
var RawConfigReader = class extends Effect8.Service()("RawConfigReader", {
|
|
686
|
+
effect: Effect8.gen(function* () {
|
|
687
|
+
const fs = yield* FileSystem5.FileSystem;
|
|
640
688
|
const pathService = yield* Path4.Path;
|
|
641
|
-
const findConfig =
|
|
689
|
+
const findConfig = Effect8.fn("RawConfigReader.findConfig")(function* (projectFolder) {
|
|
642
690
|
for (const name of ALLOWED_CONFIG_NAMES) {
|
|
643
691
|
const filePath = pathService.join(projectFolder, name);
|
|
644
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
692
|
+
const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
|
|
645
693
|
if (exists) {
|
|
646
694
|
return filePath;
|
|
647
695
|
}
|
|
648
696
|
}
|
|
649
697
|
return null;
|
|
650
698
|
});
|
|
651
|
-
const readRawConfig =
|
|
652
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
699
|
+
const readRawConfig = Effect8.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
|
|
700
|
+
const exists = yield* fs.exists(filePath).pipe(Effect8.catchAll(() => Effect8.succeed(false)));
|
|
653
701
|
if (!exists) {
|
|
654
|
-
return yield*
|
|
702
|
+
return yield* Effect8.fail(
|
|
655
703
|
new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
|
|
656
704
|
);
|
|
657
705
|
}
|
|
658
706
|
const fileContents = yield* fs.readFileString(filePath).pipe(
|
|
659
|
-
|
|
707
|
+
Effect8.mapError(
|
|
660
708
|
() => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
|
|
661
709
|
)
|
|
662
710
|
);
|
|
663
711
|
if (fileContents.length === 0) {
|
|
664
|
-
return yield*
|
|
712
|
+
return yield* Effect8.fail(
|
|
665
713
|
new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
|
|
666
714
|
);
|
|
667
715
|
}
|
|
@@ -676,7 +724,7 @@ var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
|
|
|
676
724
|
parsed = parseYaml(fileContents);
|
|
677
725
|
}
|
|
678
726
|
} catch (error) {
|
|
679
|
-
return yield*
|
|
727
|
+
return yield* Effect8.fail(
|
|
680
728
|
new ConfigFileParseError({
|
|
681
729
|
message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
682
730
|
filePath,
|
|
@@ -685,21 +733,21 @@ var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
|
|
|
685
733
|
);
|
|
686
734
|
}
|
|
687
735
|
if (parsed == null) {
|
|
688
|
-
return yield*
|
|
736
|
+
return yield* Effect8.fail(
|
|
689
737
|
new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
|
|
690
738
|
);
|
|
691
739
|
}
|
|
692
740
|
if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
|
|
693
|
-
return yield*
|
|
741
|
+
return yield* Effect8.fail(
|
|
694
742
|
new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
|
|
695
743
|
);
|
|
696
744
|
}
|
|
697
745
|
return parsed;
|
|
698
746
|
});
|
|
699
747
|
const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
748
|
+
Effect8.map((parsed) => parsed),
|
|
749
|
+
Effect8.catchTag("ConfigFileNotFoundError", () => Effect8.succeed(null)),
|
|
750
|
+
Effect8.withSpan("RawConfigReader.readConfigFile")
|
|
703
751
|
);
|
|
704
752
|
return { findConfig, readRawConfig, readConfigFile };
|
|
705
753
|
})
|
|
@@ -709,17 +757,17 @@ var RawConfigReader = class extends Effect6.Service()("RawConfigReader", {
|
|
|
709
757
|
// src/services/schema-validator.ts
|
|
710
758
|
import Ajv from "ajv";
|
|
711
759
|
import addFormats from "ajv-formats";
|
|
712
|
-
import { Effect as
|
|
713
|
-
var SchemaValidator = class extends
|
|
714
|
-
effect:
|
|
760
|
+
import { Effect as Effect9 } from "effect";
|
|
761
|
+
var SchemaValidator = class extends Effect9.Service()("SchemaValidator", {
|
|
762
|
+
effect: Effect9.gen(function* () {
|
|
715
763
|
const ajv = new Ajv();
|
|
716
764
|
addFormats(ajv);
|
|
717
|
-
const validate =
|
|
765
|
+
const validate = Effect9.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
|
|
718
766
|
const compiledValidate = ajv.compile(schema);
|
|
719
767
|
const valid = compiledValidate(config);
|
|
720
768
|
if (!valid) {
|
|
721
769
|
const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
|
|
722
|
-
return yield*
|
|
770
|
+
return yield* Effect9.fail(
|
|
723
771
|
new ConfigSchemaValidationError({
|
|
724
772
|
message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
|
|
725
773
|
filePath,
|
|
@@ -734,9 +782,9 @@ var SchemaValidator = class extends Effect7.Service()("SchemaValidator", {
|
|
|
734
782
|
};
|
|
735
783
|
|
|
736
784
|
// src/services/v4-config-parser.ts
|
|
737
|
-
import { FileSystem as
|
|
785
|
+
import { FileSystem as FileSystem6, Path as Path5 } from "@effect/platform";
|
|
738
786
|
import { getFilesForPattern } from "@gigadrive/build-utils";
|
|
739
|
-
import { Effect as
|
|
787
|
+
import { Effect as Effect10 } from "effect";
|
|
740
788
|
import { minimatch } from "minimatch";
|
|
741
789
|
import safeRegex from "safe-regex2";
|
|
742
790
|
var MAX_ASSET_DEPTH = 100;
|
|
@@ -749,6 +797,23 @@ var DEFAULT_FUNCTION_SETTINGS = {
|
|
|
749
797
|
excludeFiles: void 0,
|
|
750
798
|
includeFiles: void 0
|
|
751
799
|
};
|
|
800
|
+
var toArray = (value) => {
|
|
801
|
+
if (value == null) return void 0;
|
|
802
|
+
return Array.isArray(value) ? value : [value];
|
|
803
|
+
};
|
|
804
|
+
var runtimeStreamsByDefault = (runtime) => runtime == null || runtime.startsWith("node-") || runtime.startsWith("bun-");
|
|
805
|
+
var normalizeRouteDestination = (destination) => {
|
|
806
|
+
const [withoutHash] = destination.split("#", 1);
|
|
807
|
+
const [withoutQuery] = withoutHash.split("?", 1);
|
|
808
|
+
return withoutQuery.replace(/^\/+/, "");
|
|
809
|
+
};
|
|
810
|
+
var destinationMatchesEntrypoint = (destination, entrypointPath) => {
|
|
811
|
+
const normalizedDestination = normalizeRouteDestination(destination);
|
|
812
|
+
if (normalizedDestination === entrypointPath) return true;
|
|
813
|
+
if (!normalizedDestination.includes("$")) return false;
|
|
814
|
+
const pattern = normalizedDestination.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\$[\w]+/g, ".+");
|
|
815
|
+
return new RegExp(`^${pattern}$`).test(entrypointPath);
|
|
816
|
+
};
|
|
752
817
|
var matchesPattern = (path2, pattern) => {
|
|
753
818
|
if (minimatch(path2, pattern)) return true;
|
|
754
819
|
try {
|
|
@@ -767,10 +832,12 @@ var getFunctionSettings = (path2, config) => {
|
|
|
767
832
|
}
|
|
768
833
|
return settings;
|
|
769
834
|
};
|
|
770
|
-
var resolveRouteHandler = (destination, redirect) => {
|
|
835
|
+
var resolveRouteHandler = (destination, redirect, entrypoints = []) => {
|
|
771
836
|
const isExternal = destination.toLowerCase().startsWith("http://") || destination.toLowerCase().startsWith("https://");
|
|
772
837
|
if (redirect === true) return "HTTP_REDIRECT";
|
|
773
|
-
|
|
838
|
+
if (isExternal) return "HTTP_PROXY";
|
|
839
|
+
const matchingEntrypoints = entrypoints.filter((item) => destinationMatchesEntrypoint(destination, item.path));
|
|
840
|
+
return matchingEntrypoints.length > 0 && matchingEntrypoints.every((entrypoint) => entrypoint.streaming === true) ? "SERVERLESS_FUNCTION_STREAMING" : "SERVERLESS_FUNCTION";
|
|
774
841
|
};
|
|
775
842
|
var isRegion = (r) => AVAILABLE_REGIONS.includes(r);
|
|
776
843
|
var resolveRegions = (configRegions) => {
|
|
@@ -778,28 +845,27 @@ var resolveRegions = (configRegions) => {
|
|
|
778
845
|
const valid = configRegions?.filter(isRegion);
|
|
779
846
|
return valid && valid.length > 0 ? valid : AVAILABLE_REGIONS;
|
|
780
847
|
};
|
|
781
|
-
var mapRoute = (route) => ({
|
|
848
|
+
var mapRoute = (route, entrypoints) => ({
|
|
782
849
|
path: route.source,
|
|
783
850
|
destination: route.destination,
|
|
784
|
-
handler: resolveRouteHandler(route.destination, route.redirect),
|
|
851
|
+
handler: resolveRouteHandler(route.destination, route.redirect, entrypoints),
|
|
785
852
|
headers: route.headers ?? {},
|
|
786
853
|
methods: route.methods ?? ["ANY"],
|
|
787
854
|
positiveRequirements: route.has,
|
|
788
855
|
negativeRequirements: route.missing,
|
|
789
856
|
status: route.statusCode
|
|
790
857
|
});
|
|
791
|
-
var parseEntrypoints =
|
|
858
|
+
var parseEntrypoints = Effect10.fn("parseEntrypoints")(function* (config, projectFolder) {
|
|
792
859
|
const entrypoints = [];
|
|
793
860
|
if (config.functions == null) return entrypoints;
|
|
794
861
|
for (const [fnPath, func] of Object.entries(config.functions)) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
yield* new FunctionConfigError({
|
|
862
|
+
if (getFunctionSettings(fnPath, config) == null) {
|
|
863
|
+
return yield* new FunctionConfigError({
|
|
798
864
|
message: `Settings invalid for function at path '${fnPath}'`,
|
|
799
865
|
functionPath: fnPath
|
|
800
866
|
});
|
|
801
867
|
}
|
|
802
|
-
const matchedFiles = yield*
|
|
868
|
+
const matchedFiles = yield* Effect10.tryPromise({
|
|
803
869
|
try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
|
|
804
870
|
catch: (error) => new FunctionConfigError({
|
|
805
871
|
message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -809,27 +875,40 @@ var parseEntrypoints = Effect8.fn("parseEntrypoints")(function* (config, project
|
|
|
809
875
|
for (const file of matchedFiles) {
|
|
810
876
|
if (entrypoints.some((ep) => ep.path === file)) continue;
|
|
811
877
|
if (Object.keys(config.functions).some((f) => f === file && f !== fnPath)) continue;
|
|
878
|
+
const settings = getFunctionSettings(file, config);
|
|
879
|
+
if (settings == null) {
|
|
880
|
+
return yield* new FunctionConfigError({
|
|
881
|
+
message: `Settings invalid for function at path '${file}'`,
|
|
882
|
+
functionPath: file
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
const runtime = settings.runtime ?? "node-20";
|
|
886
|
+
const streaming = settings.streaming ?? runtimeStreamsByDefault(runtime);
|
|
812
887
|
entrypoints.push({
|
|
813
888
|
path: file,
|
|
814
|
-
runtime
|
|
889
|
+
runtime,
|
|
815
890
|
memory: settings.memory ?? 128,
|
|
816
891
|
maxDuration: settings.max_duration ?? 30,
|
|
817
892
|
schedule: func.schedule,
|
|
818
893
|
symlinks: func.symlinks,
|
|
819
|
-
streaming
|
|
894
|
+
streaming,
|
|
895
|
+
package: settings.includeFiles != null || settings.excludeFiles != null ? {
|
|
896
|
+
includeFiles: toArray(settings.includeFiles),
|
|
897
|
+
excludeFiles: toArray(settings.excludeFiles)
|
|
898
|
+
} : void 0
|
|
820
899
|
});
|
|
821
900
|
}
|
|
822
901
|
}
|
|
823
902
|
return entrypoints;
|
|
824
903
|
});
|
|
825
|
-
var collectAssets =
|
|
904
|
+
var collectAssets = Effect10.fn("collectAssets")(function* (config, projectFolder) {
|
|
826
905
|
if (config.assets == null) return [];
|
|
827
|
-
const fs = yield*
|
|
906
|
+
const fs = yield* FileSystem6.FileSystem;
|
|
828
907
|
const pathService = yield* Path5.Path;
|
|
829
908
|
const assetsPath = pathService.join(projectFolder, config.assets);
|
|
830
|
-
const assetsExist = yield* fs.exists(assetsPath).pipe(
|
|
909
|
+
const assetsExist = yield* fs.exists(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(false)));
|
|
831
910
|
if (!assetsExist) return [];
|
|
832
|
-
const stat = yield* fs.stat(assetsPath).pipe(
|
|
911
|
+
const stat = yield* fs.stat(assetsPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
|
|
833
912
|
if (!stat || stat.type !== "Directory") return [];
|
|
834
913
|
const allFiles = yield* collectFilesRecursively(assetsPath);
|
|
835
914
|
const assets = [];
|
|
@@ -840,18 +919,18 @@ var collectAssets = Effect8.fn("collectAssets")(function* (config, projectFolder
|
|
|
840
919
|
}
|
|
841
920
|
return assets;
|
|
842
921
|
});
|
|
843
|
-
var collectFilesRecursively =
|
|
922
|
+
var collectFilesRecursively = Effect10.fn("collectFilesRecursively")(
|
|
844
923
|
function* (basePath, relativePath = "", depth = 0) {
|
|
845
924
|
if (depth > MAX_ASSET_DEPTH) return [];
|
|
846
|
-
const fs = yield*
|
|
925
|
+
const fs = yield* FileSystem6.FileSystem;
|
|
847
926
|
const pathSvc = yield* Path5.Path;
|
|
848
927
|
const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
|
|
849
|
-
const entries = yield* fs.readDirectory(currentPath).pipe(
|
|
928
|
+
const entries = yield* fs.readDirectory(currentPath).pipe(Effect10.catchAll(() => Effect10.succeed([])));
|
|
850
929
|
const result = [];
|
|
851
930
|
for (const name of entries) {
|
|
852
931
|
const fullPath = pathSvc.join(currentPath, name);
|
|
853
932
|
const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
|
|
854
|
-
const stat = yield* fs.stat(fullPath).pipe(
|
|
933
|
+
const stat = yield* fs.stat(fullPath).pipe(Effect10.catchAll(() => Effect10.succeed(null)));
|
|
855
934
|
if (!stat) continue;
|
|
856
935
|
if (stat.type === "Directory") {
|
|
857
936
|
const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
|
|
@@ -863,16 +942,16 @@ var collectFilesRecursively = Effect8.fn("collectFilesRecursively")(
|
|
|
863
942
|
return result;
|
|
864
943
|
}
|
|
865
944
|
);
|
|
866
|
-
var V4ConfigParser = class extends
|
|
945
|
+
var V4ConfigParser = class extends Effect10.Service()("V4ConfigParser", {
|
|
867
946
|
accessors: true,
|
|
868
|
-
effect:
|
|
947
|
+
effect: Effect10.succeed({
|
|
869
948
|
/**
|
|
870
949
|
* Parses a ConfigV4 into a NormalizedConfig.
|
|
871
950
|
*
|
|
872
951
|
* @param config - The raw V4 config object
|
|
873
952
|
* @param projectFolder - Absolute path to the project root
|
|
874
953
|
*/
|
|
875
|
-
parse:
|
|
954
|
+
parse: Effect10.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
|
|
876
955
|
const entrypoints = yield* parseEntrypoints(config, projectFolder);
|
|
877
956
|
const assets = yield* collectAssets(config, projectFolder);
|
|
878
957
|
return {
|
|
@@ -888,7 +967,7 @@ var V4ConfigParser = class extends Effect8.Service()("V4ConfigParser", {
|
|
|
888
967
|
entrypoints,
|
|
889
968
|
errors: [],
|
|
890
969
|
warnings: [],
|
|
891
|
-
routes: (config.routes ?? []).map(mapRoute)
|
|
970
|
+
routes: (config.routes ?? []).map((route) => mapRoute(route, entrypoints))
|
|
892
971
|
};
|
|
893
972
|
})
|
|
894
973
|
})
|
|
@@ -899,7 +978,7 @@ var V4ConfigParser = class extends Effect8.Service()("V4ConfigParser", {
|
|
|
899
978
|
import { Path as Path7 } from "@effect/platform";
|
|
900
979
|
import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
|
|
901
980
|
import { deepMerge } from "@gigadrive/commons";
|
|
902
|
-
import { Effect as
|
|
981
|
+
import { Effect as Effect12 } from "effect";
|
|
903
982
|
|
|
904
983
|
// src/build-output-v3/determine-repo-root.ts
|
|
905
984
|
import path from "path";
|
|
@@ -935,24 +1014,24 @@ var determineRepoRoot = (projectFolder, config) => {
|
|
|
935
1014
|
};
|
|
936
1015
|
|
|
937
1016
|
// src/build-output-v3/get-default-path-map.ts
|
|
938
|
-
import { FileSystem as
|
|
939
|
-
import { Effect as
|
|
940
|
-
var getDefaultPathMap =
|
|
941
|
-
const fs = yield*
|
|
1017
|
+
import { FileSystem as FileSystem7, Path as Path6 } from "@effect/platform";
|
|
1018
|
+
import { Effect as Effect11 } from "effect";
|
|
1019
|
+
var getDefaultPathMap = Effect11.fn("getDefaultPathMap")(function* (directory) {
|
|
1020
|
+
const fs = yield* FileSystem7.FileSystem;
|
|
942
1021
|
const pathService = yield* Path6.Path;
|
|
943
1022
|
const result = {};
|
|
944
|
-
const exists = yield* fs.exists(directory).pipe(
|
|
1023
|
+
const exists = yield* fs.exists(directory).pipe(Effect11.catchAll(() => Effect11.succeed(false)));
|
|
945
1024
|
if (!exists) {
|
|
946
1025
|
return result;
|
|
947
1026
|
}
|
|
948
1027
|
const MAX_DEPTH = 100;
|
|
949
|
-
const processDirectory = (currentPath, basePath = "", depth = 0) =>
|
|
1028
|
+
const processDirectory = (currentPath, basePath = "", depth = 0) => Effect11.gen(function* () {
|
|
950
1029
|
if (depth > MAX_DEPTH) return;
|
|
951
|
-
const entries = yield* fs.readDirectory(currentPath).pipe(
|
|
1030
|
+
const entries = yield* fs.readDirectory(currentPath).pipe(Effect11.catchAll(() => Effect11.succeed([])));
|
|
952
1031
|
for (const name of entries) {
|
|
953
1032
|
const fullPath = pathService.join(currentPath, name);
|
|
954
1033
|
const relativePath = basePath ? pathService.join(basePath, name) : name;
|
|
955
|
-
const stat = yield* fs.stat(fullPath).pipe(
|
|
1034
|
+
const stat = yield* fs.stat(fullPath).pipe(Effect11.catchAll(() => Effect11.succeed(null)));
|
|
956
1035
|
if (!stat) continue;
|
|
957
1036
|
if (stat.type === "Directory") {
|
|
958
1037
|
yield* processDirectory(fullPath, relativePath, depth + 1);
|
|
@@ -1026,11 +1105,11 @@ var translateVercelRuntime = (runtime) => {
|
|
|
1026
1105
|
var CONFIG_PATH = ".vercel/output/config.json";
|
|
1027
1106
|
var FUNCTIONS_FOLDER = ".vercel/output/functions";
|
|
1028
1107
|
var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
|
|
1029
|
-
var VercelBuildOutputParser = class extends
|
|
1030
|
-
effect:
|
|
1108
|
+
var VercelBuildOutputParser = class extends Effect12.Service()("VercelBuildOutputParser", {
|
|
1109
|
+
effect: Effect12.gen(function* () {
|
|
1031
1110
|
const rawConfigReader = yield* RawConfigReader;
|
|
1032
1111
|
const pathService = yield* Path7.Path;
|
|
1033
|
-
const parse =
|
|
1112
|
+
const parse = Effect12.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
|
|
1034
1113
|
const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
|
|
1035
1114
|
if (!config || typeof config.version !== "number" || config.version < 3) {
|
|
1036
1115
|
return parseResult;
|
|
@@ -1041,8 +1120,8 @@ var VercelBuildOutputParser = class extends Effect10.Service()("VercelBuildOutpu
|
|
|
1041
1120
|
merged.regions = [...new Set(merged.regions)];
|
|
1042
1121
|
return merged;
|
|
1043
1122
|
});
|
|
1044
|
-
const loadFunctions =
|
|
1045
|
-
const functionConfigs = yield*
|
|
1123
|
+
const loadFunctions = Effect12.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
|
|
1124
|
+
const functionConfigs = yield* Effect12.tryPromise({
|
|
1046
1125
|
try: () => getFilesForPattern2(FUNCTION_CONFIGS_PATTERN, projectFolder),
|
|
1047
1126
|
catch: (error) => new ConfigFileParseError({
|
|
1048
1127
|
message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -1088,7 +1167,7 @@ var VercelBuildOutputParser = class extends Effect10.Service()("VercelBuildOutpu
|
|
|
1088
1167
|
Object.assign(environmentVariables, env);
|
|
1089
1168
|
}
|
|
1090
1169
|
}
|
|
1091
|
-
const streaming =
|
|
1170
|
+
const streaming = functionConfig.supportsResponseStreaming ?? functionConfig.experimentalResponseStreaming ?? runtime.startsWith("node-");
|
|
1092
1171
|
let filePathMap = {};
|
|
1093
1172
|
for (const [key, value] of Object.entries(configFilePathMap)) {
|
|
1094
1173
|
filePathMap[pathService.join(projectFolder, key)] = value;
|
|
@@ -1224,6 +1303,10 @@ var schema_default = {
|
|
|
1224
1303
|
$ref: "#/$defs/runtimes",
|
|
1225
1304
|
description: "The runtime to use for the function."
|
|
1226
1305
|
},
|
|
1306
|
+
streaming: {
|
|
1307
|
+
type: "boolean",
|
|
1308
|
+
description: "Enable function response streaming. When omitted, Node and Bun runtimes stream by default."
|
|
1309
|
+
},
|
|
1227
1310
|
schedule: {
|
|
1228
1311
|
type: "string",
|
|
1229
1312
|
description: "An expression to schedule the function to run at specific times.",
|
|
@@ -1496,7 +1579,7 @@ var schema_default = {
|
|
|
1496
1579
|
};
|
|
1497
1580
|
|
|
1498
1581
|
// src/parse-config.ts
|
|
1499
|
-
var parseConfigRaw =
|
|
1582
|
+
var parseConfigRaw = Effect13.fn("parseConfigRaw")(function* (filePath, projectFolder) {
|
|
1500
1583
|
const rawReader = yield* RawConfigReader;
|
|
1501
1584
|
const validator = yield* SchemaValidator;
|
|
1502
1585
|
const v4Parser = yield* V4ConfigParser;
|
|
@@ -1507,7 +1590,7 @@ var parseConfigRaw = Effect11.fn("parseConfigRaw")(function* (filePath, projectF
|
|
|
1507
1590
|
};
|
|
1508
1591
|
const schema = schemaMap[version];
|
|
1509
1592
|
if (!schema) {
|
|
1510
|
-
return yield*
|
|
1593
|
+
return yield* Effect13.fail(
|
|
1511
1594
|
new ConfigVersionError({
|
|
1512
1595
|
message: `Config file at ${filePath} has an unsupported version: ${version}`,
|
|
1513
1596
|
filePath,
|
|
@@ -1518,11 +1601,11 @@ var parseConfigRaw = Effect11.fn("parseConfigRaw")(function* (filePath, projectF
|
|
|
1518
1601
|
yield* validator.validate(parsed, schema, filePath);
|
|
1519
1602
|
return yield* v4Parser.parse(parsed, projectFolder);
|
|
1520
1603
|
});
|
|
1521
|
-
var parseConfig =
|
|
1604
|
+
var parseConfig = Effect13.fn("parseConfig")(function* (filePath, projectFolder) {
|
|
1522
1605
|
const parseResult = yield* parseConfigRaw(filePath, projectFolder);
|
|
1523
1606
|
return yield* postProcessConfig(parseResult, projectFolder);
|
|
1524
1607
|
});
|
|
1525
|
-
var postProcessConfig =
|
|
1608
|
+
var postProcessConfig = Effect13.fn("postProcessConfig")(function* (config, projectFolder) {
|
|
1526
1609
|
const vercelParser = yield* VercelBuildOutputParser;
|
|
1527
1610
|
let result = yield* vercelParser.parse(config, projectFolder);
|
|
1528
1611
|
if (result.entrypoints.length === 0 && (result.assets?.paths?.length || 0) === 0 && result.routes.length === 0) {
|