@farm.js/core 0.1.0-beta.14 → 0.1.0-beta.16

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.
Files changed (93) hide show
  1. package/dist/api/route-manager.cjs.map +1 -1
  2. package/dist/api/route-manager.mjs +2 -2
  3. package/dist/api/runtime.cjs.map +1 -1
  4. package/dist/api/runtime.mjs +1 -1
  5. package/dist/api.cjs +18 -10
  6. package/dist/api.cjs.map +1 -1
  7. package/dist/api.mjs +3 -3
  8. package/dist/{chunk-B232I2GP.mjs → chunk-3HIVDX7J.mjs} +12 -1
  9. package/dist/chunk-3HIVDX7J.mjs.map +1 -0
  10. package/dist/{chunk-JDEOUK5V.mjs → chunk-6YXKHAFU.mjs} +3 -3
  11. package/dist/{chunk-VUL55IAX.mjs → chunk-AN3PQVKH.mjs} +14 -16
  12. package/dist/{chunk-VUL55IAX.mjs.map → chunk-AN3PQVKH.mjs.map} +1 -1
  13. package/dist/{chunk-Z5CQMP54.mjs → chunk-ARRYKOI5.mjs} +2 -2
  14. package/dist/{chunk-KLA67WKG.mjs → chunk-B3FFOIWS.mjs} +2 -2
  15. package/dist/{chunk-ARCGE2VT.mjs → chunk-BWJC5ZOD.mjs} +2 -2
  16. package/dist/{chunk-ARCGE2VT.mjs.map → chunk-BWJC5ZOD.mjs.map} +1 -1
  17. package/dist/{chunk-PFE6GMNE.mjs → chunk-HMRFYJK6.mjs} +19 -11
  18. package/dist/chunk-HMRFYJK6.mjs.map +1 -0
  19. package/dist/{chunk-32W4QEJP.mjs → chunk-KFTGPFRD.mjs} +1 -1
  20. package/dist/chunk-KFTGPFRD.mjs.map +1 -0
  21. package/dist/{chunk-PNFQQSRA.mjs → chunk-OSWV5IJB.mjs} +114 -35
  22. package/dist/chunk-OSWV5IJB.mjs.map +1 -0
  23. package/dist/{chunk-OPHK6OJN.mjs → chunk-SLDBGSC3.mjs} +2 -2
  24. package/dist/{chunk-L2PE36GQ.mjs → chunk-T2KL7VEL.mjs} +3 -3
  25. package/dist/{chunk-WDU6QXNK.mjs → chunk-UCYWGN2P.mjs} +1 -1
  26. package/dist/chunk-UCYWGN2P.mjs.map +1 -0
  27. package/dist/{chunk-65A7QIKI.mjs → chunk-UMVLB3PN.mjs} +3 -3
  28. package/dist/chunk-UMVLB3PN.mjs.map +1 -0
  29. package/dist/{chunk-VY2UYN5R.mjs → chunk-VPCFICID.mjs} +82 -3
  30. package/dist/chunk-VPCFICID.mjs.map +1 -0
  31. package/dist/{chunk-H3TE3LOV.mjs → chunk-XMFTIVJH.mjs} +2 -2
  32. package/dist/{chunk-UB5UOSHB.mjs → chunk-ZVMV3THA.mjs} +71 -2
  33. package/dist/chunk-ZVMV3THA.mjs.map +1 -0
  34. package/dist/client.cjs.map +1 -1
  35. package/dist/client.mjs +3 -3
  36. package/dist/deployment.cjs +12 -0
  37. package/dist/deployment.cjs.map +1 -1
  38. package/dist/deployment.mjs +3 -1
  39. package/dist/{devtools-GAZ7F3KL.mjs → devtools-E4YNCY5J.mjs} +4 -4
  40. package/dist/docs.cjs.map +1 -1
  41. package/dist/docs.mjs +4 -4
  42. package/dist/index.cjs +306 -52
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.mjs +28 -16
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/internal/build-runtime.cjs +133 -40
  47. package/dist/internal/build-runtime.cjs.map +1 -1
  48. package/dist/internal/build-runtime.mjs +11 -11
  49. package/dist/internal/config-runtime.cjs.map +1 -1
  50. package/dist/internal/config-runtime.mjs +3 -3
  51. package/dist/navigation.cjs.map +1 -1
  52. package/dist/navigation.mjs +3 -3
  53. package/dist/plugin.cjs +115 -28
  54. package/dist/plugin.cjs.map +1 -1
  55. package/dist/plugin.mjs +8 -8
  56. package/dist/server-action-security.cjs +23 -1
  57. package/dist/server-action-security.cjs.map +1 -1
  58. package/dist/server-action-security.mjs +1 -1
  59. package/dist/server-fn-client.cjs.map +1 -1
  60. package/dist/server-fn-client.mjs +1 -1
  61. package/dist/server-fn.cjs +140 -3
  62. package/dist/server-fn.cjs.map +1 -1
  63. package/dist/server-fn.mjs +14 -3
  64. package/dist/server-query.cjs +99 -1
  65. package/dist/server-query.cjs.map +1 -1
  66. package/dist/server-query.mjs +3 -3
  67. package/dist/server.cjs +234 -31
  68. package/dist/server.cjs.map +1 -1
  69. package/dist/server.mjs +11 -11
  70. package/dist/testing.cjs.map +1 -1
  71. package/dist/testing.mjs +3 -3
  72. package/dist/version.cjs +1 -1
  73. package/dist/version.cjs.map +1 -1
  74. package/dist/version.mjs +1 -1
  75. package/dist/vite.cjs +116 -29
  76. package/dist/vite.cjs.map +1 -1
  77. package/dist/vite.mjs +8 -8
  78. package/package.json +1 -1
  79. package/dist/chunk-32W4QEJP.mjs.map +0 -1
  80. package/dist/chunk-65A7QIKI.mjs.map +0 -1
  81. package/dist/chunk-B232I2GP.mjs.map +0 -1
  82. package/dist/chunk-PFE6GMNE.mjs.map +0 -1
  83. package/dist/chunk-PNFQQSRA.mjs.map +0 -1
  84. package/dist/chunk-UB5UOSHB.mjs.map +0 -1
  85. package/dist/chunk-VY2UYN5R.mjs.map +0 -1
  86. package/dist/chunk-WDU6QXNK.mjs.map +0 -1
  87. /package/dist/{chunk-JDEOUK5V.mjs.map → chunk-6YXKHAFU.mjs.map} +0 -0
  88. /package/dist/{chunk-Z5CQMP54.mjs.map → chunk-ARRYKOI5.mjs.map} +0 -0
  89. /package/dist/{chunk-KLA67WKG.mjs.map → chunk-B3FFOIWS.mjs.map} +0 -0
  90. /package/dist/{chunk-OPHK6OJN.mjs.map → chunk-SLDBGSC3.mjs.map} +0 -0
  91. /package/dist/{chunk-L2PE36GQ.mjs.map → chunk-T2KL7VEL.mjs.map} +0 -0
  92. /package/dist/{chunk-H3TE3LOV.mjs.map → chunk-XMFTIVJH.mjs.map} +0 -0
  93. /package/dist/{devtools-GAZ7F3KL.mjs.map → devtools-E4YNCY5J.mjs.map} +0 -0
