@gigadrive/network-config 2.0.4 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -18,22 +18,98 @@ import addFormats from "ajv-formats";
18
18
 
19
19
  // src/build-output-v3/parse.ts
20
20
  import { getFilesForPattern } from "@gigadrive/build-utils";
21
- import fs3 from "fs";
21
+ import { deepMerge } from "@gigadrive/commons";
22
+ import path5 from "path";
23
+
24
+ // src/build-output-v3/determine-repo-root.ts
25
+ import path2 from "path";
26
+ var determineRepoRoot = (projectFolder, config) => {
27
+ if (!config.entrypoints?.length) {
28
+ return projectFolder;
29
+ }
30
+ const filePaths = [];
31
+ for (const entrypoint of config.entrypoints) {
32
+ if (entrypoint.package?.filePathMap) {
33
+ filePaths.push(...Object.keys(entrypoint.package.filePathMap));
34
+ }
35
+ }
36
+ if (filePaths.length === 0) {
37
+ return projectFolder;
38
+ }
39
+ const pathParts = filePaths.map((p) => p.split(path2.sep));
40
+ const firstPath = pathParts[0];
41
+ let commonParts = [];
42
+ for (let i = 0; i < firstPath.length; i++) {
43
+ const part = firstPath[i];
44
+ if (pathParts.every((parts) => parts[i] === part)) {
45
+ commonParts.push(part);
46
+ } else {
47
+ break;
48
+ }
49
+ }
50
+ const commonRoot = commonParts.join(path2.sep);
51
+ if (commonRoot && projectFolder.startsWith(commonRoot) && commonRoot !== projectFolder) {
52
+ return commonRoot;
53
+ }
54
+ return projectFolder;
55
+ };
56
+
57
+ // src/build-output-v3/get-default-path-map.ts
58
+ import fs2 from "fs";
22
59
  import path3 from "path";
60
+ var getDefaultPathMap = (directory) => {
61
+ const result = {};
62
+ if (!fs2.existsSync(directory)) {
63
+ return result;
64
+ }
65
+ const processDirectory = (currentPath, basePath = "") => {
66
+ const files = fs2.readdirSync(currentPath, { withFileTypes: true });
67
+ for (const file of files) {
68
+ const fullPath = path3.join(currentPath, file.name);
69
+ const relativePath = path3.join(basePath, file.name);
70
+ if (file.isDirectory()) {
71
+ processDirectory(fullPath, relativePath);
72
+ } else {
73
+ result[fullPath] = relativePath;
74
+ }
75
+ }
76
+ };
77
+ processDirectory(directory);
78
+ return result;
79
+ };
80
+
81
+ // src/build-output-v3/get-monorepo-files.ts
82
+ function getMonorepoFiles(directory, filePathMaps) {
83
+ const result = [];
84
+ for (const filePathMap of filePathMaps ?? []) {
85
+ if (!filePathMap) {
86
+ continue;
87
+ }
88
+ for (const file of Object.keys(filePathMap)) {
89
+ if (!file.startsWith(directory)) {
90
+ result.push(file);
91
+ }
92
+ }
93
+ }
94
+ return result;
95
+ }
96
+
97
+ // src/build-output-v3/read-config-file.ts
98
+ import fs4 from "fs";
23
99
 
24
100
  // src/parse-raw-config.ts
25
- import fs2 from "fs";
26
- import path2 from "path";
101
+ import fs3 from "fs";
102
+ import path4 from "path";
27
103
  import { parse as parseYaml } from "yaml";
