@gigadrive/network-config 4.6.1 → 5.1.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 +513 -91
- package/dist/index.d.ts +513 -91
- package/dist/index.js +1724 -448
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1715 -454
- 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,
|
|
@@ -68,20 +75,28 @@ __export(src_exports, {
|
|
|
68
75
|
StaticAssetManifestV1Schema: () => StaticAssetManifestV1Schema,
|
|
69
76
|
V4ConfigParser: () => V4ConfigParser,
|
|
70
77
|
VercelBuildOutputParser: () => VercelBuildOutputParser,
|
|
78
|
+
collectAssetFiles: () => collectAssetFiles,
|
|
79
|
+
composeDeclaresApp: () => composeDeclaresApp,
|
|
80
|
+
containerEntrypointPath: () => containerEntrypointPath,
|
|
71
81
|
defineConfig: () => defineConfig,
|
|
82
|
+
detectContainerProject: () => detectContainerProject,
|
|
72
83
|
detectFramework: () => detectFramework,
|
|
73
84
|
detectPackageManager: () => detectPackageManager,
|
|
85
|
+
dockerFunctionContainerName: () => dockerFunctionContainerName,
|
|
74
86
|
filterFunctionsFromAssets: () => filterFunctionsFromAssets,
|
|
75
87
|
generateConfig: () => generateConfig,
|
|
76
88
|
getFunctionSettings: () => getFunctionSettings,
|
|
77
89
|
mergeWithFrameworkDefaults: () => mergeWithFrameworkDefaults,
|
|
90
|
+
normalizeContainers: () => normalizeContainers,
|
|
78
91
|
parseConfig: () => parseConfig,
|
|
79
92
|
parseConfigRaw: () => parseConfigRaw,
|
|
80
93
|
parseGigadriveNextBuildManifest: () => parseGigadriveNextBuildManifest,
|
|
81
94
|
parseGigadriveNextPrerenderManifest: () => parseGigadriveNextPrerenderManifest,
|
|
82
95
|
parseStaticAssetManifest: () => parseStaticAssetManifest,
|
|
83
96
|
postProcessConfig: () => postProcessConfig,
|
|
84
|
-
|
|
97
|
+
readComposeContainers: () => readComposeContainers,
|
|
98
|
+
readDependencies: () => readDependencies,
|
|
99
|
+
splitCommandWords: () => splitCommandWords
|
|
85
100
|
});
|
|
86
101
|
module.exports = __toCommonJS(src_exports);
|
|
87
102
|
|
|
@@ -142,16 +157,862 @@ var StaticAssetManifestV1Schema = import_effect2.Schema.mutable(
|
|
|
142
157
|
).pipe(import_effect2.Schema.filter(({ assets }) => new Set(assets.map(({ path: path2 }) => path2)).size === assets.length));
|
|
143
158
|
var parseStaticAssetManifest = (content) => decodeJson(StaticAssetManifestV1Schema, content);
|
|
144
159
|
|
|
160
|
+
// src/collect-asset-files.ts
|
|
161
|
+
var import_platform = require("@effect/platform");
|
|
162
|
+
var import_effect3 = require("effect");
|
|
163
|
+
var MAX_ASSET_DEPTH = 100;
|
|
164
|
+
var DISALLOWED_ASSET_EXTENSIONS = [".htaccess", ".htpasswd"];
|
|
165
|
+
var collectFilesRecursively = import_effect3.Effect.fn("collectFilesRecursively")(
|
|
166
|
+
function* (basePath, relativePath = "", depth = 0) {
|
|
167
|
+
if (depth > MAX_ASSET_DEPTH) return [];
|
|
168
|
+
const fs = yield* import_platform.FileSystem.FileSystem;
|
|
169
|
+
const pathSvc = yield* import_platform.Path.Path;
|
|
170
|
+
const currentPath = relativePath ? pathSvc.join(basePath, relativePath) : basePath;
|
|
171
|
+
const entries = yield* fs.readDirectory(currentPath).pipe(import_effect3.Effect.catchAll(() => import_effect3.Effect.succeed([])));
|
|
172
|
+
const result = [];
|
|
173
|
+
for (const name of entries) {
|
|
174
|
+
const fullPath = pathSvc.join(currentPath, name);
|
|
175
|
+
const entryRelative = relativePath ? pathSvc.join(relativePath, name) : name;
|
|
176
|
+
const stat = yield* fs.stat(fullPath).pipe(import_effect3.Effect.catchAll(() => import_effect3.Effect.succeed(null)));
|
|
177
|
+
if (!stat) continue;
|
|
178
|
+
if (stat.type === "Directory") {
|
|
179
|
+
const nested = yield* collectFilesRecursively(basePath, entryRelative, depth + 1);
|
|
180
|
+
result.push(...nested);
|
|
181
|
+
} else {
|
|
182
|
+
result.push(entryRelative);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
var collectAssetFiles = import_effect3.Effect.fn("collectAssetFiles")(function* (projectFolder, assetsDir) {
|
|
189
|
+
const fs = yield* import_platform.FileSystem.FileSystem;
|
|
190
|
+
const pathService = yield* import_platform.Path.Path;
|
|
191
|
+
const assetsPath = pathService.join(projectFolder, assetsDir);
|
|
192
|
+
const stat = yield* fs.stat(assetsPath).pipe(import_effect3.Effect.catchAll(() => import_effect3.Effect.succeed(null)));
|
|
193
|
+
if (!stat || stat.type !== "Directory") return [];
|
|
194
|
+
const files = yield* collectFilesRecursively(assetsPath);
|
|
195
|
+
return files.map((file) => file.replaceAll("\\", "/")).filter((file) => !DISALLOWED_ASSET_EXTENSIONS.some((extension) => file.toLowerCase().endsWith(extension))).sort();
|
|
196
|
+
});
|
|
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
|
+
|
|
145
932
|
// src/define-config.ts
|
|
146
933
|
var defineConfig = (config) => config;
|
|
147
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
|
+
|
|
148
1009
|
// src/detection/detect-framework.ts
|
|
149
|
-
var
|
|
150
|
-
var
|
|
1010
|
+
var import_platform11 = require("@effect/platform");
|
|
1011
|
+
var import_effect17 = require("effect");
|
|
151
1012
|
|
|
152
1013
|
// src/detection/detect-package-manager.ts
|
|
153
|
-
var
|
|
154
|
-
var
|
|
1014
|
+
var import_platform4 = require("@effect/platform");
|
|
1015
|
+
var import_effect7 = require("effect");
|
|
155
1016
|
var LOCKFILE_MAP = [
|
|
156
1017
|
{ files: ["bun.lockb", "bun.lock"], pm: "bun" },
|
|
157
1018
|
{ files: ["pnpm-lock.yaml"], pm: "pnpm" },
|
|
@@ -159,19 +1020,19 @@ var LOCKFILE_MAP = [
|
|
|
159
1020
|
{ files: ["package-lock.json"], pm: "npm" },
|
|
160
1021
|
{ files: ["composer.lock"], pm: "composer" }
|
|
161
1022
|
];
|
|
162
|
-
var detectPackageManager =
|
|
163
|
-
const fs = yield*
|
|
164
|
-
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;
|
|
165
1026
|
for (const { files, pm } of LOCKFILE_MAP) {
|
|
166
1027
|
for (const file of files) {
|
|
167
|
-
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)));
|
|
168
1029
|
if (exists) {
|
|
169
|
-
yield*
|
|
1030
|
+
yield* import_effect7.Effect.logDebug(`Detected package manager: ${pm} (via ${file})`);
|
|
170
1031
|
return pm;
|
|
171
1032
|
}
|
|
172
1033
|
}
|
|
173
1034
|
}
|
|
174
|
-
yield*
|
|
1035
|
+
yield* import_effect7.Effect.logDebug("No lockfile found, defaulting to npm");
|
|
175
1036
|
return "npm";
|
|
176
1037
|
});
|
|
177
1038
|
|
|
@@ -197,8 +1058,8 @@ var astro = {
|
|
|
197
1058
|
};
|
|
198
1059
|
|
|
199
1060
|
// src/detection/frameworks/resolve-node-entrypoint.ts
|
|
200
|
-
var
|
|
201
|
-
var
|
|
1061
|
+
var import_platform5 = require("@effect/platform");
|
|
1062
|
+
var import_effect8 = require("effect");
|
|
202
1063
|
var SCRIPT_RUNNERS = /* @__PURE__ */ new Set(["node", "bun", "tsx", "ts-node"]);
|
|
203
1064
|
var COMMON_ENTRYPOINT_CANDIDATES = [
|
|
204
1065
|
"index.js",
|
|
@@ -214,11 +1075,11 @@ var COMMON_ENTRYPOINT_CANDIDATES = [
|
|
|
214
1075
|
"server.ts",
|
|
215
1076
|
"src/server.ts"
|
|
216
1077
|
];
|
|
217
|
-
var
|
|
1078
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
218
1079
|
var parsePackageJson = (content) => {
|
|
219
1080
|
try {
|
|
220
1081
|
const parsed = JSON.parse(content);
|
|
221
|
-
if (!
|
|
1082
|
+
if (!isRecord2(parsed)) return void 0;
|
|
222
1083
|
return parsed;
|
|
223
1084
|
} catch {
|
|
224
1085
|
return void 0;
|
|
@@ -246,14 +1107,14 @@ var applyEntrypoint = (defaults, entrypoint) => ({
|
|
|
246
1107
|
(route) => route.destination === defaults.entrypoint ? { ...route, destination: entrypoint } : route
|
|
247
1108
|
)
|
|
248
1109
|
});
|
|
249
|
-
var resolveNodeServerEntrypoint = (defaults, projectFolder) =>
|
|
250
|
-
const fs = yield*
|
|
251
|
-
const pathService = yield*
|
|
1110
|
+
var resolveNodeServerEntrypoint = (defaults, projectFolder) => import_effect8.Effect.gen(function* () {
|
|
1111
|
+
const fs = yield* import_platform5.FileSystem.FileSystem;
|
|
1112
|
+
const pathService = yield* import_platform5.Path.Path;
|
|
252
1113
|
const isFile = (relativePath) => fs.stat(pathService.join(projectFolder, relativePath)).pipe(
|
|
253
|
-
|
|
254
|
-
|
|
1114
|
+
import_effect8.Effect.map((info) => info.type === "File"),
|
|
1115
|
+
import_effect8.Effect.catchAll(() => import_effect8.Effect.succeed(false))
|
|
255
1116
|
);
|
|
256
|
-
const content = yield* fs.readFileString(pathService.join(projectFolder, "package.json")).pipe(
|
|
1117
|
+
const content = yield* fs.readFileString(pathService.join(projectFolder, "package.json")).pipe(import_effect8.Effect.catchAll(() => import_effect8.Effect.succeed(void 0)));
|
|
257
1118
|
const manifest = content ? parsePackageJson(content) : void 0;
|
|
258
1119
|
const startScript = typeof manifest?.scripts?.start === "string" ? manifest.scripts.start : void 0;
|
|
259
1120
|
const candidates = [
|
|
@@ -385,13 +1246,13 @@ var laravel = {
|
|
|
385
1246
|
};
|
|
386
1247
|
|
|
387
1248
|
// src/detection/frameworks/nestjs.ts
|
|
388
|
-
var
|
|
389
|
-
var
|
|
390
|
-
var
|
|
1249
|
+
var import_platform6 = require("@effect/platform");
|
|
1250
|
+
var import_effect9 = require("effect");
|
|
1251
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null;
|
|
391
1252
|
var parseNestCliJson = (content) => {
|
|
392
1253
|
try {
|
|
393
1254
|
const parsed = JSON.parse(content);
|
|
394
|
-
if (!
|
|
1255
|
+
if (!isRecord3(parsed)) return void 0;
|
|
395
1256
|
return parsed;
|
|
396
1257
|
} catch {
|
|
397
1258
|
return void 0;
|
|
@@ -437,9 +1298,9 @@ var nestjs = {
|
|
|
437
1298
|
detectors: [{ matchPackage: "@nestjs/core" }],
|
|
438
1299
|
priority: 90,
|
|
439
1300
|
getDefaultConfig: () => createNestConfig("dist"),
|
|
440
|
-
refineDefaultConfig: (defaults, projectFolder) =>
|
|
441
|
-
const fs = yield*
|
|
442
|
-
const content = yield* fs.readFileString(`${projectFolder}/nest-cli.json`).pipe(
|
|
1301
|
+
refineDefaultConfig: (defaults, projectFolder) => import_effect9.Effect.gen(function* () {
|
|
1302
|
+
const fs = yield* import_platform6.FileSystem.FileSystem;
|
|
1303
|
+
const content = yield* fs.readFileString(`${projectFolder}/nest-cli.json`).pipe(import_effect9.Effect.catchAll(() => import_effect9.Effect.succeed(void 0)));
|
|
443
1304
|
if (!content) return defaults;
|
|
444
1305
|
const nestConfig = parseNestCliJson(content);
|
|
445
1306
|
const outputPath = nestConfig ? getProjectOutputPath(nestConfig) : void 0;
|
|
@@ -448,28 +1309,28 @@ var nestjs = {
|
|
|
448
1309
|
};
|
|
449
1310
|
|
|
450
1311
|
// src/detection/frameworks/nextjs.ts
|
|
451
|
-
var
|
|
452
|
-
var
|
|
1312
|
+
var import_platform8 = require("@effect/platform");
|
|
1313
|
+
var import_effect12 = require("effect");
|
|
453
1314
|
|
|
454
1315
|
// src/build-output-v3/get-default-path-map.ts
|
|
455
|
-
var
|
|
456
|
-
var
|
|
457
|
-
var getDefaultPathMap =
|
|
458
|
-
const fs = yield*
|
|
459
|
-
const pathService = yield*
|
|
1316
|
+
var import_platform7 = require("@effect/platform");
|
|
1317
|
+
var import_effect10 = require("effect");
|
|
1318
|
+
var getDefaultPathMap = import_effect10.Effect.fn("getDefaultPathMap")(function* (directory) {
|
|
1319
|
+
const fs = yield* import_platform7.FileSystem.FileSystem;
|
|
1320
|
+
const pathService = yield* import_platform7.Path.Path;
|
|
460
1321
|
const result = {};
|
|
461
|
-
const exists = yield* fs.exists(directory).pipe(
|
|
1322
|
+
const exists = yield* fs.exists(directory).pipe(import_effect10.Effect.catchAll(() => import_effect10.Effect.succeed(false)));
|
|
462
1323
|
if (!exists) {
|
|
463
1324
|
return result;
|
|
464
1325
|
}
|
|
465
1326
|
const MAX_DEPTH = 100;
|
|
466
|
-
const processDirectory = (currentPath, basePath = "", depth = 0) =>
|
|
1327
|
+
const processDirectory = (currentPath, basePath = "", depth = 0) => import_effect10.Effect.gen(function* () {
|
|
467
1328
|
if (depth > MAX_DEPTH) return;
|
|
468
|
-
const entries = yield* fs.readDirectory(currentPath).pipe(
|
|
1329
|
+
const entries = yield* fs.readDirectory(currentPath).pipe(import_effect10.Effect.catchAll(() => import_effect10.Effect.succeed([])));
|
|
469
1330
|
for (const name of entries) {
|
|
470
1331
|
const fullPath = pathService.join(currentPath, name);
|
|
471
1332
|
const relativePath = basePath ? pathService.join(basePath, name) : name;
|
|
472
|
-
const stat = yield* fs.stat(fullPath).pipe(
|
|
1333
|
+
const stat = yield* fs.stat(fullPath).pipe(import_effect10.Effect.catchAll(() => import_effect10.Effect.succeed(null)));
|
|
473
1334
|
if (!stat) continue;
|
|
474
1335
|
if (stat.type === "Directory") {
|
|
475
1336
|
yield* processDirectory(fullPath, relativePath, depth + 1);
|
|
@@ -486,291 +1347,269 @@ var getDefaultPathMap = import_effect6.Effect.fn("getDefaultPathMap")(function*
|
|
|
486
1347
|
var MAXIMUM_ENTRY_PAGE_PATHS = 50;
|
|
487
1348
|
|
|
488
1349
|
// src/nextjs-manifest.ts
|
|
489
|
-
var
|
|
490
|
-
var StringArraySchema =
|
|
491
|
-
var StringRecordSchema =
|
|
492
|
-
var JsonValueSchema =
|
|
493
|
-
() =>
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
1350
|
+
var import_effect11 = require("effect");
|
|
1351
|
+
var StringArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(import_effect11.Schema.String));
|
|
1352
|
+
var StringRecordSchema = import_effect11.Schema.mutable(import_effect11.Schema.Record({ key: import_effect11.Schema.String, value: import_effect11.Schema.String }));
|
|
1353
|
+
var JsonValueSchema = import_effect11.Schema.suspend(
|
|
1354
|
+
() => import_effect11.Schema.Union(
|
|
1355
|
+
import_effect11.Schema.Null,
|
|
1356
|
+
import_effect11.Schema.Boolean,
|
|
1357
|
+
import_effect11.Schema.Number,
|
|
1358
|
+
import_effect11.Schema.String,
|
|
1359
|
+
import_effect11.Schema.mutable(import_effect11.Schema.Array(JsonValueSchema)),
|
|
1360
|
+
import_effect11.Schema.mutable(import_effect11.Schema.Record({ key: import_effect11.Schema.String, value: JsonValueSchema }))
|
|
500
1361
|
)
|
|
501
1362
|
);
|
|
502
|
-
var ImageLocalPatternSchema =
|
|
503
|
-
|
|
504
|
-
pathname:
|
|
505
|
-
search:
|
|
1363
|
+
var ImageLocalPatternSchema = import_effect11.Schema.mutable(
|
|
1364
|
+
import_effect11.Schema.Struct({
|
|
1365
|
+
pathname: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1366
|
+
search: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
506
1367
|
})
|
|
507
1368
|
);
|
|
508
|
-
var ImageRemotePatternSchema =
|
|
509
|
-
|
|
510
|
-
protocol:
|
|
511
|
-
hostname:
|
|
512
|
-
port:
|
|
513
|
-
pathname:
|
|
514
|
-
search:
|
|
1369
|
+
var ImageRemotePatternSchema = import_effect11.Schema.mutable(
|
|
1370
|
+
import_effect11.Schema.Struct({
|
|
1371
|
+
protocol: import_effect11.Schema.optional(import_effect11.Schema.Literal("http", "https")),
|
|
1372
|
+
hostname: import_effect11.Schema.String,
|
|
1373
|
+
port: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1374
|
+
pathname: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1375
|
+
search: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
515
1376
|
})
|
|
516
1377
|
);
|
|
517
|
-
var ImageVariantSchema =
|
|
518
|
-
|
|
519
|
-
width:
|
|
520
|
-
height:
|
|
521
|
-
quality:
|
|
522
|
-
format:
|
|
523
|
-
fit:
|
|
1378
|
+
var ImageVariantSchema = import_effect11.Schema.mutable(
|
|
1379
|
+
import_effect11.Schema.Struct({
|
|
1380
|
+
width: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1381
|
+
height: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1382
|
+
quality: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1383
|
+
format: import_effect11.Schema.optional(import_effect11.Schema.Literal("image/avif", "image/webp", "image/jpeg", "image/png")),
|
|
1384
|
+
fit: import_effect11.Schema.optional(import_effect11.Schema.Literal("contain", "cover", "fill", "inside", "outside"))
|
|
524
1385
|
})
|
|
525
1386
|
);
|
|
526
|
-
var PositiveIntSchema =
|
|
527
|
-
var ImagePolicySchema =
|
|
528
|
-
|
|
529
|
-
localPatterns:
|
|
530
|
-
remotePatterns:
|
|
531
|
-
widths:
|
|
532
|
-
heights:
|
|
533
|
-
qualities:
|
|
534
|
-
formats:
|
|
535
|
-
minimumCacheTTL:
|
|
536
|
-
dangerouslyAllowSVG:
|
|
537
|
-
contentSecurityPolicy:
|
|
538
|
-
contentDispositionType:
|
|
539
|
-
maximumRedirects:
|
|
540
|
-
maximumResponseBody:
|
|
541
|
-
variants:
|
|
1387
|
+
var PositiveIntSchema = import_effect11.Schema.Int.pipe(import_effect11.Schema.greaterThan(0));
|
|
1388
|
+
var ImagePolicySchema = import_effect11.Schema.mutable(
|
|
1389
|
+
import_effect11.Schema.Struct({
|
|
1390
|
+
localPatterns: import_effect11.Schema.mutable(import_effect11.Schema.Array(ImageLocalPatternSchema)),
|
|
1391
|
+
remotePatterns: import_effect11.Schema.mutable(import_effect11.Schema.Array(ImageRemotePatternSchema)),
|
|
1392
|
+
widths: import_effect11.Schema.mutable(import_effect11.Schema.Array(PositiveIntSchema)),
|
|
1393
|
+
heights: import_effect11.Schema.mutable(import_effect11.Schema.Array(PositiveIntSchema)),
|
|
1394
|
+
qualities: import_effect11.Schema.mutable(import_effect11.Schema.Array(import_effect11.Schema.Number.pipe(import_effect11.Schema.between(1, 100)))),
|
|
1395
|
+
formats: import_effect11.Schema.mutable(import_effect11.Schema.Array(import_effect11.Schema.Literal("image/avif", "image/webp", "image/jpeg", "image/png"))),
|
|
1396
|
+
minimumCacheTTL: import_effect11.Schema.Number,
|
|
1397
|
+
dangerouslyAllowSVG: import_effect11.Schema.Boolean,
|
|
1398
|
+
contentSecurityPolicy: import_effect11.Schema.String,
|
|
1399
|
+
contentDispositionType: import_effect11.Schema.Literal("inline", "attachment"),
|
|
1400
|
+
maximumRedirects: import_effect11.Schema.Number,
|
|
1401
|
+
maximumResponseBody: import_effect11.Schema.Number,
|
|
1402
|
+
variants: import_effect11.Schema.mutable(import_effect11.Schema.Record({ key: import_effect11.Schema.String, value: ImageVariantSchema }))
|
|
542
1403
|
})
|
|
543
1404
|
);
|
|
544
1405
|
var GigadriveNextPrerenderOutputFields = {
|
|
545
|
-
id:
|
|
546
|
-
type:
|
|
1406
|
+
id: import_effect11.Schema.String,
|
|
1407
|
+
type: import_effect11.Schema.Literal("PRERENDER"),
|
|
547
1408
|
pathname: UrlPathnameSchema,
|
|
548
|
-
route:
|
|
549
|
-
parentOutputId:
|
|
550
|
-
groupId:
|
|
551
|
-
pprChain:
|
|
552
|
-
parentFallbackMode:
|
|
553
|
-
fallback:
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
filePath:
|
|
557
|
-
initialStatus:
|
|
558
|
-
initialHeaders:
|
|
559
|
-
initialExpiration:
|
|
560
|
-
initialRevalidate:
|
|
561
|
-
postponedState:
|
|
1409
|
+
route: import_effect11.Schema.optional(UrlPathnameSchema),
|
|
1410
|
+
parentOutputId: import_effect11.Schema.String,
|
|
1411
|
+
groupId: import_effect11.Schema.Number,
|
|
1412
|
+
pprChain: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Struct({ headers: HttpSingleValueHeadersSchema }))),
|
|
1413
|
+
parentFallbackMode: import_effect11.Schema.optional(JsonValueSchema),
|
|
1414
|
+
fallback: import_effect11.Schema.optional(
|
|
1415
|
+
import_effect11.Schema.mutable(
|
|
1416
|
+
import_effect11.Schema.Struct({
|
|
1417
|
+
filePath: import_effect11.Schema.optional(PortableRelativePathSchema),
|
|
1418
|
+
initialStatus: import_effect11.Schema.optional(import_effect11.Schema.Int.pipe(import_effect11.Schema.between(100, 599))),
|
|
1419
|
+
initialHeaders: import_effect11.Schema.optional(HttpHeadersSchema),
|
|
1420
|
+
initialExpiration: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1421
|
+
initialRevalidate: import_effect11.Schema.optional(import_effect11.Schema.Union(import_effect11.Schema.Number, import_effect11.Schema.Literal(false))),
|
|
1422
|
+
postponedState: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
562
1423
|
})
|
|
563
1424
|
)
|
|
564
1425
|
),
|
|
565
|
-
config:
|
|
566
|
-
|
|
567
|
-
allowQuery:
|
|
568
|
-
allowHeader:
|
|
569
|
-
bypassFor:
|
|
570
|
-
renderingMode:
|
|
571
|
-
partialFallback:
|
|
572
|
-
bypassToken:
|
|
1426
|
+
config: import_effect11.Schema.mutable(
|
|
1427
|
+
import_effect11.Schema.Struct({
|
|
1428
|
+
allowQuery: import_effect11.Schema.optional(StringArraySchema),
|
|
1429
|
+
allowHeader: import_effect11.Schema.optional(StringArraySchema),
|
|
1430
|
+
bypassFor: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(JsonValueSchema))),
|
|
1431
|
+
renderingMode: import_effect11.Schema.optional(import_effect11.Schema.String),
|
|
1432
|
+
partialFallback: import_effect11.Schema.optional(import_effect11.Schema.Boolean),
|
|
1433
|
+
bypassToken: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
573
1434
|
})
|
|
574
1435
|
)
|
|
575
1436
|
};
|
|
576
|
-
var GigadriveNextPrerenderClassificationSchema =
|
|
577
|
-
routeType:
|
|
578
|
-
response:
|
|
579
|
-
compute:
|
|
580
|
-
htmlSize:
|
|
1437
|
+
var GigadriveNextPrerenderClassificationSchema = import_effect11.Schema.Struct({
|
|
1438
|
+
routeType: import_effect11.Schema.Literal("route", "fallback", "shell", "page"),
|
|
1439
|
+
response: import_effect11.Schema.Literal("empty", "initial", "complete"),
|
|
1440
|
+
compute: import_effect11.Schema.Literal("blocking", "resuming", "static"),
|
|
1441
|
+
htmlSize: import_effect11.Schema.optional(import_effect11.Schema.Number)
|
|
581
1442
|
});
|
|
582
|
-
var GigadriveNextPrerenderWithoutClassificationSchema =
|
|
583
|
-
routeType:
|
|
584
|
-
response:
|
|
585
|
-
compute:
|
|
586
|
-
htmlSize:
|
|
1443
|
+
var GigadriveNextPrerenderWithoutClassificationSchema = import_effect11.Schema.Struct({
|
|
1444
|
+
routeType: import_effect11.Schema.optional(import_effect11.Schema.Never),
|
|
1445
|
+
response: import_effect11.Schema.optional(import_effect11.Schema.Never),
|
|
1446
|
+
compute: import_effect11.Schema.optional(import_effect11.Schema.Never),
|
|
1447
|
+
htmlSize: import_effect11.Schema.optional(import_effect11.Schema.Never)
|
|
587
1448
|
});
|
|
588
|
-
var GigadriveNextPrerenderOutputSchema =
|
|
589
|
-
|
|
590
|
-
|
|
1449
|
+
var GigadriveNextPrerenderOutputSchema = import_effect11.Schema.Union(
|
|
1450
|
+
import_effect11.Schema.mutable(
|
|
1451
|
+
import_effect11.Schema.Struct({ ...GigadriveNextPrerenderOutputFields, ...GigadriveNextPrerenderClassificationSchema.fields })
|
|
591
1452
|
),
|
|
592
|
-
|
|
593
|
-
|
|
1453
|
+
import_effect11.Schema.mutable(
|
|
1454
|
+
import_effect11.Schema.Struct({
|
|
594
1455
|
...GigadriveNextPrerenderOutputFields,
|
|
595
1456
|
...GigadriveNextPrerenderWithoutClassificationSchema.fields
|
|
596
1457
|
})
|
|
597
1458
|
)
|
|
598
1459
|
);
|
|
599
|
-
var GigadriveNextStaticAssetPrefixSchema =
|
|
600
|
-
|
|
1460
|
+
var GigadriveNextStaticAssetPrefixSchema = import_effect11.Schema.mutable(
|
|
1461
|
+
import_effect11.Schema.Struct({
|
|
601
1462
|
sourceDir: PortableRelativePathSchema,
|
|
602
1463
|
urlPrefix: PortableRelativePathSchema,
|
|
603
|
-
immutable:
|
|
1464
|
+
immutable: import_effect11.Schema.Boolean
|
|
604
1465
|
})
|
|
605
1466
|
);
|
|
606
|
-
var GigadriveNextRouteConditionSchema =
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
type:
|
|
610
|
-
key:
|
|
611
|
-
value:
|
|
1467
|
+
var GigadriveNextRouteConditionSchema = import_effect11.Schema.Union(
|
|
1468
|
+
import_effect11.Schema.mutable(
|
|
1469
|
+
import_effect11.Schema.Struct({
|
|
1470
|
+
type: import_effect11.Schema.Literal("header", "cookie", "query"),
|
|
1471
|
+
key: import_effect11.Schema.String,
|
|
1472
|
+
value: import_effect11.Schema.optional(import_effect11.Schema.String)
|
|
612
1473
|
})
|
|
613
1474
|
),
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
type:
|
|
617
|
-
value:
|
|
1475
|
+
import_effect11.Schema.mutable(
|
|
1476
|
+
import_effect11.Schema.Struct({
|
|
1477
|
+
type: import_effect11.Schema.Literal("host"),
|
|
1478
|
+
value: import_effect11.Schema.String
|
|
618
1479
|
})
|
|
619
1480
|
)
|
|
620
1481
|
);
|
|
621
|
-
var GigadriveNextMiddlewareMatcherSchema =
|
|
622
|
-
|
|
623
|
-
source:
|
|
624
|
-
sourceRegex:
|
|
625
|
-
has:
|
|
626
|
-
missing:
|
|
1482
|
+
var GigadriveNextMiddlewareMatcherSchema = import_effect11.Schema.mutable(
|
|
1483
|
+
import_effect11.Schema.Struct({
|
|
1484
|
+
source: import_effect11.Schema.String,
|
|
1485
|
+
sourceRegex: import_effect11.Schema.String,
|
|
1486
|
+
has: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextRouteConditionSchema))),
|
|
1487
|
+
missing: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextRouteConditionSchema)))
|
|
627
1488
|
})
|
|
628
1489
|
);
|
|
629
|
-
var GigadriveNextMiddlewareDescriptorSchema =
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
present:
|
|
633
|
-
matchers:
|
|
1490
|
+
var GigadriveNextMiddlewareDescriptorSchema = import_effect11.Schema.Union(
|
|
1491
|
+
import_effect11.Schema.mutable(
|
|
1492
|
+
import_effect11.Schema.Struct({
|
|
1493
|
+
present: import_effect11.Schema.Literal(true),
|
|
1494
|
+
matchers: import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextMiddlewareMatcherSchema))
|
|
634
1495
|
})
|
|
635
1496
|
),
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
present:
|
|
639
|
-
matchers:
|
|
1497
|
+
import_effect11.Schema.mutable(
|
|
1498
|
+
import_effect11.Schema.Struct({
|
|
1499
|
+
present: import_effect11.Schema.Literal(false),
|
|
1500
|
+
matchers: import_effect11.Schema.mutable(import_effect11.Schema.Tuple())
|
|
640
1501
|
})
|
|
641
1502
|
)
|
|
642
1503
|
);
|
|
643
|
-
var GigadriveNextServerDescriptorSchema =
|
|
644
|
-
|
|
645
|
-
maxDuration:
|
|
646
|
-
preferredRegion:
|
|
647
|
-
env:
|
|
1504
|
+
var GigadriveNextServerDescriptorSchema = import_effect11.Schema.mutable(
|
|
1505
|
+
import_effect11.Schema.Struct({
|
|
1506
|
+
maxDuration: import_effect11.Schema.optional(import_effect11.Schema.Number),
|
|
1507
|
+
preferredRegion: import_effect11.Schema.optional(import_effect11.Schema.Union(import_effect11.Schema.String, StringArraySchema)),
|
|
1508
|
+
env: import_effect11.Schema.optional(StringRecordSchema)
|
|
648
1509
|
})
|
|
649
1510
|
);
|
|
650
|
-
var PrerenderArraySchema =
|
|
651
|
-
var StaticAssetArraySchema =
|
|
652
|
-
var JsonValueArraySchema =
|
|
653
|
-
var GigadriveNextPrerenderSeedMethodsSchema =
|
|
654
|
-
|
|
1511
|
+
var PrerenderArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextPrerenderOutputSchema));
|
|
1512
|
+
var StaticAssetArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(GigadriveNextStaticAssetPrefixSchema));
|
|
1513
|
+
var JsonValueArraySchema = import_effect11.Schema.mutable(import_effect11.Schema.Array(JsonValueSchema));
|
|
1514
|
+
var GigadriveNextPrerenderSeedMethodsSchema = import_effect11.Schema.mutable(
|
|
1515
|
+
import_effect11.Schema.Tuple(import_effect11.Schema.Literal("GET"), import_effect11.Schema.Literal("HEAD"))
|
|
655
1516
|
);
|
|
656
|
-
var GigadriveNextBuildManifestV1Schema =
|
|
657
|
-
|
|
658
|
-
version:
|
|
659
|
-
output:
|
|
1517
|
+
var GigadriveNextBuildManifestV1Schema = import_effect11.Schema.mutable(
|
|
1518
|
+
import_effect11.Schema.Struct({
|
|
1519
|
+
version: import_effect11.Schema.Literal(1),
|
|
1520
|
+
output: import_effect11.Schema.Literal("standalone", "export"),
|
|
660
1521
|
distDir: PortableRelativePathSchema,
|
|
661
1522
|
repoRootToProject: RepositoryRelativePathSchema,
|
|
662
|
-
nextVersion:
|
|
663
|
-
buildId:
|
|
1523
|
+
nextVersion: import_effect11.Schema.String,
|
|
1524
|
+
buildId: import_effect11.Schema.String
|
|
664
1525
|
})
|
|
665
1526
|
);
|
|
666
|
-
var GigadriveNextBuildManifestV2ExportSchema =
|
|
667
|
-
|
|
668
|
-
version:
|
|
669
|
-
mode:
|
|
1527
|
+
var GigadriveNextBuildManifestV2ExportSchema = import_effect11.Schema.mutable(
|
|
1528
|
+
import_effect11.Schema.Struct({
|
|
1529
|
+
version: import_effect11.Schema.Literal(2),
|
|
1530
|
+
mode: import_effect11.Schema.Literal("export"),
|
|
670
1531
|
distDir: PortableRelativePathSchema,
|
|
671
1532
|
repoRootToProject: RepositoryRelativePathSchema,
|
|
672
|
-
nextVersion:
|
|
673
|
-
buildId:
|
|
1533
|
+
nextVersion: import_effect11.Schema.String,
|
|
1534
|
+
buildId: import_effect11.Schema.String
|
|
674
1535
|
})
|
|
675
1536
|
);
|
|
676
|
-
var GigadriveNextBuildManifestV2StandaloneSchema =
|
|
677
|
-
|
|
678
|
-
version:
|
|
679
|
-
mode:
|
|
1537
|
+
var GigadriveNextBuildManifestV2StandaloneSchema = import_effect11.Schema.mutable(
|
|
1538
|
+
import_effect11.Schema.Struct({
|
|
1539
|
+
version: import_effect11.Schema.Literal(2),
|
|
1540
|
+
mode: import_effect11.Schema.Literal("standalone-v2"),
|
|
680
1541
|
distDir: PortableRelativePathSchema,
|
|
681
1542
|
repoRootToProject: RepositoryRelativePathSchema,
|
|
682
|
-
nextVersion:
|
|
683
|
-
buildId:
|
|
1543
|
+
nextVersion: import_effect11.Schema.String,
|
|
1544
|
+
buildId: import_effect11.Schema.String,
|
|
684
1545
|
server: GigadriveNextServerDescriptorSchema,
|
|
685
|
-
config:
|
|
686
|
-
|
|
687
|
-
basePath:
|
|
688
|
-
trailingSlash:
|
|
689
|
-
cacheComponents:
|
|
690
|
-
i18n:
|
|
691
|
-
images:
|
|
1546
|
+
config: import_effect11.Schema.mutable(
|
|
1547
|
+
import_effect11.Schema.Struct({
|
|
1548
|
+
basePath: import_effect11.Schema.String,
|
|
1549
|
+
trailingSlash: import_effect11.Schema.Boolean,
|
|
1550
|
+
cacheComponents: import_effect11.Schema.Boolean,
|
|
1551
|
+
i18n: import_effect11.Schema.optional(JsonValueSchema),
|
|
1552
|
+
images: import_effect11.Schema.optional(ImagePolicySchema)
|
|
692
1553
|
})
|
|
693
1554
|
),
|
|
694
|
-
routing:
|
|
695
|
-
|
|
1555
|
+
routing: import_effect11.Schema.mutable(
|
|
1556
|
+
import_effect11.Schema.Struct({
|
|
696
1557
|
beforeMiddleware: JsonValueArraySchema,
|
|
697
1558
|
beforeFiles: JsonValueArraySchema,
|
|
698
1559
|
afterFiles: JsonValueArraySchema,
|
|
699
1560
|
dynamicRoutes: JsonValueArraySchema,
|
|
700
1561
|
onMatch: JsonValueArraySchema,
|
|
701
1562
|
fallback: JsonValueArraySchema,
|
|
702
|
-
shouldNormalizeNextData:
|
|
1563
|
+
shouldNormalizeNextData: import_effect11.Schema.Boolean,
|
|
703
1564
|
rsc: JsonValueSchema
|
|
704
1565
|
})
|
|
705
1566
|
),
|
|
706
|
-
outputs:
|
|
707
|
-
|
|
1567
|
+
outputs: import_effect11.Schema.mutable(
|
|
1568
|
+
import_effect11.Schema.Struct({
|
|
708
1569
|
prerenders: PrerenderArraySchema,
|
|
709
|
-
prerenderManifest:
|
|
710
|
-
assetManifest:
|
|
711
|
-
entryPagePaths:
|
|
1570
|
+
prerenderManifest: import_effect11.Schema.optional(PortableRelativePathSchema),
|
|
1571
|
+
assetManifest: import_effect11.Schema.optional(PortableRelativePathSchema),
|
|
1572
|
+
entryPagePaths: import_effect11.Schema.optional(import_effect11.Schema.mutable(import_effect11.Schema.Array(UrlPathnameSchema))),
|
|
712
1573
|
staticAssets: StaticAssetArraySchema,
|
|
713
|
-
middleware:
|
|
1574
|
+
middleware: import_effect11.Schema.optional(GigadriveNextMiddlewareDescriptorSchema)
|
|
714
1575
|
})
|
|
715
1576
|
)
|
|
716
1577
|
})
|
|
717
1578
|
);
|
|
718
|
-
var GigadriveNextBuildManifestSchema =
|
|
1579
|
+
var GigadriveNextBuildManifestSchema = import_effect11.Schema.Union(
|
|
719
1580
|
GigadriveNextBuildManifestV1Schema,
|
|
720
1581
|
GigadriveNextBuildManifestV2ExportSchema,
|
|
721
1582
|
GigadriveNextBuildManifestV2StandaloneSchema
|
|
722
1583
|
);
|
|
723
|
-
var GigadriveNextPrerenderManifestV1Schema =
|
|
724
|
-
|
|
725
|
-
version:
|
|
726
|
-
seedMethods:
|
|
1584
|
+
var GigadriveNextPrerenderManifestV1Schema = import_effect11.Schema.mutable(
|
|
1585
|
+
import_effect11.Schema.Struct({
|
|
1586
|
+
version: import_effect11.Schema.Literal(1),
|
|
1587
|
+
seedMethods: import_effect11.Schema.optional(GigadriveNextPrerenderSeedMethodsSchema),
|
|
727
1588
|
prerenders: PrerenderArraySchema
|
|
728
1589
|
})
|
|
729
1590
|
);
|
|
730
1591
|
var parseGigadriveNextBuildManifest = (content) => decodeJson(GigadriveNextBuildManifestSchema, content);
|
|
731
1592
|
var parseGigadriveNextPrerenderManifest = (content) => decodeJson(GigadriveNextPrerenderManifestV1Schema, content);
|
|
732
1593
|
|
|
733
|
-
// src/regions.ts
|
|
734
|
-
var REGION_DEFINITIONS = [
|
|
735
|
-
"us-east-1",
|
|
736
|
-
"us-east-2",
|
|
737
|
-
"us-west-1",
|
|
738
|
-
"us-west-2",
|
|
739
|
-
"ap-south-1",
|
|
740
|
-
"ap-northeast-3",
|
|
741
|
-
"ap-northeast-2",
|
|
742
|
-
"ap-southeast-1",
|
|
743
|
-
"ap-southeast-2",
|
|
744
|
-
"ap-northeast-1",
|
|
745
|
-
"ca-central-1",
|
|
746
|
-
"eu-central-1",
|
|
747
|
-
"eu-west-1",
|
|
748
|
-
"eu-west-2",
|
|
749
|
-
"eu-west-3",
|
|
750
|
-
"eu-north-1",
|
|
751
|
-
"sa-east-1"
|
|
752
|
-
];
|
|
753
|
-
var AVAILABLE_REGIONS = [...REGION_DEFINITIONS];
|
|
754
|
-
|
|
755
1594
|
// src/detection/frameworks/nextjs.ts
|
|
756
1595
|
var toPortablePath = (value) => value.replaceAll("\\", "/");
|
|
757
|
-
var STANDALONE_SERVER_MEMORY_MB = 1024;
|
|
758
|
-
var resolveStandaloneServer =
|
|
759
|
-
const fs = yield*
|
|
760
|
-
const pathService = yield*
|
|
1596
|
+
var STANDALONE_SERVER_MEMORY_MB = 1024;
|
|
1597
|
+
var resolveStandaloneServer = import_effect12.Effect.fn("nextjs.resolveStandaloneServer")(function* (projectFolder, distDir, repoRootToProject) {
|
|
1598
|
+
const fs = yield* import_platform8.FileSystem.FileSystem;
|
|
1599
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
761
1600
|
const standaloneRoot = pathService.join(projectFolder, distDir, "standalone");
|
|
762
1601
|
const monorepoServer = pathService.join(standaloneRoot, repoRootToProject, "server.js");
|
|
763
1602
|
const rootServer = pathService.join(standaloneRoot, "server.js");
|
|
764
|
-
const monorepoServerExists = yield* fs.exists(monorepoServer).pipe(
|
|
1603
|
+
const monorepoServerExists = yield* fs.exists(monorepoServer).pipe(import_effect12.Effect.catchAll(() => import_effect12.Effect.succeed(false)));
|
|
765
1604
|
const serverPath = monorepoServerExists ? monorepoServer : rootServer;
|
|
766
|
-
const serverExists = yield* fs.exists(serverPath).pipe(
|
|
1605
|
+
const serverExists = yield* fs.exists(serverPath).pipe(import_effect12.Effect.catchAll(() => import_effect12.Effect.succeed(false)));
|
|
767
1606
|
if (!serverExists) return void 0;
|
|
768
1607
|
const serverDirectory = pathService.dirname(serverPath);
|
|
769
1608
|
const entrypoint = toPortablePath(pathService.relative(standaloneRoot, serverPath));
|
|
770
1609
|
return { standaloneRoot, serverDirectory, entrypoint };
|
|
771
1610
|
});
|
|
772
|
-
var buildStandalonePublicAssets =
|
|
773
|
-
const pathService = yield*
|
|
1611
|
+
var buildStandalonePublicAssets = import_effect12.Effect.fn("nextjs.buildStandalonePublicAssets")(function* (projectFolder, standaloneRoot, serverDirectory) {
|
|
1612
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
774
1613
|
const publicFiles = yield* getDefaultPathMap(pathService.join(projectFolder, "public"));
|
|
775
1614
|
const assetPaths = [];
|
|
776
1615
|
const assetOverrides = {};
|
|
@@ -786,8 +1625,8 @@ var buildStandalonePublicAssets = import_effect8.Effect.fn("nextjs.buildStandalo
|
|
|
786
1625
|
}
|
|
787
1626
|
return { assetPaths, assetOverrides, filePathMap };
|
|
788
1627
|
});
|
|
789
|
-
var createStaticExportConfig =
|
|
790
|
-
const pathService = yield*
|
|
1628
|
+
var createStaticExportConfig = import_effect12.Effect.fn("nextjs.createStaticExportConfig")(function* (defaults, projectFolder) {
|
|
1629
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
791
1630
|
const outputDirectory = pathService.join(projectFolder, "out");
|
|
792
1631
|
const files = yield* getDefaultPathMap(outputDirectory);
|
|
793
1632
|
const assetPaths = [];
|
|
@@ -810,8 +1649,8 @@ var createStaticExportConfig = import_effect8.Effect.fn("nextjs.createStaticExpo
|
|
|
810
1649
|
package: void 0
|
|
811
1650
|
};
|
|
812
1651
|
});
|
|
813
|
-
var createStandaloneConfig =
|
|
814
|
-
const pathService = yield*
|
|
1652
|
+
var createStandaloneConfig = import_effect12.Effect.fn("nextjs.createStandaloneConfig")(function* (defaults, projectFolder, manifest) {
|
|
1653
|
+
const pathService = yield* import_platform8.Path.Path;
|
|
815
1654
|
const resolved = yield* resolveStandaloneServer(projectFolder, manifest.distDir, manifest.repoRootToProject);
|
|
816
1655
|
if (!resolved) return defaults;
|
|
817
1656
|
const { standaloneRoot, serverDirectory, entrypoint } = resolved;
|
|
@@ -844,7 +1683,7 @@ var createStandaloneConfig = import_effect8.Effect.fn("nextjs.createStandaloneCo
|
|
|
844
1683
|
}
|
|
845
1684
|
};
|
|
846
1685
|
});
|
|
847
|
-
var createStandaloneV2Config =
|
|
1686
|
+
var createStandaloneV2Config = import_effect12.Effect.fn("nextjs.createStandaloneV2Config")(function* (defaults, projectFolder, manifest) {
|
|
848
1687
|
const resolved = yield* resolveStandaloneServer(projectFolder, manifest.distDir, manifest.repoRootToProject);
|
|
849
1688
|
if (!resolved) return defaults;
|
|
850
1689
|
const { standaloneRoot, serverDirectory, entrypoint } = resolved;
|
|
@@ -942,14 +1781,19 @@ var nextjs = {
|
|
|
942
1781
|
streaming: true,
|
|
943
1782
|
commands: ["next build"],
|
|
944
1783
|
entrypoint: ".next/standalone/server.js",
|
|
945
|
-
assetsDir
|
|
1784
|
+
// No `assetsDir`: this is only the fallback for a standalone build whose
|
|
1785
|
+
// Gigadrive manifest is missing, and `.next/static` answers
|
|
1786
|
+
// `/_next/static/...` rather than its own stripped prefix. Every path that
|
|
1787
|
+
// resolves a real Next.js build (`refineDefaultConfig`) maps those chunks
|
|
1788
|
+
// itself, so declaring the directory here would publish them at the wrong
|
|
1789
|
+
// URLs.
|
|
946
1790
|
populateAssetCache: true,
|
|
947
1791
|
routes: [{ source: "/*", destination: ".next/standalone/server.js" }],
|
|
948
1792
|
environmentVariables: { NODE_ENV: "production" }
|
|
949
1793
|
}),
|
|
950
|
-
refineDefaultConfig: (defaults, projectFolder) =>
|
|
951
|
-
const fs = yield*
|
|
952
|
-
const manifestContent = yield* fs.readFileString(`${projectFolder}/.gigadrive/nextjs.json`).pipe(
|
|
1794
|
+
refineDefaultConfig: (defaults, projectFolder) => import_effect12.Effect.gen(function* () {
|
|
1795
|
+
const fs = yield* import_platform8.FileSystem.FileSystem;
|
|
1796
|
+
const manifestContent = yield* fs.readFileString(`${projectFolder}/.gigadrive/nextjs.json`).pipe(import_effect12.Effect.catchAll(() => import_effect12.Effect.succeed(void 0)));
|
|
953
1797
|
const manifest = manifestContent ? parseGigadriveNextBuildManifest(manifestContent) : void 0;
|
|
954
1798
|
if (!manifest) return defaults;
|
|
955
1799
|
if (manifest.version === 2) {
|
|
@@ -960,8 +1804,8 @@ var nextjs = {
|
|
|
960
1804
|
};
|
|
961
1805
|
|
|
962
1806
|
// src/detection/frameworks/nuxt.ts
|
|
963
|
-
var
|
|
964
|
-
var
|
|
1807
|
+
var import_platform9 = require("@effect/platform");
|
|
1808
|
+
var import_effect13 = require("effect");
|
|
965
1809
|
var isVercelBuildOutputV3 = (content) => {
|
|
966
1810
|
try {
|
|
967
1811
|
const config = JSON.parse(content);
|
|
@@ -988,9 +1832,9 @@ var nuxt = {
|
|
|
988
1832
|
routes: [{ source: "/*", destination: ".output/server/index.mjs" }],
|
|
989
1833
|
environmentVariables: { NODE_ENV: "production", NITRO_PRESET: "node-server" }
|
|
990
1834
|
}),
|
|
991
|
-
refineDefaultConfig: (defaults, projectFolder) =>
|
|
992
|
-
const fs = yield*
|
|
993
|
-
const buildOutputConfig = yield* fs.readFileString(`${projectFolder}/.vercel/output/config.json`).pipe(
|
|
1835
|
+
refineDefaultConfig: (defaults, projectFolder) => import_effect13.Effect.gen(function* () {
|
|
1836
|
+
const fs = yield* import_platform9.FileSystem.FileSystem;
|
|
1837
|
+
const buildOutputConfig = yield* fs.readFileString(`${projectFolder}/.vercel/output/config.json`).pipe(import_effect13.Effect.catchAll(() => import_effect13.Effect.succeed(void 0)));
|
|
994
1838
|
if (!buildOutputConfig || !isVercelBuildOutputV3(buildOutputConfig)) {
|
|
995
1839
|
return defaults;
|
|
996
1840
|
}
|
|
@@ -1113,7 +1957,7 @@ var FRAMEWORK_DEFINITIONS = [
|
|
|
1113
1957
|
].sort((a, b) => b.priority - a.priority);
|
|
1114
1958
|
|
|
1115
1959
|
// src/detection/generate-config.ts
|
|
1116
|
-
var
|
|
1960
|
+
var import_effect14 = require("effect");
|
|
1117
1961
|
var getInstallCommand = (pm) => {
|
|
1118
1962
|
switch (pm) {
|
|
1119
1963
|
case "bun":
|
|
@@ -1129,11 +1973,11 @@ var getInstallCommand = (pm) => {
|
|
|
1129
1973
|
return "npm install";
|
|
1130
1974
|
}
|
|
1131
1975
|
};
|
|
1132
|
-
var generateConfig =
|
|
1976
|
+
var generateConfig = import_effect14.Effect.fn("generateConfig")(function* (framework, packageManager, projectFolder, refinedDefaults) {
|
|
1133
1977
|
const defaults = refinedDefaults ?? framework.getDefaultConfig(packageManager);
|
|
1134
1978
|
const installCmd = defaults.installCommand ?? getInstallCommand(packageManager);
|
|
1135
1979
|
const commands = [installCmd, ...defaults.commands];
|
|
1136
|
-
yield*
|
|
1980
|
+
yield* import_effect14.Effect.logDebug(`Generating config for ${framework.name}`, {
|
|
1137
1981
|
runtime: defaults.runtime,
|
|
1138
1982
|
entrypoint: defaults.entrypoint,
|
|
1139
1983
|
commands
|
|
@@ -1168,10 +2012,26 @@ var generateConfig = import_effect10.Effect.fn("generateConfig")(function* (fram
|
|
|
1168
2012
|
...defaults.normalizedConfig
|
|
1169
2013
|
};
|
|
1170
2014
|
if (defaults.assetsDir || defaults.assetPaths || defaults.assetPrefixes || defaults.assetManifests) {
|
|
2015
|
+
const paths = defaults.assetPaths ? [...defaults.assetPaths] : [];
|
|
2016
|
+
const overrides = { ...defaults.assetOverrides };
|
|
2017
|
+
const servesDirectoryIndexes = entrypoints.length === 0 && routes.length === 0;
|
|
2018
|
+
const assetsDir = defaults.assetsDir;
|
|
2019
|
+
if (assetsDir && !defaults.assetPaths && !defaults.assetPrefixes && !defaults.assetManifests) {
|
|
2020
|
+
for (const file of yield* collectAssetFiles(projectFolder, assetsDir)) {
|
|
2021
|
+
if (framework.language === "php" && /\.(php|phtml|phar)$/i.test(file)) continue;
|
|
2022
|
+
paths.push(`${assetsDir}/${file}`);
|
|
2023
|
+
if (!servesDirectoryIndexes || file in overrides) continue;
|
|
2024
|
+
if (file === "index.html") {
|
|
2025
|
+
overrides[file] = { path: "" };
|
|
2026
|
+
} else if (file.endsWith("/index.html")) {
|
|
2027
|
+
overrides[file] = { path: file.slice(0, -"/index.html".length) };
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
1171
2031
|
config.assets = {
|
|
1172
|
-
paths
|
|
2032
|
+
paths,
|
|
1173
2033
|
prefixToStrip: defaults.assetsPrefixToStrip ?? (defaults.assetsDir ? defaults.assetsDir + "/" : ""),
|
|
1174
|
-
overrides:
|
|
2034
|
+
overrides: Object.keys(overrides).length > 0 ? overrides : void 0,
|
|
1175
2035
|
prefixes: defaults.assetPrefixes ? defaults.assetPrefixes.map((prefix) => ({ ...prefix })) : void 0,
|
|
1176
2036
|
manifests: defaults.assetManifests ? defaults.assetManifests.map((manifest) => ({ ...manifest })) : void 0,
|
|
1177
2037
|
dynamicRoutes: true,
|
|
@@ -1182,31 +2042,31 @@ var generateConfig = import_effect10.Effect.fn("generateConfig")(function* (fram
|
|
|
1182
2042
|
});
|
|
1183
2043
|
|
|
1184
2044
|
// src/detection/read-dependencies.ts
|
|
1185
|
-
var
|
|
1186
|
-
var
|
|
2045
|
+
var import_platform10 = require("@effect/platform");
|
|
2046
|
+
var import_effect16 = require("effect");
|
|
1187
2047
|
|
|
1188
2048
|
// src/detection/types.ts
|
|
1189
|
-
var
|
|
1190
|
-
var ManifestNotFoundError = class extends
|
|
1191
|
-
message:
|
|
1192
|
-
filePath:
|
|
2049
|
+
var import_effect15 = require("effect");
|
|
2050
|
+
var ManifestNotFoundError = class extends import_effect15.Schema.TaggedError()("ManifestNotFoundError", {
|
|
2051
|
+
message: import_effect15.Schema.String,
|
|
2052
|
+
filePath: import_effect15.Schema.String
|
|
1193
2053
|
}) {
|
|
1194
2054
|
};
|
|
1195
|
-
var ManifestReadError = class extends
|
|
1196
|
-
message:
|
|
1197
|
-
filePath:
|
|
2055
|
+
var ManifestReadError = class extends import_effect15.Schema.TaggedError()("ManifestReadError", {
|
|
2056
|
+
message: import_effect15.Schema.String,
|
|
2057
|
+
filePath: import_effect15.Schema.String
|
|
1198
2058
|
}) {
|
|
1199
2059
|
};
|
|
1200
|
-
var ManifestParseError = class extends
|
|
1201
|
-
message:
|
|
1202
|
-
filePath:
|
|
2060
|
+
var ManifestParseError = class extends import_effect15.Schema.TaggedError()("ManifestParseError", {
|
|
2061
|
+
message: import_effect15.Schema.String,
|
|
2062
|
+
filePath: import_effect15.Schema.String
|
|
1203
2063
|
}) {
|
|
1204
2064
|
};
|
|
1205
|
-
var FrameworkNotDetectedError = class extends
|
|
2065
|
+
var FrameworkNotDetectedError = class extends import_effect15.Schema.TaggedError()(
|
|
1206
2066
|
"FrameworkNotDetectedError",
|
|
1207
2067
|
{
|
|
1208
|
-
message:
|
|
1209
|
-
directory:
|
|
2068
|
+
message: import_effect15.Schema.String,
|
|
2069
|
+
directory: import_effect15.Schema.String
|
|
1210
2070
|
}
|
|
1211
2071
|
) {
|
|
1212
2072
|
};
|
|
@@ -1216,25 +2076,25 @@ var MANIFEST_CONFIG = {
|
|
|
1216
2076
|
node: { file: "package.json", depKeys: ["dependencies", "devDependencies"] },
|
|
1217
2077
|
php: { file: "composer.json", depKeys: ["require", "require-dev"] }
|
|
1218
2078
|
};
|
|
1219
|
-
var readManifest =
|
|
1220
|
-
const fs = yield*
|
|
1221
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2079
|
+
var readManifest = import_effect16.Effect.fn("readManifest")(function* (filePath) {
|
|
2080
|
+
const fs = yield* import_platform10.FileSystem.FileSystem;
|
|
2081
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect16.Effect.catchAll(() => import_effect16.Effect.succeed(false)));
|
|
1222
2082
|
if (!exists) {
|
|
1223
|
-
return yield*
|
|
2083
|
+
return yield* import_effect16.Effect.fail(new ManifestNotFoundError({ message: "Manifest not found", filePath }));
|
|
1224
2084
|
}
|
|
1225
|
-
const content = yield* fs.readFileString(filePath).pipe(
|
|
1226
|
-
const parsed = yield*
|
|
2085
|
+
const content = yield* fs.readFileString(filePath).pipe(import_effect16.Effect.mapError(() => new ManifestReadError({ message: "Failed to read manifest", filePath })));
|
|
2086
|
+
const parsed = yield* import_effect16.Effect.try({
|
|
1227
2087
|
try: () => JSON.parse(content),
|
|
1228
2088
|
catch: () => new ManifestParseError({ message: "Failed to parse manifest JSON", filePath })
|
|
1229
2089
|
});
|
|
1230
2090
|
return parsed;
|
|
1231
2091
|
});
|
|
1232
|
-
var readDependencies =
|
|
1233
|
-
const pathService = yield*
|
|
2092
|
+
var readDependencies = import_effect16.Effect.fn("readDependencies")(function* (projectFolder, language) {
|
|
2093
|
+
const pathService = yield* import_platform10.Path.Path;
|
|
1234
2094
|
const config = MANIFEST_CONFIG[language];
|
|
1235
2095
|
const filePath = pathService.join(projectFolder, config.file);
|
|
1236
2096
|
const manifest = yield* readManifest(filePath).pipe(
|
|
1237
|
-
|
|
2097
|
+
import_effect16.Effect.catchTag("ManifestNotFoundError", () => import_effect16.Effect.succeed(null))
|
|
1238
2098
|
);
|
|
1239
2099
|
if (!manifest) {
|
|
1240
2100
|
return /* @__PURE__ */ new Set();
|
|
@@ -1252,9 +2112,9 @@ var readDependencies = import_effect12.Effect.fn("readDependencies")(function* (
|
|
|
1252
2112
|
});
|
|
1253
2113
|
|
|
1254
2114
|
// src/detection/detect-framework.ts
|
|
1255
|
-
var matchesDetectionItem =
|
|
1256
|
-
const fs = yield*
|
|
1257
|
-
const pathService = yield*
|
|
2115
|
+
var matchesDetectionItem = import_effect17.Effect.fn("matchesDetectionItem")(function* (item, projectFolder, framework, cachedReadDeps) {
|
|
2116
|
+
const fs = yield* import_platform11.FileSystem.FileSystem;
|
|
2117
|
+
const pathService = yield* import_platform11.Path.Path;
|
|
1258
2118
|
if (item.matchPackage != null) {
|
|
1259
2119
|
const deps = yield* cachedReadDeps(`${projectFolder}\0${framework.language}`);
|
|
1260
2120
|
if (!deps.has(item.matchPackage)) {
|
|
@@ -1263,12 +2123,12 @@ var matchesDetectionItem = import_effect13.Effect.fn("matchesDetectionItem")(fun
|
|
|
1263
2123
|
}
|
|
1264
2124
|
if (item.path != null) {
|
|
1265
2125
|
const filePath = pathService.join(projectFolder, item.path);
|
|
1266
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2126
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect17.Effect.catchAll(() => import_effect17.Effect.succeed(false)));
|
|
1267
2127
|
if (!exists) {
|
|
1268
2128
|
return false;
|
|
1269
2129
|
}
|
|
1270
2130
|
if (item.matchContent != null) {
|
|
1271
|
-
const content = yield* fs.readFileString(filePath).pipe(
|
|
2131
|
+
const content = yield* fs.readFileString(filePath).pipe(import_effect17.Effect.catchAll(() => import_effect17.Effect.succeed("")));
|
|
1272
2132
|
let regexMatch = false;
|
|
1273
2133
|
try {
|
|
1274
2134
|
regexMatch = new RegExp(item.matchContent).test(content);
|
|
@@ -1281,7 +2141,7 @@ var matchesDetectionItem = import_effect13.Effect.fn("matchesDetectionItem")(fun
|
|
|
1281
2141
|
}
|
|
1282
2142
|
return true;
|
|
1283
2143
|
});
|
|
1284
|
-
var matchesFramework =
|
|
2144
|
+
var matchesFramework = import_effect17.Effect.fn("matchesFramework")(function* (framework, projectFolder, cachedReadDeps) {
|
|
1285
2145
|
for (const detector of framework.detectors) {
|
|
1286
2146
|
const matches = yield* matchesDetectionItem(detector, projectFolder, framework, cachedReadDeps);
|
|
1287
2147
|
if (!matches) {
|
|
@@ -1290,9 +2150,9 @@ var matchesFramework = import_effect13.Effect.fn("matchesFramework")(function* (
|
|
|
1290
2150
|
}
|
|
1291
2151
|
return true;
|
|
1292
2152
|
});
|
|
1293
|
-
var detectFramework =
|
|
1294
|
-
yield*
|
|
1295
|
-
const cachedReadDeps = yield*
|
|
2153
|
+
var detectFramework = import_effect17.Effect.fn("detectFramework")(function* (projectFolder) {
|
|
2154
|
+
yield* import_effect17.Effect.logDebug(`Detecting framework in ${projectFolder}`);
|
|
2155
|
+
const cachedReadDeps = yield* import_effect17.Effect.cachedFunction((key) => {
|
|
1296
2156
|
const sepIndex = key.lastIndexOf("\0");
|
|
1297
2157
|
const folder = key.slice(0, sepIndex);
|
|
1298
2158
|
const language = key.slice(sepIndex + 1);
|
|
@@ -1301,16 +2161,16 @@ var detectFramework = import_effect13.Effect.fn("detectFramework")(function* (pr
|
|
|
1301
2161
|
for (const framework of FRAMEWORK_DEFINITIONS) {
|
|
1302
2162
|
const matches = yield* matchesFramework(framework, projectFolder, cachedReadDeps);
|
|
1303
2163
|
if (matches) {
|
|
1304
|
-
yield*
|
|
2164
|
+
yield* import_effect17.Effect.log(`Detected framework: ${framework.name}`, { slug: framework.slug });
|
|
1305
2165
|
const detectedPackageManager = yield* detectPackageManager(projectFolder);
|
|
1306
2166
|
const packageManager = framework.language === "php" ? "composer" : detectedPackageManager;
|
|
1307
2167
|
const defaults = framework.getDefaultConfig(packageManager);
|
|
1308
2168
|
const refinedDefaults = framework.refineDefaultConfig ? yield* framework.refineDefaultConfig(defaults, projectFolder) : defaults;
|
|
1309
|
-
const config = yield* generateConfig(framework, packageManager, refinedDefaults);
|
|
2169
|
+
const config = yield* generateConfig(framework, packageManager, projectFolder, refinedDefaults);
|
|
1310
2170
|
return { framework, packageManager, config };
|
|
1311
2171
|
}
|
|
1312
2172
|
}
|
|
1313
|
-
return yield*
|
|
2173
|
+
return yield* import_effect17.Effect.fail(
|
|
1314
2174
|
new FrameworkNotDetectedError({
|
|
1315
2175
|
message: `No framework detected in project directory`,
|
|
1316
2176
|
directory: projectFolder
|
|
@@ -1319,15 +2179,22 @@ var detectFramework = import_effect13.Effect.fn("detectFramework")(function* (pr
|
|
|
1319
2179
|
});
|
|
1320
2180
|
|
|
1321
2181
|
// src/detection/merge-config.ts
|
|
1322
|
-
var
|
|
1323
|
-
var mergeWithFrameworkDefaults =
|
|
1324
|
-
yield*
|
|
2182
|
+
var import_effect18 = require("effect");
|
|
2183
|
+
var mergeWithFrameworkDefaults = import_effect18.Effect.fn("mergeWithFrameworkDefaults")(function* (userConfig, frameworkConfig) {
|
|
2184
|
+
yield* import_effect18.Effect.logDebug("Merging user config with framework defaults");
|
|
1325
2185
|
const userHasAssets = (userConfig.assets?.paths?.length ?? 0) > 0 || (userConfig.assets?.prefixes?.length ?? 0) > 0 || (userConfig.assets?.manifests?.length ?? 0) > 0;
|
|
2186
|
+
const isContainer = (entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME;
|
|
2187
|
+
const userFileFunctions = userConfig.entrypoints.filter((entrypoint) => !isContainer(entrypoint));
|
|
2188
|
+
const containerPaths = new Set(userConfig.entrypoints.filter(isContainer).map((entrypoint) => entrypoint.path));
|
|
2189
|
+
const targetsContainer = (route) => containerPaths.has(route.destination.replace(/^\/+/, ""));
|
|
1326
2190
|
const merged = {
|
|
1327
2191
|
regions: userConfig.regions,
|
|
1328
2192
|
commands: userConfig.commands.length > 0 ? userConfig.commands : frameworkConfig.commands,
|
|
1329
|
-
entrypoints:
|
|
1330
|
-
|
|
2193
|
+
entrypoints: [
|
|
2194
|
+
...userFileFunctions.length > 0 ? userFileFunctions : frameworkConfig.entrypoints,
|
|
2195
|
+
...userConfig.entrypoints.filter(isContainer)
|
|
2196
|
+
],
|
|
2197
|
+
routes: containerPaths.size > 0 && userConfig.routes.every(targetsContainer) ? [...userConfig.routes, ...frameworkConfig.routes] : userConfig.routes.length > 0 ? userConfig.routes : frameworkConfig.routes,
|
|
1331
2198
|
assets: userHasAssets ? userConfig.assets : frameworkConfig.assets,
|
|
1332
2199
|
environmentVariables: {
|
|
1333
2200
|
...frameworkConfig.environmentVariables,
|
|
@@ -1335,6 +2202,7 @@ var mergeWithFrameworkDefaults = import_effect14.Effect.fn("mergeWithFrameworkDe
|
|
|
1335
2202
|
},
|
|
1336
2203
|
excludeFiles: userConfig.excludeFiles && userConfig.excludeFiles.length > 0 ? userConfig.excludeFiles : frameworkConfig.excludeFiles,
|
|
1337
2204
|
services: userConfig.services,
|
|
2205
|
+
...userConfig.sidecars !== void 0 && { sidecars: userConfig.sidecars },
|
|
1338
2206
|
userArchive: userConfig.userArchive,
|
|
1339
2207
|
warnings: [...frameworkConfig.warnings, ...userConfig.warnings],
|
|
1340
2208
|
errors: [...frameworkConfig.errors, ...userConfig.errors]
|
|
@@ -1342,51 +2210,6 @@ var mergeWithFrameworkDefaults = import_effect14.Effect.fn("mergeWithFrameworkDe
|
|
|
1342
2210
|
return merged;
|
|
1343
2211
|
});
|
|
1344
2212
|
|
|
1345
|
-
// src/errors.ts
|
|
1346
|
-
var import_effect15 = require("effect");
|
|
1347
|
-
var ConfigFileNotFoundError = class extends import_effect15.Schema.TaggedError()("ConfigFileNotFoundError", {
|
|
1348
|
-
message: import_effect15.Schema.String,
|
|
1349
|
-
filePath: import_effect15.Schema.String
|
|
1350
|
-
}) {
|
|
1351
|
-
};
|
|
1352
|
-
var ConfigFileEmptyError = class extends import_effect15.Schema.TaggedError()("ConfigFileEmptyError", {
|
|
1353
|
-
message: import_effect15.Schema.String,
|
|
1354
|
-
filePath: import_effect15.Schema.String
|
|
1355
|
-
}) {
|
|
1356
|
-
};
|
|
1357
|
-
var ConfigFileParseError = class extends import_effect15.Schema.TaggedError()("ConfigFileParseError", {
|
|
1358
|
-
message: import_effect15.Schema.String,
|
|
1359
|
-
filePath: import_effect15.Schema.String,
|
|
1360
|
-
cause: import_effect15.Schema.optional(import_effect15.Schema.String)
|
|
1361
|
-
}) {
|
|
1362
|
-
};
|
|
1363
|
-
var ConfigModuleLoadError = class extends import_effect15.Schema.TaggedError()("ConfigModuleLoadError", {
|
|
1364
|
-
message: import_effect15.Schema.String,
|
|
1365
|
-
filePath: import_effect15.Schema.String,
|
|
1366
|
-
cause: import_effect15.Schema.optional(import_effect15.Schema.String)
|
|
1367
|
-
}) {
|
|
1368
|
-
};
|
|
1369
|
-
var ConfigVersionError = class extends import_effect15.Schema.TaggedError()("ConfigVersionError", {
|
|
1370
|
-
message: import_effect15.Schema.String,
|
|
1371
|
-
filePath: import_effect15.Schema.String,
|
|
1372
|
-
version: import_effect15.Schema.optional(import_effect15.Schema.Number)
|
|
1373
|
-
}) {
|
|
1374
|
-
};
|
|
1375
|
-
var ConfigSchemaValidationError = class extends import_effect15.Schema.TaggedError()(
|
|
1376
|
-
"ConfigSchemaValidationError",
|
|
1377
|
-
{
|
|
1378
|
-
message: import_effect15.Schema.String,
|
|
1379
|
-
filePath: import_effect15.Schema.String,
|
|
1380
|
-
validationErrors: import_effect15.Schema.Array(import_effect15.Schema.String)
|
|
1381
|
-
}
|
|
1382
|
-
) {
|
|
1383
|
-
};
|
|
1384
|
-
var FunctionConfigError = class extends import_effect15.Schema.TaggedError()("FunctionConfigError", {
|
|
1385
|
-
message: import_effect15.Schema.String,
|
|
1386
|
-
functionPath: import_effect15.Schema.String
|
|
1387
|
-
}) {
|
|
1388
|
-
};
|
|
1389
|
-
|
|
1390
2213
|
// src/filter-functions-from-assets.ts
|
|
1391
2214
|
var filterFunctionsFromAssets = (config) => {
|
|
1392
2215
|
return {
|
|
@@ -1398,28 +2221,24 @@ var filterFunctionsFromAssets = (config) => {
|
|
|
1398
2221
|
};
|
|
1399
2222
|
};
|
|
1400
2223
|
|
|
1401
|
-
// src/normalized-config.ts
|
|
1402
|
-
var DEFAULT_FUNCTION_DURATION_SECONDS = 30;
|
|
1403
|
-
var MAX_FUNCTION_DURATION_SECONDS = 28800;
|
|
1404
|
-
|
|
1405
2224
|
// src/parse-config.ts
|
|
1406
|
-
var
|
|
2225
|
+
var import_effect24 = require("effect");
|
|
1407
2226
|
|
|
1408
2227
|
// src/services/raw-config-reader.ts
|
|
1409
|
-
var
|
|
1410
|
-
var
|
|
1411
|
-
var
|
|
2228
|
+
var import_platform12 = require("@effect/platform");
|
|
2229
|
+
var import_effect20 = require("effect");
|
|
2230
|
+
var import_yaml2 = require("yaml");
|
|
1412
2231
|
|
|
1413
2232
|
// src/services/config-module-loader.ts
|
|
1414
|
-
var
|
|
2233
|
+
var import_effect19 = require("effect");
|
|
1415
2234
|
var import_jiti = require("jiti");
|
|
1416
2235
|
var MISSING_DEFAULT_EXPORT = /* @__PURE__ */ Symbol("MissingDefaultExport");
|
|
1417
2236
|
var STRICT_DEFAULT_EXPORT_EXTENSIONS = [".ts", ".mts", ".mjs"];
|
|
1418
|
-
var ConfigModuleLoader = class extends
|
|
1419
|
-
effect:
|
|
1420
|
-
const loadConfigModule =
|
|
2237
|
+
var ConfigModuleLoader = class extends import_effect19.Effect.Service()("ConfigModuleLoader", {
|
|
2238
|
+
effect: import_effect19.Effect.gen(function* () {
|
|
2239
|
+
const loadConfigModule = import_effect19.Effect.fn("ConfigModuleLoader.loadConfigModule")(function* (filePath) {
|
|
1421
2240
|
const extension = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
1422
|
-
const mod = yield*
|
|
2241
|
+
const mod = yield* import_effect19.Effect.tryPromise({
|
|
1423
2242
|
try: async () => {
|
|
1424
2243
|
const jiti = (0, import_jiti.createJiti)(filePath, { fsCache: false, interopDefault: true, moduleCache: false });
|
|
1425
2244
|
const namespace = await jiti.import(filePath);
|
|
@@ -1438,7 +2257,7 @@ var ConfigModuleLoader = class extends import_effect16.Effect.Service()("ConfigM
|
|
|
1438
2257
|
})
|
|
1439
2258
|
});
|
|
1440
2259
|
if (mod === MISSING_DEFAULT_EXPORT) {
|
|
1441
|
-
return yield*
|
|
2260
|
+
return yield* import_effect19.Effect.fail(
|
|
1442
2261
|
new ConfigModuleLoadError({
|
|
1443
2262
|
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.`,
|
|
1444
2263
|
filePath
|
|
@@ -1446,7 +2265,7 @@ var ConfigModuleLoader = class extends import_effect16.Effect.Service()("ConfigM
|
|
|
1446
2265
|
);
|
|
1447
2266
|
}
|
|
1448
2267
|
if (typeof mod === "function") {
|
|
1449
|
-
return yield*
|
|
2268
|
+
return yield* import_effect19.Effect.fail(
|
|
1450
2269
|
new ConfigModuleLoadError({
|
|
1451
2270
|
message: `Config module at ${filePath} default-exports a function; config factories are not supported. Export a config object instead (optionally wrapped in defineConfig).`,
|
|
1452
2271
|
filePath
|
|
@@ -1454,7 +2273,7 @@ var ConfigModuleLoader = class extends import_effect16.Effect.Service()("ConfigM
|
|
|
1454
2273
|
);
|
|
1455
2274
|
}
|
|
1456
2275
|
if (typeof mod !== "object" || mod === null || Array.isArray(mod)) {
|
|
1457
|
-
return yield*
|
|
2276
|
+
return yield* import_effect19.Effect.fail(
|
|
1458
2277
|
new ConfigModuleLoadError({
|
|
1459
2278
|
message: `Config module at ${filePath} must default-export a config object.`,
|
|
1460
2279
|
filePath
|
|
@@ -1484,36 +2303,36 @@ var ALLOWED_CONFIG_NAMES = [
|
|
|
1484
2303
|
"nebula.json"
|
|
1485
2304
|
];
|
|
1486
2305
|
var MODULE_EXTENSIONS = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
1487
|
-
var RawConfigReader = class extends
|
|
2306
|
+
var RawConfigReader = class extends import_effect20.Effect.Service()("RawConfigReader", {
|
|
1488
2307
|
dependencies: [ConfigModuleLoader.Default],
|
|
1489
|
-
effect:
|
|
1490
|
-
const fs = yield*
|
|
1491
|
-
const pathService = yield*
|
|
2308
|
+
effect: import_effect20.Effect.gen(function* () {
|
|
2309
|
+
const fs = yield* import_platform12.FileSystem.FileSystem;
|
|
2310
|
+
const pathService = yield* import_platform12.Path.Path;
|
|
1492
2311
|
const moduleLoader = yield* ConfigModuleLoader;
|
|
1493
|
-
const findConfig =
|
|
2312
|
+
const findConfig = import_effect20.Effect.fn("RawConfigReader.findConfig")(function* (projectFolder) {
|
|
1494
2313
|
for (const name of ALLOWED_CONFIG_NAMES) {
|
|
1495
2314
|
const filePath = pathService.join(projectFolder, name);
|
|
1496
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2315
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect20.Effect.catchAll(() => import_effect20.Effect.succeed(false)));
|
|
1497
2316
|
if (exists) {
|
|
1498
2317
|
return filePath;
|
|
1499
2318
|
}
|
|
1500
2319
|
}
|
|
1501
2320
|
return null;
|
|
1502
2321
|
});
|
|
1503
|
-
const readRawConfig =
|
|
1504
|
-
const exists = yield* fs.exists(filePath).pipe(
|
|
2322
|
+
const readRawConfig = import_effect20.Effect.fn("RawConfigReader.readRawConfig")(function* (filePath, options) {
|
|
2323
|
+
const exists = yield* fs.exists(filePath).pipe(import_effect20.Effect.catchAll(() => import_effect20.Effect.succeed(false)));
|
|
1505
2324
|
if (!exists) {
|
|
1506
|
-
return yield*
|
|
2325
|
+
return yield* import_effect20.Effect.fail(
|
|
1507
2326
|
new ConfigFileNotFoundError({ message: `Config file not found at ${filePath}`, filePath })
|
|
1508
2327
|
);
|
|
1509
2328
|
}
|
|
1510
2329
|
const fileContents = yield* fs.readFileString(filePath).pipe(
|
|
1511
|
-
|
|
2330
|
+
import_effect20.Effect.mapError(
|
|
1512
2331
|
() => new ConfigFileParseError({ message: `Failed to read config file at ${filePath}`, filePath })
|
|
1513
2332
|
)
|
|
1514
2333
|
);
|
|
1515
2334
|
if (fileContents.length === 0) {
|
|
1516
|
-
return yield*
|
|
2335
|
+
return yield* import_effect20.Effect.fail(
|
|
1517
2336
|
new ConfigFileEmptyError({ message: `Config file is empty at ${filePath}`, filePath })
|
|
1518
2337
|
);
|
|
1519
2338
|
}
|
|
@@ -1526,10 +2345,10 @@ var RawConfigReader = class extends import_effect17.Effect.Service()("RawConfigR
|
|
|
1526
2345
|
if (fileExtension === ".json") {
|
|
1527
2346
|
parsed = JSON.parse(fileContents);
|
|
1528
2347
|
} else {
|
|
1529
|
-
parsed = (0,
|
|
2348
|
+
parsed = (0, import_yaml2.parse)(fileContents);
|
|
1530
2349
|
}
|
|
1531
2350
|
} catch (error) {
|
|
1532
|
-
return yield*
|
|
2351
|
+
return yield* import_effect20.Effect.fail(
|
|
1533
2352
|
new ConfigFileParseError({
|
|
1534
2353
|
message: `Failed to parse config file at ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1535
2354
|
filePath,
|
|
@@ -1539,21 +2358,21 @@ var RawConfigReader = class extends import_effect17.Effect.Service()("RawConfigR
|
|
|
1539
2358
|
}
|
|
1540
2359
|
}
|
|
1541
2360
|
if (parsed == null) {
|
|
1542
|
-
return yield*
|
|
2361
|
+
return yield* import_effect20.Effect.fail(
|
|
1543
2362
|
new ConfigFileParseError({ message: `Config file could not be parsed at ${filePath}`, filePath })
|
|
1544
2363
|
);
|
|
1545
2364
|
}
|
|
1546
2365
|
if (!options?.disableVersionCheck && typeof parsed.version !== "number") {
|
|
1547
|
-
return yield*
|
|
2366
|
+
return yield* import_effect20.Effect.fail(
|
|
1548
2367
|
new ConfigVersionError({ message: `Config file is missing version at ${filePath}`, filePath })
|
|
1549
2368
|
);
|
|
1550
2369
|
}
|
|
1551
2370
|
return parsed;
|
|
1552
2371
|
});
|
|
1553
2372
|
const readConfigFile = (configFilePath) => readRawConfig(configFilePath, { disableVersionCheck: true }).pipe(
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
2373
|
+
import_effect20.Effect.map((parsed) => parsed),
|
|
2374
|
+
import_effect20.Effect.catchTag("ConfigFileNotFoundError", () => import_effect20.Effect.succeed(null)),
|
|
2375
|
+
import_effect20.Effect.withSpan("RawConfigReader.readConfigFile")
|
|
1557
2376
|
);
|
|
1558
2377
|
return { findConfig, readRawConfig, readConfigFile };
|
|
1559
2378
|
})
|
|
@@ -1563,17 +2382,17 @@ var RawConfigReader = class extends import_effect17.Effect.Service()("RawConfigR
|
|
|
1563
2382
|
// src/services/schema-validator.ts
|
|
1564
2383
|
var import_ajv = __toESM(require("ajv"));
|
|
1565
2384
|
var import_ajv_formats = __toESM(require("ajv-formats"));
|
|
1566
|
-
var
|
|
1567
|
-
var SchemaValidator = class extends
|
|
1568
|
-
effect:
|
|
2385
|
+
var import_effect21 = require("effect");
|
|
2386
|
+
var SchemaValidator = class extends import_effect21.Effect.Service()("SchemaValidator", {
|
|
2387
|
+
effect: import_effect21.Effect.gen(function* () {
|
|
1569
2388
|
const ajv = new import_ajv.default();
|
|
1570
2389
|
(0, import_ajv_formats.default)(ajv);
|
|
1571
|
-
const validate =
|
|
2390
|
+
const validate = import_effect21.Effect.fn("SchemaValidator.validate")(function* (config, schema, filePath) {
|
|
1572
2391
|
const compiledValidate = ajv.compile(schema);
|
|
1573
2392
|
const valid = compiledValidate(config);
|
|
1574
2393
|
if (!valid) {
|
|
1575
2394
|
const errors = compiledValidate.errors?.map((e) => `${e.instancePath || "/"} ${e.message ?? ""}`.trim()) ?? [];
|
|
1576
|
-
return yield*
|
|
2395
|
+
return yield* import_effect21.Effect.fail(
|
|
1577
2396
|
new ConfigSchemaValidationError({
|
|
1578
2397
|
message: `Config file at ${filePath} is invalid: ${ajv.errorsText(compiledValidate.errors)}`,
|
|
1579
2398
|
filePath,
|
|
@@ -1587,9 +2406,6 @@ var SchemaValidator = class extends import_effect18.Effect.Service()("SchemaVali
|
|
|
1587
2406
|
}) {
|
|
1588
2407
|
};
|
|
1589
2408
|
|
|
1590
|
-
// src/services/v4-config-parser.ts
|
|
1591
|
-
var import_platform10 = require("@effect/platform");
|
|
1592
|
-
|
|
1593
2409
|
// ../build-utils/src/get-files-for-pattern.ts
|
|
1594
2410
|
var import_minimatch = require("minimatch");
|
|
1595
2411
|
var import_promises = require("fs/promises");
|
|
@@ -1632,11 +2448,10 @@ var getFilesForPattern = async (pattern, projectFolder, excludeFiles = []) => {
|
|
|
1632
2448
|
};
|
|
1633
2449
|
|
|
1634
2450
|
// src/services/v4-config-parser.ts
|
|
1635
|
-
var
|
|
2451
|
+
var import_effect22 = require("effect");
|
|
1636
2452
|
var import_minimatch2 = require("minimatch");
|
|
2453
|
+
var import_node_path2 = require("path");
|
|
1637
2454
|
var import_safe_regex2 = __toESM(require("safe-regex2"));
|
|
1638
|
-
var MAX_ASSET_DEPTH = 100;
|
|
1639
|
-
var DISALLOWED_ASSET_EXTENSIONS = [".htaccess", ".htpasswd"];
|
|
1640
2455
|
var DEFAULT_FUNCTION_SETTINGS = {
|
|
1641
2456
|
memory: 128,
|
|
1642
2457
|
max_duration: DEFAULT_FUNCTION_DURATION_SECONDS,
|
|
@@ -1668,6 +2483,46 @@ var normalizeImagePolicy = (images) => {
|
|
|
1668
2483
|
variants: images.variants ?? {}
|
|
1669
2484
|
};
|
|
1670
2485
|
};
|
|
2486
|
+
var DURATION_UNIT_SECONDS = { s: 1, m: 60, h: 3600, d: 86400 };
|
|
2487
|
+
var queueDurationSeconds = (value) => {
|
|
2488
|
+
if (value === void 0) return void 0;
|
|
2489
|
+
if (typeof value === "number") return value;
|
|
2490
|
+
const match = /^(\d+(?:\.\d+)?)(s|m|h|d)$/.exec(value);
|
|
2491
|
+
if (!match)
|
|
2492
|
+
throw new Error(`Invalid queue duration "${value}". Use seconds or a string such as 30s, 10m, 1.5h or 4d.`);
|
|
2493
|
+
return Math.ceil(Number(match[1]) * DURATION_UNIT_SECONDS[match[2]]);
|
|
2494
|
+
};
|
|
2495
|
+
var byName = (left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
|
|
2496
|
+
var definedOnly = (value) => Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
2497
|
+
var normalizeQueue = (name, queue) => {
|
|
2498
|
+
if (queue === null) return { name };
|
|
2499
|
+
const schedules = queue.schedules ? Object.entries(queue.schedules).map(
|
|
2500
|
+
([scheduleName, schedule]) => definedOnly({
|
|
2501
|
+
name: scheduleName,
|
|
2502
|
+
cron: schedule.cron,
|
|
2503
|
+
timezone: schedule.timezone,
|
|
2504
|
+
body: schedule.body === void 0 || typeof schedule.body === "string" ? schedule.body : JSON.stringify(schedule.body),
|
|
2505
|
+
// A plain-text body labelled JSON would fail to decode on every fire.
|
|
2506
|
+
contentType: schedule.contentType ?? (typeof schedule.body === "string" ? "text/plain; charset=utf-8" : void 0),
|
|
2507
|
+
headers: schedule.headers,
|
|
2508
|
+
enabled: schedule.enabled
|
|
2509
|
+
})
|
|
2510
|
+
).sort(byName) : void 0;
|
|
2511
|
+
return definedOnly({
|
|
2512
|
+
name,
|
|
2513
|
+
consumer: queue.consumer,
|
|
2514
|
+
visibilityTimeoutSeconds: queueDurationSeconds(queue.visibilityTimeout),
|
|
2515
|
+
retentionSeconds: queueDurationSeconds(queue.retention),
|
|
2516
|
+
maxAttempts: queue.maxAttempts,
|
|
2517
|
+
retryBackoffMinSeconds: queueDurationSeconds(queue.retryBackoff?.min),
|
|
2518
|
+
retryBackoffMaxSeconds: queueDurationSeconds(queue.retryBackoff?.max),
|
|
2519
|
+
deduplicationWindowSeconds: queueDurationSeconds(queue.deduplicationWindow),
|
|
2520
|
+
concurrency: queue.concurrency,
|
|
2521
|
+
rateLimit: queue.rateLimit == null ? queue.rateLimit : { count: queue.rateLimit.count, periodSeconds: queueDurationSeconds(queue.rateLimit.period) ?? 1 },
|
|
2522
|
+
deadLetter: queue.deadLetter,
|
|
2523
|
+
schedules
|
|
2524
|
+
});
|
|
2525
|
+
};
|
|
1671
2526
|
var normalizeServices = (services) => {
|
|
1672
2527
|
if (services == null) return void 0;
|
|
1673
2528
|
const normalized = [];
|
|
@@ -1680,7 +2535,13 @@ var normalizeServices = (services) => {
|
|
|
1680
2535
|
if (services.storage !== void 0) {
|
|
1681
2536
|
normalized.push({
|
|
1682
2537
|
type: "storage",
|
|
1683
|
-
buckets: Object.entries(services.storage.buckets).map(([name, bucket]) => ({ name, visibility: bucket?.visibility ?? "private" })).sort(
|
|
2538
|
+
buckets: Object.entries(services.storage.buckets).map(([name, bucket]) => ({ name, visibility: bucket?.visibility ?? "private" })).sort(byName)
|
|
2539
|
+
});
|
|
2540
|
+
}
|
|
2541
|
+
if (services.queues !== void 0) {
|
|
2542
|
+
normalized.push({
|
|
2543
|
+
type: "queues",
|
|
2544
|
+
queues: Object.entries(services.queues).map(([name, queue]) => normalizeQueue(name, queue)).sort(byName)
|
|
1684
2545
|
});
|
|
1685
2546
|
}
|
|
1686
2547
|
return normalized.length > 0 ? normalized : void 0;
|
|
@@ -1738,9 +2599,10 @@ var mapRoute = (route, entrypoints) => ({
|
|
|
1738
2599
|
negativeRequirements: route.missing,
|
|
1739
2600
|
status: route.statusCode
|
|
1740
2601
|
});
|
|
1741
|
-
var parseEntrypoints =
|
|
2602
|
+
var parseEntrypoints = import_effect22.Effect.fn("parseEntrypoints")(function* (config, projectFolder) {
|
|
1742
2603
|
const entrypoints = [];
|
|
1743
|
-
|
|
2604
|
+
const dockerFunctions = [];
|
|
2605
|
+
if (config.functions == null) return { entrypoints, dockerFunctions };
|
|
1744
2606
|
for (const [fnPath, func] of Object.entries(config.functions)) {
|
|
1745
2607
|
if (getFunctionSettings(fnPath, config) == null) {
|
|
1746
2608
|
return yield* new FunctionConfigError({
|
|
@@ -1748,7 +2610,7 @@ var parseEntrypoints = import_effect19.Effect.fn("parseEntrypoints")(function* (
|
|
|
1748
2610
|
functionPath: fnPath
|
|
1749
2611
|
});
|
|
1750
2612
|
}
|
|
1751
|
-
const matchedFiles = yield*
|
|
2613
|
+
const matchedFiles = yield* import_effect22.Effect.tryPromise({
|
|
1752
2614
|
try: () => getFilesForPattern(fnPath, projectFolder, func.excludeFiles),
|
|
1753
2615
|
catch: (error) => new FunctionConfigError({
|
|
1754
2616
|
message: `Failed to resolve files for function pattern '${fnPath}': ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -1765,6 +2627,35 @@ var parseEntrypoints = import_effect19.Effect.fn("parseEntrypoints")(function* (
|
|
|
1765
2627
|
functionPath: file
|
|
1766
2628
|
});
|
|
1767
2629
|
}
|
|
2630
|
+
if (settings.runtime === CONTAINER_RUNTIME) {
|
|
2631
|
+
const unsupported = ["symlinks", "includeFiles"].filter((key) => settings[key] !== void 0);
|
|
2632
|
+
if (unsupported.length > 0) {
|
|
2633
|
+
return yield* new FunctionConfigError({
|
|
2634
|
+
message: `Function '${file}' runs a Dockerfile, so ${unsupported.join(" and ")} do not apply. Copy files in the Dockerfile instead.`,
|
|
2635
|
+
functionPath: file
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
const declared = Object.entries(config.functions).filter(([pattern]) => matchesPattern(file, pattern)).reduce((merged, [, value]) => ({ ...merged, ...value }), {});
|
|
2639
|
+
dockerFunctions.push({
|
|
2640
|
+
file,
|
|
2641
|
+
name: dockerFunctionContainerName(file),
|
|
2642
|
+
container: {
|
|
2643
|
+
build: { context: import_node_path2.posix.dirname(file), dockerfile: import_node_path2.posix.basename(file) },
|
|
2644
|
+
...declared.port !== void 0 && { port: declared.port },
|
|
2645
|
+
...declared.memory !== void 0 && { memory: declared.memory },
|
|
2646
|
+
...declared.max_duration !== void 0 && { max_duration: declared.max_duration },
|
|
2647
|
+
...declared.streaming !== void 0 && { streaming: declared.streaming },
|
|
2648
|
+
...func.schedule !== void 0 && { schedule: func.schedule }
|
|
2649
|
+
}
|
|
2650
|
+
});
|
|
2651
|
+
continue;
|
|
2652
|
+
}
|
|
2653
|
+
if (settings.port !== void 0) {
|
|
2654
|
+
return yield* new FunctionConfigError({
|
|
2655
|
+
message: `Function '${file}' sets port, which only applies to 'runtime: docker'.`,
|
|
2656
|
+
functionPath: file
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
1768
2659
|
const runtime = settings.runtime ?? "node-20";
|
|
1769
2660
|
const streaming = settings.streaming ?? runtimeStreamsByDefault(runtime);
|
|
1770
2661
|
entrypoints.push({
|
|
@@ -1782,61 +2673,84 @@ var parseEntrypoints = import_effect19.Effect.fn("parseEntrypoints")(function* (
|
|
|
1782
2673
|
});
|
|
1783
2674
|
}
|
|
1784
2675
|
}
|
|
1785
|
-
|
|
2676
|
+
dockerFunctions.sort((left, right) => left.file < right.file ? -1 : left.file > right.file ? 1 : 0);
|
|
2677
|
+
for (const [index, { file, name }] of dockerFunctions.entries()) {
|
|
2678
|
+
const clash = dockerFunctions.slice(0, index).find((candidate) => candidate.name === name);
|
|
2679
|
+
if (clash !== void 0) {
|
|
2680
|
+
return yield* new FunctionConfigError({
|
|
2681
|
+
message: `Functions '${clash.file}' and '${file}' would both be named '${name}'. Declare one of them under 'containers' with an explicit name.`,
|
|
2682
|
+
functionPath: file
|
|
2683
|
+
});
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
return { entrypoints, dockerFunctions };
|
|
1786
2687
|
});
|
|
1787
|
-
var collectAssets =
|
|
2688
|
+
var collectAssets = import_effect22.Effect.fn("collectAssets")(function* (config, projectFolder) {
|
|
1788
2689
|
if (config.assets == null) return [];
|
|
1789
|
-
const
|
|
1790
|
-
|
|
1791
|
-
const assetsPath = pathService.join(projectFolder, config.assets);
|
|
1792
|
-
const assetsExist = yield* fs.exists(assetsPath).pipe(import_effect19.Effect.catchAll(() => import_effect19.Effect.succeed(false)));
|
|
1793
|
-
if (!assetsExist) return [];
|
|
1794
|
-
const stat = yield* fs.stat(assetsPath).pipe(import_effect19.Effect.catchAll(() => import_effect19.Effect.succeed(null)));
|
|
1795
|
-
if (!stat || stat.type !== "Directory") return [];
|
|
1796
|
-
const allFiles = yield* collectFilesRecursively(assetsPath);
|
|
1797
|
-
const assets = [];
|
|
1798
|
-
for (const assetName of allFiles) {
|
|
1799
|
-
if (DISALLOWED_ASSET_EXTENSIONS.some((ext) => assetName.toLowerCase().endsWith(ext.toLowerCase()))) continue;
|
|
1800
|
-
if (getFunctionSettings(`${config.assets}/${assetName}`, config) != null) continue;
|
|
1801
|
-
assets.push(`${config.assets}/${assetName}`);
|
|
1802
|
-
}
|
|
1803
|
-
return assets;
|
|
2690
|
+
const assetNames = yield* collectAssetFiles(projectFolder, config.assets);
|
|
2691
|
+
return assetNames.filter((assetName) => getFunctionSettings(`${config.assets}/${assetName}`, config) == null).map((assetName) => `${config.assets}/${assetName}`);
|
|
1804
2692
|
});
|
|
1805
|
-
var
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
const
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
2693
|
+
var reservedRuntimePorts = (entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME ? [] : entrypoint.runtime.startsWith("php-") ? [8080, 9e3] : [8080];
|
|
2694
|
+
var parseContainers = import_effect22.Effect.fn("parseContainers")(function* (config, projectFolder, fileEntrypoints, dockerFunctions) {
|
|
2695
|
+
const warnings = [];
|
|
2696
|
+
let containers = {};
|
|
2697
|
+
if (config.compose != null) {
|
|
2698
|
+
const imported = yield* readComposeContainers(config.compose, projectFolder);
|
|
2699
|
+
containers = imported.containers;
|
|
2700
|
+
warnings.push(...imported.warnings);
|
|
2701
|
+
}
|
|
2702
|
+
containers = { ...containers, ...config.containers ?? {} };
|
|
2703
|
+
for (const { file, name, container } of dockerFunctions) {
|
|
2704
|
+
if (containers[name] !== void 0) {
|
|
2705
|
+
return yield* new ContainerConfigError({
|
|
2706
|
+
message: `Function '${file}' runs as container '${name}', which 'containers' or the Compose file already declares. Rename one of them.`,
|
|
2707
|
+
containerName: name
|
|
2708
|
+
});
|
|
2709
|
+
}
|
|
2710
|
+
containers[name] = container;
|
|
2711
|
+
}
|
|
2712
|
+
const result = yield* normalizeContainers(containers, projectFolder);
|
|
2713
|
+
warnings.push(...result.warnings);
|
|
2714
|
+
for (const entrypoint of fileEntrypoints) {
|
|
2715
|
+
for (const port of reservedRuntimePorts(entrypoint)) {
|
|
2716
|
+
const sidecar = result.sidecars.find((candidate) => candidate.port === port);
|
|
2717
|
+
if (sidecar !== void 0) {
|
|
2718
|
+
return yield* new ContainerConfigError({
|
|
2719
|
+
message: `Sidecar '${sidecar.name}' listens on port ${port}, which the ${entrypoint.runtime} runtime of '${entrypoint.path}' uses inside the same microVM. Choose another port.`,
|
|
2720
|
+
containerName: sidecar.name
|
|
2721
|
+
});
|
|
1823
2722
|
}
|
|
1824
2723
|
}
|
|
1825
|
-
return result;
|
|
1826
2724
|
}
|
|
1827
|
-
|
|
1828
|
-
|
|
2725
|
+
return { ...result, warnings };
|
|
2726
|
+
});
|
|
2727
|
+
var V4ConfigParser = class extends import_effect22.Effect.Service()("V4ConfigParser", {
|
|
1829
2728
|
accessors: true,
|
|
1830
|
-
effect:
|
|
2729
|
+
effect: import_effect22.Effect.succeed({
|
|
1831
2730
|
/**
|
|
1832
2731
|
* Parses a ConfigV4 into a NormalizedConfig.
|
|
1833
2732
|
*
|
|
1834
2733
|
* @param config - The raw V4 config object
|
|
1835
2734
|
* @param projectFolder - Absolute path to the project root
|
|
1836
2735
|
*/
|
|
1837
|
-
parse:
|
|
1838
|
-
const entrypoints = yield* parseEntrypoints(config, projectFolder);
|
|
2736
|
+
parse: import_effect22.Effect.fn("V4ConfigParser.parse")(function* (config, projectFolder) {
|
|
2737
|
+
const { entrypoints: fileEntrypoints, dockerFunctions } = yield* parseEntrypoints(config, projectFolder);
|
|
2738
|
+
const containers = yield* parseContainers(config, projectFolder, fileEntrypoints, dockerFunctions);
|
|
2739
|
+
const entrypoints = [...fileEntrypoints, ...containers.entrypoints];
|
|
1839
2740
|
const assets = yield* collectAssets(config, projectFolder);
|
|
2741
|
+
const dockerFunctionPaths = new Map(
|
|
2742
|
+
dockerFunctions.map(({ file, name }) => [file, containerEntrypointPath(name)])
|
|
2743
|
+
);
|
|
2744
|
+
const routes = (config.routes ?? []).map(
|
|
2745
|
+
(route) => mapRoute(
|
|
2746
|
+
{
|
|
2747
|
+
...route,
|
|
2748
|
+
destination: dockerFunctionPaths.get(normalizeRouteDestination(route.destination)) ?? route.destination
|
|
2749
|
+
},
|
|
2750
|
+
entrypoints
|
|
2751
|
+
)
|
|
2752
|
+
);
|
|
2753
|
+
const warnings = [...containers.warnings];
|
|
1840
2754
|
return {
|
|
1841
2755
|
regions: resolveRegions(config.regions),
|
|
1842
2756
|
assets: {
|
|
@@ -1849,10 +2763,11 @@ var V4ConfigParser = class extends import_effect19.Effect.Service()("V4ConfigPar
|
|
|
1849
2763
|
commands: config.build_commands ?? [],
|
|
1850
2764
|
images: normalizeImagePolicy(config.images),
|
|
1851
2765
|
services: normalizeServices(config.services),
|
|
2766
|
+
...containers.sidecars.length > 0 && { sidecars: containers.sidecars },
|
|
1852
2767
|
entrypoints,
|
|
1853
2768
|
errors: [],
|
|
1854
|
-
warnings
|
|
1855
|
-
routes
|
|
2769
|
+
warnings,
|
|
2770
|
+
routes
|
|
1856
2771
|
};
|
|
1857
2772
|
})
|
|
1858
2773
|
})
|
|
@@ -1860,7 +2775,7 @@ var V4ConfigParser = class extends import_effect19.Effect.Service()("V4ConfigPar
|
|
|
1860
2775
|
};
|
|
1861
2776
|
|
|
1862
2777
|
// src/services/vercel-build-output-parser.ts
|
|
1863
|
-
var
|
|
2778
|
+
var import_platform13 = require("@effect/platform");
|
|
1864
2779
|
|
|
1865
2780
|
// ../commons/src/deep-merge.ts
|
|
1866
2781
|
var deepMerge = (target, ...partials) => {
|
|
@@ -1889,7 +2804,7 @@ var deepMerge = (target, ...partials) => {
|
|
|
1889
2804
|
};
|
|
1890
2805
|
|
|
1891
2806
|
// src/services/vercel-build-output-parser.ts
|
|
1892
|
-
var
|
|
2807
|
+
var import_effect23 = require("effect");
|
|
1893
2808
|
|
|
1894
2809
|
// src/build-output-v3/determine-repo-root.ts
|
|
1895
2810
|
var import_path = __toESM(require("path"));
|
|
@@ -1985,11 +2900,11 @@ var translateVercelRuntime = (runtime) => {
|
|
|
1985
2900
|
var CONFIG_PATH = ".vercel/output/config.json";
|
|
1986
2901
|
var FUNCTIONS_FOLDER = ".vercel/output/functions";
|
|
1987
2902
|
var FUNCTION_CONFIGS_PATTERN = `${FUNCTIONS_FOLDER}/**/*.func/.vc-config.json`;
|
|
1988
|
-
var VercelBuildOutputParser = class extends
|
|
1989
|
-
effect:
|
|
2903
|
+
var VercelBuildOutputParser = class extends import_effect23.Effect.Service()("VercelBuildOutputParser", {
|
|
2904
|
+
effect: import_effect23.Effect.gen(function* () {
|
|
1990
2905
|
const rawConfigReader = yield* RawConfigReader;
|
|
1991
|
-
const pathService = yield*
|
|
1992
|
-
const parse =
|
|
2906
|
+
const pathService = yield* import_platform13.Path.Path;
|
|
2907
|
+
const parse = import_effect23.Effect.fn("VercelBuildOutputParser.parse")(function* (parseResult, projectFolder) {
|
|
1993
2908
|
const config = yield* rawConfigReader.readConfigFile(pathService.join(projectFolder, CONFIG_PATH));
|
|
1994
2909
|
if (!config || typeof config.version !== "number" || config.version < 3) {
|
|
1995
2910
|
return parseResult;
|
|
@@ -2001,8 +2916,8 @@ var VercelBuildOutputParser = class extends import_effect20.Effect.Service()("Ve
|
|
|
2001
2916
|
merged.regions = [...new Set(merged.regions)];
|
|
2002
2917
|
return merged;
|
|
2003
2918
|
});
|
|
2004
|
-
const loadFunctions =
|
|
2005
|
-
const functionConfigs = yield*
|
|
2919
|
+
const loadFunctions = import_effect23.Effect.fn("VercelBuildOutputParser.loadFunctions")(function* (config, parseResult, projectFolder) {
|
|
2920
|
+
const functionConfigs = yield* import_effect23.Effect.tryPromise({
|
|
2006
2921
|
try: () => getFilesForPattern(FUNCTION_CONFIGS_PATTERN, projectFolder),
|
|
2007
2922
|
catch: (error) => new ConfigFileParseError({
|
|
2008
2923
|
message: `Failed to scan for function configs: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -2288,17 +3203,22 @@ var schema_default = {
|
|
|
2288
3203
|
minimum: 1
|
|
2289
3204
|
},
|
|
2290
3205
|
runtime: {
|
|
2291
|
-
$ref: "#/$defs/runtimes",
|
|
2292
|
-
description: "The runtime to use for the function."
|
|
3206
|
+
anyOf: [{ $ref: "#/$defs/runtimes" }, { const: "docker" }],
|
|
3207
|
+
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."
|
|
3208
|
+
},
|
|
3209
|
+
port: {
|
|
3210
|
+
type: "integer",
|
|
3211
|
+
minimum: 1,
|
|
3212
|
+
maximum: 65535,
|
|
3213
|
+
description: "TCP port the image listens on. Only for `runtime: docker`. Defaults to the first exposed port of the image, then 8080."
|
|
2293
3214
|
},
|
|
2294
3215
|
streaming: {
|
|
2295
3216
|
type: "boolean",
|
|
2296
3217
|
description: "Enable function response streaming. When omitted, Node and Bun runtimes stream by default."
|
|
2297
3218
|
},
|
|
2298
3219
|
schedule: {
|
|
2299
|
-
|
|
2300
|
-
description: "An expression to schedule the function to run at specific times."
|
|
2301
|
-
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]+))?)*)[)])$"
|
|
3220
|
+
$ref: "#/$defs/schedule",
|
|
3221
|
+
description: "An expression to schedule the function to run at specific times."
|
|
2302
3222
|
},
|
|
2303
3223
|
symlinks: {
|
|
2304
3224
|
type: "object",
|
|
@@ -2390,6 +3310,151 @@ var schema_default = {
|
|
|
2390
3310
|
}
|
|
2391
3311
|
}
|
|
2392
3312
|
},
|
|
3313
|
+
compose: {
|
|
3314
|
+
type: ["string", "null"],
|
|
3315
|
+
minLength: 1,
|
|
3316
|
+
maxLength: 1024,
|
|
3317
|
+
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."
|
|
3318
|
+
},
|
|
3319
|
+
containers: {
|
|
3320
|
+
type: ["object", "null"],
|
|
3321
|
+
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>`.",
|
|
3322
|
+
maxProperties: 16,
|
|
3323
|
+
propertyNames: {
|
|
3324
|
+
pattern: "^[a-z][a-z0-9_-]{0,62}$",
|
|
3325
|
+
not: {
|
|
3326
|
+
enum: ["localhost"]
|
|
3327
|
+
}
|
|
3328
|
+
},
|
|
3329
|
+
additionalProperties: {
|
|
3330
|
+
type: "object",
|
|
3331
|
+
additionalProperties: false,
|
|
3332
|
+
oneOf: [
|
|
3333
|
+
{
|
|
3334
|
+
required: ["image"]
|
|
3335
|
+
},
|
|
3336
|
+
{
|
|
3337
|
+
required: ["build"]
|
|
3338
|
+
}
|
|
3339
|
+
],
|
|
3340
|
+
properties: {
|
|
3341
|
+
image: {
|
|
3342
|
+
type: "string",
|
|
3343
|
+
minLength: 1,
|
|
3344
|
+
maxLength: 512,
|
|
3345
|
+
pattern: "^[^\\s]+$",
|
|
3346
|
+
description: "Registry image reference, e.g. `redis:7-alpine` or `ghcr.io/acme/api:1.4`."
|
|
3347
|
+
},
|
|
3348
|
+
build: {
|
|
3349
|
+
description: "Build context directory, or the full build settings, for a Dockerfile in the repository.",
|
|
3350
|
+
oneOf: [
|
|
3351
|
+
{
|
|
3352
|
+
type: "string",
|
|
3353
|
+
minLength: 1,
|
|
3354
|
+
maxLength: 1024
|
|
3355
|
+
},
|
|
3356
|
+
{
|
|
3357
|
+
type: "object",
|
|
3358
|
+
additionalProperties: false,
|
|
3359
|
+
properties: {
|
|
3360
|
+
context: {
|
|
3361
|
+
type: "string",
|
|
3362
|
+
minLength: 1,
|
|
3363
|
+
maxLength: 1024
|
|
3364
|
+
},
|
|
3365
|
+
dockerfile: {
|
|
3366
|
+
type: "string",
|
|
3367
|
+
minLength: 1,
|
|
3368
|
+
maxLength: 1024
|
|
3369
|
+
},
|
|
3370
|
+
target: {
|
|
3371
|
+
type: "string",
|
|
3372
|
+
minLength: 1,
|
|
3373
|
+
maxLength: 128
|
|
3374
|
+
},
|
|
3375
|
+
args: {
|
|
3376
|
+
type: "object",
|
|
3377
|
+
maxProperties: 100,
|
|
3378
|
+
additionalProperties: {
|
|
3379
|
+
type: "string",
|
|
3380
|
+
maxLength: 65536
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
]
|
|
3386
|
+
},
|
|
3387
|
+
sidecar: {
|
|
3388
|
+
type: "boolean",
|
|
3389
|
+
description: "Run next to every function instance instead of serving routes. Defaults to false."
|
|
3390
|
+
},
|
|
3391
|
+
port: {
|
|
3392
|
+
type: "integer",
|
|
3393
|
+
minimum: 1,
|
|
3394
|
+
maximum: 65535,
|
|
3395
|
+
description: "TCP port the container listens on. Defaults to the first exposed port of the image, then 8080."
|
|
3396
|
+
},
|
|
3397
|
+
entrypoint: {
|
|
3398
|
+
$ref: "#/$defs/stringOrStringArray",
|
|
3399
|
+
description: "Replaces the image ENTRYPOINT. A string is split into words the way Compose splits it."
|
|
3400
|
+
},
|
|
3401
|
+
command: {
|
|
3402
|
+
$ref: "#/$defs/stringOrStringArray",
|
|
3403
|
+
description: "Replaces the image CMD. A string is split into words the way Compose splits it."
|
|
3404
|
+
},
|
|
3405
|
+
env: {
|
|
3406
|
+
type: "object",
|
|
3407
|
+
maxProperties: 100,
|
|
3408
|
+
additionalProperties: {
|
|
3409
|
+
type: "string",
|
|
3410
|
+
maxLength: 65536
|
|
3411
|
+
},
|
|
3412
|
+
description: "Environment variables baked into the container, merged over the image ENV."
|
|
3413
|
+
},
|
|
3414
|
+
working_dir: {
|
|
3415
|
+
type: "string",
|
|
3416
|
+
minLength: 1,
|
|
3417
|
+
maxLength: 1024,
|
|
3418
|
+
pattern: "^/",
|
|
3419
|
+
description: "Replaces the image WORKDIR. Must be absolute."
|
|
3420
|
+
},
|
|
3421
|
+
user: {
|
|
3422
|
+
oneOf: [
|
|
3423
|
+
{
|
|
3424
|
+
type: "string",
|
|
3425
|
+
minLength: 1,
|
|
3426
|
+
maxLength: 256
|
|
3427
|
+
},
|
|
3428
|
+
{
|
|
3429
|
+
type: "integer",
|
|
3430
|
+
minimum: 0
|
|
3431
|
+
}
|
|
3432
|
+
],
|
|
3433
|
+
description: "Replaces the image USER: a name, a uid, `name:group` or `uid:gid`. A bare uid may be a number."
|
|
3434
|
+
},
|
|
3435
|
+
memory: {
|
|
3436
|
+
type: "integer",
|
|
3437
|
+
minimum: 128,
|
|
3438
|
+
maximum: 3009,
|
|
3439
|
+
description: "Memory in MB. Defaults to 512 for a container function and 256 for a sidecar."
|
|
3440
|
+
},
|
|
3441
|
+
max_duration: {
|
|
3442
|
+
type: "number",
|
|
3443
|
+
minimum: 1,
|
|
3444
|
+
maximum: 28800,
|
|
3445
|
+
description: "Maximum lifetime in seconds of one request. Container functions only."
|
|
3446
|
+
},
|
|
3447
|
+
streaming: {
|
|
3448
|
+
type: "boolean",
|
|
3449
|
+
description: "Stream responses. Defaults to true. Container functions only."
|
|
3450
|
+
},
|
|
3451
|
+
schedule: {
|
|
3452
|
+
$ref: "#/$defs/schedule",
|
|
3453
|
+
description: "An expression to run the container function at specific times. Container functions only."
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
},
|
|
2393
3458
|
services: {
|
|
2394
3459
|
type: "object",
|
|
2395
3460
|
description: "Managed services to provision for the deployment environment.",
|
|
@@ -2540,11 +3605,179 @@ var schema_default = {
|
|
|
2540
3605
|
}
|
|
2541
3606
|
}
|
|
2542
3607
|
}
|
|
3608
|
+
},
|
|
3609
|
+
queues: {
|
|
3610
|
+
type: "object",
|
|
3611
|
+
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.",
|
|
3612
|
+
propertyNames: {
|
|
3613
|
+
maxLength: 255,
|
|
3614
|
+
pattern: "^[A-Za-z0-9_][A-Za-z0-9_.~:@+=-]*$"
|
|
3615
|
+
},
|
|
3616
|
+
additionalProperties: {
|
|
3617
|
+
oneOf: [
|
|
3618
|
+
{
|
|
3619
|
+
type: "null"
|
|
3620
|
+
},
|
|
3621
|
+
{
|
|
3622
|
+
type: "object",
|
|
3623
|
+
additionalProperties: false,
|
|
3624
|
+
properties: {
|
|
3625
|
+
consumer: {
|
|
3626
|
+
type: ["string", "null"],
|
|
3627
|
+
pattern: "^/(?!/)\\S*$",
|
|
3628
|
+
maxLength: 2048,
|
|
3629
|
+
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."
|
|
3630
|
+
},
|
|
3631
|
+
visibilityTimeout: {
|
|
3632
|
+
$ref: "#/$defs/queueDuration",
|
|
3633
|
+
description: "How long a push delivery may run, or how long a received message stays leased. Defaults to 60 seconds, at most 12 hours."
|
|
3634
|
+
},
|
|
3635
|
+
retention: {
|
|
3636
|
+
$ref: "#/$defs/queueDuration",
|
|
3637
|
+
description: "How long an undelivered message is kept. Defaults to 4 days, at most 14 days."
|
|
3638
|
+
},
|
|
3639
|
+
maxAttempts: {
|
|
3640
|
+
type: "integer",
|
|
3641
|
+
minimum: 1,
|
|
3642
|
+
maximum: 100,
|
|
3643
|
+
description: "Deliveries per message before it moves to the dead-letter list. Defaults to 10."
|
|
3644
|
+
},
|
|
3645
|
+
retryBackoff: {
|
|
3646
|
+
type: "object",
|
|
3647
|
+
additionalProperties: false,
|
|
3648
|
+
description: "Exponential backoff between failed deliveries. Defaults to 5 seconds, doubling up to 15 minutes.",
|
|
3649
|
+
properties: {
|
|
3650
|
+
min: {
|
|
3651
|
+
$ref: "#/$defs/queueDuration"
|
|
3652
|
+
},
|
|
3653
|
+
max: {
|
|
3654
|
+
$ref: "#/$defs/queueDuration"
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
},
|
|
3658
|
+
deduplicationWindow: {
|
|
3659
|
+
$ref: "#/$defs/queueDuration",
|
|
3660
|
+
description: "How long a deduplication key is remembered. Defaults to 24 hours, at most 7 days."
|
|
3661
|
+
},
|
|
3662
|
+
concurrency: {
|
|
3663
|
+
type: ["integer", "null"],
|
|
3664
|
+
minimum: 1,
|
|
3665
|
+
maximum: 1e3,
|
|
3666
|
+
description: "Most push deliveries in flight at once. Defaults to 100."
|
|
3667
|
+
},
|
|
3668
|
+
rateLimit: {
|
|
3669
|
+
oneOf: [
|
|
3670
|
+
{
|
|
3671
|
+
type: "null"
|
|
3672
|
+
},
|
|
3673
|
+
{
|
|
3674
|
+
type: "object",
|
|
3675
|
+
required: ["count"],
|
|
3676
|
+
additionalProperties: false,
|
|
3677
|
+
properties: {
|
|
3678
|
+
count: {
|
|
3679
|
+
type: "integer",
|
|
3680
|
+
minimum: 1,
|
|
3681
|
+
maximum: 1e6
|
|
3682
|
+
},
|
|
3683
|
+
period: {
|
|
3684
|
+
$ref: "#/$defs/queueDuration"
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
],
|
|
3689
|
+
description: "Most deliveries started per period. The period defaults to one second."
|
|
3690
|
+
},
|
|
3691
|
+
deadLetter: {
|
|
3692
|
+
type: "boolean",
|
|
3693
|
+
description: "Keep messages that run out of attempts so you can inspect and redrive them. Defaults to true."
|
|
3694
|
+
},
|
|
3695
|
+
schedules: {
|
|
3696
|
+
type: "object",
|
|
3697
|
+
description: "Cron schedules that send a message into this queue, keyed by schedule name.",
|
|
3698
|
+
propertyNames: {
|
|
3699
|
+
maxLength: 128,
|
|
3700
|
+
pattern: "^[A-Za-z0-9_][A-Za-z0-9_.-]*$"
|
|
3701
|
+
},
|
|
3702
|
+
additionalProperties: {
|
|
3703
|
+
type: "object",
|
|
3704
|
+
required: ["cron"],
|
|
3705
|
+
additionalProperties: false,
|
|
3706
|
+
properties: {
|
|
3707
|
+
cron: {
|
|
3708
|
+
type: "string",
|
|
3709
|
+
minLength: 1,
|
|
3710
|
+
maxLength: 255,
|
|
3711
|
+
description: "Five-field cron expression, or a macro such as @hourly or @daily."
|
|
3712
|
+
},
|
|
3713
|
+
timezone: {
|
|
3714
|
+
type: "string",
|
|
3715
|
+
description: "IANA time zone the expression is evaluated in. Defaults to UTC."
|
|
3716
|
+
},
|
|
3717
|
+
body: {
|
|
3718
|
+
description: "Message body. Strings are sent as is; any other value is sent as JSON."
|
|
3719
|
+
},
|
|
3720
|
+
contentType: {
|
|
3721
|
+
type: "string",
|
|
3722
|
+
description: "Content type of the body. Defaults to text/plain for a string body and application/json otherwise."
|
|
3723
|
+
},
|
|
3724
|
+
headers: {
|
|
3725
|
+
type: "object",
|
|
3726
|
+
additionalProperties: {
|
|
3727
|
+
type: "string"
|
|
3728
|
+
},
|
|
3729
|
+
description: "Headers delivered with every message from this schedule."
|
|
3730
|
+
},
|
|
3731
|
+
enabled: {
|
|
3732
|
+
type: "boolean",
|
|
3733
|
+
description: "Set to false to keep the schedule without sending. Defaults to true."
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
}
|
|
3740
|
+
]
|
|
3741
|
+
}
|
|
2543
3742
|
}
|
|
2544
3743
|
}
|
|
2545
3744
|
}
|
|
2546
3745
|
},
|
|
2547
3746
|
$defs: {
|
|
3747
|
+
schedule: {
|
|
3748
|
+
type: "string",
|
|
3749
|
+
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]+))?)*)[)])$"
|
|
3750
|
+
},
|
|
3751
|
+
stringOrStringArray: {
|
|
3752
|
+
oneOf: [
|
|
3753
|
+
{
|
|
3754
|
+
type: "string",
|
|
3755
|
+
minLength: 1,
|
|
3756
|
+
maxLength: 4096
|
|
3757
|
+
},
|
|
3758
|
+
{
|
|
3759
|
+
type: "array",
|
|
3760
|
+
maxItems: 256,
|
|
3761
|
+
items: {
|
|
3762
|
+
type: "string",
|
|
3763
|
+
maxLength: 4096
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
]
|
|
3767
|
+
},
|
|
3768
|
+
queueDuration: {
|
|
3769
|
+
oneOf: [
|
|
3770
|
+
{
|
|
3771
|
+
type: "integer",
|
|
3772
|
+
minimum: 0
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
type: "string",
|
|
3776
|
+
pattern: "^[0-9]+(\\.[0-9]+)?(s|m|h|d)$"
|
|
3777
|
+
}
|
|
3778
|
+
],
|
|
3779
|
+
description: "A duration in seconds, or a string such as 30s, 10m, 1.5h or 4d."
|
|
3780
|
+
},
|
|
2548
3781
|
runtimes: {
|
|
2549
3782
|
type: "string",
|
|
2550
3783
|
enum: ["php-84", "php-83", "php-81", "node-22", "node-20", "node-18", "node-16", "bun-1"]
|
|
@@ -2601,7 +3834,7 @@ var schema_default = {
|
|
|
2601
3834
|
};
|
|
2602
3835
|
|
|
2603
3836
|
// src/parse-config.ts
|
|
2604
|
-
var parseConfigRaw =
|
|
3837
|
+
var parseConfigRaw = import_effect24.Effect.fn("parseConfigRaw")(function* (filePath, projectFolder) {
|
|
2605
3838
|
const rawReader = yield* RawConfigReader;
|
|
2606
3839
|
const validator = yield* SchemaValidator;
|
|
2607
3840
|
const v4Parser = yield* V4ConfigParser;
|
|
@@ -2612,7 +3845,7 @@ var parseConfigRaw = import_effect21.Effect.fn("parseConfigRaw")(function* (file
|
|
|
2612
3845
|
};
|
|
2613
3846
|
const schema = schemaMap[version];
|
|
2614
3847
|
if (!schema) {
|
|
2615
|
-
return yield*
|
|
3848
|
+
return yield* import_effect24.Effect.fail(
|
|
2616
3849
|
new ConfigVersionError({
|
|
2617
3850
|
message: `Config file at ${filePath} has an unsupported version: ${version}`,
|
|
2618
3851
|
filePath,
|
|
@@ -2623,14 +3856,42 @@ var parseConfigRaw = import_effect21.Effect.fn("parseConfigRaw")(function* (file
|
|
|
2623
3856
|
yield* validator.validate(parsed, schema, filePath);
|
|
2624
3857
|
return yield* v4Parser.parse(parsed, projectFolder);
|
|
2625
3858
|
});
|
|
2626
|
-
var parseConfig =
|
|
3859
|
+
var parseConfig = import_effect24.Effect.fn("parseConfig")(function* (filePath, projectFolder) {
|
|
2627
3860
|
const parseResult = yield* parseConfigRaw(filePath, projectFolder);
|
|
2628
3861
|
return yield* postProcessConfig(parseResult, projectFolder);
|
|
2629
3862
|
});
|
|
2630
|
-
var postProcessConfig =
|
|
3863
|
+
var postProcessConfig = import_effect24.Effect.fn("postProcessConfig")(function* (config, projectFolder) {
|
|
2631
3864
|
const vercelParser = yield* VercelBuildOutputParser;
|
|
2632
3865
|
let result = yield* vercelParser.parse(config, projectFolder);
|
|
2633
3866
|
const hasAssets = (result.assets?.paths?.length ?? 0) > 0 || (result.assets?.prefixes?.length ?? 0) > 0 || (result.assets?.manifests?.length ?? 0) > 0;
|
|
3867
|
+
const containerFunctions = result.entrypoints.filter((entrypoint) => entrypoint.runtime === CONTAINER_RUNTIME);
|
|
3868
|
+
const [onlyFunction] = result.entrypoints;
|
|
3869
|
+
if (onlyFunction !== void 0 && onlyFunction.runtime === CONTAINER_RUNTIME && result.entrypoints.length === 1 && result.routes.length === 0 && !hasAssets) {
|
|
3870
|
+
result = {
|
|
3871
|
+
...result,
|
|
3872
|
+
routes: [
|
|
3873
|
+
{
|
|
3874
|
+
path: "/*",
|
|
3875
|
+
destination: onlyFunction.path,
|
|
3876
|
+
handler: onlyFunction.streaming === true ? "SERVERLESS_FUNCTION_STREAMING" : "SERVERLESS_FUNCTION",
|
|
3877
|
+
methods: ["ANY"],
|
|
3878
|
+
headers: {}
|
|
3879
|
+
}
|
|
3880
|
+
]
|
|
3881
|
+
};
|
|
3882
|
+
} else {
|
|
3883
|
+
for (const entrypoint of containerFunctions) {
|
|
3884
|
+
const routed = result.routes.some((route) => route.destination.replace(/^\/+/, "") === entrypoint.path);
|
|
3885
|
+
if (!routed && entrypoint.schedule === void 0) {
|
|
3886
|
+
result.warnings.push(
|
|
3887
|
+
`Container function '${entrypoint.displayName ?? entrypoint.path}' has no route and no schedule, so nothing reaches it. Add a route with destination '${entrypoint.path}'.`
|
|
3888
|
+
);
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
if ((result.sidecars?.length ?? 0) > 0 && result.entrypoints.length === 0) {
|
|
3893
|
+
result.warnings.push("Sidecars run next to functions, and this deployment has none, so no sidecar will start.");
|
|
3894
|
+
}
|
|
2634
3895
|
if (result.entrypoints.length === 0 && !hasAssets && result.routes.length === 0) {
|
|
2635
3896
|
result.errors.push(
|
|
2636
3897
|
"The current project config does not resolve to any functions, assets or routes and can not be deployed."
|
|
@@ -2656,19 +3917,22 @@ var RUNTIME_DEFINITIONS = [
|
|
|
2656
3917
|
var AVAILABLE_RUNTIMES = [...RUNTIME_DEFINITIONS];
|
|
2657
3918
|
|
|
2658
3919
|
// src/services/index.ts
|
|
2659
|
-
var
|
|
2660
|
-
var BaseLayers =
|
|
3920
|
+
var import_effect25 = require("effect");
|
|
3921
|
+
var BaseLayers = import_effect25.Layer.mergeAll(
|
|
2661
3922
|
ConfigModuleLoader.Default,
|
|
2662
3923
|
RawConfigReader.Default,
|
|
2663
3924
|
SchemaValidator.Default,
|
|
2664
3925
|
V4ConfigParser.Default
|
|
2665
3926
|
);
|
|
2666
|
-
var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(
|
|
3927
|
+
var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect25.Layer.provideMerge(BaseLayers));
|
|
2667
3928
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2668
3929
|
0 && (module.exports = {
|
|
2669
3930
|
ALLOWED_CONFIG_NAMES,
|
|
2670
3931
|
AVAILABLE_REGIONS,
|
|
2671
3932
|
AVAILABLE_RUNTIMES,
|
|
3933
|
+
COMPOSE_FILE_NAMES,
|
|
3934
|
+
CONTAINER_ENTRYPOINT_PREFIX,
|
|
3935
|
+
CONTAINER_RUNTIME,
|
|
2672
3936
|
ConfigFileEmptyError,
|
|
2673
3937
|
ConfigFileNotFoundError,
|
|
2674
3938
|
ConfigFileParseError,
|
|
@@ -2676,7 +3940,10 @@ var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect22.Lay
|
|
|
2676
3940
|
ConfigModuleLoader,
|
|
2677
3941
|
ConfigSchemaValidationError,
|
|
2678
3942
|
ConfigVersionError,
|
|
3943
|
+
ContainerConfigError,
|
|
3944
|
+
DEFAULT_CONTAINER_MEMORY_MB,
|
|
2679
3945
|
DEFAULT_FUNCTION_DURATION_SECONDS,
|
|
3946
|
+
DEFAULT_SIDECAR_MEMORY_MB,
|
|
2680
3947
|
FRAMEWORK_DEFINITIONS,
|
|
2681
3948
|
FrameworkNotDetectedError,
|
|
2682
3949
|
FunctionConfigError,
|
|
@@ -2693,6 +3960,7 @@ var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect22.Lay
|
|
|
2693
3960
|
GigadriveNextServerDescriptorSchema,
|
|
2694
3961
|
GigadriveNextStaticAssetPrefixSchema,
|
|
2695
3962
|
MAX_FUNCTION_DURATION_SECONDS,
|
|
3963
|
+
MAX_SIDECARS,
|
|
2696
3964
|
ManifestNotFoundError,
|
|
2697
3965
|
ManifestParseError,
|
|
2698
3966
|
ManifestReadError,
|
|
@@ -2704,19 +3972,27 @@ var NetworkConfigLive = VercelBuildOutputParser.Default.pipe(import_effect22.Lay
|
|
|
2704
3972
|
StaticAssetManifestV1Schema,
|
|
2705
3973
|
V4ConfigParser,
|
|
2706
3974
|
VercelBuildOutputParser,
|
|
3975
|
+
collectAssetFiles,
|
|
3976
|
+
composeDeclaresApp,
|
|
3977
|
+
containerEntrypointPath,
|
|
2707
3978
|
defineConfig,
|
|
3979
|
+
detectContainerProject,
|
|
2708
3980
|
detectFramework,
|
|
2709
3981
|
detectPackageManager,
|
|
3982
|
+
dockerFunctionContainerName,
|
|
2710
3983
|
filterFunctionsFromAssets,
|
|
2711
3984
|
generateConfig,
|
|
2712
3985
|
getFunctionSettings,
|
|
2713
3986
|
mergeWithFrameworkDefaults,
|
|
3987
|
+
normalizeContainers,
|
|
2714
3988
|
parseConfig,
|
|
2715
3989
|
parseConfigRaw,
|
|
2716
3990
|
parseGigadriveNextBuildManifest,
|
|
2717
3991
|
parseGigadriveNextPrerenderManifest,
|
|
2718
3992
|
parseStaticAssetManifest,
|
|
2719
3993
|
postProcessConfig,
|
|
2720
|
-
|
|
3994
|
+
readComposeContainers,
|
|
3995
|
+
readDependencies,
|
|
3996
|
+
splitCommandWords
|
|
2721
3997
|
});
|
|
2722
3998
|
//# sourceMappingURL=index.js.map
|