package/dist/index.cjs CHANGED
@@ -4842,6 +4842,72 @@ var init_cache_invalidation = __esm({
4842
4842
  }
4843
4843
  });
4844
4844
 
4845
+ // src/server-fn-error.ts
4846
+ function isServerFnFailure(value) {
4847
+ if (!value || typeof value !== "object") return false;
4848
+ const candidate = value;
4849
+ return candidate[FARM_SERVER_FN_FAILURE_SYMBOL] === true && candidate.name === "ServerFnFailure" && typeof candidate.code === "string" && Number.isInteger(candidate.status) && (candidate.status ?? 0) >= 400 && (candidate.status ?? 0) <= 599;
4850
+ }
4851
+ function serializeServerFnFailure(value) {
4852
+ if (!isServerFnFailure(value)) return null;
4853
+ return {
4854
+ name: "ServerFnFailure",
4855
+ message: value.message,
4856
+ code: value.code,
4857
+ status: value.status,
4858
+ data: value.data
4859
+ };
4860
+ }
4861
+ function createServerFnTransportError(value) {
4862
+ if (isSerializedServerFnFailure(value)) {
4863
+ return new ServerFnFailure(value.code, value.data, {
4864
+ status: value.status,
4865
+ message: value.message
4866
+ });
4867
+ }
4868
+ const message = value && typeof value === "object" && "message" in value && typeof value.message === "string" ? value.message : "Server function failed";
4869
+ return new ServerActionError(message);
4870
+ }
4871
+ function isSerializedServerFnFailure(value) {
4872
+ if (!value || typeof value !== "object") return false;
4873
+ const candidate = value;
4874
+ return candidate.name === "ServerFnFailure" && typeof candidate.message === "string" && typeof candidate.code === "string" && Number.isInteger(candidate.status) && (candidate.status ?? 0) >= 400 && (candidate.status ?? 0) <= 599 && "data" in candidate;
4875
+ }
4876
+ var FARM_SERVER_FN_FAILURE_SYMBOL, _ServerFnFailure, ServerFnFailure, _ServerActionError, ServerActionError;
4877
+ var init_server_fn_error = __esm({
4878
+ "src/server-fn-error.ts"() {
4879
+ "use strict";
4880
+ FARM_SERVER_FN_FAILURE_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn.failure");
4881
+ _ServerFnFailure = class _ServerFnFailure extends Error {
4882
+ constructor(code, data, options) {
4883
+ super(options.message);
4884
+ this.name = "ServerFnFailure";
4885
+ this.code = code;
4886
+ this.data = data;
4887
+ this.status = options.status;
4888
+ Object.defineProperty(this, FARM_SERVER_FN_FAILURE_SYMBOL, {
4889
+ value: true,
4890
+ enumerable: false
4891
+ });
4892
+ }
4893
+ };
4894
+ __name(_ServerFnFailure, "ServerFnFailure");
4895
+ ServerFnFailure = _ServerFnFailure;
4896
+ _ServerActionError = class _ServerActionError extends Error {
4897
+ constructor(message = "Server function failed") {
4898
+ super(message);
4899
+ this.name = "ServerActionError";
4900
+ }
4901
+ };
4902
+ __name(_ServerActionError, "ServerActionError");
4903
+ ServerActionError = _ServerActionError;
4904
+ __name(isServerFnFailure, "isServerFnFailure");
4905
+ __name(serializeServerFnFailure, "serializeServerFnFailure");
4906
+ __name(createServerFnTransportError, "createServerFnTransportError");
4907
+ __name(isSerializedServerFnFailure, "isSerializedServerFnFailure");
4908
+ }
4909
+ });
4910
+
4845
4911
  // src/server-action-security.ts
4846
4912
  function resolveServerActionsConfig(config) {
4847
4913
  const allowedOrigins = (config?.allowedOrigins ?? []).map(normalizeAllowedOriginPattern);
@@ -4928,7 +4994,9 @@ function createServerActionRequestErrorResponse(error) {
4928
4994
  headers: headers2
4929
4995
  });
4930
4996
  }