28
104
  var parseRawConfig = async (filePath, { disableVersionCheck = false } = {}) => {
29
- if (!fs2.existsSync(filePath)) {
105
+ if (!fs3.existsSync(filePath)) {
30
106
  throw new Error(`Config file not found at ${filePath}`);
31
107
  }
32
- const fileContents = fs2.readFileSync(filePath, "utf8");
108
+ const fileContents = fs3.readFileSync(filePath, "utf8");
33
109
  if (fileContents.length === 0) {
34
110
  throw new Error(`Config file is empty at ${filePath}`);
35
111
  }
36
- const fileExtension = path2.extname(filePath).toLowerCase();
112
+ const fileExtension = path4.extname(filePath).toLowerCase();
37
113
  let parsed;
38
114
  try {
39
115
  if (fileExtension === ".json") {
@@ -57,150 +133,187 @@ var parseRawConfig = async (filePath, { disableVersionCheck = false } = {}) => {
57
133
  return parsed;
58
134
  };
59
135
 
136
+ // src/build-output-v3/read-config-file.ts
137
+ var readConfigFile = async (configFilePath) => {
138
+ if (!fs4.existsSync(configFilePath)) {
139
+ return null;
140
+ }
141
+ const parsed = await parseRawConfig(configFilePath, { disableVersionCheck: true });
142
+ return parsed;
143
+ };
144
+
145
+ // src/build-output-v3/translate-vercel-region.ts
146
+ var translateVercelRegion = (region) => {
147
+ const regionMap = {
148
+ arn1: "eu-north-1",
149
+ bom1: "ap-south-1",
150
+ cdg1: "eu-west-3",
151
+ cle1: "us-east-2",
152
+ cpt1: "af-south-1",
153
+ dub1: "eu-west-1",
154
+ fra1: "eu-central-1",
155
+ gru1: "sa-east-1",
156
+ hkg1: "ap-east-1",
157
+ hnd1: "ap-northeast-1",
158
+ iad1: "us-east-1",
159
+ icn1: "ap-northeast-2",
160
+ kix1: "ap-northeast-3",
161
+ lhr1: "eu-west-2",
162
+ pdx1: "us-west-2",
163
+ sfo1: "us-west-1",
164
+ sin1: "ap-southeast-1",
165
+ syd1: "ap-southeast-2"
166
+ };
167
+ return regionMap[region.toLowerCase()] ?? "us-east-1";
168
+ };
169
+
170
+ // src/build-output-v3/translate-vercel-runtime.ts
171
+ var translateVercelRuntime = (runtime) => {
172
+ switch (runtime) {
173
+ case "nodejs12.x":
174
+ case "nodejs14.x":
175
+ case "nodejs16.x":
176
+ case "nodejs18.x":
177
+ return "node-18";
178
+ case "nodejs20.x":
179
+ case "nodejs22.x":
180
+ return "node-20";
181
+ default:
182
+ return null;
183
+ }
184
+ };
185
+
60
186
  // src/build-output-v3/parse.ts
61
187
  var configPath = ".vercel/output/config.json";
62
- var functionConfigsPattern = ".vercel/output/functions/*.func/.vc-config.json";
188
+ var functionsFolder = ".vercel/output/functions";
189
+ var functionConfigsPattern = `${functionsFolder}/**/*.func/.vc-config.json`;
63
190
  var parseVercelBuildOutputV3 = async (parseResult, projectFolder) => {
64
- const config = await readConfigFile(path3.join(projectFolder, configPath));
191
+ const config = await readConfigFile(path5.join(projectFolder, configPath));
65
192
  if (!config || config.version < 3) {
66
193
  return parseResult;
67
194
  }
68
- await loadFunctions(config, parseResult, projectFolder);
69
- await loadAssetOverrides(config, parseResult);
70
- return parseResult;
195
+ const functionData = await loadFunctions(config, parseResult, projectFolder);
196
+ const assetOverrides = await loadAssetOverrides(config, parseResult);
197
+ return deepMerge(parseResult, functionData, assetOverrides);
71
198
  };
72
199
  var loadAssetOverrides = async (config, parseResult) => {
73
- if (!parseResult.assets) {
74
- parseResult.assets = {
75
- paths: [],
76
- prefixToStrip: ""
77
- };
78
- }
79
- parseResult.assets.overrides = {
80
- ...parseResult.assets.overrides ?? {},
81
- ...config.overrides
200
+ return {
201
+ assets: {
202
+ overrides: {
203
+ ...parseResult.assets?.overrides ?? {},
204
+ ...config.overrides
205
+ }
206
+ }
82
207
  };
83
208
  };
84
209
  var loadFunctions = async (config, parseResult, projectFolder) => {
85
210
  const functionConfigs = await getFilesForPattern(functionConfigsPattern, projectFolder);
211
+ const result = {
212
+ entrypoints: [],
213
+ routes: [],
214
+ regions: []
215
+ };
86
216
  for (const functionConfigPath of functionConfigs) {
87
- const functionConfig = await readConfigFile(path3.join(projectFolder, functionConfigPath));
217
+ const functionConfig = await readConfigFile(path5.join(projectFolder, functionConfigPath));
88
218
  if (!functionConfig) {
89
219
  parseResult.errors.push(`Failed to read function config at ${functionConfigPath}`);
90
220
  continue;
91
221
  }
92
- const functionName = path3.basename(path3.dirname(functionConfigPath)).replace(/\.func$/, "");
222
+ const functionPathRelative = path5.dirname(functionConfigPath).replace(functionsFolder, "");
223
+ const functionName = functionPathRelative.replace(/^\/|\.func$/g, "");
93
224
  const runtime = translateVercelRuntime(functionConfig.runtime);
94
225
  if (!runtime) {
95
226
  parseResult.errors.push(`Unsupported runtime for function ${functionName}: ${functionConfig.runtime}`);
96
227
  continue;
97
228
  }
98
229
  const functionDirectory = `.vercel/output/functions/${functionName}.func`;
99
- const handler = functionConfig.handler;
100
- const maxDuration = functionConfig.maxDuration;
101
- const memory = functionConfig.memory;
102
- parseResult.regions = Array.from(
103
- /* @__PURE__ */ new Set([
104
- ...parseResult.regions ?? [],
105
- ...(functionConfig.regions ?? ["us-east-1"]).map((r) => translateVercelRegion(r))
106
- ])
107
- );
230
+ const {
231
+ handler,
232
+ maxDuration,
233
+ memory,
234
+ regions = [],
235
+ environment,
236
+ filePathMap: configFilePathMap = {}
237
+ } = functionConfig;
238
+ const translatedRegions = regions.length > 0 ? regions.map(translateVercelRegion) : ["us-east-1"];
239
+ result.regions = Array.from(/* @__PURE__ */ new Set([...parseResult.regions, ...translatedRegions]));
108
240
  const environmentVariables = {};
109
- const functionEnv = functionConfig.environment;
110
- if (functionEnv != null && typeof functionEnv === "object") {
111
- for (const env of Object.values(functionEnv)) {
112
- for (const [key, value] of Object.entries(env)) {
113
- environmentVariables[key] = value;
114
- }
241
+ if (environment && typeof environment === "object") {
242
+ for (const env of Object.values(environment)) {
243
+ Object.assign(environmentVariables, env);
115
244
  }
116
245
  }
117
- const streaming = runtime == null || runtime.startsWith("node-") || runtime.startsWith("bun-");
118
- const filePathMap = {};
119
- for (const [key, value] of Object.entries(functionConfig.filePathMap ?? {})) {
120
- filePathMap[path3.join(projectFolder, key)] = value;
246
+ const streaming = runtime.startsWith("node-") || runtime.startsWith("bun-");
247
+ let filePathMap = {};
248
+ for (const [key, value] of Object.entries(configFilePathMap)) {
249
+ filePathMap[path5.join(projectFolder, key)] = value;
250
+ }
251
+ if (Object.keys(filePathMap).length === 0) {
252
+ filePathMap = getDefaultPathMap(path5.join(projectFolder, functionDirectory));
121
253
  }
122
- parseResult.entrypoints.push({
254
+ if (!result.entrypoints) {
255
+ result.entrypoints = [];
256
+ }
257
+ result.entrypoints.push({
123
258
  displayName: functionName,
124
259
  runtime,
125
- path: handler,
260
+ path: path5.join(functionDirectory, handler),
126
261
  memory: memory ?? 1024,
127
262
  maxDuration: maxDuration ?? 15,
128
263
  environmentVariables,
129
264
  streaming,
130
265
  package: {
131
- rootOverwrite: path3.join(projectFolder, functionDirectory),
132
266
  filePathMap
133
267
  }
134
268
  });
135
269
  const handlerType = streaming ? "SERVERLESS_FUNCTION_STREAMING" : "SERVERLESS_FUNCTION";
136
- [
137
- {
138
- path: `/${functionName}`,
139
- methods: ["ANY"],
140
- headers: {},
141
- destination: handler,
142
- handler: handlerType
143
- },
144
- ...config.routes?.filter((r) => r.dest === `/${functionName}`).map((r) => ({
270
+ const defaultRoute = {
271
+ path: `/${functionName}`,
272
+ methods: ["ANY"],
273
+ headers: {},
274
+ destination: handler,
275
+ handler: handlerType
276
+ };
277
+ const configRoutes = config.routes?.filter((r) => r.dest === `/${functionName}`).map(
278
+ (r) => ({
145
279
  path: r.src ?? `/${functionName}`,
146
280
  methods: ["ANY"],
147
281
  headers: {},
148
282
  destination: handler,
149
283
  handler: handlerType
150
- })) ?? []
151
- ].forEach((route) => {
152
- parseResult.routes.push(route);
153
- });
154
- }
155
- };
156
- var readConfigFile = async (configFilePath) => {
157
- if (!fs3.existsSync(configFilePath)) {
158
- return null;
159
- }
160
- const parsed = await parseRawConfig(configFilePath, { disableVersionCheck: true });
161
- return parsed;
162
- };
163
- var translateVercelRuntime = (runtime) => {
164
- switch (runtime) {
165
- case "nodejs12.x":
166
- case "nodejs14.x":
167
- case "nodejs16.x":
168
- case "nodejs18.x":
169
- return "node-18";
170
- case "nodejs20.x":
171
- case "nodejs22.x":
172
- return "node-20";
173
- default:
174
- return null;
284
+ })
285
+ ) ?? [];
286
+ if (!result.routes) {
287
+ result.routes = [];
288
+ }
289
+ result.routes.push(defaultRoute, ...configRoutes);
175
290
  }
291
+ return {
292
+ ...result,
293
+ userArchive: {
294
+ rootOverwrite: determineRepoRoot(projectFolder, result),
295
+ fileWhitelist: [
296
+ `${projectFolder}/*`,
297
+ ...getMonorepoFiles(projectFolder, result.entrypoints?.map((e) => e.package?.filePathMap ?? {}) ?? [])
298
+ ]
299
+ }
300
+ };
176
301
  };
177
- var translateVercelRegion = (region) => {
178
- const regionMap = {
179
- arn1: "eu-north-1",
180
- bom1: "ap-south-1",
181
- cdg1: "eu-west-3",
182
- cle1: "us-east-2",
183
- cpt1: "af-south-1",
184
- dub1: "eu-west-1",
185
- fra1: "eu-central-1",
186
- gru1: "sa-east-1",
187
- hkg1: "ap-east-1",
188
- hnd1: "ap-northeast-1",
189
- iad1: "us-east-1",
190
- icn1: "ap-northeast-2",
191
- kix1: "ap-northeast-3",
192
- lhr1: "eu-west-2",
193
- pdx1: "us-west-2",
194
- sfo1: "us-west-1",
195
- sin1: "ap-southeast-1",
196
- syd1: "ap-southeast-2"
302
+
303
+ // src/filter-functions-from-assets.ts
304
+ var filterFunctionsFromAssets = async (config) => {
305
+ return {
306
+ ...config,
307
+ assets: {
308
+ ...config.assets,
309
+ paths: config.assets?.paths?.filter((path6) => !config.entrypoints.some((entrypoint) => entrypoint.path === path6))
310
+ }
197
311
  };
198
- return regionMap[region.toLowerCase()] ?? "us-east-1";
199
312
  };
200
313
 
201
314
  // src/v4/parse.ts
202
315
  import { getFilesForPattern as getFilesForPattern2 } from "@gigadrive/build-utils";
203
- import fs4 from "fs";
316
+ import fs5 from "fs";
204
317
  import { minimatch } from "minimatch";
205
318
 
206
319
  // src/regions.ts
@@ -235,16 +348,16 @@ var parseConfigV4 = async (config, projectFolder) => {
235
348
  const errors = [];
236
349
  const warnings = [];
237
350
  if (config.functions != null) {
238
- for (const [path4, func] of Object.entries(config.functions)) {
239
- const settings = getFunctionSettings(path4, config);
351
+ for (const [path6, func] of Object.entries(config.functions)) {
352
+ const settings = getFunctionSettings(path6, config);
240
353
  if (settings == null) {
241
- throw new Error(`Settings invalid for function at path '${path4}'`);
354
+ throw new Error(`Settings invalid for function at path '${path6}'`);
242
355
  }
243
- (await getFilesForPattern2(path4, projectFolder, func.excludeFiles)).forEach((file) => {
356
+ (await getFilesForPattern2(path6, projectFolder, func.excludeFiles)).forEach((file) => {
244
357
  if (entrypoints.find((entrypoint) => entrypoint.path === file)) {
245
358
  return;
246
359
  }
247
- if (config.functions != null && Object.keys(config.functions).find((func2) => func2 === file && func2 !== path4)) {
360
+ if (config.functions != null && Object.keys(config.functions).find((func2) => func2 === file && func2 !== path6)) {
248
361
  return;
249
362
  }
250
363
  entrypoints.push({
@@ -262,11 +375,11 @@ var parseConfigV4 = async (config, projectFolder) => {
262
375
  const assets = [];
263
376
  if (config.assets != null) {
264
377
  const assetsPath = `${projectFolder}/${config.assets}`;
265
- if (fs4.existsSync(assetsPath) && fs4.statSync(assetsPath).isDirectory()) {
266
- for (const asset of fs4.readdirSync(`${projectFolder}/${config.assets}`, {
378
+ if (fs5.existsSync(assetsPath) && fs5.statSync(assetsPath).isDirectory()) {
379
+ for (const asset of fs5.readdirSync(`${projectFolder}/${config.assets}`, {
267
380
  recursive: true
268
381
  })) {
269
- if (fs4.statSync(`${projectFolder}/${config.assets}/${asset}`).isDirectory()) {
382
+ if (fs5.statSync(`${projectFolder}/${config.assets}/${asset}`).isDirectory()) {
270
383
  continue;
271
384
  }
272
385
  const disallowedExtensions = [".htaccess", ".htpasswd"];
@@ -274,6 +387,9 @@ var parseConfigV4 = async (config, projectFolder) => {
274
387
  if (disallowedExtensions.some((ext) => assetName.toLowerCase().endsWith(ext.toLowerCase()))) {
275
388
  continue;
276
389
  }
390
+ if (getFunctionSettings(`${config.assets}/${assetName}`, config) != null) {
391
+ continue;
392
+ }
277
393
  assets.push(`${config.assets}/${assetName}`);
278
394
  }
279
395
  }
@@ -307,10 +423,10 @@ var parseConfigV4 = async (config, projectFolder) => {
307
423
  })
308
424
  };
309
425
  };
310
- var getFunctionSettings = (path4, config) => {
426
+ var getFunctionSettings = (path6, config) => {
311
427
  let functionSettings;
312
428
  for (const [key, value] of Object.entries(config.functions ?? {})) {
313
- if (minimatch(path4, key) || new RegExp(key).test(path4)) {
429
+ if (minimatch(path6, key) || new RegExp(key).test(path6)) {
314
430
  if (functionSettings == null) {
315
431
  functionSettings = {
316
432
  memory: 128,
@@ -720,6 +836,7 @@ var parseConfig = async (filePath, projectFolder) => {
720
836
  "The current project config does not resolve to any functions, assets or routes and can not be deployed."
721
837
  );
722
838
  }
839
+ parseResult = await filterFunctionsFromAssets(parseResult);
723
840
  return parseResult;
724
841
  };
725
842