@gigadrive/network-config 5.0.0 → 5.2.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/define-config.d.mts +156 -2
- package/dist/define-config.d.ts +156 -2
- package/dist/index.d.mts +492 -80
- package/dist/index.d.ts +492 -80
- package/dist/index.js +1863 -420
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1850 -421
- package/dist/index.mjs.map +1 -1
- package/dist/v4/schema.json +323 -5
- package/package.json +2 -2
- package/src/v4/schema.json +323 -5
package/dist/index.js
CHANGED
|
@@ -33,6 +33,9 @@ __export(src_exports, {
|
|
|
33
33
|
ALLOWED_CONFIG_NAMES: () => ALLOWED_CONFIG_NAMES,
|
|
34
34
|
AVAILABLE_REGIONS: () => AVAILABLE_REGIONS,
|
|
35
35
|
AVAILABLE_RUNTIMES: () => AVAILABLE_RUNTIMES,
|
|
36
|
+
COMPOSE_FILE_NAMES: () => COMPOSE_FILE_NAMES,
|
|
37
|
+
CONTAINER_ENTRYPOINT_PREFIX: () => CONTAINER_ENTRYPOINT_PREFIX,
|
|
38
|
+
CONTAINER_RUNTIME: () => CONTAINER_RUNTIME,
|
|
36
39
|
ConfigFileEmptyError: () => ConfigFileEmptyError,
|
|
37
40
|
ConfigFileNotFoundError: () => ConfigFileNotFoundError,
|
|
38
41
|
ConfigFileParseError: () => ConfigFileParseError,
|
|
@@ -40,7 +43,10 @@ __export(src_exports, {
|
|
|
40
43
|
ConfigModuleLoader: () => ConfigModuleLoader,
|
|
41
44
|
ConfigSchemaValidationError: () => ConfigSchemaValidationError,
|
|
42
45
|
ConfigVersionError: () => ConfigVersionError,
|
|
46
|
+
ContainerConfigError: () => ContainerConfigError,
|
|
47
|
+
DEFAULT_CONTAINER_MEMORY_MB: () => DEFAULT_CONTAINER_MEMORY_MB,
|
|
43
48
|
DEFAULT_FUNCTION_DURATION_SECONDS: () => DEFAULT_FUNCTION_DURATION_SECONDS,
|
|
49
|
+
DEFAULT_SIDECAR_MEMORY_MB: () => DEFAULT_SIDECAR_MEMORY_MB,
|
|
44
50
|
FRAMEWORK_DEFINITIONS: () => FRAMEWORK_DEFINITIONS,
|
|
45
51
|
FrameworkNotDetectedError: () => FrameworkNotDetectedError,
|
|
46
52
|
FunctionConfigError: () => FunctionConfigError,
|
|
@@ -57,6 +63,7 @@ __export(src_exports, {
|
|
|
57
63
|
GigadriveNextServerDescriptorSchema: () => GigadriveNextServerDescriptorSchema,
|
|
58
64
|
GigadriveNextStaticAssetPrefixSchema: () => GigadriveNextStaticAssetPrefixSchema,
|
|
59
65
|
MAX_FUNCTION_DURATION_SECONDS: () => MAX_FUNCTION_DURATION_SECONDS,
|
|
66
|
+
MAX_SIDECARS: () => MAX_SIDECARS,
|
|
60
67
|
ManifestNotFoundError: () => ManifestNotFoundError,
|
|
61
68
|
ManifestParseError: () => ManifestParseError,
|
|
62
69
|
ManifestReadError: () => ManifestReadError,
|
|
@@ -69,20 +76,27 @@ __export(src_exports, {
|
|
|
69
76
|
V4ConfigParser: () => V4ConfigParser,
|
|
70
77
|
VercelBuildOutputParser: () => VercelBuildOutputParser,
|
|
71
78
|
collectAssetFiles: () => collectAssetFiles,
|
|
79
|
+
composeDeclaresApp: () => composeDeclaresApp,
|
|
80
|
+
containerEntrypointPath: () => containerEntrypointPath,
|
|
72
81
|
defineConfig: () => defineConfig,
|
|
82
|
+
detectContainerProject: () => detectContainerProject,
|
|
73
83
|
detectFramework: () => detectFramework,
|
|
74
84
|
detectPackageManager: () => detectPackageManager,
|
|
85
|
+
dockerFunctionContainerName: () => dockerFunctionContainerName,
|
|
75
86
|
filterFunctionsFromAssets: () => filterFunctionsFromAssets,
|
|
76
87
|
generateConfig: () => generateConfig,
|
|
77
88
|
getFunctionSettings: () => getFunctionSettings,
|
|
78
89
|
mergeWithFrameworkDefaults: () => mergeWithFrameworkDefaults,
|
|
90
|
+
normalizeContainers: () => normalizeContainers,
|
|
79
91
|
parseConfig: () => parseConfig,
|
|
80
92
|
parseConfigRaw: () => parseConfigRaw,
|
|
81
93
|
parseGigadriveNextBuildManifest: () => parseGigadriveNextBuildManifest,
|
|
82
94
|
parseGigadriveNextPrerenderManifest: () => parseGigadriveNextPrerenderManifest,
|
|
83
95
|
parseStaticAssetManifest: () => parseStaticAssetManifest,
|
|
84
96
|
postProcessConfig: () => postProcessConfig,
|
|
85
|
-
|
|
97
|
+
readComposeContainers: () => readComposeContainers,
|
|
98
|
+
readDependencies: () => readDependencies,
|
|
99
|
+
splitCommandWords: () => splitCommandWords
|
|
86
100
|
});
|
|
87
101
|
module.exports = __toCommonJS(src_exports);
|
|
88
102
|
|
|
@@ -181,16 +195,824 @@ var collectAssetFiles = import_effect3.Effect.fn("collectAssetFiles")(function*
|
|
|
181
195
|
return files.map((file) => file.replaceAll("\\", "/")).filter((file) => !DISALLOWED_ASSET_EXTENSIONS.some((extension) => file.toLowerCase().endsWith(extension))).sort();
|
|
182
196
|
});
|
|
183
197
|
|
|
198
|
+
// src/containers.ts
|
|
199
|
+
var import_platform2 = require("@effect/platform");
|
|
200
|
+
var import_effect5 = require("effect");
|
|
201
|
+
var import_node_path = require("path");
|
|
202
|
+
var import_yaml = require("yaml");
|
|
203
|
+
|
|
204
|
+
// src/errors.ts
|
|
205
|
+
var import_effect4 = require("effect");
|
|
206
|
+
var ConfigFileNotFoundError = class extends import_effect4.Schema.TaggedError()("ConfigFileNotFoundError", {
|
|
207
|
+
message: import_effect4.Schema.String,
|
|
208
|
+
filePath: import_effect4.Schema.String
|
|
209
|
+
}) {
|
|
210
|
+
};
|
|
211
|
+
var ConfigFileEmptyError = class extends import_effect4.Schema.TaggedError()("ConfigFileEmptyError", {
|
|
212
|
+
message: import_effect4.Schema.String,
|
|
213
|
+
filePath: import_effect4.Schema.String
|
|
214
|
+
}) {
|
|
215
|
+
};
|
|
216
|
+
var ConfigFileParseError = class extends import_effect4.Schema.TaggedError()("ConfigFileParseError", {
|
|
217
|
+
message: import_effect4.Schema.String,
|
|
218
|
+
filePath: import_effect4.Schema.String,
|
|
219
|
+
cause: import_effect4.Schema.optional(import_effect4.Schema.String)
|
|
220
|
+
}) {
|
|
221
|
+
};
|
|
222
|
+
var ConfigModuleLoadError = class extends import_effect4.Schema.TaggedError()("ConfigModuleLoadError", {
|
|
223
|
+
message: import_effect4.Schema.String,
|
|
224
|
+
filePath: import_effect4.Schema.String,
|
|
225
|
+
cause: import_effect4.Schema.optional(import_effect4.Schema.String)
|
|
226
|
+
}) {
|
|
227
|
+
};
|
|
228
|
+
var ConfigVersionError = class extends import_effect4.Schema.TaggedError()("ConfigVersionError", {
|
|
229
|
+
message: import_effect4.Schema.String,
|
|
230
|
+
filePath: import_effect4.Schema.String,
|
|
231
|
+
version: import_effect4.Schema.optional(import_effect4.Schema.Number)
|
|
232
|
+
}) {
|
|
233
|
+
};
|
|
234
|
+
var ConfigSchemaValidationError = class extends import_effect4.Schema.TaggedError()(
|
|
235
|
+
"ConfigSchemaValidationError",
|
|
236
|
+
{
|
|
237
|
+
message: import_effect4.Schema.String,
|
|
238
|
+
filePath: import_effect4.Schema.String,
|
|
239
|
+
validationErrors: import_effect4.Schema.Array(import_effect4.Schema.String)
|
|
240
|
+
}
|
|
241
|
+
) {
|
|
242
|
+
};
|
|
243
|
+
var FunctionConfigError = class extends import_effect4.Schema.TaggedError()("FunctionConfigError", {
|
|
244
|
+
message: import_effect4.Schema.String,
|
|
245
|
+
functionPath: import_effect4.Schema.String
|
|
246
|
+
}) {
|
|
247
|
+
};
|
|
248
|
+
var ContainerConfigError = class extends import_effect4.Schema.TaggedError()("ContainerConfigError", {
|
|
249
|
+
message: import_effect4.Schema.String,
|
|
250
|
+
containerName: import_effect4.Schema.optional(import_effect4.Schema.String),
|
|
251
|
+
filePath: import_effect4.Schema.optional(import_effect4.Schema.String)
|
|
252
|
+
}) {
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// src/normalized-config.ts
|
|
256
|
+
var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
|
|
257
|
+
var MAX_FUNCTION_DURATION_SECONDS = 28800;
|
|
258
|
+
var CONTAINER_RUNTIME = "docker";
|
|
259
|
+
var CONTAINER_ENTRYPOINT_PREFIX = "container:";
|
|
260
|
+
var DEFAULT_CONTAINER_MEMORY_MB = 512;
|
|
261
|
+
var DEFAULT_SIDECAR_MEMORY_MB = 256;
|
|
262
|
+
var MAX_SIDECARS = 4;
|
|
263
|
+
|
|
264
|
+
// src/containers.ts
|
|
265
|
+
var COMPOSE_FILE_NAMES = ["compose.yaml", "compose.yml", "docker-compose.yaml", "docker-compose.yml"];
|
|
266
|
+
var CONTAINER_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
267
|
+
var CONTAINER_NAME_RULES = "1 to 63 lowercase letters, digits, '-' or '_', starting with a letter, and not 'localhost'";
|
|
268
|
+
var MIN_CONTAINER_MEMORY_MB = 128;
|
|
269
|
+
var MAX_CONTAINER_MEMORY_MB = 3009;
|
|
270
|
+
var MAX_CONTAINER_ENV_VARS = 100;
|
|
271
|
+
var MAX_CONTAINER_ENV_VALUE_LENGTH = 65536;
|
|
272
|
+
var containerEntrypointPath = (name) => `${CONTAINER_ENTRYPOINT_PREFIX}${name}`;
|
|
273
|
+
var toContainerName = (raw) => {
|
|
274
|
+
const cleaned = raw.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^[^a-z0-9]+/, "");
|
|
275
|
+
const name = (cleaned === "" || /^[a-z]/.test(cleaned) ? cleaned : `app-${cleaned}`).slice(0, 63);
|
|
276
|
+
return name === "" || name === "localhost" ? "app" : name;
|
|
277
|
+
};
|
|
278
|
+
var dockerFunctionContainerName = (file) => {
|
|
279
|
+
const { dir, base } = import_node_path.posix.parse(file);
|
|
280
|
+
const variant = base.replace(/^Dockerfile[.-]?/i, "").replace(/[.-]?Dockerfile$/i, "");
|
|
281
|
+
const raw = [import_node_path.posix.basename(dir), variant === base ? import_node_path.posix.parse(base).name : variant].filter((part) => part !== "").join("-");
|
|
282
|
+
return toContainerName(raw);
|
|
283
|
+
};
|
|
284
|
+
var splitCommandWords = (input) => {
|
|
285
|
+
const words = [];
|
|
286
|
+
let current = "";
|
|
287
|
+
let inWord = false;
|
|
288
|
+
let quote;
|
|
289
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
290
|
+
const char = input[index];
|
|
291
|
+
if (quote === "'") {
|
|
292
|
+
if (char === "'") quote = void 0;
|
|
293
|
+
else current += char;
|
|
294
|
+
} else if (char === "\\" && index + 1 < input.length) {
|
|
295
|
+
index += 1;
|
|
296
|
+
current += input[index];
|
|
297
|
+
inWord = true;
|
|
298
|
+
} else if (quote === '"') {
|
|
299
|
+
if (char === '"') quote = void 0;
|
|
300
|
+
else current += char;
|
|
301
|
+
} else if (char === "'" || char === '"') {
|
|
302
|
+
quote = char;
|
|
303
|
+
inWord = true;
|
|
304
|
+
} else if (/\s/.test(char)) {
|
|
305
|
+
if (inWord) words.push(current);
|
|
306
|
+
current = "";
|
|
307
|
+
inWord = false;
|
|
308
|
+
} else {
|
|
309
|
+
current += char;
|
|
310
|
+
inWord = true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (quote) throw new Error(`Unterminated ${quote} quote`);
|
|
314
|
+
if (inWord) words.push(current);
|
|
315
|
+
return words;
|
|
316
|
+
};
|
|
317
|
+
var normalizeProjectPath = (input) => {
|
|
318
|
+
if (import_node_path.posix.isAbsolute(input)) return void 0;
|
|
319
|
+
const normalized = import_node_path.posix.normalize(input.replace(/\\/g, "/")).replace(/\/+$/, "") || ".";
|
|
320
|
+
if (normalized === ".." || normalized.startsWith("../")) return void 0;
|
|
321
|
+
return normalized;
|
|
322
|
+
};
|
|
323
|
+
var resolveProjectRoot = (projectFolder) => import_effect5.Effect.flatMap(
|
|
324
|
+
import_platform2.FileSystem.FileSystem,
|
|
325
|
+
(fs) => fs.realPath(projectFolder).pipe(import_effect5.Effect.orElseSucceed(() => projectFolder))
|
|
326
|
+
);
|
|
327
|
+
var resolveInsideProject = (projectRoot, projectRelative, subject, context) => import_effect5.Effect.gen(function* () {
|
|
328
|
+
const fs = yield* import_platform2.FileSystem.FileSystem;
|
|
329
|
+
const pathSvc = yield* import_platform2.Path.Path;
|
|
330
|
+
const resolved = yield* fs.realPath(pathSvc.join(projectRoot, projectRelative)).pipe(import_effect5.Effect.option);
|
|
331
|
+
if (import_effect5.Option.isNone(resolved)) return resolved;
|
|
332
|
+
const relative = pathSvc.relative(projectRoot, resolved.value);
|
|
333
|
+
if (relative === ".." || relative.startsWith(`..${pathSvc.sep}`) || pathSvc.isAbsolute(relative)) {
|
|
334
|
+
return yield* new ContainerConfigError({
|
|
335
|
+
message: `${subject} leads through a symbolic link to a location outside the project. Only files inside the project can be deployed.`,
|
|
336
|
+
...context
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return resolved;
|
|
340
|
+
});
|
|
341
|
+
var readInsideProject = (projectRoot, projectRelative, subject, context) => import_effect5.Effect.gen(function* () {
|
|
342
|
+
const fs = yield* import_platform2.FileSystem.FileSystem;
|
|
343
|
+
const resolved = yield* resolveInsideProject(projectRoot, projectRelative, subject, context);
|
|
344
|
+
if (import_effect5.Option.isNone(resolved)) return import_effect5.Option.none();
|
|
345
|
+
return yield* fs.readFileString(resolved.value).pipe(import_effect5.Effect.option);
|
|
346
|
+
});
|
|
347
|
+
var toArgv = (name, key, value) => value === void 0 ? import_effect5.Effect.succeed(void 0) : Array.isArray(value) ? import_effect5.Effect.succeed(value) : import_effect5.Effect.try({
|
|
348
|
+
try: () => splitCommandWords(value),
|
|
349
|
+
catch: (error) => new ContainerConfigError({
|
|
350
|
+
message: `Container '${name}' has an invalid ${key}: ${error instanceof Error ? error.message : String(error)}`,
|
|
351
|
+
containerName: name
|
|
352
|
+
})
|
|
353
|
+
});
|
|
354
|
+
var isIntegerBetween = (value, min, max) => Number.isInteger(value) && value >= min && value <= max;
|
|
355
|
+
var validateContainer = (name, container) => {
|
|
356
|
+
const build = typeof container.build === "object" ? container.build : void 0;
|
|
357
|
+
const buildArgs = Object.values(build?.args ?? {});
|
|
358
|
+
const env = Object.entries(container.env ?? {});
|
|
359
|
+
const user = container.user === void 0 ? void 0 : String(container.user);
|
|
360
|
+
const badEnvKey = env.find(([key]) => key === "" || key.includes("=") || key.includes("\0"))?.[0];
|
|
361
|
+
const longEnvKey = env.find(([, value]) => value.length > MAX_CONTAINER_ENV_VALUE_LENGTH)?.[0];
|
|
362
|
+
const problem = [
|
|
363
|
+
[
|
|
364
|
+
container.image !== void 0 && !/^\S{1,512}$/.test(container.image),
|
|
365
|
+
"has an invalid image reference. Use 1 to 512 characters without whitespace."
|
|
366
|
+
],
|
|
367
|
+
[
|
|
368
|
+
container.port !== void 0 && !isIntegerBetween(container.port, 1, 65535),
|
|
369
|
+
`listens on port ${container.port}. Use a whole number from 1 to 65535.`
|
|
370
|
+
],
|
|
371
|
+
[
|
|
372
|
+
container.memory !== void 0 && !isIntegerBetween(container.memory, MIN_CONTAINER_MEMORY_MB, MAX_CONTAINER_MEMORY_MB),
|
|
373
|
+
`asks for ${container.memory} MB of memory. Use a whole number from ${MIN_CONTAINER_MEMORY_MB} to ${MAX_CONTAINER_MEMORY_MB}.`
|
|
374
|
+
],
|
|
375
|
+
[
|
|
376
|
+
container.working_dir !== void 0 && !(container.working_dir.startsWith("/") && container.working_dir.length <= 1024),
|
|
377
|
+
`sets working_dir '${container.working_dir}', which must be an absolute path of at most 1024 characters.`
|
|
378
|
+
],
|
|
379
|
+
[
|
|
380
|
+
typeof container.user === "number" && !isIntegerBetween(container.user, 0, Number.MAX_SAFE_INTEGER),
|
|
381
|
+
`sets user ${container.user}. A numeric user must be a non-negative whole number.`
|
|
382
|
+
],
|
|
383
|
+
[
|
|
384
|
+
user !== void 0 && (user.length === 0 || user.length > 256),
|
|
385
|
+
"sets an empty or overlong user. Use 1 to 256 characters: a name, a uid, name:group or uid:gid."
|
|
386
|
+
],
|
|
387
|
+
[
|
|
388
|
+
build?.target !== void 0 && (build.target.length === 0 || build.target.length > 128),
|
|
389
|
+
"has an empty build target or one longer than 128 characters."
|
|
390
|
+
],
|
|
391
|
+
[
|
|
392
|
+
buildArgs.length > MAX_CONTAINER_ENV_VARS || buildArgs.some((value) => value.length > MAX_CONTAINER_ENV_VALUE_LENGTH),
|
|
393
|
+
`sets more than ${MAX_CONTAINER_ENV_VARS} build args, or one longer than ${MAX_CONTAINER_ENV_VALUE_LENGTH} characters.`
|
|
394
|
+
],
|
|
395
|
+
[
|
|
396
|
+
env.length > MAX_CONTAINER_ENV_VARS,
|
|
397
|
+
`sets ${env.length} environment variables. At most ${MAX_CONTAINER_ENV_VARS} are allowed.`
|
|
398
|
+
],
|
|
399
|
+
[
|
|
400
|
+
badEnvKey !== void 0,
|
|
401
|
+
`sets an environment variable named '${badEnvKey}'. Names must be non-empty and contain no '='.`
|
|
402
|
+
],
|
|
403
|
+
[
|
|
404
|
+
longEnvKey !== void 0,
|
|
405
|
+
`sets environment variable '${longEnvKey}' to a value longer than ${MAX_CONTAINER_ENV_VALUE_LENGTH} characters.`
|
|
406
|
+
]
|
|
407
|
+
].find(([failed]) => failed)?.[1];
|
|
408
|
+
return problem === void 0 ? import_effect5.Effect.void : import_effect5.Effect.fail(new ContainerConfigError({ message: `Container '${name}' ${problem}`, containerName: name }));
|
|
409
|
+
};
|
|
410
|
+
var toContainerSpec = import_effect5.Effect.fn("toContainerSpec")(function* (name, container, projectFolder) {
|
|
411
|
+
yield* validateContainer(name, container);
|
|
412
|
+
let source;
|
|
413
|
+
if (container.image !== void 0 && container.build === void 0) {
|
|
414
|
+
source = { type: "registry", reference: container.image };
|
|
415
|
+
} else if (container.build !== void 0 && container.image === void 0) {
|
|
416
|
+
const build = typeof container.build === "string" ? { context: container.build } : container.build;
|
|
417
|
+
const dockerfile = build.dockerfile ?? "Dockerfile";
|
|
418
|
+
const context = normalizeProjectPath(build.context ?? ".");
|
|
419
|
+
const dockerfilePath = context === void 0 || import_node_path.posix.isAbsolute(dockerfile) ? void 0 : normalizeProjectPath(import_node_path.posix.join(context, dockerfile));
|
|
420
|
+
if (context === void 0 || dockerfilePath === void 0) {
|
|
421
|
+
return yield* new ContainerConfigError({
|
|
422
|
+
message: `Container '${name}' has a build context or Dockerfile outside the project.`,
|
|
423
|
+
containerName: name
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
const projectRoot = yield* resolveProjectRoot(projectFolder);
|
|
427
|
+
yield* resolveInsideProject(projectRoot, context, `The build context '${context}' of container '${name}'`, {
|
|
428
|
+
containerName: name
|
|
429
|
+
});
|
|
430
|
+
const dockerfileReal = yield* resolveInsideProject(
|
|
431
|
+
projectRoot,
|
|
432
|
+
dockerfilePath,
|
|
433
|
+
`The Dockerfile '${dockerfilePath}' of container '${name}'`,
|
|
434
|
+
{ containerName: name }
|
|
435
|
+
);
|
|
436
|
+
if (import_effect5.Option.isNone(dockerfileReal)) {
|
|
437
|
+
return yield* new ContainerConfigError({
|
|
438
|
+
message: `Container '${name}' builds '${dockerfilePath}', which does not exist.`,
|
|
439
|
+
containerName: name
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
source = {
|
|
443
|
+
type: "dockerfile",
|
|
444
|
+
context,
|
|
445
|
+
dockerfile: import_node_path.posix.relative(context, dockerfilePath),
|
|
446
|
+
...build.target !== void 0 && { target: build.target },
|
|
447
|
+
...build.args !== void 0 && Object.keys(build.args).length > 0 && { buildArgs: { ...build.args } }
|
|
448
|
+
};
|
|
449
|
+
} else {
|
|
450
|
+
return yield* new ContainerConfigError({
|
|
451
|
+
message: `Container '${name}' must set exactly one of 'image' and 'build'.`,
|
|
452
|
+
containerName: name
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
const entrypoint = yield* toArgv(name, "entrypoint", container.entrypoint);
|
|
456
|
+
const command = yield* toArgv(name, "command", container.command);
|
|
457
|
+
const spec = {
|
|
458
|
+
name,
|
|
459
|
+
source,
|
|
460
|
+
...container.port !== void 0 && { port: container.port },
|
|
461
|
+
...entrypoint !== void 0 && { entrypoint },
|
|
462
|
+
...command !== void 0 && { command },
|
|
463
|
+
...container.working_dir !== void 0 && { workingDirectory: container.working_dir },
|
|
464
|
+
...container.user !== void 0 && { user: String(container.user) },
|
|
465
|
+
...container.env !== void 0 && Object.keys(container.env).length > 0 && { environmentVariables: { ...container.env } }
|
|
466
|
+
};
|
|
467
|
+
return spec;
|
|
468
|
+
});
|
|
469
|
+
var normalizeContainers = import_effect5.Effect.fn("normalizeContainers")(function* (containers, projectFolder) {
|
|
470
|
+
const entrypoints = [];
|
|
471
|
+
const sidecars = [];
|
|
472
|
+
const warnings = [];
|
|
473
|
+
for (const [name, container] of Object.entries(containers)) {
|
|
474
|
+
if (!CONTAINER_NAME_PATTERN.test(name) || name === "localhost") {
|
|
475
|
+
return yield* new ContainerConfigError({
|
|
476
|
+
message: `Container name '${name}' is invalid. The name is also the hostname the function reaches the container by, so it must be ${CONTAINER_NAME_RULES}. Try '${toContainerName(name)}'.`,
|
|
477
|
+
containerName: name
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
const spec = yield* toContainerSpec(name, container, projectFolder);
|
|
481
|
+
if (container.sidecar === true) {
|
|
482
|
+
const ignored = ["max_duration", "streaming", "schedule"].filter(
|
|
483
|
+
(key) => container[key] !== void 0
|
|
484
|
+
);
|
|
485
|
+
if (ignored.length > 0) {
|
|
486
|
+
warnings.push(
|
|
487
|
+
`Sidecar '${name}' ignores ${ignored.join(", ")}: those settings apply to container functions only.`
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
sidecars.push({ ...spec, memory: container.memory ?? DEFAULT_SIDECAR_MEMORY_MB });
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
entrypoints.push({
|
|
494
|
+
path: containerEntrypointPath(name),
|
|
495
|
+
displayName: name,
|
|
496
|
+
runtime: CONTAINER_RUNTIME,
|
|
497
|
+
memory: container.memory ?? DEFAULT_CONTAINER_MEMORY_MB,
|
|
498
|
+
maxDuration: container.max_duration ?? DEFAULT_FUNCTION_DURATION_SECONDS,
|
|
499
|
+
streaming: container.streaming ?? true,
|
|
500
|
+
...container.schedule !== void 0 && { schedule: container.schedule },
|
|
501
|
+
container: spec
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
if (sidecars.length > MAX_SIDECARS) {
|
|
505
|
+
return yield* new ContainerConfigError({
|
|
506
|
+
message: `A deployment may declare at most ${MAX_SIDECARS} sidecars; this one declares ${sidecars.length}.`
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
const sidecarPorts = /* @__PURE__ */ new Map();
|
|
510
|
+
for (const sidecar of sidecars) {
|
|
511
|
+
if (sidecar.port === void 0) continue;
|
|
512
|
+
const owner = sidecarPorts.get(sidecar.port);
|
|
513
|
+
if (owner !== void 0) {
|
|
514
|
+
return yield* new ContainerConfigError({
|
|
515
|
+
message: `Sidecars '${owner}' and '${sidecar.name}' both listen on port ${sidecar.port}. Sidecars share one network namespace, so their ports must differ.`,
|
|
516
|
+
containerName: sidecar.name
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
sidecarPorts.set(sidecar.port, sidecar.name);
|
|
520
|
+
}
|
|
521
|
+
for (const entrypoint of entrypoints) {
|
|
522
|
+
const port = entrypoint.container?.port;
|
|
523
|
+
const sidecar = port === void 0 ? void 0 : sidecarPorts.get(port);
|
|
524
|
+
if (sidecar !== void 0) {
|
|
525
|
+
return yield* new ContainerConfigError({
|
|
526
|
+
message: `Container '${entrypoint.displayName}' and sidecar '${sidecar}' both listen on port ${port}. Sidecars run inside the function's microVM, so their ports must differ.`,
|
|
527
|
+
containerName: sidecar
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return { entrypoints, sidecars, warnings };
|
|
532
|
+
});
|
|
533
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
534
|
+
var isStringArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
535
|
+
var scalarToString = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : void 0;
|
|
536
|
+
var gigadriveExtension = (service) => isRecord(service["x-gigadrive"]) ? service["x-gigadrive"] : {};
|
|
537
|
+
var COMPOSE_OVERRIDE_FILE_NAMES = [
|
|
538
|
+
"compose.override.yaml",
|
|
539
|
+
"compose.override.yml",
|
|
540
|
+
"docker-compose.override.yaml",
|
|
541
|
+
"docker-compose.override.yml"
|
|
542
|
+
];
|
|
543
|
+
var findClosingQuote = (body, quote) => {
|
|
544
|
+
for (let index = 0; index < body.length; index += 1) {
|
|
545
|
+
if (quote === '"' && body[index] === "\\") index += 1;
|
|
546
|
+
else if (body[index] === quote) return index;
|
|
547
|
+
}
|
|
548
|
+
return -1;
|
|
549
|
+
};
|
|
550
|
+
var DOUBLE_QUOTE_ESCAPES = { n: "\n", r: "\r", t: " " };
|
|
551
|
+
var parseDotEnv = (content) => {
|
|
552
|
+
const values = {};
|
|
553
|
+
const lines = content.split(/\r?\n/);
|
|
554
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
555
|
+
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_.-]*)\s*=(.*)$/.exec(lines[index]);
|
|
556
|
+
if (!match) continue;
|
|
557
|
+
const [, key, rest] = match;
|
|
558
|
+
const quote = rest.trimStart()[0];
|
|
559
|
+
if (quote === '"' || quote === "'") {
|
|
560
|
+
let body = rest.trimStart().slice(1);
|
|
561
|
+
let end = index;
|
|
562
|
+
let close = findClosingQuote(body, quote);
|
|
563
|
+
while (close === -1 && end + 1 < lines.length) {
|
|
564
|
+
end += 1;
|
|
565
|
+
body += `
|
|
566
|
+
${lines[end]}`;
|
|
567
|
+
close = findClosingQuote(body, quote);
|
|
568
|
+
}
|
|
569
|
+
if (close !== -1) {
|
|
570
|
+
const raw = body.slice(0, close);
|
|
571
|
+
values[key] = quote === '"' ? raw.replace(/\\([nrt"\\])/g, (_match, char) => DOUBLE_QUOTE_ESCAPES[char] ?? char) : raw;
|
|
572
|
+
index = end;
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
values[key] = rest.replace(/\s+#.*$/, "").trim();
|
|
577
|
+
}
|
|
578
|
+
return values;
|
|
579
|
+
};
|
|
580
|
+
var InterpolationError = class extends Error {
|
|
581
|
+
};
|
|
582
|
+
var findClosingBrace = (value, start) => {
|
|
583
|
+
let depth = 0;
|
|
584
|
+
for (let index = start; index < value.length; index += 1) {
|
|
585
|
+
if (value[index] === "$" && (value[index + 1] === "$" || value[index + 1] === "{")) {
|
|
586
|
+
if (value[index + 1] === "{") depth += 1;
|
|
587
|
+
index += 1;
|
|
588
|
+
} else if (value[index] === "}") {
|
|
589
|
+
if (depth === 0) return index;
|
|
590
|
+
depth -= 1;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return -1;
|
|
594
|
+
};
|
|
595
|
+
var interpolate = (value, variables, missing, where) => {
|
|
596
|
+
let result = "";
|
|
597
|
+
let index = 0;
|
|
598
|
+
while (index < value.length) {
|
|
599
|
+
const dollar = value.indexOf("$", index);
|
|
600
|
+
if (dollar === -1) {
|
|
601
|
+
result += value.slice(index);
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
result += value.slice(index, dollar);
|
|
605
|
+
const next = value[dollar + 1];
|
|
606
|
+
if (next === "$") {
|
|
607
|
+
result += "$";
|
|
608
|
+
index = dollar + 2;
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
if (next === "{") {
|
|
612
|
+
const close = findClosingBrace(value, dollar + 2);
|
|
613
|
+
const expression = close === -1 ? null : /^([A-Za-z_][A-Za-z0-9_]*)(?:(:?[-?+])([\s\S]*))?$/.exec(value.slice(dollar + 2, close));
|
|
614
|
+
if (expression === null) {
|
|
615
|
+
throw new InterpolationError(`has an invalid variable reference in ${where}. Write '$$' for a literal '$'.`);
|
|
616
|
+
}
|
|
617
|
+
const [, name, operator, operand = ""] = expression;
|
|
618
|
+
const current = variables[name];
|
|
619
|
+
const isSet = current !== void 0 && !(operator?.startsWith(":") === true && current === "");
|
|
620
|
+
if (operator === void 0) {
|
|
621
|
+
if (current === void 0) missing.add(name);
|
|
622
|
+
result += current ?? "";
|
|
623
|
+
} else if (operator.endsWith("-")) {
|
|
624
|
+
result += isSet ? current : interpolate(operand, variables, missing, where);
|
|
625
|
+
} else if (operator.endsWith("+")) {
|
|
626
|
+
result += isSet ? interpolate(operand, variables, missing, where) : "";
|
|
627
|
+
} else if (isSet) {
|
|
628
|
+
result += current;
|
|
629
|
+
} else {
|
|
630
|
+
const reason = interpolate(operand, variables, missing, where);
|
|
631
|
+
throw new InterpolationError(
|
|
632
|
+
`needs variable '${name}' in ${where}, which is ${current === void 0 ? "not set" : "empty"}${reason === "" ? "" : `: ${reason}`}. Compose variables come only from the .env file next to the Compose file.`
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
index = close + 1;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
const bare = /^[A-Za-z_][A-Za-z0-9_]*/.exec(value.slice(dollar + 1))?.[0];
|
|
639
|
+
if (bare === void 0) {
|
|
640
|
+
result += "$";
|
|
641
|
+
index = dollar + 1;
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
if (variables[bare] === void 0) missing.add(bare);
|
|
645
|
+
result += variables[bare] ?? "";
|
|
646
|
+
index = dollar + 1 + bare.length;
|
|
647
|
+
}
|
|
648
|
+
return result;
|
|
649
|
+
};
|
|
650
|
+
var interpolateDeep = (value, variables, missing, where) => {
|
|
651
|
+
if (typeof value === "string") return interpolate(value, variables, missing, where);
|
|
652
|
+
if (Array.isArray(value)) {
|
|
653
|
+
return value.map((item, index) => interpolateDeep(item, variables, missing, `${where}[${index}]`));
|
|
654
|
+
}
|
|
655
|
+
if (isRecord(value)) {
|
|
656
|
+
return Object.fromEntries(
|
|
657
|
+
Object.entries(value).map(([key, item]) => [
|
|
658
|
+
key,
|
|
659
|
+
interpolateDeep(item, variables, missing, where === "" ? key : `${where}.${key}`)
|
|
660
|
+
])
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
return value;
|
|
664
|
+
};
|
|
665
|
+
var parseComposeMemory = (value) => {
|
|
666
|
+
if (typeof value === "number") {
|
|
667
|
+
return Number.isFinite(value) && value >= 0 ? Math.ceil(value / 1024 ** 2) : void 0;
|
|
668
|
+
}
|
|
669
|
+
if (typeof value !== "string") return void 0;
|
|
670
|
+
const match = /^(\d+(?:\.\d+)?) ?([kmgtp])?i?b?$/i.exec(value.trim());
|
|
671
|
+
if (!match) return void 0;
|
|
672
|
+
const exponent = " kmgtp".indexOf((match[2] ?? " ").toLowerCase());
|
|
673
|
+
return Math.ceil(Number(match[1]) * 1024 ** exponent / 1024 ** 2);
|
|
674
|
+
};
|
|
675
|
+
var parseComposePort = (entry) => {
|
|
676
|
+
let port = entry;
|
|
677
|
+
if (isRecord(entry)) {
|
|
678
|
+
if (typeof entry.protocol === "string" && entry.protocol.toLowerCase() !== "tcp") return void 0;
|
|
679
|
+
port = entry.target;
|
|
680
|
+
} else if (typeof entry === "string") {
|
|
681
|
+
const [withoutProtocol, protocol] = entry.split("/");
|
|
682
|
+
if (protocol !== void 0 && protocol.toLowerCase() !== "tcp") return void 0;
|
|
683
|
+
port = (withoutProtocol.split(":").at(-1) ?? "").split("-")[0];
|
|
684
|
+
}
|
|
685
|
+
const number = typeof port === "number" ? port : typeof port === "string" && /^\d+$/.test(port) ? Number(port) : NaN;
|
|
686
|
+
return isIntegerBetween(number, 1, 65535) ? number : void 0;
|
|
687
|
+
};
|
|
688
|
+
var parseComposeEnvironment = (serviceName, value, warnings) => {
|
|
689
|
+
if (value === void 0 || value === null) return void 0;
|
|
690
|
+
const environment = {};
|
|
691
|
+
if (Array.isArray(value)) {
|
|
692
|
+
for (const item of value) {
|
|
693
|
+
if (typeof item !== "string") continue;
|
|
694
|
+
const separator = item.indexOf("=");
|
|
695
|
+
if (separator === -1) {
|
|
696
|
+
warnings.push(
|
|
697
|
+
`Compose service '${serviceName}' takes '${item}' from the host environment, which deployments do not have. Set it in the console instead.`
|
|
698
|
+
);
|
|
699
|
+
continue;
|
|
700
|
+
}
|
|
701
|
+
environment[item.slice(0, separator)] = item.slice(separator + 1);
|
|
702
|
+
}
|
|
703
|
+
} else if (isRecord(value)) {
|
|
704
|
+
for (const [key, item] of Object.entries(value)) {
|
|
705
|
+
const scalar = scalarToString(item);
|
|
706
|
+
if (scalar === void 0) {
|
|
707
|
+
warnings.push(
|
|
708
|
+
`Compose service '${serviceName}' takes '${key}' from the host environment, which deployments do not have. Set it in the console instead.`
|
|
709
|
+
);
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
environment[key] = scalar;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return environment;
|
|
716
|
+
};
|
|
717
|
+
var isPublicMarked = (service) => gigadriveExtension(service).public === true;
|
|
718
|
+
var buildsFromSource = (service) => service.build !== void 0 && gigadriveExtension(service).sidecar !== true;
|
|
719
|
+
var loadComposeServices = import_effect5.Effect.fn("loadComposeServices")(function* (composePath, projectFolder) {
|
|
720
|
+
const relativePath = normalizeProjectPath(composePath);
|
|
721
|
+
if (relativePath === void 0) {
|
|
722
|
+
return yield* new ContainerConfigError({
|
|
723
|
+
message: `Compose file '${composePath}' is outside the project.`,
|
|
724
|
+
filePath: composePath
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
const projectRoot = yield* resolveProjectRoot(projectFolder);
|
|
728
|
+
const content = yield* readInsideProject(projectRoot, relativePath, `Compose file '${relativePath}'`, {
|
|
729
|
+
filePath: relativePath
|
|
730
|
+
});
|
|
731
|
+
if (import_effect5.Option.isNone(content)) {
|
|
732
|
+
return yield* new ContainerConfigError({
|
|
733
|
+
message: `Compose file '${relativePath}' could not be read.`,
|
|
734
|
+
filePath: relativePath
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
const document = yield* import_effect5.Effect.try({
|
|
738
|
+
try: () => (0, import_yaml.parse)(content.value),
|
|
739
|
+
catch: (error) => {
|
|
740
|
+
const position = error instanceof import_yaml.YAMLError ? error.linePos?.[0] : void 0;
|
|
741
|
+
return new ContainerConfigError({
|
|
742
|
+
message: `Compose file '${relativePath}' is not valid YAML${position ? ` (line ${position.line}, column ${position.col})` : ""}.`,
|
|
743
|
+
filePath: relativePath
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
if (!isRecord(document) || !isRecord(document.services) || Object.keys(document.services).length === 0) {
|
|
748
|
+
return yield* new ContainerConfigError({
|
|
749
|
+
message: `Compose file '${relativePath}' declares no services.`,
|
|
750
|
+
filePath: relativePath
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
const services = Object.entries(document.services).filter(
|
|
754
|
+
(entry) => isRecord(entry[1]) && !(isStringArray(entry[1].profiles) && entry[1].profiles.length > 0) && gigadriveExtension(entry[1]).skip !== true
|
|
755
|
+
);
|
|
756
|
+
return { relativePath, projectRoot, services };
|
|
757
|
+
});
|
|
758
|
+
var composeDeclaresApp = import_effect5.Effect.fn("composeDeclaresApp")(function* (composePath, projectFolder) {
|
|
759
|
+
const { services } = yield* loadComposeServices(composePath, projectFolder);
|
|
760
|
+
return services.some(([, service]) => isPublicMarked(service) || buildsFromSource(service));
|
|
761
|
+
});
|
|
762
|
+
var readComposeContainers = import_effect5.Effect.fn("readComposeContainers")(function* (composePath, projectFolder) {
|
|
763
|
+
const fs = yield* import_platform2.FileSystem.FileSystem;
|
|
764
|
+
const pathSvc = yield* import_platform2.Path.Path;
|
|
765
|
+
const { relativePath, projectRoot, services } = yield* loadComposeServices(composePath, projectFolder);
|
|
766
|
+
const composeDirectory = import_node_path.posix.dirname(relativePath);
|
|
767
|
+
const warnings = [];
|
|
768
|
+
for (const [name] of services) {
|
|
769
|
+
if (!CONTAINER_NAME_PATTERN.test(name) || name === "localhost") {
|
|
770
|
+
return yield* new ContainerConfigError({
|
|
771
|
+
message: `Compose service '${name}' cannot be imported under that name. The service name becomes the hostname the function reaches it by, so it must be ${CONTAINER_NAME_RULES}. Rename the service to '${toContainerName(name)}' in '${relativePath}'.`,
|
|
772
|
+
containerName: name,
|
|
773
|
+
filePath: relativePath
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
const marked = services.filter(([, service]) => isPublicMarked(service)).map(([name]) => name);
|
|
778
|
+
const built = services.filter(([, service]) => buildsFromSource(service)).map(([name]) => name);
|
|
779
|
+
if (marked.length > 1) {
|
|
780
|
+
return yield* new ContainerConfigError({
|
|
781
|
+
message: `Compose file '${relativePath}' marks ${marked.map((name) => `'${name}'`).join(", ")} as public. One service serves HTTP: keep 'x-gigadrive: { public: true }' on that one only.`,
|
|
782
|
+
filePath: relativePath
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
const publicService = marked[0] ?? (built.length === 1 ? built[0] : void 0);
|
|
786
|
+
if (publicService === void 0) {
|
|
787
|
+
return yield* new ContainerConfigError({
|
|
788
|
+
message: built.length === 0 ? `Compose file '${relativePath}' has no service that builds from source, so it is unclear which service serves HTTP. Mark it with 'x-gigadrive: { public: true }'.` : `Compose file '${relativePath}' builds ${built.map((name) => `'${name}'`).join(", ")} from source, so it is unclear which service serves HTTP. Mark it with 'x-gigadrive: { public: true }'.`,
|
|
789
|
+
filePath: relativePath
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
if (COMPOSE_FILE_NAMES.includes(import_node_path.posix.basename(relativePath))) {
|
|
793
|
+
for (const overrideName of COMPOSE_OVERRIDE_FILE_NAMES) {
|
|
794
|
+
const overridePath = import_node_path.posix.join(composeDirectory, overrideName);
|
|
795
|
+
const overrideExists = yield* fs.exists(pathSvc.join(projectRoot, overridePath)).pipe(import_effect5.Effect.orElseSucceed(() => false));
|
|
796
|
+
if (overrideExists) {
|
|
797
|
+
warnings.push(
|
|
798
|
+
`Compose file '${relativePath}' has the override file '${overridePath}' next to it, which is not merged. Move its settings into '${relativePath}' or gigadrive.yaml.`
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
const dotEnv = yield* readInsideProject(
|
|
804
|
+
projectRoot,
|
|
805
|
+
import_node_path.posix.join(composeDirectory, ".env"),
|
|
806
|
+
`The .env file next to '${relativePath}'`,
|
|
807
|
+
{ filePath: relativePath }
|
|
808
|
+
);
|
|
809
|
+
const variables = import_effect5.Option.isSome(dotEnv) ? parseDotEnv(dotEnv.value) : {};
|
|
810
|
+
const missing = /* @__PURE__ */ new Set();
|
|
811
|
+
const containers = {};
|
|
812
|
+
for (const [name, rawService] of services) {
|
|
813
|
+
const isPublic = name === publicService;
|
|
814
|
+
const service = yield* import_effect5.Effect.try({
|
|
815
|
+
try: () => interpolateDeep(rawService, variables, missing, ""),
|
|
816
|
+
catch: (error) => new ContainerConfigError({
|
|
817
|
+
message: `Compose service '${name}' ${error instanceof InterpolationError ? error.message : "could not be interpolated."}`,
|
|
818
|
+
containerName: name,
|
|
819
|
+
filePath: relativePath
|
|
820
|
+
})
|
|
821
|
+
});
|
|
822
|
+
const container = {};
|
|
823
|
+
if (service.extends !== void 0) {
|
|
824
|
+
warnings.push(
|
|
825
|
+
`Compose service '${name}' uses 'extends', which is not supported. The service is deployed as written, without the settings it would inherit.`
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
if (typeof service.image === "string" && service.build === void 0) {
|
|
829
|
+
container.image = service.image;
|
|
830
|
+
} else if (typeof service.build === "string" || isRecord(service.build)) {
|
|
831
|
+
const build = typeof service.build === "string" ? { context: service.build } : service.build;
|
|
832
|
+
if (build.dockerfile_inline !== void 0) {
|
|
833
|
+
return yield* new ContainerConfigError({
|
|
834
|
+
message: `Compose service '${name}' uses build.dockerfile_inline, which is not supported. Commit the Dockerfile and point build.dockerfile at it.`,
|
|
835
|
+
containerName: name,
|
|
836
|
+
filePath: relativePath
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
const rawContext = typeof build.context === "string" ? build.context : ".";
|
|
840
|
+
const context = import_node_path.posix.isAbsolute(rawContext) ? rawContext : import_node_path.posix.join(composeDirectory, rawContext);
|
|
841
|
+
const args = Array.isArray(build.args) ? Object.fromEntries(
|
|
842
|
+
build.args.filter((item) => typeof item === "string" && item.includes("=")).map((item) => [item.slice(0, item.indexOf("=")), item.slice(item.indexOf("=") + 1)])
|
|
843
|
+
) : isRecord(build.args) ? Object.fromEntries(Object.entries(build.args).map(([key, item]) => [key, scalarToString(item) ?? ""])) : void 0;
|
|
844
|
+
container.build = {
|
|
845
|
+
context,
|
|
846
|
+
...typeof build.dockerfile === "string" && { dockerfile: build.dockerfile },
|
|
847
|
+
...typeof build.target === "string" && { target: build.target },
|
|
848
|
+
...args !== void 0 && Object.keys(args).length > 0 && { args }
|
|
849
|
+
};
|
|
850
|
+
} else {
|
|
851
|
+
return yield* new ContainerConfigError({
|
|
852
|
+
message: `Compose service '${name}' has neither an image nor a build.`,
|
|
853
|
+
containerName: name,
|
|
854
|
+
filePath: relativePath
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
if (!isPublic) container.sidecar = true;
|
|
858
|
+
const ports = [
|
|
859
|
+
...isPublic && Array.isArray(service.ports) ? service.ports : [],
|
|
860
|
+
...Array.isArray(service.expose) ? service.expose : [],
|
|
861
|
+
...!isPublic && Array.isArray(service.ports) ? service.ports : []
|
|
862
|
+
];
|
|
863
|
+
const port = ports.map(parseComposePort).find((value) => value !== void 0);
|
|
864
|
+
if (port !== void 0) container.port = port;
|
|
865
|
+
for (const key of ["entrypoint", "command"]) {
|
|
866
|
+
const value = service[key];
|
|
867
|
+
if (typeof value === "string" || isStringArray(value)) container[key] = value;
|
|
868
|
+
}
|
|
869
|
+
const environment = {};
|
|
870
|
+
const envFiles = (typeof service.env_file === "string" ? [service.env_file] : Array.isArray(service.env_file) ? service.env_file : []).flatMap(
|
|
871
|
+
(entry) => typeof entry === "string" ? [{ path: entry }] : isRecord(entry) && typeof entry.path === "string" ? [{ path: entry.path, ...typeof entry.required === "boolean" && { required: entry.required } }] : []
|
|
872
|
+
);
|
|
873
|
+
for (const envFile of envFiles) {
|
|
874
|
+
const envFilePath = import_node_path.posix.isAbsolute(envFile.path) ? void 0 : normalizeProjectPath(import_node_path.posix.join(composeDirectory, envFile.path));
|
|
875
|
+
const envContent = envFilePath === void 0 ? import_effect5.Option.none() : yield* readInsideProject(
|
|
876
|
+
projectRoot,
|
|
877
|
+
envFilePath,
|
|
878
|
+
`The env_file '${envFile.path}' of Compose service '${name}'`,
|
|
879
|
+
{ containerName: name, filePath: relativePath }
|
|
880
|
+
);
|
|
881
|
+
if (import_effect5.Option.isSome(envContent)) {
|
|
882
|
+
Object.assign(environment, parseDotEnv(envContent.value));
|
|
883
|
+
} else if (envFile.required === true) {
|
|
884
|
+
return yield* new ContainerConfigError({
|
|
885
|
+
message: `Compose service '${name}' requires env_file '${envFile.path}', which is not in the deployed source. Commit it, mark it 'required: false', or set those variables in the console.`,
|
|
886
|
+
containerName: name,
|
|
887
|
+
filePath: relativePath
|
|
888
|
+
});
|
|
889
|
+
} else if (envFile.required === void 0) {
|
|
890
|
+
warnings.push(
|
|
891
|
+
`Compose service '${name}' reads env_file '${envFile.path}', which is not in the deployed source. Set those variables in the console instead.`
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
Object.assign(environment, parseComposeEnvironment(name, service.environment, warnings));
|
|
896
|
+
if (Object.keys(environment).length > 0) container.env = environment;
|
|
897
|
+
if (typeof service.working_dir === "string") container.working_dir = service.working_dir;
|
|
898
|
+
if (typeof service.user === "string" || typeof service.user === "number") container.user = String(service.user);
|
|
899
|
+
const deploy = isRecord(service.deploy) ? service.deploy : {};
|
|
900
|
+
const resources = isRecord(deploy.resources) ? deploy.resources : {};
|
|
901
|
+
const limits = isRecord(resources.limits) ? resources.limits : {};
|
|
902
|
+
const memoryLimit = limits.memory ?? service.mem_limit;
|
|
903
|
+
if (memoryLimit !== void 0 && memoryLimit !== null) {
|
|
904
|
+
const memory = parseComposeMemory(memoryLimit);
|
|
905
|
+
if (memory === void 0) {
|
|
906
|
+
warnings.push(
|
|
907
|
+
`Compose service '${name}' sets the memory limit ${JSON.stringify(memoryLimit)}, which is not a size Docker accepts. The default is used instead.`
|
|
908
|
+
);
|
|
909
|
+
} else if (memory >= MIN_CONTAINER_MEMORY_MB && memory <= MAX_CONTAINER_MEMORY_MB) {
|
|
910
|
+
container.memory = memory;
|
|
911
|
+
} else if (memory > 0) {
|
|
912
|
+
warnings.push(
|
|
913
|
+
`Compose service '${name}' asks for ${memory} MB of memory, outside the supported ${MIN_CONTAINER_MEMORY_MB} to ${MAX_CONTAINER_MEMORY_MB} MB. The default is used instead.`
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
if (service.volumes !== void 0) {
|
|
918
|
+
warnings.push(
|
|
919
|
+
`Compose service '${name}' declares volumes. Containers on Gigadrive Network have no persistent volumes, so anything written there is lost when the instance stops.`
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
containers[name] = container;
|
|
923
|
+
}
|
|
924
|
+
if (missing.size > 0) {
|
|
925
|
+
warnings.push(
|
|
926
|
+
`Compose file '${relativePath}' uses ${[...missing].sort().join(", ")}, which ${missing.size === 1 ? "is" : "are"} not set. ${missing.size === 1 ? "It was" : "They were"} replaced with an empty string.`
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
return { containers, publicService, warnings };
|
|
930
|
+
});
|
|
931
|
+
|
|
184
932
|
// src/define-config.ts
|
|
185
933
|
var defineConfig = (config) => config;
|
|
186
934
|
|
|
935
|
+
// src/detection/detect-container-project.ts
|
|
936
|
+
var import_platform3 = require("@effect/platform");
|
|
937
|
+
var import_effect6 = require("effect");
|
|
938
|
+
|
|
939
|
+
// src/regions.ts
|
|
940
|
+
var REGION_DEFINITIONS = [
|
|
941
|
+
"us-east-1",
|
|
942
|
+
"us-east-2",
|
|
943
|
+
"us-west-1",
|
|
944
|
+
"us-west-2",
|
|
945
|
+
"ap-south-1",
|
|
946
|
+
"ap-northeast-3",
|
|
947
|
+
"ap-northeast-2",
|
|
948
|
+
"ap-southeast-1",
|
|
949
|
+
"ap-southeast-2",
|
|
950
|
+
"ap-northeast-1",
|
|
951
|
+
"ca-central-1",
|
|
952
|
+
"eu-central-1",
|
|
953
|
+
"eu-west-1",
|
|
954
|
+
"eu-west-2",
|
|
955
|
+
"eu-west-3",
|
|
956
|
+
"eu-north-1",
|
|
957
|
+
"sa-east-1"
|
|
958
|
+
];
|
|
959
|
+
var AVAILABLE_REGIONS = [...REGION_DEFINITIONS];
|
|
960
|
+
|
|
961
|
+
// src/detection/detect-container-project.ts
|
|
962
|
+
var detectContainerProject = import_effect6.Effect.fn("detectContainerProject")(function* (projectFolder) {
|
|
963
|
+
const fs = yield* import_platform3.FileSystem.FileSystem;
|
|
964
|
+
const pathSvc = yield* import_platform3.Path.Path;
|
|
965
|
+
const exists = (file) => fs.exists(pathSvc.join(projectFolder, file)).pipe(import_effect6.Effect.catchAll(() => import_effect6.Effect.succeed(false)));
|
|
966
|
+
let detection;
|
|
967
|
+
const warnings = [];
|
|
968
|
+
const composeFile = yield* import_effect6.Effect.findFirst(COMPOSE_FILE_NAMES, exists);
|
|
969
|
+
if (composeFile._tag === "Some" && (yield* composeDeclaresApp(composeFile.value, projectFolder))) {
|
|
970
|
+
const imported = yield* readComposeContainers(composeFile.value, projectFolder);
|
|
971
|
+
warnings.push(...imported.warnings);
|
|
972
|
+
detection = { kind: "compose", file: composeFile.value, containers: imported.containers };
|
|
973
|
+
} else if (yield* exists("Dockerfile")) {
|
|
974
|
+
detection = { kind: "dockerfile", file: "Dockerfile", containers: { app: { build: "." } } };
|
|
975
|
+
} else {
|
|
976
|
+
return void 0;
|
|
977
|
+
}
|
|
978
|
+
const {
|
|
979
|
+
entrypoints,
|
|
980
|
+
sidecars,
|
|
981
|
+
warnings: containerWarnings
|
|
982
|
+
} = yield* normalizeContainers(detection.containers, projectFolder);
|
|
983
|
+
const [publicContainer] = entrypoints;
|
|
984
|
+
const config = {
|
|
985
|
+
regions: [...AVAILABLE_REGIONS],
|
|
986
|
+
environmentVariables: {},
|
|
987
|
+
commands: [],
|
|
988
|
+
entrypoints,
|
|
989
|
+
...sidecars.length > 0 && { sidecars },
|
|
990
|
+
routes: publicContainer ? [
|
|
991
|
+
{
|
|
992
|
+
path: "/*",
|
|
993
|
+
destination: publicContainer.path,
|
|
994
|
+
handler: "SERVERLESS_FUNCTION_STREAMING",
|
|
995
|
+
methods: ["ANY"],
|
|
996
|
+
headers: {}
|
|
997
|
+
}
|
|
998
|
+
] : [],
|
|
999
|
+
warnings: [
|
|
1000
|
+
`Auto-detected ${detection.kind === "compose" ? "Docker Compose" : "Dockerfile"} project (${detection.file}). Create a gigadrive.yaml to customize.`,
|
|
1001
|
+
...warnings,
|
|
1002
|
+
...containerWarnings
|
|
1003
|
+
],
|
|
1004
|
+
errors: []
|
|
1005
|
+
};
|
|
1006
|
+
return { kind: detection.kind, file: detection.file, config };
|
|
1007
|
+
});
|
|
1008
|
+
|
|
187
1009
|
// src/detection/detect-framework.ts
|
|
188
|
-
var
|
|
189
|
-
var
|
|
1010
|
+
var import_platform12 = require("@effect/platform");
|
|
1011
|
+
var import_effect18 = require("effect");
|
|
190
1012
|
|
|
191
1013
|
// src/detection/detect-package-manager.ts
|
|
192
|
-
var
|
|
193
|
-
var
|
|
1014
|
+
var import_platform4 = require("@effect/platform");
|
|
1015
|
+
var import_effect7 = require("effect");
|
|
194
1016
|
var LOCKFILE_MAP = [
|
|
195
1017
|
{ files: ["bun.lockb", "bun.lock"], pm: "bun" },
|
|
196
1018
|
{ files: ["pnpm-lock.yaml"], pm: "pnpm" },
|
|
@@ -198,19 +1020,19 @@ var LOCKFILE_MAP = [
|
|
|
198
1020
|
{ files: ["package-lock.json"], pm: "npm" },
|
|
199
1021
|
{ files: ["composer.lock"], pm: "composer" }
|
|
200
1022
|
];
|
|
201
|
-
var detectPackageManager =
|
|
202
|
-
const fs = yield*
|
|
203
|
-
const pathService = yield*
|
|
1023
|
+
var detectPackageManager = import_effect7.Effect.fn("detectPackageManager")(function* (projectFolder) {
|
|
1024
|
+
const fs = yield* import_platform4.FileSystem.FileSystem;
|
|
1025
|
+
const pathService = yield* import_platform4.Path.Path;
|
|
204
1026
|
for (const { files, pm } of LOCKFILE_MAP) {
|
|
205
1027
|
for (const file of files) {
|
|
206
|
-
const exists = yield* fs.exists(pathService.join(projectFolder, file)).pipe(
|
|
1028
|
+
const exists = yield* fs.exists(pathService.join(projectFolder, file)).pipe(import_effect7.Effect.catchAll(() => import_effect7.Effect.succeed(false)));
|
|
207
1029
|
if (exists) {
|
|
208
|
-
yield*
|
|
1030
|
+
yield* import_effect7.Effect.logDebug(`Detected package manager: ${pm} (via ${file})`);
|
|
209
1031
|
return pm;
|
|
210
1032
|
}
|
|
211
1033
|
}
|
|
212
1034
|
}
|
|
213
|
-
yield*
|
|
1035
|
+
yield* import_effect7.Effect.logDebug("No lockfile found, defaulting to npm");
|
|
214
1036
|
return "npm";
|
|
215
1037
|
});
|
|
216
1038
|
|
|
@@ -235,9 +1057,71 @@ var astro = {
|
|
|
235
1057
|
})
|
|
236
1058
|
};
|
|
237
1059
|
|
|
1060
|
+
// src/detection/frameworks/php-front-controller.ts
|
|
1061
|
+
var phpFrontControllerDefaults = ({
|
|
1062
|
+
documentRoot,
|
|
1063
|
+
writablePaths = [],
|
|
1064
|
+
excludeFiles = [],
|
|
1065
|
+
memory = 256,
|
|
1066
|
+
environmentVariables = {}
|
|
1067
|
+
}) => {
|
|
1068
|
+
const entrypoint = documentRoot === "." ? "index.php" : `${documentRoot}/index.php`;
|
|
1069
|
+
return {
|
|
1070
|
+
runtime: "php-84",
|
|
1071
|
+
memory,
|
|
1072
|
+
maxDuration: 30,
|
|
1073
|
+
streaming: false,
|
|
1074
|
+
commands: [],
|
|
1075
|
+
entrypoint,
|
|
1076
|
+
assetsDir: documentRoot,
|
|
1077
|
+
excludeFiles: [".ddev", "node_modules/", ...excludeFiles],
|
|
1078
|
+
routes: [{ source: "/*", destination: entrypoint }],
|
|
1079
|
+
environmentVariables,
|
|
1080
|
+
...writablePaths.length > 0 ? { package: { writablePaths } } : {}
|
|
1081
|
+
};
|
|
1082
|
+
};
|
|
1083
|
+
|
|
1084
|
+
// src/detection/frameworks/cakephp.ts
|
|
1085
|
+
var cakephp = {
|
|
1086
|
+
slug: "cakephp",
|
|
1087
|
+
name: "CakePHP",
|
|
1088
|
+
language: "php",
|
|
1089
|
+
detectors: [{ matchPackage: "cakephp/cakephp" }, { path: "webroot/index.php" }],
|
|
1090
|
+
priority: 80,
|
|
1091
|
+
getDefaultConfig: () => phpFrontControllerDefaults({
|
|
1092
|
+
documentRoot: "webroot",
|
|
1093
|
+
// config/paths.php puts TMP and LOGS inside the project.
|
|
1094
|
+
writablePaths: [
|
|
1095
|
+
"tmp/cache/models",
|
|
1096
|
+
"tmp/cache/persistent",
|
|
1097
|
+
"tmp/cache/views",
|
|
1098
|
+
"tmp/sessions",
|
|
1099
|
+
"tmp/tests",
|
|
1100
|
+
"logs"
|
|
1101
|
+
],
|
|
1102
|
+
excludeFiles: ["tests/", "tmp/", "logs/"]
|
|
1103
|
+
})
|
|
1104
|
+
};
|
|
1105
|
+
|
|
1106
|
+
// src/detection/frameworks/codeigniter.ts
|
|
1107
|
+
var codeigniter = {
|
|
1108
|
+
slug: "codeigniter",
|
|
1109
|
+
name: "CodeIgniter",
|
|
1110
|
+
language: "php",
|
|
1111
|
+
detectors: [{ matchPackage: "codeigniter4/framework" }, { path: "spark" }],
|
|
1112
|
+
priority: 80,
|
|
1113
|
+
getDefaultConfig: () => phpFrontControllerDefaults({
|
|
1114
|
+
documentRoot: "public",
|
|
1115
|
+
// WRITEPATH: the cache, file session and log handlers write below it.
|
|
1116
|
+
writablePaths: ["writable/cache", "writable/debugbar", "writable/logs", "writable/session", "writable/uploads"],
|
|
1117
|
+
excludeFiles: ["tests/", "writable/"],
|
|
1118
|
+
environmentVariables: { CI_ENVIRONMENT: "production" }
|
|
1119
|
+
})
|
|
1120
|
+
};
|
|
1121
|
+
|
|
238
1122
|
// src/detection/frameworks/resolve-node-entrypoint.ts
|
|
239
|
-
var
|
|
240
|
-
var
|
|
1123
|
+
var import_platform5 = require("@effect/platform");
|
|
1124
|
+
var import_effect8 = require("effect");
|
|
241
1125
|
var SCRIPT_RUNNERS = /* @__PURE__ */ new Set(["node", "bun", "tsx", "ts-node"]);
|
|
242
1126
|
var COMMON_ENTRYPOINT_CANDIDATES = [
|
|
243
1127
|
"index.js",
|
|
@@ -253,11 +1137,11 @@ var COMMON_ENTRYPOINT_CANDIDATES = [
|
|
|
253
1137
|
"server.ts",
|
|
254
1138
|
"src/server.ts"
|
|
255
1139
|
];
|
|
256
|
-
var
|
|
1140
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
257
1141
|
var parsePackageJson = (content) => {
|
|
258
1142
|
try {
|
|
259
1143
|
const parsed = JSON.parse(content);
|
|
260
|
-
if (!
|
|
1144
|
+
if (!isRecord2(parsed)) return void 0;
|
|
261
1145
|
return parsed;
|
|
262
1146
|
} catch {
|
|
263
1147
|
return void 0;
|
|
@@ -285,14 +1169,14 @@ var applyEntrypoint = (defaults, entrypoint) => ({
|
|
|
285
1169
|
(route) => route.destination === defaults.entrypoint ? { ...route, destination: entrypoint } : route
|
|
286
1170
|
)
|
|
287
1171
|
});
|
|
288
|
-
var resolveNodeServerEntrypoint = (defaults, projectFolder) =>
|
|
289
|
-
const fs = yield*
|
|
290
|
-
const pathService = yield*
|
|
1172
|
+
var resolveNodeServerEntrypoint = (defaults, projectFolder) => import_effect8.Effect.gen(function* () {
|
|
1173
|
+
const fs = yield* import_platform5.FileSystem.FileSystem;
|
|
1174
|
+
const pathService = yield* import_platform5.Path.Path;
|
|
291
1175
|
const isFile = (relativePath) => fs.stat(pathService.join(projectFolder, relativePath)).pipe(
|
|
292
|
-
|
|
293
|
-
|
|
1176
|
+
import_effect8.Effect.map((info) => info.type === "File"),
|
|
1177
|
+
import_effect8.Effect.catchAll(() => import_effect8.Effect.succeed(false))
|
|
294
1178
|
);
|
|
295
|
-
const content = yield* fs.readFileString(pathService.join(projectFolder, "package.json")).pipe(
|
|
1179
|
+
const content = yield* fs.readFileString(pathService.join(projectFolder, "package.json")).pipe(import_effect8.Effect.catchAll(() => import_effect8.Effect.succeed(void 0)));
|
|
296
1180
|
const manifest = content ? parsePackageJson(content) : void 0;
|
|
297
1181
|
const startScript = typeof manifest?.scripts?.start === "string" ? manifest.scripts.start : void 0;
|
|
298
1182
|
const candidates = [
|
|
@@ -392,6 +1276,21 @@ var hono = {
|
|
|
392
1276
|
refineDefaultConfig: resolveNodeServerEntrypoint
|
|
393
1277
|
};
|
|
394
1278
|
|
|
1279
|
+
// src/detection/frameworks/laminas.ts
|
|
1280
|
+
var laminas = {
|
|
1281
|
+
slug: "laminas",
|
|
1282
|
+
name: "Laminas MVC",
|
|
1283
|
+
language: "php",
|
|
1284
|
+
detectors: [{ matchPackage: "laminas/laminas-mvc" }, { path: "public/index.php" }],
|
|
1285
|
+
priority: 80,
|
|
1286
|
+
getDefaultConfig: () => phpFrontControllerDefaults({
|
|
1287
|
+
documentRoot: "public",
|
|
1288
|
+
// The merged-config and module-map caches of the skeleton.
|
|
1289
|
+
writablePaths: ["data/cache"],
|
|
1290
|
+
excludeFiles: ["test/", "data/cache/"]
|
|
1291
|
+
})
|
|
1292
|
+
};
|
|
1293
|
+
|
|
395
1294
|
// src/detection/frameworks/laravel.ts
|
|
396
1295
|
var laravel = {
|
|
397
1296
|
slug: "laravel",
|
|
@@ -410,6 +1309,18 @@ var laravel = {
|
|
|
410
1309
|
populateAssetCache: true,
|
|
411
1310
|
excludeFiles: ["tests/", "storage/", ".ddev", "node_modules/"],
|
|
412
1311
|
routes: [{ source: "/*", destination: "public/index.php" }],
|
|
1312
|
+
package: {
|
|
1313
|
+
// storage/ is excluded, so the directories Laravel writes compiled
|
|
1314
|
+
// views, file caches, sessions and logs to are created empty.
|
|
1315
|
+
writablePaths: [
|
|
1316
|
+
"bootstrap/cache",
|
|
1317
|
+
"storage/app/public",
|
|
1318
|
+
"storage/framework/cache/data",
|
|
1319
|
+
"storage/framework/sessions",
|
|
1320
|
+
"storage/framework/views",
|
|
1321
|
+
"storage/logs"
|
|
1322
|
+
]
|
|
1323
|
+
},
|
|
413
1324
|
environmentVariables: {
|
|
414
1325
|
APP_NAME: "Laravel",
|
|
415
1326
|
APP_ENV: "production",
|
|
@@ -423,14 +1334,29 @@ var laravel = {
|
|
|
423
1334
|
})
|
|
424
1335
|
};
|
|
425
1336
|
|
|
1337
|
+
// src/detection/frameworks/mezzio.ts
|
|
1338
|
+
var mezzio = {
|
|
1339
|
+
slug: "mezzio",
|
|
1340
|
+
name: "Mezzio",
|
|
1341
|
+
language: "php",
|
|
1342
|
+
detectors: [{ matchPackage: "mezzio/mezzio" }, { path: "public/index.php" }],
|
|
1343
|
+
priority: 80,
|
|
1344
|
+
getDefaultConfig: () => phpFrontControllerDefaults({
|
|
1345
|
+
documentRoot: "public",
|
|
1346
|
+
// config/config.php writes the merged config cache here.
|
|
1347
|
+
writablePaths: ["data/cache"],
|
|
1348
|
+
excludeFiles: ["test/", "data/cache/"]
|
|
1349
|
+
})
|
|
1350
|
+
};
|
|
1351
|
+
|
|
426
1352
|
// src/detection/frameworks/nestjs.ts
|
|
427
|
-
var
|
|
428
|
-
var
|
|
429
|
-
var
|
|
1353
|
+
var import_platform6 = require("@effect/platform");
|
|
1354
|
+
var import_effect9 = require("effect");
|
|
1355
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null;
|
|
430
1356
|
var parseNestCliJson = (content) => {
|
|
431
1357
|
try {
|
|
432
1358
|
const parsed = JSON.parse(content);
|
|
433
|
-
if (!
|
|
1359
|
+
if (!isRecord3(parsed)) return void 0;
|
|
434
1360
|
return parsed;
|
|
435
1361
|
} catch {
|
|
436
1362
|
return void 0;
|
|
@@ -476,9 +1402,9 @@ var nestjs = {
|
|
|
476
1402
|
detectors: [{ matchPackage: "@nestjs/core" }],
|
|
477
1403
|
priority: 90,
|
|
478
1404
|
getDefaultConfig: () => createNestConfig("dist"),
|
|
479
|
-
refineDefaultConfig: (defaults, projectFolder) =>
|
|
480
|
-
const fs = yield*
|
|
481
|
-
const content = yield* fs.readFileString(`${projectFolder}/nest-cli.json`).pipe(
|
|
1405
|
+
refineDefaultConfig: (defaults, projectFolder) => import_effect9.Effect.gen(function* () {
|
|
1406
|
+
const fs = yield* import_platform6.FileSystem.FileSystem;
|
|
1407
|
+
const content = yield* fs.readFileString(`${projectFolder}/nest-cli.json`).pipe(import_effect9.Effect.catchAll(() => import_effect9.Effect.succeed(void 0)));
|
|
482
1408
|
if (!content) return defaults;
|
|
483
1409
|
const nestConfig = parseNestCliJson(content);
|
|
484
1410
|
const outputPath = nestConfig ? getProjectOutputPath(nestConfig) : void 0;
|
|
@@ -487,28 +1413,28 @@ var nestjs = {
|
|
|
487
1413
|
};
|
|
488
1414
|
|
|
489
1415
|
// src/detection/frameworks/nextjs.ts
|
|
490
|
-
var
|
|
491
|
-
var
|
|
1416
|
+
var import_platform8 = require("@effect/platform");
|
|
1417
|
+
var import_effect12 = require("effect");
|
|
492
1418
|
|
|
493
1419
|
// src/build-output-v3/get-default-path-map.ts
|
|
494
|
-
var
|
|
495
|
-
var
|
|
496
|
-
var getDefaultPathMap =
|
|
497
|
-
const fs = yield*
|
|
498
|
-
const pathService = yield*
|
|
1420
|
+
var import_platform7 = require("@effect/platform");
|
|
1421
|
+
var import_effect10 = require("effect");
|
|
1422
|
+
var getDefaultPathMap = import_effect10.Effect.fn("getDefaultPathMap")(function* (directory) {
|
|
1423
|
+
const fs = yield* import_platform7.FileSystem.FileSystem;
|
|
1424
|
+
const pathService = yield* import_platform7.Path.Path;
|
|
499
1425
|
const result = {};
|
|
500
|
-
const exists = yield* fs.exists(directory).pipe(
|
|
1426
|
+
const exists = yield* fs.exists(directory).pipe(import_effect10.Effect.catchAll(() => import_effect10.Effect.succeed(false)));
|
|
501
1427
|
if (!exists) {
|
|
502
1428
|
return result;
|
|
503
1429
|
}
|
|
504
1430
|
const MAX_DEPTH = 100;
|
|
505
|
-
const processDirectory = (currentPath, basePath = "", depth = 0) =>
|
|
1431
|
+
const processDirectory = (currentPath, basePath = "", depth = 0) => import_effect10.Effect.gen(function* () {
|
|
506
1432
|
if (depth > MAX_DEPTH) return;
|
|
507
|
-
const entries = yield* fs.readDirectory(currentPath).pipe(
|
|
1433
|
+
const entries = yield* fs.readDirectory(currentPath).pipe(import_effect10.Effect.catchAll(() => import_effect10.Effect.succeed([])));
|
|
508
1434
|
for (const name of entries) {
|
|
509
1435
|
const fullPath = pathService.join(currentPath, name);
|
|
510
1436
|
const relativePath = basePath ? pathService.join(basePath, name) : name;
|
|
511
|
-
const stat = yield* fs.stat(fullPath).pipe(
|
|
1437
|
+
const stat = yield* fs.stat(fullPath).pipe(import_effect10.Effect.catchAll(() => import_effect10.Effect.succeed(null)));
|
|
512
1438
|
if (!stat) continue;
|
|
513
1439
|
if (stat.type === "Directory") {
|
|
514
1440
|
yield* processDirectory(fullPath, relativePath, depth + 1);
|
|
@@ -525,291 +1451,269 @@ var getDefaultPathMap = import_effect7.Effect.fn("getDefaultPathMap")(function*
|
|
|
525
1451
|
var MAXIMUM_ENTRY_PAGE_PATHS = 50;
|
|
526
1452
|
|
|
527
1453
|
// src/nextjs-manifest.ts
|
|
528
|
-
var
|
|
529
|
-
var StringArraySchema =
|
|
530
|
-
var StringRecordSchema =
|
|
531
|
-
var JsonValueSchema =
|
|
532
|
-
() =>
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
1454
|
+
var import_effect11 = require("effect");
|
|
1455
|
+
var StringArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(import_effect11.Schema.String));
|
|
1456
|
+
var StringRecordSchema = import_effect11.Schema.mutable(import_effect11.Schema.Record({ key: import_effect11.Schema.String, value: import_effect11.Schema.String }));
|
|
1457
|
+
var JsonValueSchema = import_effect11.Schema.suspend(
|
|
1458
|
+
() => import_effect11.Schema.Union(
|
|
1459
|
+
import_effect11.Schema.Null,
|
|
1460
|
+
import_effect11.Schema.Boolean,
|
|
1461
|
+
import_effect11.Schema.Number,
|
|
1462
|
+
import_effect11.Schema.String,
|
|
1463
|
+
import_effect11.Schema.mutable(import_effect11.Schema.Array(JsonValueSchema)),
|
|
1464
|
+
import_effect11.Schema.mutable(import_effect11.Schema.Record({ key: import_effect11.Schema.String, value: JsonValueSchema }))
|
|
539
1465
|
)
|
|
540
1466
|
);
|
|
541
|
-
var ImageLocalPatternSchema =
|
|
542
|
-
|
|
543
|
-
pathname:
|
|
544
|
-
search:
|
|
1467
|
+
var ImageLocalPatternSchema = import_effect11.Schema.mutable(
|
|
1468
|
+
import_effect11.Schema.Struct({
|
|
1469
|
+
pathname: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1470
|
+
search: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
545
1471
|
})
|
|
546
1472
|
);
|
|
547
|
-
var ImageRemotePatternSchema =
|
|
548
|
-
|
|
549
|
-
protocol:
|
|
550
|
-
hostname:
|
|
551
|
-
port:
|
|
552
|
-
pathname:
|
|
553
|
-
search:
|
|
1473
|
+
var ImageRemotePatternSchema = import_effect11.Schema.mutable(
|
|
1474
|
+
import_effect11.Schema.Struct({
|
|
1475
|
+
protocol: import_effect11.Schema.optional(import_effect11.Schema.Literal("http", "https")),
|
|
1476
|
+
hostname: import_effect11.Schema.String,
|
|
1477
|
+
port: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1478
|
+
pathname: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1479
|
+
search: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
554
1480
|
})
|
|
555
1481
|
);
|
|
556
|
-
var ImageVariantSchema =
|
|
557
|
-
|
|
558
|
-
width:
|
|
559
|
-
height:
|
|
560
|
-
quality:
|
|
561
|
-
format:
|
|
562
|
-
fit:
|
|
1482
|
+
var ImageVariantSchema = import_effect11.Schema.mutable(
|
|
1483
|
+
import_effect11.Schema.Struct({
|
|
1484
|
+
width: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1485
|
+
height: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1486
|
+
quality: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1487
|
+
format: import_effect11.Schema.optional(import_effect11.Schema.Literal("image/avif", "image/webp", "image/jpeg", "image/png")),
|
|
1488
|
+
fit: import_effect11.Schema.optional(import_effect11.Schema.Literal("contain", "cover", "fill", "inside", "outside"))
|
|
563
1489
|
})
|
|
564
1490
|
);
|
|
565
|
-
var PositiveIntSchema =
|
|
566
|
-
var ImagePolicySchema =
|
|
567
|
-
|
|
568
|
-
localPatterns:
|
|
569
|
-
remotePatterns:
|
|
570
|
-
widths:
|
|
571
|
-
heights:
|
|
572
|
-
qualities:
|
|
573
|
-
formats:
|
|
574
|
-
minimumCacheTTL:
|
|
575
|
-
dangerouslyAllowSVG:
|
|
576
|
-
contentSecurityPolicy:
|
|
577
|
-
contentDispositionType:
|
|
578
|
-
maximumRedirects:
|
|
579
|
-
maximumResponseBody:
|
|
580
|
-
variants:
|
|
1491
|
+
var PositiveIntSchema = import_effect11.Schema.Int.pipe(import_effect11.Schema.greaterThan(0));
|
|
1492
|
+
var ImagePolicySchema = import_effect11.Schema.mutable(
|
|
1493
|
+
import_effect11.Schema.Struct({
|
|
1494
|
+
localPatterns: import_effect11.Schema.mutable(import_effect11.Schema.Array(ImageLocalPatternSchema)),
|
|
1495
|
+
remotePatterns: import_effect11.Schema.mutable(import_effect11.Schema.Array(ImageRemotePatternSchema)),
|
|
1496
|
+
widths: import_effect11.Schema.mutable(import_effect11.Schema.Array(PositiveIntSchema)),
|
|
1497
|
+
heights: import_effect11.Schema.mutable(import_effect11.Schema.Array(PositiveIntSchema)),
|
|
1498
|
+
qualities: import_effect11.Schema.mutable(import_effect11.Schema.Array(import_effect11.Schema.Number.pipe(import_effect11.Schema.between(1, 100)))),
|
|
1499
|
+
formats: import_effect11.Schema.mutable(import_effect11.Schema.Array(import_effect11.Schema.Literal("image/avif", "image/webp", "image/jpeg", "image/png"))),
|
|
1500
|
+
minimumCacheTTL: import_effect11.Schema.Number,
|
|
1501
|
+
dangerouslyAllowSVG: import_effect11.Schema.Boolean,
|
|
1502
|
+
contentSecurityPolicy: import_effect11.Schema.String,
|
|
1503
|
+
contentDispositionType: import_effect11.Schema.Literal("inline", "attachment"),
|
|
1504
|
+
maximumRedirects: import_effect11.Schema.Number,
|
|
1505
|
+
maximumResponseBody: import_effect11.Schema.Number,
|
|
1506
|
+
variants: import_effect11.Schema.mutable(import_effect11.Schema.Record({ key: import_effect11.Schema.String, value: ImageVariantSchema }))
|
|
581
1507
|
})
|
|
582
1508
|
);
|
|
583
1509
|
var GigadriveNextPrerenderOutputFields = {
|
|
584
|
-
id:
|
|
585
|
-
type:
|
|
1510
|
+
id: import_effect11.Schema.String,
|
|
1511
|
+
type: import_effect11.Schema.Literal("PRERENDER"),
|
|
586
1512
|
pathname: UrlPathnameSchema,
|
|
587
|
-
route:
|
|
588
|
-
parentOutputId:
|
|
589
|
-
groupId:
|
|
590
|
-
pprChain:
|
|
591
|
-
parentFallbackMode:
|
|
592
|
-
fallback:
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
filePath:
|
|
596
|
-
initialStatus:
|
|
597
|
-
initialHeaders:
|
|
598
|
-
initialExpiration:
|
|
599
|
-
initialRevalidate:
|
|
600
|
-
postponedState:
|
|
1513
|
+
route: import_effect11.Schema.optional(UrlPathnameSchema),
|
|
1514
|
+
parentOutputId: import_effect11.Schema.String,
|
|
1515
|
+
groupId: import_effect11.Schema.Number,
|
|
1516
|
+
pprChain: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Struct({ headers: HttpSingleValueHeadersSchema }))),
|
|
1517
|
+
parentFallbackMode: import_effect11.Schema.optional(JsonValueSchema),
|
|
1518
|
+
fallback: import_effect11.Schema.optional(
|
|
1519
|
+
import_effect11.Schema.mutable(
|
|
1520
|
+
import_effect11.Schema.Struct({
|
|
1521
|
+
filePath: import_effect11.Schema.optional(PortableRelativePathSchema),
|
|
1522
|
+
initialStatus: import_effect11.Schema.optional(import_effect11.Schema.Int.pipe(import_effect11.Schema.between(100, 599))),
|
|
1523
|
+
initialHeaders: import_effect11.Schema.optional(HttpHeadersSchema),
|
|
1524
|
+
initialExpiration: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1525
|
+
initialRevalidate: import_effect11.Schema.optional(import_effect11.Schema.Union(import_effect11.Schema.Number, import_effect11.Schema.Literal(false))),
|
|
1526
|
+
postponedState: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
601
1527
|
})
|
|
602
1528
|
)
|
|
603
1529
|
),
|
|
604
|
-
config:
|
|
605
|
-
|
|
606
|
-
allowQuery:
|
|
607
|
-
allowHeader:
|
|
608
|
-
bypassFor:
|
|
609
|
-
renderingMode:
|
|
610
|
-
partialFallback:
|
|
611
|
-
bypassToken:
|
|
1530
|
+
config: import_effect11.Schema.mutable(
|
|
1531
|
+
import_effect11.Schema.Struct({
|
|
1532
|
+
allowQuery: import_effect11.Schema.optional(StringArraySchema),
|
|
1533
|
+
allowHeader: import_effect11.Schema.optional(StringArraySchema),
|
|
1534
|
+
bypassFor: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(JsonValueSchema))),
|
|
1535
|
+
renderingMode: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1536
|
+
partialFallback: import_effect11.Schema.optional(import_effect11.Schema.Boolean),
|
|
1537
|
+
bypassToken: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
612
1538
|
})
|
|
613
1539
|
)
|
|
614
1540
|
};
|
|
615
|
-
var GigadriveNextPrerenderClassificationSchema =
|
|
616
|
-
routeType:
|
|
617
|
-
response:
|
|
618
|
-
compute:
|
|
619
|
-
htmlSize:
|
|
1541
|
+
var GigadriveNextPrerenderClassificationSchema = import_effect11.Schema.Struct({
|
|
1542
|
+
routeType: import_effect11.Schema.Literal("route", "fallback", "shell", "page"),
|
|
1543
|
+
response: import_effect11.Schema.Literal("empty", "initial", "complete"),
|
|
1544
|
+
compute: import_effect11.Schema.Literal("blocking", "resuming", "static"),
|
|
1545
|
+
htmlSize: import_effect11.Schema.optional(import_effect11.Schema.Number)
|
|
620
1546
|
});
|
|
621
|
-
var GigadriveNextPrerenderWithoutClassificationSchema =
|
|
622
|
-
routeType:
|
|
623
|
-
response:
|
|
624
|
-
compute:
|
|
625
|
-
htmlSize:
|
|
1547
|
+
var GigadriveNextPrerenderWithoutClassificationSchema = import_effect11.Schema.Struct({
|
|
1548
|
+
routeType: import_effect11.Schema.optional(import_effect11.Schema.Never),
|
|
1549
|
+
response: import_effect11.Schema.optional(import_effect11.Schema.Never),
|
|
1550
|
+
compute: import_effect11.Schema.optional(import_effect11.Schema.Never),
|
|
1551
|
+
htmlSize: import_effect11.Schema.optional(import_effect11.Schema.Never)
|
|
626
1552
|
});
|
|
627
|
-
var GigadriveNextPrerenderOutputSchema =
|
|
628
|
-
|
|
629
|
-
|
|
1553
|
+
var GigadriveNextPrerenderOutputSchema = import_effect11.Schema.Union(
|
|
1554
|
+
import_effect11.Schema.mutable(
|
|
1555
|
+
import_effect11.Schema.Struct({ ...GigadriveNextPrerenderOutputFields, ...GigadriveNextPrerenderClassificationSchema.fields })
|
|
630
1556
|
),
|
|
631
|
-
|
|
632
|
-
|
|
1557
|
+
import_effect11.Schema.mutable(
|
|
1558
|
+
import_effect11.Schema.Struct({
|
|
633
1559
|
...GigadriveNextPrerenderOutputFields,
|
|
634
1560
|
...GigadriveNextPrerenderWithoutClassificationSchema.fields
|
|
635
1561
|
})
|
|
636
1562
|
)
|
|
637
1563
|
);
|
|
638
|
-
var GigadriveNextStaticAssetPrefixSchema =
|
|
639
|
-
|
|
1564
|
+
var GigadriveNextStaticAssetPrefixSchema = import_effect11.Schema.mutable(
|
|
1565
|
+
import_effect11.Schema.Struct({
|
|
640
1566
|
sourceDir: PortableRelativePathSchema,
|
|
641
1567
|
urlPrefix: PortableRelativePathSchema,
|
|
642
|
-
immutable:
|
|
1568
|
+
immutable: import_effect11.Schema.Boolean
|
|
643
1569
|
})
|
|
644
1570
|
);
|
|
645
|
-
var GigadriveNextRouteConditionSchema =
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
type:
|
|
649
|
-
key:
|
|
650
|
-
value:
|
|
1571
|
+
var GigadriveNextRouteConditionSchema = import_effect11.Schema.Union(
|
|
1572
|
+
import_effect11.Schema.mutable(
|
|
1573
|
+
import_effect11.Schema.Struct({
|
|
1574
|
+
type: import_effect11.Schema.Literal("header", "cookie", "query"),
|
|
1575
|
+
key: import_effect11.Schema.String,
|
|
1576
|
+
value: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
651
1577
|
})
|
|
652
1578
|
),
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
type:
|
|
656
|
-
value:
|
|
1579
|
+
import_effect11.Schema.mutable(
|
|
1580
|
+
import_effect11.Schema.Struct({
|
|
1581
|
+
type: import_effect11.Schema.Literal("host"),
|
|
1582
|
+
value: import_effect11.Schema.String
|
|
657
1583
|
})
|
|
658
1584
|
)
|
|
659
1585
|
);
|
|
660
|
-
var GigadriveNextMiddlewareMatcherSchema =
|
|
661
|
-
|
|
662
|
-
source:
|
|
663
|
-
sourceRegex:
|
|
664
|
-
has:
|
|
665
|
-
missing:
|
|
1586
|
+
var GigadriveNextMiddlewareMatcherSchema = import_effect11.Schema.mutable(
|
|
1587
|
+
import_effect11.Schema.Struct({
|
|
1588
|
+
source: import_effect11.Schema.String,
|
|
1589
|
+
sourceRegex: import_effect11.Schema.String,
|
|
1590
|
+
has: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextRouteConditionSchema))),
|
|
1591
|
+
missing: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextRouteConditionSchema)))
|
|
666
1592
|
})
|
|
667
1593
|
);
|
|
668
|
-
var GigadriveNextMiddlewareDescriptorSchema =
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
present:
|
|
672
|
-
matchers:
|
|
1594
|
+
var GigadriveNextMiddlewareDescriptorSchema = import_effect11.Schema.Union(
|
|
1595
|
+
import_effect11.Schema.mutable(
|
|
1596
|
+
import_effect11.Schema.Struct({
|
|
1597
|
+
present: import_effect11.Schema.Literal(true),
|
|
1598
|
+
matchers: import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextMiddlewareMatcherSchema))
|
|
673
1599
|
})
|
|
674
1600
|
),
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
present:
|
|
678
|
-
matchers:
|
|
1601
|
+
import_effect11.Schema.mutable(
|
|
1602
|
+
import_effect11.Schema.Struct({
|
|
1603
|
+
present: import_effect11.Schema.Literal(false),
|
|
1604
|
+
matchers: import_effect11.Schema.mutable(import_effect11.Schema.Tuple())
|
|
679
1605
|
})
|
|
680
1606
|
)
|
|
681
1607
|
);
|
|
682
|
-
var GigadriveNextServerDescriptorSchema =
|
|
683
|
-
|
|
684
|
-
maxDuration:
|
|
685
|
-
preferredRegion:
|
|
686
|
-
env:
|
|
1608
|
+
var GigadriveNextServerDescriptorSchema = import_effect11.Schema.mutable(
|
|
1609
|
+
import_effect11.Schema.Struct({
|
|
1610
|
+
maxDuration: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1611
|
+
preferredRegion: import_effect11.Schema.optional(import_effect11.Schema.Union(import_effect11.Schema.String, StringArraySchema)),
|
|
1612
|
+
env: import_effect11.Schema.optional(StringRecordSchema)
|
|
687
1613
|
})
|
|
688
1614
|
);
|
|
689
|
-
var PrerenderArraySchema =
|
|
690
|
-
var StaticAssetArraySchema =
|
|
691
|
-
var JsonValueArraySchema =
|
|
692
|
-
var GigadriveNextPrerenderSeedMethodsSchema =
|
|
693
|
-
|
|
1615
|
+
var PrerenderArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextPrerenderOutputSchema));
|
|
1616
|
+
var StaticAssetArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextStaticAssetPrefixSchema));
|
|
1617
|
+
var JsonValueArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(JsonValueSchema));
|
|
1618
|
+
var GigadriveNextPrerenderSeedMethodsSchema = import_effect11.Schema.mutable(
|
|
1619
|
+
import_effect11.Schema.Tuple(import_effect11.Schema.Literal("GET"), import_effect11.Schema.Literal("HEAD"))
|
|
694
1620
|
);
|
|
695
|
-
var GigadriveNextBuildManifestV1Schema =
|
|
696
|
-
|
|
697
|
-
version:
|
|
698
|
-
output:
|
|
1621
|
+
var GigadriveNextBuildManifestV1Schema = import_effect11.Schema.mutable(
|
|
1622
|
+
import_effect11.Schema.Struct({
|
|
1623
|
+
version: import_effect11.Schema.Literal(1),
|
|
1624
|
+
output: import_effect11.Schema.Literal("standalone", "export"),
|
|
699
1625
|
distDir: PortableRelativePathSchema,
|
|
700
1626
|
repoRootToProject: RepositoryRelativePathSchema,
|
|
701
|
-
nextVersion:
|
|
702
|
-
buildId:
|
|
1627
|
+
nextVersion: import_effect11.Schema.String,
|
|
1628
|
+
buildId: import_effect11.Schema.String
|
|
703
1629
|
})
|
|
704
1630
|
);
|
|
705
|
-
var GigadriveNextBuildManifestV2ExportSchema =
|
|
706
|
-
|
|
707
|
-
version:
|
|
708
|
-
mode:
|
|
1631
|
+
var GigadriveNextBuildManifestV2ExportSchema = import_effect11.Schema.mutable(
|
|
1632
|
+
import_effect11.Schema.Struct({
|
|
1633
|
+
version: import_effect11.Schema.Literal(2),
|
|
1634
|
+
mode: import_effect11.Schema.Literal("export"),
|
|
709
1635
|
distDir: PortableRelativePathSchema,
|
|
710
1636
|
repoRootToProject: RepositoryRelativePathSchema,
|
|
711
|
-
nextVersion:
|
|
712
|
-
buildId:
|
|
1637
|
+
nextVersion: import_effect11.Schema.String,
|
|
1638
|
+
buildId: import_effect11.Schema.String
|
|
713
1639
|
})
|
|
714
1640
|
);
|
|
715
|
-
var GigadriveNextBuildManifestV2StandaloneSchema =
|
|
716
|
-
|
|
717
|
-
version:
|
|
718
|
-
mode:
|
|
1641
|
+
var GigadriveNextBuildManifestV2StandaloneSchema = import_effect11.Schema.mutable(
|
|
1642
|
+
import_effect11.Schema.Struct({
|
|
1643
|
+
version: import_effect11.Schema.Literal(2),
|
|
1644
|
+
mode: import_effect11.Schema.Literal("standalone-v2"),
|
|
719
1645
|
distDir: PortableRelativePathSchema,
|
|
720
1646
|
repoRootToProject: RepositoryRelativePathSchema,
|
|
721
|
-
nextVersion:
|
|
722
|
-
buildId:
|
|
1647
|
+
nextVersion: import_effect11.Schema.String,
|
|
1648
|
+
buildId: import_effect11.Schema.String,
|
|
723
1649
|
server: GigadriveNextServerDescriptorSchema,
|
|
724
|
-
config:
|
|
725
|
-
|
|
726
|
-
basePath:
|
|
727
|
-
trailingSlash:
|
|
728
|
-
cacheComponents:
|
|
729
|
-
i18n:
|
|
730
|
-
images:
|
|
1650
|
+
config: import_effect11.Schema.mutable(
|
|
1651
|
+
import_effect11.Schema.Struct({
|
|
1652
|
+
basePath: import_effect11.Schema.String,
|
|
1653
|
+
trailingSlash: import_effect11.Schema.Boolean,
|
|
1654
|
+
cacheComponents: import_effect11.Schema.Boolean,
|
|
1655
|
+
i18n: import_effect11.Schema.optional(JsonValueSchema),
|
|
1656
|
+
images: import_effect11.Schema.optional(ImagePolicySchema)
|
|
731
1657
|
})
|
|
732
1658
|
),
|
|
733
|
-
routing:
|
|
734
|
-
|
|
1659
|
+
routing: import_effect11.Schema.mutable(
|
|
1660
|
+
import_effect11.Schema.Struct({
|
|
735
1661
|
beforeMiddleware: JsonValueArraySchema,
|
|
736
1662
|
beforeFiles: JsonValueArraySchema,
|
|
737
1663
|
afterFiles: JsonValueArraySchema,
|
|
738
1664
|
dynamicRoutes: JsonValueArraySchema,
|
|
739
1665
|
onMatch: JsonValueArraySchema,
|
|
740
1666
|
fallback: JsonValueArraySchema,
|
|
741
|
-
shouldNormalizeNextData:
|
|
1667
|
+
shouldNormalizeNextData: import_effect11.Schema.Boolean,
|
|
742
1668
|
rsc: JsonValueSchema
|
|
743
1669
|
})
|
|
744
1670
|
),
|
|
745
|
-
outputs:
|
|
746
|
-
|
|
1671
|
+
outputs: import_effect11.Schema.mutable(
|
|
1672
|
+
import_effect11.Schema.Struct({
|
|
747
1673
|
prerenders: PrerenderArraySchema,
|
|
748
|
-
prerenderManifest:
|
|
749
|
-
assetManifest:
|
|
750
|
-
entryPagePaths:
|
|
751
|
-
staticAssets: StaticAssetArraySchema,
|
|
752
|
-
middleware:
|
|
753
|
-
})
|
|
754
|
-
)
|
|
755
|
-
})
|
|
756
|
-
);
|
|
757
|
-
var GigadriveNextBuildManifestSchema =
|
|
758
|
-
GigadriveNextBuildManifestV1Schema,
|
|
759
|
-
GigadriveNextBuildManifestV2ExportSchema,
|
|
760
|
-
GigadriveNextBuildManifestV2StandaloneSchema
|
|
761
|
-
);
|
|
762
|
-
var GigadriveNextPrerenderManifestV1Schema =
|
|
763
|
-
|
|
764
|
-
version:
|
|
765
|
-
seedMethods:
|
|
766
|
-
prerenders: PrerenderArraySchema
|
|
767
|
-
})
|
|
768
|
-
);
|
|
769
|
-
var parseGigadriveNextBuildManifest = (content) => decodeJson(GigadriveNextBuildManifestSchema, content);
|
|
770
|
-
var parseGigadriveNextPrerenderManifest = (content) => decodeJson(GigadriveNextPrerenderManifestV1Schema, content);
|
|
771
|
-
|
|
772
|
-
// src/regions.ts
|
|
773
|
-
var REGION_DEFINITIONS = [
|
|
774
|
-
"us-east-1",
|
|
775
|
-
"us-east-2",
|
|
776
|
-
"us-west-1",
|
|
777
|
-
"us-west-2",
|
|
778
|
-
"ap-south-1",
|
|
779
|
-
"ap-northeast-3",
|
|
780
|
-
"ap-northeast-2",
|
|
781
|
-
"ap-southeast-1",
|
|
782
|
-
"ap-southeast-2",
|
|
783
|
-
"ap-northeast-1",
|
|
784
|
-
"ca-central-1",
|
|
785
|
-
"eu-central-1",
|
|
786
|
-
"eu-west-1",
|
|
787
|
-
"eu-west-2",
|
|
788
|
-
"eu-west-3",
|
|
789
|
-
"eu-north-1",
|
|
790
|
-
"sa-east-1"
|
|
791
|
-
];
|
|
792
|
-
var AVAILABLE_REGIONS = [...REGION_DEFINITIONS];
|
|
1674
|
+
prerenderManifest: import_effect11.Schema.optional(PortableRelativePathSchema),
|
|
1675
|
+
assetManifest: import_effect11.Schema.optional(PortableRelativePathSchema),
|
|
1676
|
+
entryPagePaths: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(UrlPathnameSchema))),
|
|
1677
|
+
staticAssets: StaticAssetArraySchema,
|
|
1678
|
+
middleware: import_effect11.Schema.optional(GigadriveNextMiddlewareDescriptorSchema)
|
|
1679
|
+
})
|
|
1680
|
+
)
|
|
1681
|
+
})
|
|
1682
|
+
);
|
|
1683
|
+
var GigadriveNextBuildManifestSchema = import_effect11.Schema.Union(
|
|
1684
|
+
GigadriveNextBuildManifestV1Schema,
|
|
1685
|
+
GigadriveNextBuildManifestV2ExportSchema,
|
|
1686
|
+
GigadriveNextBuildManifestV2StandaloneSchema
|
|
1687
|
+
);
|
|
1688
|
+
var GigadriveNextPrerenderManifestV1Schema = import_effect11.Schema.mutable(
|
|
1689
|
+
import_effect11.Schema.Struct({
|
|
1690
|
+
version: import_effect11.Schema.Literal(1),
|
|
1691
|
+
seedMethods: import_effect11.Schema.optional(GigadriveNextPrerenderSeedMethodsSchema),
|
|
1692
|
+
prerenders: PrerenderArraySchema
|
|
1693
|
+
})
|
|
1694
|
+
);
|
|
1695
|
+
var parseGigadriveNextBuildManifest = (content) => decodeJson(GigadriveNextBuildManifestSchema, content);
|
|
1696
|
+
var parseGigadriveNextPrerenderManifest = (content) => decodeJson(GigadriveNextPrerenderManifestV1Schema, content);
|
|
793
1697
|
|
|
794
1698
|
// src/detection/frameworks/nextjs.ts
|
|
795
1699
|
var toPortablePath = (value) => value.replaceAll("\\", "/");
|
|
796
1700
|
var STANDALONE_SERVER_MEMORY_MB = 1024;
|
|
797
|
-
var resolveStandaloneServer =
|
|
798
|
-
const fs = yield*
|
|
799
|
-
const pathService = yield*
|
|
1701
|
+
var resolveStandaloneServer = import_effect12.Effect.fn("nextjs.resolveStandaloneServer")(function* (projectFolder, distDir, repoRootToProject) {
|
|
1702
|
+
const fs = yield* import_platform8.FileSystem.FileSystem;
|
|
1703
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
800
1704
|
const standaloneRoot = pathService.join(projectFolder, distDir, "standalone");
|
|
801
1705
|
const monorepoServer = pathService.join(standaloneRoot, repoRootToProject, "server.js");
|
|
802
1706
|
const rootServer = pathService.join(standaloneRoot, "server.js");
|
|
803
|
-
const monorepoServerExists = yield* fs.exists(monorepoServer).pipe(
|
|
1707
|
+
const monorepoServerExists = yield* fs.exists(monorepoServer).pipe(import_effect12.Effect.catchAll(() => import_effect12.Effect.succeed(false)));
|
|
804
1708
|
const serverPath = monorepoServerExists ? monorepoServer : rootServer;
|
|
805
|
-
const serverExists = yield* fs.exists(serverPath).pipe(
|
|
1709
|
+
const serverExists = yield* fs.exists(serverPath).pipe(import_effect12.Effect.catchAll(() => import_effect12.Effect.succeed(false)));
|
|
806
1710
|
if (!serverExists) return void 0;
|
|
807
1711
|
const serverDirectory = pathService.dirname(serverPath);
|
|
808
1712
|
const entrypoint = toPortablePath(pathService.relative(standaloneRoot, serverPath));
|
|
809
1713
|
return { standaloneRoot, serverDirectory, entrypoint };
|
|
810
1714
|
});
|
|
811
|
-
var buildStandalonePublicAssets =
|
|
812
|
-
const pathService = yield*
|
|
1715
|
+
var buildStandalonePublicAssets = import_effect12.Effect.fn("nextjs.buildStandalonePublicAssets")(function* (projectFolder, standaloneRoot, serverDirectory) {
|
|
1716
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
813
1717
|
const publicFiles = yield* getDefaultPathMap(pathService.join(projectFolder, "public"));
|
|
814
1718
|
const assetPaths = [];
|
|
815
1719
|
const assetOverrides = {};
|
|
@@ -825,8 +1729,8 @@ var buildStandalonePublicAssets = import_effect9.Effect.fn("nextjs.buildStandalo
|
|
|
825
1729
|
}
|
|
826
1730
|
return { assetPaths, assetOverrides, filePathMap };
|
|
827
1731
|
});
|
|
828
|
-
var createStaticExportConfig =
|
|
829
|
-
const pathService = yield*
|
|
1732
|
+
var createStaticExportConfig = import_effect12.Effect.fn("nextjs.createStaticExportConfig")(function* (defaults, projectFolder) {
|
|
1733
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
830
1734
|
const outputDirectory = pathService.join(projectFolder, "out");
|
|
831
1735
|
const files = yield* getDefaultPathMap(outputDirectory);
|
|
832
1736
|
const assetPaths = [];
|
|
@@ -849,8 +1753,8 @@ var createStaticExportConfig = import_effect9.Effect.fn("nextjs.createStaticExpo
|
|
|
849
1753
|
package: void 0
|
|
850
1754
|
};
|
|
851
1755
|
});
|
|
852
|
-
var createStandaloneConfig =
|
|
853
|
-
const pathService = yield*
|
|
1756
|
+
var createStandaloneConfig = import_effect12.Effect.fn("nextjs.createStandaloneConfig")(function* (defaults, projectFolder, manifest) {
|
|
1757
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
854
1758
|
const resolved = yield* resolveStandaloneServer(projectFolder, manifest.distDir, manifest.repoRootToProject);
|
|
855
1759
|
if (!resolved) return defaults;
|
|
856
1760
|
const { standaloneRoot, serverDirectory, entrypoint } = resolved;
|
|
@@ -883,7 +1787,7 @@ var createStandaloneConfig = import_effect9.Effect.fn("nextjs.createStandaloneCo
|
|
|
883
1787
|
}
|
|
884
1788
|
};
|
|
885
1789
|
});
|
|
886
|
-
var createStandaloneV2Config =
|
|
1790
|
+
var createStandaloneV2Config = import_effect12.Effect.fn("nextjs.createStandaloneV2Config")(function* (defaults, projectFolder, manifest) {
|
|
887
1791
|
const resolved = yield* resolveStandaloneServer(projectFolder, manifest.distDir, manifest.repoRootToProject);
|
|
888
1792
|
if (!resolved) return defaults;
|
|
889
1793
|
const { standaloneRoot, serverDirectory, entrypoint } = resolved;
|
|
@@ -991,9 +1895,9 @@ var nextjs = {
|
|
|
991
1895
|
routes: [{ source: "/*", destination: ".next/standalone/server.js" }],
|
|
992
1896
|
environmentVariables: { NODE_ENV: "production" }
|
|
993
1897
|
}),
|
|
994
|
-
refineDefaultConfig: (defaults, projectFolder) =>
|
|
995
|
-
const fs = yield*
|
|
996
|
-
const manifestContent = yield* fs.readFileString(`${projectFolder}/.gigadrive/nextjs.json`).pipe(
|
|
1898
|
+
refineDefaultConfig: (defaults, projectFolder) => import_effect12.Effect.gen(function* () {
|
|
1899
|
+
const fs = yield* import_platform8.FileSystem.FileSystem;
|
|
1900
|
+
const manifestContent = yield* fs.readFileString(`${projectFolder}/.gigadrive/nextjs.json`).pipe(import_effect12.Effect.catchAll(() => import_effect12.Effect.succeed(void 0)));
|
|
997
1901
|
const manifest = manifestContent ? parseGigadriveNextBuildManifest(manifestContent) : void 0;
|
|
998
1902
|
if (!manifest) return defaults;
|
|
999
1903
|
if (manifest.version === 2) {
|
|
@@ -1004,8 +1908,8 @@ var nextjs = {
|
|
|
1004
1908
|
};
|
|
1005
1909
|
|
|
1006
1910
|
// src/detection/frameworks/nuxt.ts
|
|
1007
|
-
var
|
|
1008
|
-
var
|
|
1911
|
+
var import_platform9 = require("@effect/platform");
|
|
1912
|
+
var import_effect13 = require("effect");
|
|
1009
1913
|
var isVercelBuildOutputV3 = (content) => {
|
|
1010
1914
|
try {
|
|
1011
1915
|
const config = JSON.parse(content);
|
|
@@ -1032,9 +1936,9 @@ var nuxt = {
|
|
|
1032
1936
|
routes: [{ source: "/*", destination: ".output/server/index.mjs" }],
|
|
1033
1937
|
environmentVariables: { NODE_ENV: "production", NITRO_PRESET: "node-server" }
|
|
1034
1938
|
}),
|
|
1035
|
-
refineDefaultConfig: (defaults, projectFolder) =>
|
|
1036
|
-
const fs = yield*
|
|
1037
|
-
const buildOutputConfig = yield* fs.readFileString(`${projectFolder}/.vercel/output/config.json`).pipe(
|
|
1939
|
+
refineDefaultConfig: (defaults, projectFolder) => import_effect13.Effect.gen(function* () {
|
|
1940
|
+
const fs = yield* import_platform9.FileSystem.FileSystem;
|
|
1941
|
+
const buildOutputConfig = yield* fs.readFileString(`${projectFolder}/.vercel/output/config.json`).pipe(import_effect13.Effect.catchAll(() => import_effect13.Effect.succeed(void 0)));
|
|
1038
1942
|
if (!buildOutputConfig || !isVercelBuildOutputV3(buildOutputConfig)) {
|
|
1039
1943
|
return defaults;
|
|
1040
1944
|
}
|
|
@@ -1048,6 +1952,43 @@ var nuxt = {
|
|
|
1048
1952
|
})
|
|
1049
1953
|
};
|
|
1050
1954
|
|
|
1955
|
+
// src/detection/frameworks/php.ts
|
|
1956
|
+
var import_platform10 = require("@effect/platform");
|
|
1957
|
+
var import_effect14 = require("effect");
|
|
1958
|
+
var COMPOSER_FILES = ["composer.json", "composer.lock"];
|
|
1959
|
+
var DOCUMENT_ROOTS = ["public", "web", "webroot", "public_html", "htdocs", "."];
|
|
1960
|
+
var refinePhpDocumentRoot = (defaults, projectFolder) => import_effect14.Effect.gen(function* () {
|
|
1961
|
+
const fs = yield* import_platform10.FileSystem.FileSystem;
|
|
1962
|
+
const pathService = yield* import_platform10.Path.Path;
|
|
1963
|
+
for (const documentRoot of DOCUMENT_ROOTS) {
|
|
1964
|
+
const frontController = pathService.join(projectFolder, documentRoot, "index.php");
|
|
1965
|
+
if (yield* fs.exists(frontController).pipe(import_effect14.Effect.catchAll(() => import_effect14.Effect.succeed(false)))) {
|
|
1966
|
+
return phpFrontControllerDefaults({ documentRoot, excludeFiles: COMPOSER_FILES });
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
return defaults;
|
|
1970
|
+
});
|
|
1971
|
+
var getDefaultConfig = () => phpFrontControllerDefaults({ documentRoot: ".", excludeFiles: COMPOSER_FILES });
|
|
1972
|
+
var frontControllerPath = (documentRoot) => documentRoot === "." ? "index.php" : `${documentRoot}/index.php`;
|
|
1973
|
+
var phpComposerProjects = DOCUMENT_ROOTS.map((documentRoot) => ({
|
|
1974
|
+
slug: "php",
|
|
1975
|
+
name: "PHP",
|
|
1976
|
+
language: "php",
|
|
1977
|
+
detectors: [{ path: "composer.json" }, { path: frontControllerPath(documentRoot) }],
|
|
1978
|
+
priority: 7,
|
|
1979
|
+
getDefaultConfig,
|
|
1980
|
+
refineDefaultConfig: refinePhpDocumentRoot
|
|
1981
|
+
}));
|
|
1982
|
+
var phpSites = DOCUMENT_ROOTS.map((documentRoot) => ({
|
|
1983
|
+
slug: "php-site",
|
|
1984
|
+
name: "PHP",
|
|
1985
|
+
language: "php",
|
|
1986
|
+
detectors: [{ path: frontControllerPath(documentRoot) }],
|
|
1987
|
+
priority: 6,
|
|
1988
|
+
getDefaultConfig: () => ({ ...getDefaultConfig(), installCommand: "" }),
|
|
1989
|
+
refineDefaultConfig: (defaults, projectFolder) => refinePhpDocumentRoot(defaults, projectFolder).pipe(import_effect14.Effect.map((refined) => ({ ...refined, installCommand: "" })))
|
|
1990
|
+
}));
|
|
1991
|
+
|
|
1051
1992
|
// src/detection/frameworks/remix.ts
|
|
1052
1993
|
var remix = {
|
|
1053
1994
|
slug: "remix",
|
|
@@ -1069,6 +2010,21 @@ var remix = {
|
|
|
1069
2010
|
})
|
|
1070
2011
|
};
|
|
1071
2012
|
|
|
2013
|
+
// src/detection/frameworks/slim.ts
|
|
2014
|
+
var slim = {
|
|
2015
|
+
slug: "slim",
|
|
2016
|
+
name: "Slim",
|
|
2017
|
+
language: "php",
|
|
2018
|
+
detectors: [{ matchPackage: "slim/slim" }, { path: "public/index.php" }],
|
|
2019
|
+
priority: 75,
|
|
2020
|
+
getDefaultConfig: () => phpFrontControllerDefaults({
|
|
2021
|
+
documentRoot: "public",
|
|
2022
|
+
// slim/slim-skeleton logs to logs/ and caches the container and routes in var/cache.
|
|
2023
|
+
writablePaths: ["logs", "var/cache"],
|
|
2024
|
+
excludeFiles: ["tests/", "logs/", "var/"]
|
|
2025
|
+
})
|
|
2026
|
+
};
|
|
2027
|
+
|
|
1072
2028
|
// src/detection/frameworks/sveltekit.ts
|
|
1073
2029
|
var sveltekit = {
|
|
1074
2030
|
slug: "sveltekit",
|
|
@@ -1108,12 +2064,13 @@ var symfony = {
|
|
|
1108
2064
|
assetsDir: "public",
|
|
1109
2065
|
populateAssetCache: true,
|
|
1110
2066
|
excludeFiles: ["tests/*", ".ddev", "var"],
|
|
1111
|
-
symlinks: { var: "/tmp" },
|
|
1112
2067
|
routes: [{ source: "/*", destination: "public/index.php" }],
|
|
2068
|
+
// The kernel's cache and log directories. A symlink to /tmp used to stand
|
|
2069
|
+
// in for them, which the build rejected as pointing outside the project.
|
|
2070
|
+
package: { writablePaths: ["var/cache", "var/log"] },
|
|
1113
2071
|
environmentVariables: {
|
|
1114
2072
|
APP_ENV: "prod",
|
|
1115
2073
|
APP_DEBUG: "false",
|
|
1116
|
-
APP_SECRET: "please_change_this_value_in_your_settings",
|
|
1117
2074
|
MESSENGER_TRANSPORT_DSN: "doctrine://default?auto_setup=0"
|
|
1118
2075
|
}
|
|
1119
2076
|
})
|
|
@@ -1139,6 +2096,22 @@ var vite = {
|
|
|
1139
2096
|
})
|
|
1140
2097
|
};
|
|
1141
2098
|
|
|
2099
|
+
// src/detection/frameworks/yii.ts
|
|
2100
|
+
var yii = {
|
|
2101
|
+
slug: "yii",
|
|
2102
|
+
name: "Yii 2",
|
|
2103
|
+
language: "php",
|
|
2104
|
+
detectors: [{ matchPackage: "yiisoft/yii2" }, { path: "web/index.php" }],
|
|
2105
|
+
priority: 80,
|
|
2106
|
+
getDefaultConfig: () => phpFrontControllerDefaults({
|
|
2107
|
+
documentRoot: "web",
|
|
2108
|
+
// @runtime holds cache, logs and sessions; the asset manager publishes
|
|
2109
|
+
// bundles from vendor/ into web/assets when a page first uses them.
|
|
2110
|
+
writablePaths: ["runtime", "web/assets"],
|
|
2111
|
+
excludeFiles: ["tests/", "runtime/", "web/assets/"]
|
|
2112
|
+
})
|
|
2113
|
+
};
|
|
2114
|
+
|
|
1142
2115
|
// src/detection/frameworks/index.ts
|
|
1143
2116
|
var FRAMEWORK_DEFINITIONS = [
|
|
1144
2117
|
nextjs,
|
|
@@ -1149,15 +2122,23 @@ var FRAMEWORK_DEFINITIONS = [
|
|
|
1149
2122
|
astro,
|
|
1150
2123
|
laravel,
|
|
1151
2124
|
symfony,
|
|
2125
|
+
cakephp,
|
|
2126
|
+
codeigniter,
|
|
2127
|
+
laminas,
|
|
2128
|
+
mezzio,
|
|
2129
|
+
yii,
|
|
2130
|
+
slim,
|
|
1152
2131
|
hono,
|
|
1153
2132
|
elysia,
|
|
1154
2133
|
fastify,
|
|
1155
2134
|
express,
|
|
2135
|
+
...phpComposerProjects,
|
|
2136
|
+
...phpSites,
|
|
1156
2137
|
vite
|
|
1157
2138
|
].sort((a, b) => b.priority - a.priority);
|
|
1158
2139
|
|
|
1159
2140
|
// src/detection/generate-config.ts
|
|
1160
|
-
var
|
|
2141
|
+
var import_effect15 = require("effect");
|
|
1161
2142
|
var getInstallCommand = (pm) => {
|
|
1162
2143
|
switch (pm) {
|
|
1163
2144
|
case "bun":
|
|
@@ -1173,11 +2154,16 @@ var getInstallCommand = (pm) => {
|
|
|
1173
2154
|
return "npm install";
|
|
1174
2155
|
}
|
|
1175
2156
|
};
|
|
1176
|
-
var
|
|
2157
|
+
var COMPOSER_ROOT_FILES = /* @__PURE__ */ new Set(["composer.json", "composer.lock", "auth.json"]);
|
|
2158
|
+
var isPrivatePhpProjectFile = (projectPath) => {
|
|
2159
|
+
const segments = projectPath.split("/").filter((segment) => segment !== "" && segment !== ".");
|
|
2160
|
+
return segments.some((segment) => segment.startsWith(".")) || segments[0] === "vendor" || segments[0] === "node_modules" || segments.length === 1 && COMPOSER_ROOT_FILES.has(segments[0] ?? "");
|
|
2161
|
+
};
|
|
2162
|
+
var generateConfig = import_effect15.Effect.fn("generateConfig")(function* (framework, packageManager, projectFolder, refinedDefaults) {
|
|
1177
2163
|
const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
|
|
1178
2164
|
const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
|
|
1179
|
-
const commands = [installCmd, ...defaults.commands];
|
|
1180
|
-
yield*
|
|
2165
|
+
const commands = installCmd ? [installCmd, ...defaults.commands] : [...defaults.commands];
|
|
2166
|
+
yield* import_effect15.Effect.logDebug(`Generating config for ${framework.name}`, {
|
|
1181
2167
|
runtime: defaults.runtime,
|
|
1182
2168
|
entrypoint: defaults.entrypoint,
|
|
1183
2169
|
commands
|
|
@@ -1219,6 +2205,7 @@ var generateConfig = import_effect11.Effect.fn("generateConfig")(function* (fram
|
|
|
1219
2205
|
if (assetsDir && !defaults.assetPaths && !defaults.assetPrefixes && !defaults.assetManifests) {
|
|
1220
2206
|
for (const file of yield* collectAssetFiles(projectFolder, assetsDir)) {
|
|
1221
2207
|
if (framework.language === "php" && /\.(php|phtml|phar)$/i.test(file)) continue;
|
|
2208
|
+
if (framework.language === "php" && isPrivatePhpProjectFile(`${assetsDir}/${file}`)) continue;
|
|
1222
2209
|
paths.push(`${assetsDir}/${file}`);
|
|
1223
2210
|
if (!servesDirectoryIndexes || file in overrides) continue;
|
|
1224
2211
|
if (file === "index.html") {
|
|
@@ -1242,31 +2229,31 @@ var generateConfig = import_effect11.Effect.fn("generateConfig")(function* (fram
|
|
|
1242
2229
|
});
|
|
1243
2230
|
|
|
1244
2231
|
// src/detection/read-dependencies.ts
|
|
1245
|
-
var
|
|
1246
|
-
var
|
|
2232
|
+
var import_platform11 = require("@effect/platform");
|
|
2233
|
+
var import_effect17 = require("effect");
|
|
1247
2234
|
|
|
1248
2235
|
// src/detection/types.ts
|
|
1249
|
-
var
|
|
1250
|
-
var ManifestNotFoundError = class extends
|
|
1251
|
-
message:
|
|
1252
|
-
filePath:
|
|
2236
|
+
var import_effect16 = require("effect");
|
|
2237
|
+
var ManifestNotFoundError = class extends import_effect16.Schema.TaggedError()("ManifestNotFoundError", {
|
|
2238
|
+
message: import_effect16.Schema.String,
|
|
2239
|
+
filePath: import_effect16.Schema.String
|
|
1253
2240
|
}) {
|
|
1254
2241
|
};
|
|
1255
|
-
var ManifestReadError = class extends
|
|
1256
|
-
message:
|
|
1257
|
-
filePath:
|
|
2242
|
+
var ManifestReadError = class extends import_effect16.Schema.TaggedError()("ManifestReadError", {
|
|
2243
|
+
message: import_effect16.Schema.String,
|
|
2244
|
+
filePath: import_effect16.Schema.String
|
|
1258
2245
|
}) {
|
|
1259
2246
|
};
|
|
1260
|
-
var ManifestParseError = class extends
|
|
1261
|
-
message:
|
|
1262
|
-
filePath:
|
|
2247
|
+
var ManifestParseError = class extends import_effect16.Schema.TaggedError()("ManifestParseError", {
|
|
2248
|
+
message: import_effect16.Schema.String,
|
|
2249
|
+
filePath: import_effect16.Schema.String
|
|
1263
2250
|
}) {
|
|
1264
2251
|
};
|
|
1265
|
-
var FrameworkNotDetectedError = class extends
|
|
2252
|
+
var FrameworkNotDetectedError = class extends import_effect16.Schema.TaggedError()(
|
|
1266
2253
|
"FrameworkNotDetectedError",
|
|
1267
2254
|
{
|
|
1268
|
-
message:
|
|
1269
|
-
directory:
|
|
2255
|
+
message: import_effect16.Schema.String,
|
|
2256
|
+
directory: import_effect16.Schema.String
|
|
1270
2257
|
}
|
|
1271
2258
|
) {
|
|
1272
2259
|
};
|
|
@@ -1276,25 +2263,25 @@ var MANIFEST_CONFIG = {
|
|
|
1276
2263
|
node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
|
|
1277
2264
|
php: { file: "composer.json", depKeys: ["require", "require-dev"] }
|
|
1278
2265
|
};
|
|
1279
|
-
var readManifest =
|
|
1280
|
-
const fs = yield*
|
|
1281
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2266
|
+
var readManifest = import_effect17.Effect.fn("readManifest")(function* (filePath) {
|
|
2267
|
+
const fs = yield* import_platform11.FileSystem.FileSystem;
|
|
2268
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect17.Effect.catchAll(() => import_effect17.Effect.succeed(false)));
|
|
1282
2269
|
if (!exists) {
|
|
1283
|
-
return yield*
|
|
2270
|
+
return yield* import_effect17.Effect.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
|
|
1284
2271
|
}
|
|
1285
|
-
const content = yield* fs.readFileString(filePath).pipe(
|
|
1286
|
-
const parsed = yield*
|
|
2272
|
+
const content = yield* fs.readFileString(filePath).pipe(import_effect17.Effect.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
|
|
2273
|
+
const parsed = yield* import_effect17.Effect.try({
|
|
1287
2274
|
try: () => JSON.parse(content),
|
|
1288
2275
|
catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
|
|
1289
2276
|
});
|
|
1290
2277
|
return parsed;
|
|
1291
2278
|
});
|
|
1292
|
-
var readDependencies =
|
|
1293
|
-
const pathService = yield*
|
|
2279
|
+
var readDependencies = import_effect17.Effect.fn("readDependencies")(function* (projectFolder, language) {
|
|
2280
|
+
const pathService = yield* import_platform11.Path.Path;
|
|
1294
2281
|
const config = MANIFEST_CONFIG[language];
|
|
1295
2282
|
const filePath = pathService.join(projectFolder, config.file);
|
|
1296
2283
|
const manifest = yield* readManifest(filePath).pipe(
|
|
1297
|
-
|
|
2284
|
+
import_effect17.Effect.catchTag("ManifestNotFoundError", () => import_effect17.Effect.succeed(null))
|
|
1298
2285
|
);
|
|
1299
2286
|
if (!manifest) {
|
|
1300
2287
|
return /* @__PURE__ */ new Set();
|
|
@@ -1312,9 +2299,9 @@ var readDependencies = import_effect13.Effect.fn("readDependencies")(function* (
|
|
|
1312
2299
|
});
|
|
1313
2300
|
|
|
1314
2301
|
// src/detection/detect-framework.ts
|
|
1315
|
-
var matchesDetectionItem =
|
|
1316
|
-
const fs = yield*
|
|
1317
|
-
const pathService = yield*
|
|
2302
|
+
var matchesDetectionItem = import_effect18.Effect.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
|
|
2303
|
+
const fs = yield* import_platform12.FileSystem.FileSystem;
|
|
2304
|
+
const pathService = yield* import_platform12.Path.Path;
|
|
1318
2305
|
if (item.matchPackage != null) {
|
|
1319
2306
|
const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
|
|
1320
2307
|
if (!deps.has(item.matchPackage)) {
|
|
@@ -1323,12 +2310,12 @@ var matchesDetectionItem = import_effect14.Effect.fn("matchesDetectionItem")(fun
|
|
|
1323
2310
|
}
|
|
1324
2311
|
if (item.path != null) {
|
|
1325
2312
|
const filePath = pathService.join(projectFolder, item.path);
|
|
1326
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2313
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect18.Effect.catchAll(() => import_effect18.Effect.succeed(false)));
|
|
1327
2314
|
if (!exists) {
|
|
1328
2315
|
return false;
|
|
1329
2316
|
}
|
|
1330
2317
|
if (item.matchContent != null) {
|
|
1331
|
-
const content = yield* fs.readFileString(filePath).pipe(
|
|
2318
|
+
const content = yield* fs.readFileString(filePath).pipe(import_effect18.Effect.catchAll(() => import_effect18.Effect.succeed("")));
|
|
1332
2319
|
let regexMatch = false;
|
|
1333
2320
|
try {
|
|
1334
2321
|
regexMatch = new RegExp(item.matchContent).test(content);
|
|
@@ -1341,7 +2328,7 @@ var matchesDetectionItem = import_effect14.Effect.fn("matchesDetectionItem")(fun
|
|
|
1341
2328
|
}
|
|
1342
2329
|
return true;
|
|
1343
2330
|
});
|
|
1344
|
-
var matchesFramework =
|
|
2331
|
+
var matchesFramework = import_effect18.Effect.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
|
|
1345
2332
|
for (const detector of framework.detectors) {
|
|
1346
2333
|
const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
|
|
1347
2334
|
if (!matches) {
|
|
@@ -1350,9 +2337,9 @@ var matchesFramework = import_effect14.Effect.fn("matchesFramework")(function* (
|
|
|
1350
2337
|
}
|
|
1351
2338
|
return true;
|
|
1352
2339
|
});
|
|
1353
|
-
var detectFramework =
|
|
1354
|
-
yield*
|
|
1355
|
-
const cachedReadDeps = yield*
|
|
2340
|
+
var detectFramework = import_effect18.Effect.fn("detectFramework")(function* (projectFolder) {
|
|
2341
|
+
yield* import_effect18.Effect.logDebug(`Detecting framework in ${projectFolder}`);
|
|
2342
|
+
const cachedReadDeps = yield* import_effect18.Effect.cachedFunction((key) => {
|
|
1356
2343
|
const sepIndex = key.lastIndexOf("\0");
|
|
1357
2344
|
const folder = key.slice(0, sepIndex);
|
|
1358
2345
|
const language = key.slice(sepIndex + 1);
|
|
@@ -1361,7 +2348,7 @@ var detectFramework = import_effect14.Effect.fn("detectFramework")(function* (pr
|
|
|
1361
2348
|
for (const framework of FRAMEWORK_DEFINITIONS) {
|
|
1362
2349
|
const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
|
|
1363
2350
|
if (matches) {
|
|
1364
|
-
yield*
|
|
2351
|
+
yield* import_effect18.Effect.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
|
|
1365
2352
|
const detectedPackageManager = yield* detectPackageManager(projectFolder);
|
|
1366
2353
|
const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
|
|
1367
2354
|
const defaults = framework.getDefaultConfig(packageManager);
|
|
@@ -1370,7 +2357,7 @@ var detectFramework = import_effect14.Effect.fn("detectFramework")(function* (pr
|
|
|
1370
2357
|
return { framework, packageManager, config };
|
|
1371
2358
|
}
|
|
1372
2359
|
}
|
|
1373
|
-
return yield*
|
|
2360
|
+
return yield* import_effect18.Effect.fail(
|
|
1374
2361
|
new FrameworkNotDetectedError({
|
|
1375
2362
|
message: `No framework detected in project directory`,
|
|
1376
2363
|
directory: projectFolder
|
|
@@ -1379,15 +2366,22 @@ var detectFramework = import_effect14.Effect.fn("detectFramework")(function* (pr
|
|
|
1379
2366
|
});
|
|
1380
2367
|
|
|
1381
2368
|
// src/detection/merge-config.ts
|
|
1382
|
-
var
|
|
1383
|
-
var mergeWithFrameworkDefaults =
|
|
1384
|
-
yield*
|
|
2369
|
+
var import_effect19 = require("effect");
|
|
2370
|
+
var mergeWithFrameworkDefaults = import_effect19.Effect.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
|
|
2371
|
+
yield* import_effect19.Effect.logDebug("Merging user config with framework defaults");
|
|
1385
2372
|
const userHasAssets = (userConfig.assets?.paths?.length ?? 0) > 0 || (userConfig.assets?.prefixes?.length ?? 0) > 0 || (userConfig.assets?.manifests?.length ?? 0) > 0;
|
|
2373
|
+
const isContainer = (entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME;
|
|
2374
|
+
const userFileFunctions = userConfig.entrypoints.filter((entrypoint) => !isContainer(entrypoint));
|
|
2375
|
+
const containerPaths = new Set(userConfig.entrypoints.filter(isContainer).map((entrypoint) => entrypoint.path));
|
|
2376
|
+
const targetsContainer = (route) => containerPaths.has(route.destination.replace(/^\/+/, ""));
|
|
1386
2377
|
const merged = {
|
|
1387
2378
|
regions: userConfig.regions,
|
|
1388
2379
|
commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
|
|
1389
|
-
entrypoints:
|
|
1390
|
-
|
|
2380
|
+
entrypoints: [
|
|
2381
|
+
...userFileFunctions.length > 0 ? userFileFunctions : frameworkConfig.entrypoints,
|
|
2382
|
+
...userConfig.entrypoints.filter(isContainer)
|
|
2383
|
+
],
|
|
2384
|
+
routes: containerPaths.size > 0 && userConfig.routes.every(targetsContainer) ? [...userConfig.routes, ...frameworkConfig.routes] : userConfig.routes.length > 0 ? userConfig.routes : frameworkConfig.routes,
|
|
1391
2385
|
assets: userHasAssets ? userConfig.assets : frameworkConfig.assets,
|
|
1392
2386
|
environmentVariables: {
|
|
1393
2387
|
...frameworkConfig.environmentVariables,
|
|
@@ -1395,6 +2389,7 @@ var mergeWithFrameworkDefaults = import_effect15.Effect.fn("mergeWithFrameworkDe
|
|
|
1395
2389
|
},
|
|
1396
2390
|
excludeFiles: userConfig.excludeFiles && userConfig.excludeFiles.length > 0 ? userConfig.excludeFiles : frameworkConfig.excludeFiles,
|
|
1397
2391
|
services: userConfig.services,
|
|
2392
|
+
...userConfig.sidecars !== void 0 && { sidecars: userConfig.sidecars },
|
|
1398
2393
|
userArchive: userConfig.userArchive,
|
|
1399
2394
|
warnings: [...frameworkConfig.warnings, ...userConfig.warnings],
|
|
1400
2395
|
errors: [...frameworkConfig.errors, ...userConfig.errors]
|
|
@@ -1402,51 +2397,6 @@ var mergeWithFrameworkDefaults = import_effect15.Effect.fn("mergeWithFrameworkDe
|
|
|
1402
2397
|
return merged;
|
|
1403
2398
|
});
|
|
1404
2399
|
|
|
1405
|
-
// src/errors.ts
|
|
1406
|
-
var import_effect16 = require("effect");
|
|
1407
|
-
var ConfigFileNotFoundError = class extends import_effect16.Schema.TaggedError()("ConfigFileNotFoundError", {
|
|
1408
|
-
message: import_effect16.Schema.String,
|
|
1409
|
-
filePath: import_effect16.Schema.String
|
|
1410
|
-
}) {
|
|
1411
|
-
};
|
|
1412
|
-
var ConfigFileEmptyError = class extends import_effect16.Schema.TaggedError()("ConfigFileEmptyError", {
|
|
1413
|
-
message: import_effect16.Schema.String,
|
|
1414
|
-
filePath: import_effect16.Schema.String
|
|
1415
|
-
}) {
|
|
1416
|
-
};
|
|
1417
|
-
var ConfigFileParseError = class extends import_effect16.Schema.TaggedError()("ConfigFileParseError", {
|
|
1418
|
-
message: import_effect16.Schema.String,
|
|
1419
|
-
filePath: import_effect16.Schema.String,
|
|
1420
|
-
cause: import_effect16.Schema.optional(import_effect16.Schema.String)
|
|
1421
|
-
}) {
|
|
1422
|
-
};
|
|
1423
|
-
var ConfigModuleLoadError = class extends import_effect16.Schema.TaggedError()("ConfigModuleLoadError", {
|
|
1424
|
-
message: import_effect16.Schema.String,
|
|
1425
|
-
filePath: import_effect16.Schema.String,
|
|
1426
|
-
cause: import_effect16.Schema.optional(import_effect16.Schema.String)
|
|
1427
|
-
}) {
|
|
1428
|
-
};
|
|
1429
|
-
var ConfigVersionError = class extends import_effect16.Schema.TaggedError()("ConfigVersionError", {
|
|
1430
|
-
message: import_effect16.Schema.String,
|
|
1431
|
-
filePath: import_effect16.Schema.String,
|
|
1432
|
-
version: import_effect16.Schema.optional(import_effect16.Schema.Number)
|
|
1433
|
-
}) {
|
|
1434
|
-
};
|
|
1435
|
-
var ConfigSchemaValidationError = class extends import_effect16.Schema.TaggedError()(
|
|
1436
|
-
"ConfigSchemaValidationError",
|
|
1437
|
-
{
|
|
1438
|
-
message: import_effect16.Schema.String,
|
|
1439
|
-
filePath: import_effect16.Schema.String,
|
|
1440
|
-
validationErrors: import_effect16.Schema.Array(import_effect16.Schema.String)
|
|
1441
|
-
}
|
|
1442
|
-
) {
|
|
1443
|
-
};
|
|
1444
|
-
var FunctionConfigError = class extends import_effect16.Schema.TaggedError()("FunctionConfigError", {
|
|
1445
|
-
message: import_effect16.Schema.String,
|
|
1446
|
-
functionPath: import_effect16.Schema.String
|
|
1447
|
-
}) {
|
|
1448
|
-
};
|
|
1449
|
-
|
|
1450
2400
|
// src/filter-functions-from-assets.ts
|
|
1451
2401
|
var filterFunctionsFromAssets = (config) => {
|
|
1452
2402
|
return {
|
|
@@ -1458,28 +2408,24 @@ var filterFunctionsFromAssets = (config) => {
|
|
|
1458
2408
|
};
|
|
1459
2409
|
};
|
|
1460
2410
|
|
|
1461
|
-
// src/normalized-config.ts
|
|
1462
|
-
var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
|
|
1463
|
-
var MAX_FUNCTION_DURATION_SECONDS = 28800;
|
|
1464
|
-
|
|
1465
2411
|
// src/parse-config.ts
|
|
1466
|
-
var
|
|
2412
|
+
var import_effect25 = require("effect");
|
|
1467
2413
|
|
|
1468
2414
|
// src/services/raw-config-reader.ts
|
|
1469
|
-
var
|
|
1470
|
-
var
|
|
1471
|
-
var
|
|
2415
|
+
var import_platform13 = require("@effect/platform");
|
|
2416
|
+
var import_effect21 = require("effect");
|
|
2417
|
+
var import_yaml2 = require("yaml");
|
|
1472
2418
|
|
|
1473
2419
|
// src/services/config-module-loader.ts
|
|
1474
|
-
var
|
|
2420
|
+
var import_effect20 = require("effect");
|
|
1475
2421
|
var import_jiti = require("jiti");
|
|
1476
2422
|
var MISSING_DEFAULT_EXPORT = /* @__PURE__ */ Symbol("MissingDefaultExport");
|
|
1477
2423
|
var STRICT_DEFAULT_EXPORT_EXTENSIONS = [".ts", ".mts", ".mjs"];
|
|
1478
|
-
var ConfigModuleLoader = class extends
|
|
1479
|
-
effect:
|
|
1480
|
-
const loadConfigModule =
|
|
2424
|
+
var ConfigModuleLoader = class extends import_effect20.Effect.Service()("ConfigModuleLoader", {
|
|
2425
|
+
effect: import_effect20.Effect.gen(function* () {
|
|
2426
|
+
const loadConfigModule = import_effect20.Effect.fn("ConfigModuleLoader.loadConfigModule")(function* (filePath) {
|
|
1481
2427
|
const extension = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
1482
|
-
const mod = yield*
|
|
2428
|
+
const mod = yield* import_effect20.Effect.tryPromise({
|
|
1483
2429
|
try: async () => {
|
|
1484
2430
|
const jiti = (0, import_jiti.createJiti)(filePath, { fsCache: false, interopDefault: true, moduleCache: false });
|
|
1485
2431
|
const namespace = await jiti.import(filePath);
|
|
@@ -1498,7 +2444,7 @@ var ConfigModuleLoader = class extends import_effect17.Effect.Service()("ConfigM
|
|
|
1498
2444
|
})
|
|
1499
2445
|
});
|
|
1500
2446
|
if (mod === MISSING_DEFAULT_EXPORT) {
|
|
1501
|
-
return yield*
|
|
2447
|
+
return yield* import_effect20.Effect.fail(
|
|
1502
2448
|
new ConfigModuleLoadError({
|
|
1503
2449
|
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.`,
|
|
1504
2450
|
filePath
|
|
@@ -1506,7 +2452,7 @@ var ConfigModuleLoader = class extends import_effect17.Effect.Service()("ConfigM
|
|
|
1506
2452
|
);
|
|
1507
2453
|
}
|
|
1508
2454
|
if (typeof mod === "function") {
|
|
1509
|
-
return yield*
|
|
2455
|
+
return yield* import_effect20.Effect.fail(
|
|
1510
2456
|
new ConfigModuleLoadError({
|
|
1511
2457
|
message: `Config module at ${filePath} default-exports a function; config factories are not supported. Export a config object instead (optionally wrapped in defineConfig).`,
|
|
1512
2458
|
filePath
|
|
@@ -1514,7 +2460,7 @@ var ConfigModuleLoader = class extends import_effect17.Effect.Service()("ConfigM
|
|
|
1514
2460
|
);
|
|
1515
2461
|
}
|
|
1516
2462
|
if (typeof mod !== "object" || mod === null || Array.isArray(mod)) {
|
|
1517
|
-
return yield*
|
|
2463
|
+
return yield* import_effect20.Effect.fail(
|
|
1518
2464
|
new ConfigModuleLoadError({
|
|
1519
2465
|
message: `Config module at ${filePath} must default-export a config object.`,
|
|
1520
2466
|
filePath
|
|
@@ -1544,36 +2490,36 @@ var ALLOWED_CONFIG_NAMES = [
|
|
|
1544
2490
|
"nebula.json"
|
|
1545
2491
|
];
|
|
1546
2492
|
var MODULE_EXTENSIONS = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
1547
|
-
var RawConfigReader = class extends
|
|
2493
|
+
var RawConfigReader = class extends import_effect21.Effect.Service()("RawConfigReader", {
|
|
1548
2494
|
dependencies: [ConfigModuleLoader.Default],
|
|
1549
|
-
effect:
|
|
1550
|
-
const fs = yield*
|
|
1551
|
-
const pathService = yield*
|
|
2495
|
+
effect: import_effect21.Effect.gen(function* () {
|
|
2496
|
+
const fs = yield* import_platform13.FileSystem.FileSystem;
|
|
2497
|
+
const pathService = yield* import_platform13.Path.Path;
|
|
1552
2498
|
const moduleLoader = yield* ConfigModuleLoader;
|
|
1553
|
-
const findConfig =
|
|
2499
|
+
const findConfig = import_effect21.Effect.fn("RawConfigReader.findConfig")(function* (projectFolder) {
|
|
1554
2500
|
for (const name of ALLOWED_CONFIG_NAMES) {
|
|
1555
2501
|
const filePath = pathService.join(projectFolder, name);
|
|
1556
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2502
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect21.Effect.catchAll(() => import_effect21.Effect.succeed(false)));
|
|
1557
2503
|
if (exists) {
|
|
1558
2504
|
return filePath;
|
|
1559
2505
|
}
|
|
1560
2506
|
}
|
|
1561
2507
|
return null;
|
|
1562
2508
|
});
|
|
1563
|
-
const readRawConfig =
|
|
1564
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2509
|
+
const readRawConfig = import_effect21.Effect.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
|
|
2510
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect21.Effect.catchAll(() => import_effect21.Effect.succeed(false)));
|
|
1565
2511
|
if (!exists) {
|
|
1566
|
-
return yield*
|
|
2512
|
+
return yield* import_effect21.Effect.fail(
|
|
1567
2513
|
new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
|
|
1568
2514
|
);
|
|
1569
2515
|
}
|
|
1570
2516
|
const fileContents = yield* fs.readFileString(filePath).pipe(
|
|
1571
|
-
|
|
2517
|
+
import_effect21.Effect.mapError(
|
|
1572
2518
|
() => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
|
|
1573
2519
|
)
|
|
1574
2520
|
);
|
|
1575
2521
|
if (fileContents.length === 0) {
|
|
1576
|
-
return yield*
|
|
2522
|
+
return yield* import_effect21.Effect.fail(
|
|
1577
2523
|
new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
|
|
1578
2524
|
);
|
|
1579
2525
|
}
|
|
@@ -1586,10 +2532,10 @@ var RawConfigReader = class extends import_effect18.Effect.Service()("RawConfigR
|
|
|
1586
2532
|
if (fileExtension === ".json") {
|
|
1587
2533
|
parsed = JSON.parse(fileContents);
|
|
1588
2534
|
} else {
|
|
1589
|
-
parsed = (0,
|
|
2535
|
+
parsed = (0, import_yaml2.parse)(fileContents);
|
|
1590
2536
|
}
|
|
1591
2537
|
} catch (error) {
|
|
1592
|
-
return yield*
|
|
2538
|
+
return yield* import_effect21.Effect.fail(
|
|
1593
2539
|
new ConfigFileParseError({
|
|
1594
2540
|
message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1595
2541
|
filePath,
|
|
@@ -1599,21 +2545,21 @@ var RawConfigReader = class extends import_effect18.Effect.Service()("RawConfigR
|
|
|
1599
2545
|
}
|
|
1600
2546
|
}
|
|
1601
2547
|
if (parsed == null) {
|
|
1602
|
-
return yield*
|
|
2548
|
+
return yield* import_effect21.Effect.fail(
|
|
1603
2549
|
new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
|
|
1604
2550
|
);
|
|
1605
2551
|
}
|
|
1606
2552
|
if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
|
|
1607
|
-
return yield*
|
|
2553
|
+
return yield* import_effect21.Effect.fail(
|
|
1608
2554
|
new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
|
|
1609
2555
|
);
|
|
1610
2556
|
}
|
|
1611
2557
|
return parsed;
|
|
1612
2558
|
});
|
|
1613
2559
|
const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
2560
|
+
import_effect21.Effect.map((parsed) => parsed),
|
|
2561
|
+
import_effect21.Effect.catchTag("ConfigFileNotFoundError", () => import_effect21.Effect.succeed(null)),
|
|
2562
|
+
import_effect21.Effect.withSpan("RawConfigReader.readConfigFile")
|
|
1617
2563
|
);
|
|
1618
2564
|
return { findConfig, readRawConfig, readConfigFile };
|
|
1619
2565
|
})
|
|
@@ -1623,17 +2569,17 @@ var RawConfigReader = class extends import_effect18.Effect.Service()("RawConfigR
|
|
|
1623
2569
|
// src/services/schema-validator.ts
|
|
1624
2570
|
var import_ajv = __toESM(require("ajv"));
|
|
1625
2571
|
var import_ajv_formats = __toESM(require("ajv-formats"));
|
|
1626
|
-
var
|
|
1627
|
-
var SchemaValidator = class extends
|
|
1628
|
-
effect:
|
|
2572
|
+
var import_effect22 = require("effect");
|
|
2573
|
+
var SchemaValidator = class extends import_effect22.Effect.Service()("SchemaValidator", {
|
|
2574
|
+
effect: import_effect22.Effect.gen(function* () {
|
|
1629
2575
|
const ajv = new import_ajv.default();
|
|
1630
2576
|
(0, import_ajv_formats.default)(ajv);
|
|
1631
|
-
const validate =
|
|
2577
|
+
const validate = import_effect22.Effect.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
|
|
1632
2578
|
const compiledValidate = ajv.compile(schema);
|
|
1633
2579
|
const valid = compiledValidate(config);
|
|
1634
2580
|
if (!valid) {
|
|
1635
2581
|
const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
|
|
1636
|
-
return yield*
|
|
2582
|
+
return yield* import_effect22.Effect.fail(
|
|
1637
2583
|
new ConfigSchemaValidationError({
|
|
1638
2584
|
message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
|
|
1639
2585
|
filePath,
|
|
@@ -1689,8 +2635,9 @@ var getFilesForPattern = async (pattern, projectFolder, excludeFiles = []) => {
|
|
|
1689
2635
|
};
|
|
1690
2636
|
|
|
1691
2637
|
// src/services/v4-config-parser.ts
|
|
1692
|
-
var
|
|
2638
|
+
var import_effect23 = require("effect");
|
|
1693
2639
|
var import_minimatch2 = require("minimatch");
|
|
2640
|
+
var import_node_path2 = require("path");
|
|
1694
2641
|
var import_safe_regex2 = __toESM(require("safe-regex2"));
|
|
1695
2642
|
var DEFAULT_FUNCTION_SETTINGS = {
|
|
1696
2643
|
memory: 128,
|
|
@@ -1723,6 +2670,46 @@ var normalizeImagePolicy = (images) => {
|
|
|
1723
2670
|
variants: images.variants ?? {}
|
|
1724
2671
|
};
|
|
1725
2672
|
};
|
|
2673
|
+
var DURATION_UNIT_SECONDS = { s: 1, m: 60, h: 3600, d: 86400 };
|
|
2674
|
+
var queueDurationSeconds = (value) => {
|
|
2675
|
+
if (value === void 0) return void 0;
|
|
2676
|
+
if (typeof value === "number") return value;
|
|
2677
|
+
const match = /^(\d+(?:\.\d+)?)(s|m|h|d)$/.exec(value);
|
|
2678
|
+
if (!match)
|
|
2679
|
+
throw new Error(`Invalid queue duration "${value}". Use seconds or a string such as 30s, 10m, 1.5h or 4d.`);
|
|
2680
|
+
return Math.ceil(Number(match[1]) * DURATION_UNIT_SECONDS[match[2]]);
|
|
2681
|
+
};
|
|
2682
|
+
var byName = (left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
|
|
2683
|
+
var definedOnly = (value) => Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
2684
|
+
var normalizeQueue = (name, queue) => {
|
|
2685
|
+
if (queue === null) return { name };
|
|
2686
|
+
const schedules = queue.schedules ? Object.entries(queue.schedules).map(
|
|
2687
|
+
([scheduleName, schedule]) => definedOnly({
|
|
2688
|
+
name: scheduleName,
|
|
2689
|
+
cron: schedule.cron,
|
|
2690
|
+
timezone: schedule.timezone,
|
|
2691
|
+
body: schedule.body === void 0 || typeof schedule.body === "string" ? schedule.body : JSON.stringify(schedule.body),
|
|
2692
|
+
// A plain-text body labelled JSON would fail to decode on every fire.
|
|
2693
|
+
contentType: schedule.contentType ?? (typeof schedule.body === "string" ? "text/plain; charset=utf-8" : void 0),
|
|
2694
|
+
headers: schedule.headers,
|
|
2695
|
+
enabled: schedule.enabled
|
|
2696
|
+
})
|
|
2697
|
+
).sort(byName) : void 0;
|
|
2698
|
+
return definedOnly({
|
|
2699
|
+
name,
|
|
2700
|
+
consumer: queue.consumer,
|
|
2701
|
+
visibilityTimeoutSeconds: queueDurationSeconds(queue.visibilityTimeout),
|
|
2702
|
+
retentionSeconds: queueDurationSeconds(queue.retention),
|
|
2703
|
+
maxAttempts: queue.maxAttempts,
|
|
2704
|
+
retryBackoffMinSeconds: queueDurationSeconds(queue.retryBackoff?.min),
|
|
2705
|
+
retryBackoffMaxSeconds: queueDurationSeconds(queue.retryBackoff?.max),
|
|
2706
|
+
deduplicationWindowSeconds: queueDurationSeconds(queue.deduplicationWindow),
|
|
2707
|
+
concurrency: queue.concurrency,
|
|
2708
|
+
rateLimit: queue.rateLimit == null ? queue.rateLimit : { count: queue.rateLimit.count, periodSeconds: queueDurationSeconds(queue.rateLimit.period) ?? 1 },
|
|
2709
|
+
deadLetter: queue.deadLetter,
|
|
2710
|
+
schedules
|
|
2711
|
+
});
|
|
2712
|
+
};
|
|
1726
2713
|
var normalizeServices = (services) => {
|
|
1727
2714
|
if (services == null) return void 0;
|
|
1728
2715
|
const normalized = [];
|
|
@@ -1735,7 +2722,13 @@ var normalizeServices = (services) => {
|
|
|
1735
2722
|
if (services.storage !== void 0) {
|
|
1736
2723
|
normalized.push({
|
|
1737
2724
|
type: "storage",
|
|
1738
|
-
buckets: Object.entries(services.storage.buckets).map(([name, bucket]) => ({ name, visibility: bucket?.visibility ?? "private" })).sort(
|
|
2725
|
+
buckets: Object.entries(services.storage.buckets).map(([name, bucket]) => ({ name, visibility: bucket?.visibility ?? "private" })).sort(byName)
|
|
2726
|
+
});
|
|
2727
|
+
}
|
|
2728
|
+
if (services.queues !== void 0) {
|
|
2729
|
+
normalized.push({
|
|
2730
|
+
type: "queues",
|
|
2731
|
+
queues: Object.entries(services.queues).map(([name, queue]) => normalizeQueue(name, queue)).sort(byName)
|
|
1739
2732
|
});
|
|
1740
2733
|
}
|
|
1741
2734
|
return normalized.length > 0 ? normalized : void 0;
|
|
@@ -1793,9 +2786,10 @@ var mapRoute = (route, entrypoints) => ({
|
|
|
1793
2786
|
negativeRequirements: route.missing,
|
|
1794
2787
|
status: route.statusCode
|
|
1795
2788
|
});
|
|
1796
|
-
var parseEntrypoints =
|
|
2789
|
+
var parseEntrypoints = import_effect23.Effect.fn("parseEntrypoints")(function* (config, projectFolder) {
|
|
1797
2790
|
const entrypoints = [];
|
|
1798
|
-
|
|
2791
|
+
const dockerFunctions = [];
|
|
2792
|
+
if (config.functions == null) return { entrypoints, dockerFunctions };
|
|
1799
2793
|
for (const [fnPath, func] of Object.entries(config.functions)) {
|
|
1800
2794
|
if (getFunctionSettings(fnPath, config) == null) {
|
|
1801
2795
|
return yield* new FunctionConfigError({
|
|
@@ -1803,7 +2797,7 @@ var parseEntrypoints = import_effect20.Effect.fn("parseEntrypoints")(function* (
|
|
|
1803
2797
|
functionPath: fnPath
|
|
1804
2798
|
});
|
|
1805
2799
|
}
|
|
1806
|
-
const matchedFiles = yield*
|
|
2800
|
+
const matchedFiles = yield* import_effect23.Effect.tryPromise({
|
|
1807
2801
|
try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
|
|
1808
2802
|
catch: (error) => new FunctionConfigError({
|
|
1809
2803
|
message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -1820,6 +2814,35 @@ var parseEntrypoints = import_effect20.Effect.fn("parseEntrypoints")(function* (
|
|
|
1820
2814
|
functionPath: file
|
|
1821
2815
|
});
|
|
1822
2816
|
}
|
|
2817
|
+
if (settings.runtime === CONTAINER_RUNTIME) {
|
|
2818
|
+
const unsupported = ["symlinks", "includeFiles"].filter((key) => settings[key] !== void 0);
|
|
2819
|
+
if (unsupported.length > 0) {
|
|
2820
|
+
return yield* new FunctionConfigError({
|
|
2821
|
+
message: `Function '${file}' runs a Dockerfile, so ${unsupported.join(" and ")} do not apply. Copy files in the Dockerfile instead.`,
|
|
2822
|
+
functionPath: file
|
|
2823
|
+
});
|
|
2824
|
+
}
|
|
2825
|
+
const declared = Object.entries(config.functions).filter(([pattern]) => matchesPattern(file, pattern)).reduce((merged, [, value]) => ({ ...merged, ...value }), {});
|
|
2826
|
+
dockerFunctions.push({
|
|
2827
|
+
file,
|
|
2828
|
+
name: dockerFunctionContainerName(file),
|
|
2829
|
+
container: {
|
|
2830
|
+
build: { context: import_node_path2.posix.dirname(file), dockerfile: import_node_path2.posix.basename(file) },
|
|
2831
|
+
...declared.port !== void 0 && { port: declared.port },
|
|
2832
|
+
...declared.memory !== void 0 && { memory: declared.memory },
|
|
2833
|
+
...declared.max_duration !== void 0 && { max_duration: declared.max_duration },
|
|
2834
|
+
...declared.streaming !== void 0 && { streaming: declared.streaming },
|
|
2835
|
+
...func.schedule !== void 0 && { schedule: func.schedule }
|
|
2836
|
+
}
|
|
2837
|
+
});
|
|
2838
|
+
continue;
|
|
2839
|
+
}
|
|
2840
|
+
if (settings.port !== void 0) {
|
|
2841
|
+
return yield* new FunctionConfigError({
|
|
2842
|
+
message: `Function '${file}' sets port, which only applies to 'runtime: docker'.`,
|
|
2843
|
+
functionPath: file
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
1823
2846
|
const runtime = settings.runtime ?? "node-20";
|
|
1824
2847
|
const streaming = settings.streaming ?? runtimeStreamsByDefault(runtime);
|
|
1825
2848
|
entrypoints.push({
|
|
@@ -1837,25 +2860,84 @@ var parseEntrypoints = import_effect20.Effect.fn("parseEntrypoints")(function* (
|
|
|
1837
2860
|
});
|
|
1838
2861
|
}
|
|
1839
2862
|
}
|
|
1840
|
-
|
|
2863
|
+
dockerFunctions.sort((left, right) => left.file < right.file ? -1 : left.file > right.file ? 1 : 0);
|
|
2864
|
+
for (const [index, { file, name }] of dockerFunctions.entries()) {
|
|
2865
|
+
const clash = dockerFunctions.slice(0, index).find((candidate) => candidate.name === name);
|
|
2866
|
+
if (clash !== void 0) {
|
|
2867
|
+
return yield* new FunctionConfigError({
|
|
2868
|
+
message: `Functions '${clash.file}' and '${file}' would both be named '${name}'. Declare one of them under 'containers' with an explicit name.`,
|
|
2869
|
+
functionPath: file
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
return { entrypoints, dockerFunctions };
|
|
1841
2874
|
});
|
|
1842
|
-
var collectAssets =
|
|
2875
|
+
var collectAssets = import_effect23.Effect.fn("collectAssets")(function* (config, projectFolder) {
|
|
1843
2876
|
if (config.assets == null) return [];
|
|
1844
2877
|
const assetNames = yield* collectAssetFiles(projectFolder, config.assets);
|
|
1845
2878
|
return assetNames.filter((assetName) => getFunctionSettings(`${config.assets}/${assetName}`, config) == null).map((assetName) => `${config.assets}/${assetName}`);
|
|
1846
2879
|
});
|
|
1847
|
-
var
|
|
2880
|
+
var reservedRuntimePorts = (entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME ? [] : entrypoint.runtime.startsWith("php-") ? [8080, 9e3] : [8080];
|
|
2881
|
+
var parseContainers = import_effect23.Effect.fn("parseContainers")(function* (config, projectFolder, fileEntrypoints, dockerFunctions) {
|
|
2882
|
+
const warnings = [];
|
|
2883
|
+
let containers = {};
|
|
2884
|
+
if (config.compose != null) {
|
|
2885
|
+
const imported = yield* readComposeContainers(config.compose, projectFolder);
|
|
2886
|
+
containers = imported.containers;
|
|
2887
|
+
warnings.push(...imported.warnings);
|
|
2888
|
+
}
|
|
2889
|
+
containers = { ...containers, ...config.containers ?? {} };
|
|
2890
|
+
for (const { file, name, container } of dockerFunctions) {
|
|
2891
|
+
if (containers[name] !== void 0) {
|
|
2892
|
+
return yield* new ContainerConfigError({
|
|
2893
|
+
message: `Function '${file}' runs as container '${name}', which 'containers' or the Compose file already declares. Rename one of them.`,
|
|
2894
|
+
containerName: name
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
containers[name] = container;
|
|
2898
|
+
}
|
|
2899
|
+
const result = yield* normalizeContainers(containers, projectFolder);
|
|
2900
|
+
warnings.push(...result.warnings);
|
|
2901
|
+
for (const entrypoint of fileEntrypoints) {
|
|
2902
|
+
for (const port of reservedRuntimePorts(entrypoint)) {
|
|
2903
|
+
const sidecar = result.sidecars.find((candidate) => candidate.port === port);
|
|
2904
|
+
if (sidecar !== void 0) {
|
|
2905
|
+
return yield* new ContainerConfigError({
|
|
2906
|
+
message: `Sidecar '${sidecar.name}' listens on port ${port}, which the ${entrypoint.runtime} runtime of '${entrypoint.path}' uses inside the same microVM. Choose another port.`,
|
|
2907
|
+
containerName: sidecar.name
|
|
2908
|
+
});
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
return { ...result, warnings };
|
|
2913
|
+
});
|
|
2914
|
+
var V4ConfigParser = class extends import_effect23.Effect.Service()("V4ConfigParser", {
|
|
1848
2915
|
accessors: true,
|
|
1849
|
-
effect:
|
|
2916
|
+
effect: import_effect23.Effect.succeed({
|
|
1850
2917
|
/**
|
|
1851
2918
|
* Parses a ConfigV4 into a NormalizedConfig.
|
|
1852
2919
|
*
|
|
1853
2920
|
* @param config - The raw V4 config object
|
|
1854
2921
|
* @param projectFolder - Absolute path to the project root
|
|
1855
2922
|
*/
|
|
1856
|
-
parse:
|
|
1857
|
-
const entrypoints = yield* parseEntrypoints(config, projectFolder);
|
|
2923
|
+
parse: import_effect23.Effect.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
|
|
2924
|
+
const { entrypoints: fileEntrypoints, dockerFunctions } = yield* parseEntrypoints(config, projectFolder);
|
|
2925
|
+
const containers = yield* parseContainers(config, projectFolder, fileEntrypoints, dockerFunctions);
|
|
2926
|
+
const entrypoints = [...fileEntrypoints, ...containers.entrypoints];
|
|
1858
2927
|
const assets = yield* collectAssets(config, projectFolder);
|
|
2928
|
+
const dockerFunctionPaths = new Map(
|
|
2929
|
+
dockerFunctions.map(({ file, name }) => [file, containerEntrypointPath(name)])
|
|
2930
|
+
);
|
|
2931
|
+
const routes = (config.routes ?? []).map(
|
|
2932
|
+
(route) => mapRoute(
|
|
2933
|
+
{
|
|
2934
|
+
...route,
|
|
2935
|
+
destination: dockerFunctionPaths.get(normalizeRouteDestination(route.destination)) ?? route.destination
|
|
2936
|
+
},
|
|
2937
|
+
entrypoints
|
|
2938
|
+
)
|
|
2939
|
+
);
|
|
2940
|
+
const warnings = [...containers.warnings];
|
|
1859
2941
|
return {
|
|
1860
2942
|
regions: resolveRegions(config.regions),
|
|
1861
2943
|
assets: {
|
|
@@ -1868,10 +2950,11 @@ var V4ConfigParser = class extends import_effect20.Effect.Service()("V4ConfigPar
|
|
|
1868
2950
|
commands: config.build_commands ?? [],
|
|
1869
2951
|
images: normalizeImagePolicy(config.images),
|
|
1870
2952
|
services: normalizeServices(config.services),
|
|
2953
|
+
...containers.sidecars.length > 0 && { sidecars: containers.sidecars },
|
|
1871
2954
|
entrypoints,
|
|
1872
2955
|
errors: [],
|
|
1873
|
-
warnings
|
|
1874
|
-
routes
|
|
2956
|
+
warnings,
|
|
2957
|
+
routes
|
|
1875
2958
|
};
|
|
1876
2959
|
})
|
|
1877
2960
|
})
|
|
@@ -1879,7 +2962,7 @@ var V4ConfigParser = class extends import_effect20.Effect.Service()("V4ConfigPar
|
|
|
1879
2962
|
};
|
|
1880
2963
|
|
|
1881
2964
|
// src/services/vercel-build-output-parser.ts
|
|
1882
|
-
var
|
|
2965
|
+
var import_platform14 = require("@effect/platform");
|
|
1883
2966
|
|
|
1884
2967
|
// ../commons/src/deep-merge.ts
|
|
1885
2968
|
var deepMerge = (target, ...partials) => {
|
|
@@ -1908,7 +2991,7 @@ var deepMerge = (target, ...partials) => {
|
|
|
1908
2991
|
};
|
|
1909
2992
|
|
|
1910
2993
|
// src/services/vercel-build-output-parser.ts
|
|
1911
|
-
var
|
|
2994
|
+
var import_effect24 = require("effect");
|
|
1912
2995
|
|
|
1913
2996
|
// src/build-output-v3/determine-repo-root.ts
|
|
1914
2997
|
var import_path = __toESM(require("path"));
|
|
@@ -2004,11 +3087,11 @@ var translateVercelRuntime = (runtime) => {
|
|
|
2004
3087
|
var CONFIG_PATH = ".vercel/output/config.json";
|
|
2005
3088
|
var FUNCTIONS_FOLDER = ".vercel/output/functions";
|
|
2006
3089
|
var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
|
|
2007
|
-
var VercelBuildOutputParser = class extends
|
|
2008
|
-
effect:
|
|
3090
|
+
var VercelBuildOutputParser = class extends import_effect24.Effect.Service()("VercelBuildOutputParser", {
|
|
3091
|
+
effect: import_effect24.Effect.gen(function* () {
|
|
2009
3092
|
const rawConfigReader = yield* RawConfigReader;
|
|
2010
|
-
const pathService = yield*
|
|
2011
|
-
const parse =
|
|
3093
|
+
const pathService = yield* import_platform14.Path.Path;
|
|
3094
|
+
const parse = import_effect24.Effect.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
|
|
2012
3095
|
const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
|
|
2013
3096
|
if (!config || typeof config.version !== "number" || config.version < 3) {
|
|
2014
3097
|
return parseResult;
|
|
@@ -2020,8 +3103,8 @@ var VercelBuildOutputParser = class extends import_effect21.Effect.Service()("Ve
|
|
|
2020
3103
|
merged.regions = [...new Set(merged.regions)];
|
|
2021
3104
|
return merged;
|
|
2022
3105
|
});
|
|
2023
|
-
const loadFunctions =
|
|
2024
|
-
const functionConfigs = yield*
|
|
3106
|
+
const loadFunctions = import_effect24.Effect.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
|
|
3107
|
+
const functionConfigs = yield* import_effect24.Effect.tryPromise({
|
|
2025
3108
|
try: () => getFilesForPattern(FUNCTION_CONFIGS_PATTERN, projectFolder),
|
|
2026
3109
|
catch: (error) => new ConfigFileParseError({
|
|
2027
3110
|
message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -2307,17 +3390,22 @@ var schema_default = {
|
|
|
2307
3390
|
minimum: 1
|
|
2308
3391
|
},
|
|
2309
3392
|
runtime: {
|
|
2310
|
-
$ref: "#/$defs/runtimes",
|
|
2311
|
-
description: "The runtime to use for the function."
|
|
3393
|
+
anyOf: [{ $ref: "#/$defs/runtimes" }, { const: "docker" }],
|
|
3394
|
+
description: "The runtime to use for the function. `docker` builds the matched file as a Dockerfile, with its directory as the build context, and runs the image as the function."
|
|
3395
|
+
},
|
|
3396
|
+
port: {
|
|
3397
|
+
type: "integer",
|
|
3398
|
+
minimum: 1,
|
|
3399
|
+
maximum: 65535,
|
|
3400
|
+
description: "TCP port the image listens on. Only for `runtime: docker`. Defaults to the first exposed port of the image, then 8080."
|
|
2312
3401
|
},
|
|
2313
3402
|
streaming: {
|
|
2314
3403
|
type: "boolean",
|
|
2315
3404
|
description: "Enable function response streaming. When omitted, Node and Bun runtimes stream by default."
|
|
2316
3405
|
},
|
|
2317
3406
|
schedule: {
|
|
2318
|
-
|
|
2319
|
-
description: "An expression to schedule the function to run at specific times."
|
|
2320
|
-
pattern: "^(?:rate[(](?:(?:1[ ]+(hour|minute|day))|(?:[0-9]+[ ]+(hours|minutes|days)))[)])|(?:cron[(](?:(?:(?:[0-5]?[0-9])|[*])(?:(?:[-](?:(?:[0-5]?[0-9])|[*]))|(?:[/][0-9]+))?(?:[,](?:(?:[0-5]?[0-9])|[*])(?:(?:[-](?:(?:[0-5]?[0-9])|[*]))|(?:[/][0-9]+))?)*)[ ]+(?:(?:(?:[0-2]?[0-9])|[*])(?:(?:[-](?:(?:[0-2]?[0-9])|[*]))|(?:[/][0-9]+))?(?:[,](?:(?:[0-2]?[0-9])|[*])(?:(?:[-](?:(?:[0-2]?[0-9])|[*]))|(?:[/][0-9]+))?)*)[ ]+(?:(?:[?][ ]+(?:(?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?(?:[,](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?)*)[ ]+(?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))[#][0-5])|(?:(?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*])(?:(?:[-](?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*]))|(?:[/][0-9]+))?(?:[,](?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*])(?:(?:[-](?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*]))|(?:[/][0-9]+))?)*)))|(?:(?:(?:(?:(?:[1-3]?[0-9])W?)|LW|[L*])(?:(?:[-](?:(?:(?:[1-3]?[0-9])W?)|LW|[L*]))|(?:[/][0-9]+))?(?:[,](?:(?:(?:[1-3]?[0-9])W?)|LW|[L*])(?:(?:[-](?:(?:(?:[1-3]?[0-9])W?)|LW|[L*]))|(?:[/][0-9]+))?)*)[ ]+(?:(?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?(?:[,](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?)*)[ ]+[?]))[ ]+(?:(?:(?:[12][0-9]{3})|[*])(?:(?:[-](?:(?:[12][0-9]{3})|[*]))|(?:[/][0-9]+))?(?:[,](?:(?:[12][0-9]{3})|[*])(?:(?:[-](?:(?:[12][0-9]{3})|[*]))|(?:[/][0-9]+))?)*)[)])$"
|
|
3407
|
+
$ref: "#/$defs/schedule",
|
|
3408
|
+
description: "An expression to schedule the function to run at specific times."
|
|
2321
3409
|
},
|
|
2322
3410
|
symlinks: {
|
|
2323
3411
|
type: "object",
|
|
@@ -2409,6 +3497,151 @@ var schema_default = {
|
|
|
2409
3497
|
}
|
|
2410
3498
|
}
|
|
2411
3499
|
},
|
|
3500
|
+
compose: {
|
|
3501
|
+
type: ["string", "null"],
|
|
3502
|
+
minLength: 1,
|
|
3503
|
+
maxLength: 1024,
|
|
3504
|
+
description: "Project-relative path of a Compose file whose services are imported as containers. Entries in `containers` win over imported services of the same name."
|
|
3505
|
+
},
|
|
3506
|
+
containers: {
|
|
3507
|
+
type: ["object", "null"],
|
|
3508
|
+
description: "Container images to run, keyed by name. A container runs as a function unless `sidecar` is true; routes target it with `destination: container:<name>`. A sidecar runs next to every function instance and answers at `<name>:<port>`.",
|
|
3509
|
+
maxProperties: 16,
|
|
3510
|
+
propertyNames: {
|
|
3511
|
+
pattern: "^[a-z][a-z0-9_-]{0,62}$",
|
|
3512
|
+
not: {
|
|
3513
|
+
enum: ["localhost"]
|
|
3514
|
+
}
|
|
3515
|
+
},
|
|
3516
|
+
additionalProperties: {
|
|
3517
|
+
type: "object",
|
|
3518
|
+
additionalProperties: false,
|
|
3519
|
+
oneOf: [
|
|
3520
|
+
{
|
|
3521
|
+
required: ["image"]
|
|
3522
|
+
},
|
|
3523
|
+
{
|
|
3524
|
+
required: ["build"]
|
|
3525
|
+
}
|
|
3526
|
+
],
|
|
3527
|
+
properties: {
|
|
3528
|
+
image: {
|
|
3529
|
+
type: "string",
|
|
3530
|
+
minLength: 1,
|
|
3531
|
+
maxLength: 512,
|
|
3532
|
+
pattern: "^[^\\s]+$",
|
|
3533
|
+
description: "Registry image reference, e.g. `redis:7-alpine` or `ghcr.io/acme/api:1.4`."
|
|
3534
|
+
},
|
|
3535
|
+
build: {
|
|
3536
|
+
description: "Build context directory, or the full build settings, for a Dockerfile in the repository.",
|
|
3537
|
+
oneOf: [
|
|
3538
|
+
{
|
|
3539
|
+
type: "string",
|
|
3540
|
+
minLength: 1,
|
|
3541
|
+
maxLength: 1024
|
|
3542
|
+
},
|
|
3543
|
+
{
|
|
3544
|
+
type: "object",
|
|
3545
|
+
additionalProperties: false,
|
|
3546
|
+
properties: {
|
|
3547
|
+
context: {
|
|
3548
|
+
type: "string",
|
|
3549
|
+
minLength: 1,
|
|
3550
|
+
maxLength: 1024
|
|
3551
|
+
},
|
|
3552
|
+
dockerfile: {
|
|
3553
|
+
type: "string",
|
|
3554
|
+
minLength: 1,
|
|
3555
|
+
maxLength: 1024
|
|
3556
|
+
},
|
|
3557
|
+
target: {
|
|
3558
|
+
type: "string",
|
|
3559
|
+
minLength: 1,
|
|
3560
|
+
maxLength: 128
|
|
3561
|
+
},
|
|
3562
|
+
args: {
|
|
3563
|
+
type: "object",
|
|
3564
|
+
maxProperties: 100,
|
|
3565
|
+
additionalProperties: {
|
|
3566
|
+
type: "string",
|
|
3567
|
+
maxLength: 65536
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
]
|
|
3573
|
+
},
|
|
3574
|
+
sidecar: {
|
|
3575
|
+
type: "boolean",
|
|
3576
|
+
description: "Run next to every function instance instead of serving routes. Defaults to false."
|
|
3577
|
+
},
|
|
3578
|
+
port: {
|
|
3579
|
+
type: "integer",
|
|
3580
|
+
minimum: 1,
|
|
3581
|
+
maximum: 65535,
|
|
3582
|
+
description: "TCP port the container listens on. Defaults to the first exposed port of the image, then 8080."
|
|
3583
|
+
},
|
|
3584
|
+
entrypoint: {
|
|
3585
|
+
$ref: "#/$defs/stringOrStringArray",
|
|
3586
|
+
description: "Replaces the image ENTRYPOINT. A string is split into words the way Compose splits it."
|
|
3587
|
+
},
|
|
3588
|
+
command: {
|
|
3589
|
+
$ref: "#/$defs/stringOrStringArray",
|
|
3590
|
+
description: "Replaces the image CMD. A string is split into words the way Compose splits it."
|
|
3591
|
+
},
|
|
3592
|
+
env: {
|
|
3593
|
+
type: "object",
|
|
3594
|
+
maxProperties: 100,
|
|
3595
|
+
additionalProperties: {
|
|
3596
|
+
type: "string",
|
|
3597
|
+
maxLength: 65536
|
|
3598
|
+
},
|
|
3599
|
+
description: "Environment variables baked into the container, merged over the image ENV."
|
|
3600
|
+
},
|
|
3601
|
+
working_dir: {
|
|
3602
|
+
type: "string",
|
|
3603
|
+
minLength: 1,
|
|
3604
|
+
maxLength: 1024,
|
|
3605
|
+
pattern: "^/",
|
|
3606
|
+
description: "Replaces the image WORKDIR. Must be absolute."
|
|
3607
|
+
},
|
|
3608
|
+
user: {
|
|
3609
|
+
oneOf: [
|
|
3610
|
+
{
|
|
3611
|
+
type: "string",
|
|
3612
|
+
minLength: 1,
|
|
3613
|
+
maxLength: 256
|
|
3614
|
+
},
|
|
3615
|
+
{
|
|
3616
|
+
type: "integer",
|
|
3617
|
+
minimum: 0
|
|
3618
|
+
}
|
|
3619
|
+
],
|
|
3620
|
+
description: "Replaces the image USER: a name, a uid, `name:group` or `uid:gid`. A bare uid may be a number."
|
|
3621
|
+
},
|
|
3622
|
+
memory: {
|
|
3623
|
+
type: "integer",
|
|
3624
|
+
minimum: 128,
|
|
3625
|
+
maximum: 3009,
|
|
3626
|
+
description: "Memory in MB. Defaults to 512 for a container function and 256 for a sidecar."
|
|
3627
|
+
},
|
|
3628
|
+
max_duration: {
|
|
3629
|
+
type: "number",
|
|
3630
|
+
minimum: 1,
|
|
3631
|
+
maximum: 28800,
|
|
3632
|
+
description: "Maximum lifetime in seconds of one request. Container functions only."
|
|
3633
|
+
},
|
|
3634
|
+
streaming: {
|
|
3635
|
+
type: "boolean",
|
|
3636
|
+
description: "Stream responses. Defaults to true. Container functions only."
|
|
3637
|
+
},
|
|
3638
|
+
schedule: {
|
|
3639
|
+
$ref: "#/$defs/schedule",
|
|
3640
|
+
description: "An expression to run the container function at specific times. Container functions only."
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
},
|
|
2412
3645
|
services: {
|
|
2413
3646
|
type: "object",
|
|
2414
3647
|
description: "Managed services to provision for the deployment environment.",
|
|
@@ -2559,11 +3792,179 @@ var schema_default = {
|
|
|
2559
3792
|
}
|
|
2560
3793
|
}
|
|
2561
3794
|
}
|
|
3795
|
+
},
|
|
3796
|
+
queues: {
|
|
3797
|
+
type: "object",
|
|
3798
|
+
description: "Queues to provision in the deployment environment, keyed by name. Use null for a pull queue with default settings. Queues you stop declaring are kept, with their messages.",
|
|
3799
|
+
propertyNames: {
|
|
3800
|
+
maxLength: 255,
|
|
3801
|
+
pattern: "^[A-Za-z0-9_][A-Za-z0-9_.~:@+=-]*$"
|
|
3802
|
+
},
|
|
3803
|
+
additionalProperties: {
|
|
3804
|
+
oneOf: [
|
|
3805
|
+
{
|
|
3806
|
+
type: "null"
|
|
3807
|
+
},
|
|
3808
|
+
{
|
|
3809
|
+
type: "object",
|
|
3810
|
+
additionalProperties: false,
|
|
3811
|
+
properties: {
|
|
3812
|
+
consumer: {
|
|
3813
|
+
type: ["string", "null"],
|
|
3814
|
+
pattern: "^/(?!/)\\S*$",
|
|
3815
|
+
maxLength: 2048,
|
|
3816
|
+
description: "Deployment-relative path that receives each message as a signed POST, for example /api/queues/emails. Omit it for a pull queue that you drain with receive."
|
|
3817
|
+
},
|
|
3818
|
+
visibilityTimeout: {
|
|
3819
|
+
$ref: "#/$defs/queueDuration",
|
|
3820
|
+
description: "How long a push delivery may run, or how long a received message stays leased. Defaults to 60 seconds, at most 12 hours."
|
|
3821
|
+
},
|
|
3822
|
+
retention: {
|
|
3823
|
+
$ref: "#/$defs/queueDuration",
|
|
3824
|
+
description: "How long an undelivered message is kept. Defaults to 4 days, at most 14 days."
|
|
3825
|
+
},
|
|
3826
|
+
maxAttempts: {
|
|
3827
|
+
type: "integer",
|
|
3828
|
+
minimum: 1,
|
|
3829
|
+
maximum: 100,
|
|
3830
|
+
description: "Deliveries per message before it moves to the dead-letter list. Defaults to 10."
|
|
3831
|
+
},
|
|
3832
|
+
retryBackoff: {
|
|
3833
|
+
type: "object",
|
|
3834
|
+
additionalProperties: false,
|
|
3835
|
+
description: "Exponential backoff between failed deliveries. Defaults to 5 seconds, doubling up to 15 minutes.",
|
|
3836
|
+
properties: {
|
|
3837
|
+
min: {
|
|
3838
|
+
$ref: "#/$defs/queueDuration"
|
|
3839
|
+
},
|
|
3840
|
+
max: {
|
|
3841
|
+
$ref: "#/$defs/queueDuration"
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
},
|
|
3845
|
+
deduplicationWindow: {
|
|
3846
|
+
$ref: "#/$defs/queueDuration",
|
|
3847
|
+
description: "How long a deduplication key is remembered. Defaults to 24 hours, at most 7 days."
|
|
3848
|
+
},
|
|
3849
|
+
concurrency: {
|
|
3850
|
+
type: ["integer", "null"],
|
|
3851
|
+
minimum: 1,
|
|
3852
|
+
maximum: 1e3,
|
|
3853
|
+
description: "Most push deliveries in flight at once. Defaults to 100."
|
|
3854
|
+
},
|
|
3855
|
+
rateLimit: {
|
|
3856
|
+
oneOf: [
|
|
3857
|
+
{
|
|
3858
|
+
type: "null"
|
|
3859
|
+
},
|
|
3860
|
+
{
|
|
3861
|
+
type: "object",
|
|
3862
|
+
required: ["count"],
|
|
3863
|
+
additionalProperties: false,
|
|
3864
|
+
properties: {
|
|
3865
|
+
count: {
|
|
3866
|
+
type: "integer",
|
|
3867
|
+
minimum: 1,
|
|
3868
|
+
maximum: 1e6
|
|
3869
|
+
},
|
|
3870
|
+
period: {
|
|
3871
|
+
$ref: "#/$defs/queueDuration"
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
],
|
|
3876
|
+
description: "Most deliveries started per period. The period defaults to one second."
|
|
3877
|
+
},
|
|
3878
|
+
deadLetter: {
|
|
3879
|
+
type: "boolean",
|
|
3880
|
+
description: "Keep messages that run out of attempts so you can inspect and redrive them. Defaults to true."
|
|
3881
|
+
},
|
|
3882
|
+
schedules: {
|
|
3883
|
+
type: "object",
|
|
3884
|
+
description: "Cron schedules that send a message into this queue, keyed by schedule name.",
|
|
3885
|
+
propertyNames: {
|
|
3886
|
+
maxLength: 128,
|
|
3887
|
+
pattern: "^[A-Za-z0-9_][A-Za-z0-9_.-]*$"
|
|
3888
|
+
},
|
|
3889
|
+
additionalProperties: {
|
|
3890
|
+
type: "object",
|
|
3891
|
+
required: ["cron"],
|
|
3892
|
+
additionalProperties: false,
|
|
3893
|
+
properties: {
|
|
3894
|
+
cron: {
|
|
3895
|
+
type: "string",
|
|
3896
|
+
minLength: 1,
|
|
3897
|
+
maxLength: 255,
|
|
3898
|
+
description: "Five-field cron expression, or a macro such as @hourly or @daily."
|
|
3899
|
+
},
|
|
3900
|
+
timezone: {
|
|
3901
|
+
type: "string",
|
|
3902
|
+
description: "IANA time zone the expression is evaluated in. Defaults to UTC."
|
|
3903
|
+
},
|
|
3904
|
+
body: {
|
|
3905
|
+
description: "Message body. Strings are sent as is; any other value is sent as JSON."
|
|
3906
|
+
},
|
|
3907
|
+
contentType: {
|
|
3908
|
+
type: "string",
|
|
3909
|
+
description: "Content type of the body. Defaults to text/plain for a string body and application/json otherwise."
|
|
3910
|
+
},
|
|
3911
|
+
headers: {
|
|
3912
|
+
type: "object",
|
|
3913
|
+
additionalProperties: {
|
|
3914
|
+
type: "string"
|
|
3915
|
+
},
|
|
3916
|
+
description: "Headers delivered with every message from this schedule."
|
|
3917
|
+
},
|
|
3918
|
+
enabled: {
|
|
3919
|
+
type: "boolean",
|
|
3920
|
+
description: "Set to false to keep the schedule without sending. Defaults to true."
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
]
|
|
3928
|
+
}
|
|
2562
3929
|
}
|
|
2563
3930
|
}
|
|
2564
3931
|
}
|
|
2565
3932
|
},
|
|
2566
3933
|
$defs: {
|
|
3934
|
+
schedule: {
|
|
3935
|
+
type: "string",
|
|
3936
|
+
pattern: "^(?:rate[(](?:(?:1[ ]+(hour|minute|day))|(?:[0-9]+[ ]+(hours|minutes|days)))[)])|(?:cron[(](?:(?:(?:[0-5]?[0-9])|[*])(?:(?:[-](?:(?:[0-5]?[0-9])|[*]))|(?:[/][0-9]+))?(?:[,](?:(?:[0-5]?[0-9])|[*])(?:(?:[-](?:(?:[0-5]?[0-9])|[*]))|(?:[/][0-9]+))?)*)[ ]+(?:(?:(?:[0-2]?[0-9])|[*])(?:(?:[-](?:(?:[0-2]?[0-9])|[*]))|(?:[/][0-9]+))?(?:[,](?:(?:[0-2]?[0-9])|[*])(?:(?:[-](?:(?:[0-2]?[0-9])|[*]))|(?:[/][0-9]+))?)*)[ ]+(?:(?:[?][ ]+(?:(?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?(?:[,](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?)*)[ ]+(?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))[#][0-5])|(?:(?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*])(?:(?:[-](?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*]))|(?:[/][0-9]+))?(?:[,](?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*])(?:(?:[-](?:(?:(?:[1-7]|(?:SUN|MON|TUE|WED|THU|FRI|SAT))L?)|[L*]))|(?:[/][0-9]+))?)*)))|(?:(?:(?:(?:(?:[1-3]?[0-9])W?)|LW|[L*])(?:(?:[-](?:(?:(?:[1-3]?[0-9])W?)|LW|[L*]))|(?:[/][0-9]+))?(?:[,](?:(?:(?:[1-3]?[0-9])W?)|LW|[L*])(?:(?:[-](?:(?:(?:[1-3]?[0-9])W?)|LW|[L*]))|(?:[/][0-9]+))?)*)[ ]+(?:(?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?(?:[,](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:(?:[-](?:(?:[1]?[0-9])|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|[*])(?:[/][0-9]+)?)|(?:[/][0-9]+))?)*)[ ]+[?]))[ ]+(?:(?:(?:[12][0-9]{3})|[*])(?:(?:[-](?:(?:[12][0-9]{3})|[*]))|(?:[/][0-9]+))?(?:[,](?:(?:[12][0-9]{3})|[*])(?:(?:[-](?:(?:[12][0-9]{3})|[*]))|(?:[/][0-9]+))?)*)[)])$"
|
|
3937
|
+
},
|
|
3938
|
+
stringOrStringArray: {
|
|
3939
|
+
oneOf: [
|
|
3940
|
+
{
|
|
3941
|
+
type: "string",
|
|
3942
|
+
minLength: 1,
|
|
3943
|
+
maxLength: 4096
|
|
3944
|
+
},
|
|
3945
|
+
{
|
|
3946
|
+
type: "array",
|
|
3947
|
+
maxItems: 256,
|
|
3948
|
+
items: {
|
|
3949
|
+
type: "string",
|
|
3950
|
+
maxLength: 4096
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3953
|
+
]
|
|
3954
|
+
},
|
|
3955
|
+
queueDuration: {
|
|
3956
|
+
oneOf: [
|
|
3957
|
+
{
|
|
3958
|
+
type: "integer",
|
|
3959
|
+
minimum: 0
|
|
3960
|
+
},
|
|
3961
|
+
{
|
|
3962
|
+
type: "string",
|
|
3963
|
+
pattern: "^[0-9]+(\\.[0-9]+)?(s|m|h|d)$"
|
|
3964
|
+
}
|
|
3965
|
+
],
|
|
3966
|
+
description: "A duration in seconds, or a string such as 30s, 10m, 1.5h or 4d."
|
|
3967
|
+
},
|
|
2567
3968
|
runtimes: {
|
|
2568
3969
|
type: "string",
|
|
2569
3970
|
enum: ["php-84", "php-83", "php-81", "node-22", "node-20", "node-18", "node-16", "bun-1"]
|
|
@@ -2620,7 +4021,7 @@ var schema_default = {
|
|
|
2620
4021
|
};
|
|
2621
4022
|
|
|
2622
4023
|
// src/parse-config.ts
|
|
2623
|
-
var parseConfigRaw =
|
|
4024
|
+
var parseConfigRaw = import_effect25.Effect.fn("parseConfigRaw")(function* (filePath, projectFolder) {
|
|
2624
4025
|
const rawReader = yield* RawConfigReader;
|
|
2625
4026
|
const validator = yield* SchemaValidator;
|
|
2626
4027
|
const v4Parser = yield* V4ConfigParser;
|
|
@@ -2631,7 +4032,7 @@ var parseConfigRaw = import_effect22.Effect.fn("parseConfigRaw")(function* (file
|
|
|
2631
4032
|
};
|
|
2632
4033
|
const schema = schemaMap[version];
|
|
2633
4034
|
if (!schema) {
|
|
2634
|
-
return yield*
|
|
4035
|
+
return yield* import_effect25.Effect.fail(
|
|
2635
4036
|
new ConfigVersionError({
|
|
2636
4037
|
message: `Config file at ${filePath} has an unsupported version: ${version}`,
|
|
2637
4038
|
filePath,
|
|
@@ -2642,14 +4043,42 @@ var parseConfigRaw = import_effect22.Effect.fn("parseConfigRaw")(function* (file
|
|
|
2642
4043
|
yield* validator.validate(parsed, schema, filePath);
|
|
2643
4044
|
return yield* v4Parser.parse(parsed, projectFolder);
|
|
2644
4045
|
});
|
|
2645
|
-
var parseConfig =
|
|
4046
|
+
var parseConfig = import_effect25.Effect.fn("parseConfig")(function* (filePath, projectFolder) {
|
|
2646
4047
|
const parseResult = yield* parseConfigRaw(filePath, projectFolder);
|
|
2647
4048
|
return yield* postProcessConfig(parseResult, projectFolder);
|
|
2648
4049
|
});
|
|
2649
|
-
var postProcessConfig =
|
|
4050
|
+
var postProcessConfig = import_effect25.Effect.fn("postProcessConfig")(function* (config, projectFolder) {
|
|
2650
4051
|
const vercelParser = yield* VercelBuildOutputParser;
|
|
2651
4052
|
let result = yield* vercelParser.parse(config, projectFolder);
|
|
2652
4053
|
const hasAssets = (result.assets?.paths?.length ?? 0) > 0 || (result.assets?.prefixes?.length ?? 0) > 0 || (result.assets?.manifests?.length ?? 0) > 0;
|
|
4054
|
+
const containerFunctions = result.entrypoints.filter((entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME);
|
|
4055
|
+
const [onlyFunction] = result.entrypoints;
|
|
4056
|
+
if (onlyFunction !== void 0 && onlyFunction.runtime === CONTAINER_RUNTIME && result.entrypoints.length === 1 && result.routes.length === 0 && !hasAssets) {
|
|
4057
|
+
result = {
|
|
4058
|
+
...result,
|
|
4059
|
+
routes: [
|
|
4060
|
+
{
|
|
4061
|
+
path: "/*",
|
|
4062
|
+
destination: onlyFunction.path,
|
|
4063
|
+
handler: onlyFunction.streaming === true ? "SERVERLESS_FUNCTION_STREAMING" : "SERVERLESS_FUNCTION",
|
|
4064
|
+
methods: ["ANY"],
|
|
4065
|
+
headers: {}
|
|
4066
|
+
}
|
|
4067
|
+
]
|
|
4068
|
+
};
|
|
4069
|
+
} else {
|
|
4070
|
+
for (const entrypoint of containerFunctions) {
|
|
4071
|
+
const routed = result.routes.some((route) => route.destination.replace(/^\/+/, "") === entrypoint.path);
|
|
4072
|
+
if (!routed && entrypoint.schedule === void 0) {
|
|
4073
|
+
result.warnings.push(
|
|
4074
|
+
`Container function '${entrypoint.displayName ?? entrypoint.path}' has no route and no schedule, so nothing reaches it. Add a route with destination '${entrypoint.path}'.`
|
|
4075
|
+
);
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
if ((result.sidecars?.length ?? 0) > 0 && result.entrypoints.length === 0) {
|
|
4080
|
+
result.warnings.push("Sidecars run next to functions, and this deployment has none, so no sidecar will start.");
|
|
4081
|
+
}
|
|
2653
4082
|
if (result.entrypoints.length === 0 && !hasAssets && result.routes.length === 0) {
|
|
2654
4083
|
result.errors.push(
|
|
2655
4084
|
"The current project config does not resolve to any functions, assets or routes and can not be deployed."
|
|
@@ -2675,19 +4104,22 @@ var RUNTIME_DEFINITIONS = [
|
|
|
2675
4104
|
var AVAILABLE_RUNTIMES = [...RUNTIME_DEFINITIONS];
|
|
2676
4105
|
|
|
2677
4106
|
// src/services/index.ts
|
|
2678
|
-
var
|
|
2679
|
-
var BaseLayers =
|
|
4107
|
+
var import_effect26 = require("effect");
|
|
4108
|
+
var BaseLayers = import_effect26.Layer.mergeAll(
|
|
2680
4109
|
ConfigModuleLoader.Default,
|
|
2681
4110
|
RawConfigReader.Default,
|
|
2682
4111
|
SchemaValidator.Default,
|
|
2683
4112
|
V4ConfigParser.Default
|
|
2684
4113
|
);
|
|
2685
|
-
var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(
|
|
4114
|
+
var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect26.Layer.provideMerge(BaseLayers));
|
|
2686
4115
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2687
4116
|
0 && (module.exports = {
|
|
2688
4117
|
ALLOWED_CONFIG_NAMES,
|
|
2689
4118
|
AVAILABLE_REGIONS,
|
|
2690
4119
|
AVAILABLE_RUNTIMES,
|
|
4120
|
+
COMPOSE_FILE_NAMES,
|
|
4121
|
+
CONTAINER_ENTRYPOINT_PREFIX,
|
|
4122
|
+
CONTAINER_RUNTIME,
|
|
2691
4123
|
ConfigFileEmptyError,
|
|
2692
4124
|
ConfigFileNotFoundError,
|
|
2693
4125
|
ConfigFileParseError,
|
|
@@ -2695,7 +4127,10 @@ var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect23.Lay
|
|
|
2695
4127
|
ConfigModuleLoader,
|
|
2696
4128
|
ConfigSchemaValidationError,
|
|
2697
4129
|
ConfigVersionError,
|
|
4130
|
+
ContainerConfigError,
|
|
4131
|
+
DEFAULT_CONTAINER_MEMORY_MB,
|
|
2698
4132
|
DEFAULT_FUNCTION_DURATION_SECONDS,
|
|
4133
|
+
DEFAULT_SIDECAR_MEMORY_MB,
|
|
2699
4134
|
FRAMEWORK_DEFINITIONS,
|
|
2700
4135
|
FrameworkNotDetectedError,
|
|
2701
4136
|
FunctionConfigError,
|
|
@@ -2712,6 +4147,7 @@ var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect23.Lay
|
|
|
2712
4147
|
GigadriveNextServerDescriptorSchema,
|
|
2713
4148
|
GigadriveNextStaticAssetPrefixSchema,
|
|
2714
4149
|
MAX_FUNCTION_DURATION_SECONDS,
|
|
4150
|
+
MAX_SIDECARS,
|
|
2715
4151
|
ManifestNotFoundError,
|
|
2716
4152
|
ManifestParseError,
|
|
2717
4153
|
ManifestReadError,
|
|
@@ -2724,19 +4160,26 @@ var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect23.Lay
|
|
|
2724
4160
|
V4ConfigParser,
|
|
2725
4161
|
VercelBuildOutputParser,
|
|
2726
4162
|
collectAssetFiles,
|
|
4163
|
+
composeDeclaresApp,
|
|
4164
|
+
containerEntrypointPath,
|
|
2727
4165
|
defineConfig,
|
|
4166
|
+
detectContainerProject,
|
|
2728
4167
|
detectFramework,
|
|
2729
4168
|
detectPackageManager,
|
|
4169
|
+
dockerFunctionContainerName,
|
|
2730
4170
|
filterFunctionsFromAssets,
|
|
2731
4171
|
generateConfig,
|
|
2732
4172
|
getFunctionSettings,
|
|
2733
4173
|
mergeWithFrameworkDefaults,
|
|
4174
|
+
normalizeContainers,
|
|
2734
4175
|
parseConfig,
|
|
2735
4176
|
parseConfigRaw,
|
|
2736
4177
|
parseGigadriveNextBuildManifest,
|
|
2737
4178
|
parseGigadriveNextPrerenderManifest,
|
|
2738
4179
|
parseStaticAssetManifest,
|
|
2739
4180
|
postProcessConfig,
|
|
2740
|
-
|
|
4181
|
+
readComposeContainers,
|
|
4182
|
+
readDependencies,
|
|
4183
|
+
splitCommandWords
|
|
2741
4184
|
});
|
|
2742
4185
|
//# sourceMappingURL=index.js.map
|