4931
- function sanitizeServerActionError(_error) {
4997
+ function sanitizeServerActionError(error) {
4998
+ const declaredFailure = serializeServerFnFailure(error);
4999
+ if (declaredFailure) return declaredFailure;
4932
5000
  return {
4933
5001
  name: "ServerActionError",
4934
5002
  message: "Server function failed"
@@ -5227,6 +5295,7 @@ var init_server_action_security = __esm({
5227
5295
  "use strict";
5228
5296
  import_node_async_hooks = require("async_hooks");
5229
5297
  init_cache_invalidation();
5298
+ init_server_fn_error();
5230
5299
  DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT = 1e6;
5231
5300
  _ServerActionRequestError = class _ServerActionRequestError extends Error {
5232
5301
  constructor(code, status, message) {
@@ -10252,6 +10321,15 @@ var init_deferred = __esm({
10252
10321
  });
10253
10322
 
10254
10323
  // src/deployment.ts
10324
+ function getFarmPresetRuntime(preset) {
10325
+ if (preset === "cloudflare" || preset === "cloudflare-pages" || preset === "cloudflare-module" || preset === "netlify-edge" || preset === "vercel-edge" || preset === "deno") {
10326
+ return "edge";
10327
+ }
10328
+ if (preset === "node-server" || preset === "vercel" || preset === "netlify" || preset === "aws-lambda" || preset === "azure" || preset === "firebase" || preset === "bun" || preset === "self-host" || preset === "farm") {
10329
+ return "node";
10330
+ }
10331
+ return "unknown";
10332
+ }
10255
10333
  function normalizeFarmDeploymentId(value) {
10256
10334
  if (typeof value !== "string" || value.trim() === "") {
10257
10335
  throw new TypeError("Farm deploymentId must be a non-empty string");
@@ -10370,6 +10448,7 @@ var init_deployment = __esm({
10370
10448
  FARM_DEPLOYMENT_COOKIE = "__farm_deployment";
10371
10449
  FARM_DEPLOYMENT_MISMATCH_CODE = "FARM_DEPLOYMENT_MISMATCH";
10372
10450
  FARM_DEPLOYMENT_MISMATCH_STATUS = 409;
10451
+ __name(getFarmPresetRuntime, "getFarmPresetRuntime");
10373
10452
  _FarmDeploymentMismatchError = class _FarmDeploymentMismatchError extends Error {
10374
10453
  constructor(clientDeploymentId, serverDeploymentId) {
10375
10454
  super("The application was updated while this page was open. Refresh before trying again.");
@@ -15968,13 +16047,13 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
15968
16047
  }
15969
16048
  const middleware2 = normalizeEndpointMiddleware(options.middleware);
15970
16049
  const errors = normalizeEndpointErrors(options.errors);
15971
- const fail = createEndpointFail(errors);
16050
+ const error = createEndpointErrorHandler(errors);
15972
16051
  const wrappedHandler = /* @__PURE__ */ __name((async (ctx) => {
15973
16052
  const execution = await runEndpointMiddleware(
15974
16053
  middleware2,
15975
16054
  ctx,
15976
16055
  handler,
15977
- fail,
16056
+ error,
15978
16057
  options.invalidates
15979
16058
  );
15980
16059
  return execution.result;
@@ -15994,7 +16073,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
15994
16073
  endpoint2.__method = options.method || "GET";
15995
16074
  endpoint2.__autoPath = !path32;
15996
16075
  endpoint2.__handler = wrappedHandler;
15997
- endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, fail, options.invalidates);
16076
+ endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, error, options.invalidates);
15998
16077
  endpoint2.__middleware = middleware2;
15999
16078
  endpoint2.__sourceHandler = handler;
16000
16079
  endpoint2.__invalidates = options.invalidates;
@@ -16025,8 +16104,9 @@ function normalizeEndpointErrors(definitions) {
16025
16104
  if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
16026
16105
  throw new TypeError(`Endpoint error "${code}" status must be an integer between 400 and 599`);
16027
16106
  }
16028
- if (!definition.schema || typeof definition.schema.parse !== "function") {
16029
- throw new TypeError(`Endpoint error "${code}" requires a schema with parse()`);
16107
+ const dataSchema = resolveEndpointErrorSchema(definition);
16108
+ if (!dataSchema || typeof dataSchema.parse !== "function") {
16109
+ throw new TypeError(`Endpoint error "${code}" requires a data schema with parse()`);
16030
16110
  }
16031
16111
  if (definition.message !== void 0 && typeof definition.message !== "string") {
16032
16112
  throw new TypeError(`Endpoint error "${code}" message must be a string`);
@@ -16035,13 +16115,19 @@ function normalizeEndpointErrors(definitions) {
16035
16115
  }
16036
16116
  return Object.freeze(normalized);
16037
16117
  }
16038
- function createEndpointFail(definitions) {
16118
+ function resolveEndpointErrorSchema(definition) {
16119
+ if (definition.data && definition.schema) {
16120
+ throw new TypeError("Endpoint errors cannot define both data and schema");
16121
+ }
16122
+ return definition.data ?? definition.schema;
16123
+ }
16124
+ function createEndpointErrorHandler(definitions) {
16039
16125
  return ((code, data) => {
16040
16126
  const definition = definitions[code];
16041
16127
  if (!definition) {
16042
16128
  throw new TypeError(`Endpoint error "${code}" is not declared`);
16043
16129
  }
16044
- const parsed = definition.schema.parse(data);
16130
+ const parsed = resolveEndpointErrorSchema(definition).parse(data);
16045
16131
  throw new EndpointFailure(code, parsed, {
16046
16132
  status: definition.status,
16047
16133
  message: definition.message ?? "Request failed"
@@ -16061,7 +16147,7 @@ function normalizeEndpointMiddleware(middleware2) {
16061
16147
  }
16062
16148
  return Object.freeze(normalized);
16063
16149
  }
16064
- async function runEndpointMiddleware(middleware2, handlerContext, handler, fail, invalidations) {
16150
+ async function runEndpointMiddleware(middleware2, handlerContext, handler, error, invalidations) {
16065
16151
  let context = createInitialEndpointContext(handlerContext.context);
16066
16152
  for (let index = 0; index < middleware2.length; index++) {
16067
16153
  const result2 = await middleware2[index]({ ...handlerContext, context });
@@ -16089,7 +16175,7 @@ async function runEndpointMiddleware(middleware2, handlerContext, handler, fail,
16089
16175
  }
16090
16176
  context = mergeEndpointContext(context, result2, index);
16091
16177
  }
16092
- const result = await handler({ ...handlerContext, context, fail });
16178
+ const result = await handler({ ...handlerContext, context, error, fail: error });
16093
16179
  return {
16094
16180
  result,
16095
16181
  context,
@@ -16219,7 +16305,8 @@ var init_endpoint = __esm({
16219
16305
  EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
16220
16306
  UNSAFE_ENDPOINT_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
16221
16307
  __name(normalizeEndpointErrors, "normalizeEndpointErrors");
16222
- __name(createEndpointFail, "createEndpointFail");
16308
+ __name(resolveEndpointErrorSchema, "resolveEndpointErrorSchema");
16309
+ __name(createEndpointErrorHandler, "createEndpointErrorHandler");
16223
16310
  __name(normalizeEndpointMiddleware, "normalizeEndpointMiddleware");
16224
16311
  __name(runEndpointMiddleware, "runEndpointMiddleware");
16225
16312
  __name(applyEndpointInvalidations, "applyEndpointInvalidations");
@@ -17824,6 +17911,13 @@ function routePatternToTsTypeLiterals(pattern) {
17824
17911
  function routePatternToRouteLiteral(pattern) {
17825
17912
  return JSON.stringify(pattern);
17826
17913
  }
17914
+ function renderTypeUnion(values) {
17915
+ return values.length <= 1 ? values[0] || "never" : `
17916
+ | ${values.join("\n | ")}`;
17917
+ }
17918
+ function renderTypeAlias(name, value) {
17919
+ return `export type ${name} =${value.startsWith("\n") ? "" : " "}${value};`;
17920
+ }
17827
17921
  function createRoutePattern(route2) {
17828
17922
  if (route2.segments.length === 0) return "/";
17829
17923
  return "/" + route2.segments.map((seg) => {
@@ -17883,9 +17977,9 @@ async function createRouteTypeDeclarations(options, outPath) {
17883
17977
  const typeLiterals = Array.from(new Set(sortedPatterns.flatMap(routePatternToTsTypeLiterals)));
17884
17978
  const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
17885
17979
  const routeModulePatternLiterals = Array.from(routeModulePatterns).sort().map(routePatternToRouteLiteral);
17886
- const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
17887
- const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
17888
- const routeModulePatternType = routeModulePatternLiterals.length ? routeModulePatternLiterals.join(" | ") : "never";
17980
+ const routePathType = suppressLintOnLink ? "string" : renderTypeUnion(typeLiterals);
17981
+ const routePatternType = suppressLintOnLink ? "string" : renderTypeUnion(patternLiterals);
17982
+ const routeModulePatternType = renderTypeUnion(routeModulePatternLiterals);
17889
17983
  const routeTypesImportPath = `./${path14.basename(outPath).replace(/\.d\.ts$/, "")}`;
17890
17984
  const linkAugmentationBlock = suppressLintOnLink ? "" : `
17891
17985
  declare module "@farm.js/core/client" {
@@ -17927,9 +18021,9 @@ declare global {
17927
18021
  * Regenerated on dev start and when routes change.
17928
18022
  * Set suppressLintOnLink: true in farm.config.ts to accept any string on Link href.
17929
18023
  */
17930
- export type RoutePath = ${routePathType};
17931
- export type RoutePattern = ${routePatternType};
17932
- export type RouteModulePattern = ${routeModulePatternType};${linkAugmentationBlock}${routeModuleAugmentationBlock}
18024
+ ${renderTypeAlias("RoutePath", routePathType)}
18025
+ ${renderTypeAlias("RoutePattern", routePatternType)}
18026
+ ${renderTypeAlias("RouteModulePattern", routeModulePatternType)}${linkAugmentationBlock}${routeModuleAugmentationBlock}
17933
18027
  `;
17934
18028
  return content;
17935
18029
  }
@@ -17946,6 +18040,8 @@ var init_generate_route_types = __esm({
17946
18040
  __name(routeSegmentsToTsTypeLiteral, "routeSegmentsToTsTypeLiteral");
17947
18041
  __name(routePatternToTsTypeLiterals, "routePatternToTsTypeLiterals");
17948
18042
  __name(routePatternToRouteLiteral, "routePatternToRouteLiteral");
18043
+ __name(renderTypeUnion, "renderTypeUnion");
18044
+ __name(renderTypeAlias, "renderTypeAlias");
17949
18045
  __name(createRoutePattern, "createRoutePattern");
17950
18046
  DEFAULT_OUT_FILE = "farm-routes.d.ts";
17951
18047
  __name(generateRouteTypes, "generateRouteTypes");
@@ -18246,7 +18342,8 @@ async function generateFarmTypeArtifacts(options) {
18246
18342
  const sourceRoots = getFarmSourceRoots({ root, srcDir, layers: options.layers });
18247
18343
  const appDirs = getFarmAppDirectories({ root, srcDir, layers: options.layers });
18248
18344
  const result = {
18249
- apiRoutes: []
18345
+ apiRoutes: [],
18346
+ stalePaths: []
18250
18347
  };
18251
18348
  const unifiedTypesPath = (0, import_path8.join)(root, srcDir, "farm.d.ts");
18252
18349
  const shouldRefreshUnifiedTypes = shouldGenerateRoutes && !options.routeTypesOutFile || shouldGenerateEnv && !options.envTypesOutFile || shouldGenerateI18n && !options.i18nTypesOutFile;
@@ -18262,22 +18359,29 @@ async function generateFarmTypeArtifacts(options) {
18262
18359
  unifiedSections.push(await createRouteTypeDeclarations(routeOptions, unifiedTypesPath));
18263
18360
  result.routeTypesPath = unifiedTypesPath;
18264
18361
  } else if (shouldGenerateRoutes) {
18265
- result.routeTypesPath = await generateRouteTypes({
18362
+ const routeOptions = {
18266
18363
  root,
18267
18364
  srcDir,
18268
18365
  outFile: options.routeTypesOutFile,
18269
18366
  extraRoutes: options.extraRoutes || [],
18270
18367
  suppressLintOnLink: options.suppressLintOnLink,
18271
18368
  sourceRoots
18272
- });
18369
+ };
18370
+ if (options.check) {
18371
+ const routeTypesPath = resolveGeneratedPath(root, srcDir, options.routeTypesOutFile);
18372
+ const content = await createRouteTypeDeclarations(routeOptions, routeTypesPath);
18373
+ checkGeneratedFile(routeTypesPath, content, result.stalePaths);
18374
+ result.routeTypesPath = routeTypesPath;
18375
+ } else {
18376
+ result.routeTypesPath = await generateRouteTypes(routeOptions);
18377
+ }
18273
18378
  }
18274
18379
  if (shouldGenerateApi) {
18275
18380
  const generator = new APITypeGenerator(appDirs);
18276
18381
  const apiRoutes = generator.scanAPIRoutes();
18277
18382
  const apiTypesPath = options.apiTypesOutFile ? (0, import_path8.resolve)(root, options.apiTypesOutFile) : (0, import_path8.join)(root, srcDir, "lib", "api.generated.ts");
18278
18383
  const content = generator.generateAPIRouter(apiRoutes, { outFile: apiTypesPath });
18279
- (0, import_fs4.mkdirSync)((0, import_path8.dirname)(apiTypesPath), { recursive: true });
18280
- writeFileIfChanged(apiTypesPath, content);
18384
+ writeOrCheckGeneratedFile(apiTypesPath, content, options.check, result.stalePaths);
18281
18385
  result.apiTypesPath = apiTypesPath;
18282
18386
  result.apiRoutes = apiRoutes;
18283
18387
  }
@@ -18295,36 +18399,63 @@ async function generateFarmTypeArtifacts(options) {
18295
18399
  );
18296
18400
  result.envTypesPath = unifiedTypesPath;
18297
18401
  } else if (shouldGenerateEnv) {
18298
- result.envTypesPath = await generateEnvTypes({
18402
+ const envOptions = {
18299
18403
  root,
18300
18404
  srcDir,
18301
18405
  outFile: options.envTypesOutFile,
18302
18406
  configPath: options.configPath,
18303
18407
  layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
18304
- });
18408
+ };
18409
+ if (options.check) {
18410
+ const envTypesPath = resolveGeneratedPath(root, srcDir, options.envTypesOutFile);
18411
+ checkGeneratedFile(
18412
+ envTypesPath,
18413
+ createEnvTypeDeclarations(envOptions, envTypesPath),
18414
+ result.stalePaths
18415
+ );
18416
+ result.envTypesPath = envTypesPath;
18417
+ } else {
18418
+ result.envTypesPath = await generateEnvTypes(envOptions);
18419
+ }
18305
18420
  }
18306
18421
  if (shouldGenerateImages && options.imageTypesOutFile) {
18307
- result.imageTypesPath = generateFarmImageTypes({
18308
- root,
18309
- srcDir,
18310
- outFile: options.imageTypesOutFile
18311
- });
18422
+ const imageTypesPath = resolveGeneratedPath(root, srcDir, options.imageTypesOutFile, false);
18423
+ if (options.check) {
18424
+ checkGeneratedFile(imageTypesPath, createFarmImageTypeDeclarations(), result.stalePaths);
18425
+ result.imageTypesPath = imageTypesPath;
18426
+ } else {
18427
+ result.imageTypesPath = generateFarmImageTypes({
18428
+ root,
18429
+ srcDir,
18430
+ outFile: options.imageTypesOutFile
18431
+ });
18432
+ }
18312
18433
  }
18313
18434
  if (shouldRefreshUnifiedTypes && options.i18nConfig?.enabled && !options.i18nTypesOutFile) {
18314
18435
  const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
18315
18436
  unifiedSections.push(renderFarmI18nTypes(options.i18nConfig.locales, signatures));
18316
18437
  result.i18nTypesPath = unifiedTypesPath;
18317
18438
  } else if (shouldGenerateI18n && options.i18nConfig) {
18318
- result.i18nTypesPath = await generateFarmI18nTypes({
18319
- root,
18320
- srcDir,
18321
- config: options.i18nConfig,
18322
- outFile: options.i18nTypesOutFile
18323
- });
18439
+ if (options.check) {
18440
+ const i18nTypesPath = resolveGeneratedPath(root, srcDir, options.i18nTypesOutFile, false);
18441
+ const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
18442
+ checkGeneratedFile(
18443
+ i18nTypesPath,
18444
+ renderFarmI18nTypes(options.i18nConfig.locales, signatures),
18445
+ result.stalePaths
18446
+ );
18447
+ result.i18nTypesPath = i18nTypesPath;
18448
+ } else {
18449
+ result.i18nTypesPath = await generateFarmI18nTypes({
18450
+ root,
18451
+ srcDir,
18452
+ config: options.i18nConfig,
18453
+ outFile: options.i18nTypesOutFile
18454
+ });
18455
+ }
18324
18456
  }
18325
18457
  if (shouldRefreshUnifiedTypes) {
18326
- (0, import_fs4.mkdirSync)((0, import_path8.dirname)(unifiedTypesPath), { recursive: true });
18327
- writeFileIfChanged(
18458
+ writeOrCheckGeneratedFile(
18328
18459
  unifiedTypesPath,
18329
18460
  `/**
18330
18461
  * Generated by Farm.js. Do not edit.
@@ -18333,13 +18464,37 @@ async function generateFarmTypeArtifacts(options) {
18333
18464
 
18334
18465
  import "@farm.js/core/image";
18335
18466
 
18336
- ${unifiedSections.join("\n")}`
18467
+ ${unifiedSections.map((section) => section.trimEnd()).join("\n\n")}
18468
+ `,
18469
+ options.check,
18470
+ result.stalePaths
18337
18471
  );
18338
18472
  result.typesPath = unifiedTypesPath;
18339
- removeLegacyTypeArtifacts(root, srcDir);
18473
+ if (options.check) {
18474
+ collectLegacyTypeArtifacts(root, srcDir, result.stalePaths);
18475
+ } else {
18476
+ removeLegacyTypeArtifacts(root, srcDir);
18477
+ }
18340
18478
  }
18341
18479
  return result;
18342
18480
  }
18481
+ function resolveGeneratedPath(root, srcDir, outFile, relativeToSrc = true) {
18482
+ if ((0, import_path8.isAbsolute)(outFile)) return (0, import_path8.resolve)(outFile);
18483
+ return (0, import_path8.resolve)(root, relativeToSrc ? (0, import_path8.join)(srcDir, outFile) : outFile);
18484
+ }
18485
+ function writeOrCheckGeneratedFile(filePath, content, check, stalePaths) {
18486
+ if (check) {
18487
+ checkGeneratedFile(filePath, content, stalePaths);
18488
+ return;
18489
+ }
18490
+ (0, import_fs4.mkdirSync)((0, import_path8.dirname)(filePath), { recursive: true });
18491
+ writeFileIfChanged(filePath, content);
18492
+ }
18493
+ function checkGeneratedFile(filePath, content, stalePaths) {
18494
+ if (!(0, import_fs4.existsSync)(filePath) || (0, import_fs4.readFileSync)(filePath, "utf8") !== content) {
18495
+ stalePaths.push(filePath);
18496
+ }
18497
+ }
18343
18498
  function removeLegacyTypeArtifacts(root, srcDir) {
18344
18499
  for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
18345
18500
  const filePath = (0, import_path8.join)(root, srcDir, fileName);
@@ -18350,6 +18505,13 @@ function removeLegacyTypeArtifacts(root, srcDir) {
18350
18505
  }
18351
18506
  }
18352
18507
  }
18508
+ function collectLegacyTypeArtifacts(root, srcDir, stalePaths) {
18509
+ for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
18510
+ const filePath = (0, import_path8.join)(root, srcDir, fileName);
18511
+ if (!(0, import_fs4.existsSync)(filePath)) continue;
18512
+ if ((0, import_fs4.readFileSync)(filePath, "utf8").includes(marker)) stalePaths.push(filePath);
18513
+ }
18514
+ }
18353
18515
  var import_fs4, import_path8, LEGACY_TYPE_ARTIFACTS;
18354
18516
  var init_type_artifacts = __esm({
18355
18517
  "src/type-artifacts.ts"() {
@@ -18365,6 +18527,9 @@ var init_type_artifacts = __esm({
18365
18527
  init_layers();
18366
18528
  init_write_file_if_changed();
18367
18529
  __name(generateFarmTypeArtifacts, "generateFarmTypeArtifacts");
18530
+ __name(resolveGeneratedPath, "resolveGeneratedPath");
18531
+ __name(writeOrCheckGeneratedFile, "writeOrCheckGeneratedFile");
18532
+ __name(checkGeneratedFile, "checkGeneratedFile");
18368
18533
  LEGACY_TYPE_ARTIFACTS = [
18369
18534
  ["farm-routes.d.ts", "Auto-generated route types"],
18370
18535
  ["farm-env.d.ts", "Auto-generated env types"],
@@ -18372,6 +18537,7 @@ var init_type_artifacts = __esm({
18372
18537
  ["farm-i18n.d.ts", "Generated by Farm.js"]
18373
18538
  ];
18374
18539
  __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
18540
+ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
18375
18541
  }
18376
18542
  });
18377
18543
 
@@ -18728,7 +18894,7 @@ var init_environment_vite = __esm({
18728
18894
  var version;
18729
18895
  var init_package = __esm({
18730
18896
  "package.json"() {
18731
- version = "0.1.0-beta.14";
18897
+ version = "0.1.0-beta.16";
18732
18898
  }
18733
18899
  });
18734
18900
 
@@ -31947,6 +32113,7 @@ __export(src_exports, {
31947
32113
  FARM_DEVTOOLS_LAUNCH_PARAM: () => FARM_DEVTOOLS_LAUNCH_PARAM,
31948
32114
  FARM_DEVTOOLS_PATH: () => FARM_DEVTOOLS_PATH,
31949
32115
  FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY: () => FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY,
32116
+ FARM_SERVER_FN_FAILURE_SYMBOL: () => FARM_SERVER_FN_FAILURE_SYMBOL,
31950
32117
  FARM_SERVER_FN_SYMBOL: () => FARM_SERVER_FN_SYMBOL,
31951
32118
  FARM_SERVER_QUERY_SYMBOL: () => FARM_SERVER_QUERY_SYMBOL,
31952
32119
  FarmClientPluginManager: () => FarmClientPluginManager,
@@ -31969,7 +32136,9 @@ __export(src_exports, {
31969
32136
  PluginManager: () => PluginManager,
31970
32137
  SPARouter: () => SPARouter,
31971
32138
  ScalarAPIDocumentation: () => ScalarAPIDocumentation,
32139
+ ServerActionError: () => ServerActionError,
31972
32140
  ServerActionRequestError: () => ServerActionRequestError,
32141
+ ServerFnFailure: () => ServerFnFailure,
31973
32142
  _parseServerFnSchema: () => _parseServerFnSchema,
31974
32143
  _runWithAfterNodeResponse: () => _runWithAfterNodeResponse,
31975
32144
  _runWithAfterRequest: () => _runWithAfterRequest,
@@ -32058,6 +32227,7 @@ __export(src_exports, {
32058
32227
  createServerAPIClient: () => createServerAPIClient,
32059
32228
  createServerActionRequestErrorResponse: () => createServerActionRequestErrorResponse,
32060
32229
  createServerFn: () => createServerFn,
32230
+ createServerFnTransportError: () => createServerFnTransportError,
32061
32231
  createServerMiddleware: () => createServerMiddleware,
32062
32232
  createServerOnlyFn: () => createServerOnlyFn,
32063
32233
  createServerQuery: () => createServerQuery,
@@ -32111,6 +32281,7 @@ __export(src_exports, {
32111
32281
  getFarmDocsRouteTypeEntries: () => getFarmDocsRouteTypeEntries,
32112
32282
  getFarmIntegrationPluginServerRuntime: () => getFarmIntegrationPluginServerRuntime,
32113
32283
  getFarmLayerAliases: () => getFarmLayerAliases,
32284
+ getFarmPresetRuntime: () => getFarmPresetRuntime,
32114
32285
  getFarmRedirectError: () => getFarmRedirectError,
32115
32286
  getFarmRequestDeploymentId: () => getFarmRequestDeploymentId,
32116
32287
  getFarmResponseDeploymentId: () => getFarmResponseDeploymentId,
@@ -32174,6 +32345,7 @@ __export(src_exports, {
32174
32345
  isProgrammaticRouteManifest: () => isProgrammaticRouteManifest,
32175
32346
  isProgrammaticRoutesFileName: () => isProgrammaticRoutesFileName,
32176
32347
  isSSGModule: () => isSSGModule,
32348
+ isServerFnFailure: () => isServerFnFailure,
32177
32349
  isWebResponse: () => isWebResponse2,
32178
32350
  jsonStream: () => jsonStream,
32179
32351
  layout: () => layout,
@@ -35722,6 +35894,8 @@ init_image_types();
35722
35894
  init_server_action_security();
35723
35895
  init_request_bridge();
35724
35896
  init_cache();
35897
+ init_server_fn_error();
35898
+ init_server_fn_error();
35725
35899
  var FARM_SERVER_FN_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn");
35726
35900
  var UNSAFE_FORM_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
35727
35901
  function createServerMiddleware(options) {
@@ -35744,6 +35918,8 @@ function createServerFn(options) {
35744
35918
  throw new TypeError("createServerFn requires a handler function");
35745
35919
  }
35746
35920
  const middleware2 = resolveServerFnMiddleware(options.middleware);
35921
+ const errors = normalizeServerFnErrors(options.errors);
35922
+ const error = createServerFnErrorHandler(errors);
35747
35923
  const serverFn = /* @__PURE__ */ __name(async (value) => {
35748
35924
  const formData = isFormData2(value) ? value : void 0;
35749
35925
  const rawInput = formData ? formDataToObject2(formData) : value;
@@ -35761,7 +35937,7 @@ function createServerFn(options) {
35761
35937
  let resolvedContext = Object.freeze(/* @__PURE__ */ Object.create(null));
35762
35938
  const result = await runServerFnMiddleware(middleware2, handlerContext, async (context) => {
35763
35939
  resolvedContext = context.context;
35764
- return options.handler(context);
35940
+ return options.handler({ ...context, error });
35765
35941
  });
35766
35942
  const parsedResult = await _parseServerFnSchema(options.output, result, "output");
35767
35943
  if (options.invalidates) {
@@ -35791,6 +35967,10 @@ function createServerFn(options) {
35791
35967
  value: options.output,
35792
35968
  enumerable: false
35793
35969
  },
35970
+ __farmServerFnError: {
35971
+ value: void 0,
35972
+ enumerable: false
35973
+ },
35794
35974
  __farmServerFnMiddleware: {
35795
35975
  value: middleware2,
35796
35976
  enumerable: false
@@ -35829,6 +36009,78 @@ async function runServerFnMiddleware(middleware2, handlerContext, handler) {
35829
36009
  return dispatch(0, Object.freeze(/* @__PURE__ */ Object.create(null)));
35830
36010
  }
35831
36011
  __name(runServerFnMiddleware, "runServerFnMiddleware");
36012
+ function normalizeServerFnErrors(definitions) {
36013
+ if (definitions === void 0) return Object.freeze({});
36014
+ if (!isPlainServerFnObject(definitions)) {
36015
+ throw new TypeError("createServerFn errors must be an object");
36016
+ }
36017
+ const normalized = /* @__PURE__ */ Object.create(null);
36018
+ for (const [code, definition] of Object.entries(definitions)) {
36019
+ if (!code.trim()) {
36020
+ throw new TypeError("Server function error codes cannot be empty");
36021
+ }
36022
+ if (!definition || typeof definition !== "object") {
36023
+ throw new TypeError(`Server function error "${code}" must be an object`);
36024
+ }
36025
+ if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
36026
+ throw new TypeError(
36027
+ `Server function error "${code}" status must be an integer between 400 and 599`
36028
+ );
36029
+ }
36030
+ if (!definition.data || typeof definition.data.parse !== "function" && typeof definition.data.safeParse !== "function") {
36031
+ throw new TypeError(
36032
+ `Server function error "${code}" data must provide synchronous parse() or safeParse()`
36033
+ );
36034
+ }
36035
+ if (definition.message !== void 0 && typeof definition.message !== "string") {
36036
+ throw new TypeError(`Server function error "${code}" message must be a string`);
36037
+ }
36038
+ normalized[code] = Object.freeze({ ...definition });
36039
+ }
36040
+ return Object.freeze(normalized);
36041
+ }
36042
+ __name(normalizeServerFnErrors, "normalizeServerFnErrors");
36043
+ function createServerFnErrorHandler(definitions) {
36044
+ return ((code, data) => {
36045
+ const definition = definitions[code];
36046
+ if (!definition) {
36047
+ throw new TypeError(`Server function error "${code}" is not declared`);
36048
+ }
36049
+ const parsed = parseServerFnFailureData(code, definition.data, data);
36050
+ throw new ServerFnFailure(code, parsed, {
36051
+ status: definition.status,
36052
+ message: definition.message ?? "Server function failed"
36053
+ });
36054
+ });
36055
+ }
36056
+ __name(createServerFnErrorHandler, "createServerFnErrorHandler");
36057
+ function parseServerFnFailureData(code, schema, value) {
36058
+ if (typeof schema.safeParse === "function") {
36059
+ const result2 = schema.safeParse(value);
36060
+ if (isPromiseLike2(result2)) {
36061
+ throw new TypeError(`Server function error "${code}" data schema must parse synchronously`);
36062
+ }
36063
+ return unwrapSafeParseResult(result2);
36064
+ }
36065
+ const result = schema.parse(value);
36066
+ if (isPromiseLike2(result)) {
36067
+ throw new TypeError(`Server function error "${code}" data schema must parse synchronously`);
36068
+ }
36069
+ return result;
36070
+ }
36071
+ __name(parseServerFnFailureData, "parseServerFnFailureData");
36072
+ function isPlainServerFnObject(value) {
36073
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
36074
+ const prototype = Object.getPrototypeOf(value);
36075
+ return prototype === Object.prototype || prototype === null;
36076
+ }
36077
+ __name(isPlainServerFnObject, "isPlainServerFnObject");
36078
+ function isPromiseLike2(value) {
36079
+ return Boolean(
36080
+ value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function"
36081
+ );
36082
+ }
36083
+ __name(isPromiseLike2, "isPromiseLike");
35832
36084
  function resolveServerFnMiddleware(middleware2) {
35833
36085
  const resolved = [];
35834
36086
  const seen = /* @__PURE__ */ new Set();
@@ -36441,6 +36693,7 @@ init_fonts();
36441
36693
 
36442
36694
  // src/route-runtime-manifest.ts
36443
36695
  var import_path10 = __toESM(require("path"));
36696
+ init_deployment();
36444
36697
  init_route_runtime();
36445
36698
  init_ssg();
36446
36699
  var FARM_ROUTE_RUNTIME_MANIFEST = "route-runtime-manifest.json";
@@ -36501,10 +36754,15 @@ async function writeFarmRouteRuntimeManifest(directory, manifest) {
36501
36754
  }
36502
36755
  __name(writeFarmRouteRuntimeManifest, "writeFarmRouteRuntimeManifest");
36503
36756
  function validateFarmRouteRuntimeDeployment(manifest, preset) {
36504
- const runtime = getPresetRuntime(preset);
36757
+ const runtime = getFarmPresetRuntime(preset);
36505
36758
  const warnings = /* @__PURE__ */ new Set();
36506
36759
  for (const route2 of manifest.routes) {
36507
36760
  if (route2.rendering === "static") continue;
36761
+ if (runtime === "unknown" && route2.runtime !== "auto") {
36762
+ warnings.add(
36763
+ `Preset "${preset}" has an unknown runtime, so Farm could not verify routes that explicitly require node or edge.`
36764
+ );
36765
+ }
36508
36766
  if (runtime !== "unknown" && route2.runtime !== "auto" && route2.runtime !== runtime) {
36509
36767
  throw new Error(
36510
36768
  `Route "${route2.pattern}" requires the ${route2.runtime} runtime, but preset "${preset}" emits ${runtime} functions. Choose a compatible preset or change the route runtime.`
@@ -36524,16 +36782,6 @@ function validateFarmRouteRuntimeDeployment(manifest, preset) {
36524
36782
  return { runtime, warnings: Array.from(warnings) };
36525
36783
  }
36526
36784
  __name(validateFarmRouteRuntimeDeployment, "validateFarmRouteRuntimeDeployment");
36527
- function getPresetRuntime(preset) {
36528
- if (preset === "cloudflare" || preset === "cloudflare-pages" || preset === "cloudflare-module" || preset === "netlify-edge" || preset === "vercel-edge" || preset === "deno") {
36529
- return "edge";
36530
- }
36531
- if (preset === "node-server" || preset === "vercel" || preset === "netlify" || preset === "aws-lambda" || preset === "azure" || preset === "firebase" || preset === "bun") {
36532
- return "node";
36533
- }
36534
- return "unknown";
36535
- }
36536
- __name(getPresetRuntime, "getPresetRuntime");
36537
36785
  function normalizeManifestSource(root, modulePath) {
36538
36786
  const queryIndex = modulePath.indexOf("?");
36539
36787
  const filePath = queryIndex === -1 ? modulePath : modulePath.slice(0, queryIndex);
@@ -44526,6 +44774,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44526
44774
  FARM_DEVTOOLS_LAUNCH_PARAM,
44527
44775
  FARM_DEVTOOLS_PATH,
44528
44776
  FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY,
44777
+ FARM_SERVER_FN_FAILURE_SYMBOL,
44529
44778
  FARM_SERVER_FN_SYMBOL,
44530
44779
  FARM_SERVER_QUERY_SYMBOL,
44531
44780
  FarmClientPluginManager,
@@ -44548,7 +44797,9 @@ __name(decodeCookiePart, "decodeCookiePart");
44548
44797
  PluginManager,
44549
44798
  SPARouter,
44550
44799
  ScalarAPIDocumentation,
44800
+ ServerActionError,
44551
44801
  ServerActionRequestError,
44802
+ ServerFnFailure,
44552
44803
  _parseServerFnSchema,
44553
44804
  _runWithAfterNodeResponse,
44554
44805
  _runWithAfterRequest,
@@ -44637,6 +44888,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44637
44888
  createServerAPIClient,
44638
44889
  createServerActionRequestErrorResponse,
44639
44890
  createServerFn,
44891
+ createServerFnTransportError,
44640
44892
  createServerMiddleware,
44641
44893
  createServerOnlyFn,
44642
44894
  createServerQuery,
@@ -44690,6 +44942,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44690
44942
  getFarmDocsRouteTypeEntries,
44691
44943
  getFarmIntegrationPluginServerRuntime,
44692
44944
  getFarmLayerAliases,
44945
+ getFarmPresetRuntime,
44693
44946
  getFarmRedirectError,
44694
44947
  getFarmRequestDeploymentId,
44695
44948
  getFarmResponseDeploymentId,
@@ -44753,6 +45006,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44753
45006
  isProgrammaticRouteManifest,
44754
45007
  isProgrammaticRoutesFileName,
44755
45008
  isSSGModule,
45009
+ isServerFnFailure,
44756
45010
  isWebResponse,
44757
45011
  jsonStream,
44758
45012
  layout,