@farm.js/core 0.1.0-beta.13 → 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 (94) 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-VSDZEB5M.mjs → chunk-AN3PQVKH.mjs} +14 -16
  12. package/dist/{chunk-VSDZEB5M.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-3WIRO3N7.mjs → chunk-BWJC5ZOD.mjs} +2 -2
  16. package/dist/{chunk-3WIRO3N7.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-Z3YG4OZT.mjs → chunk-OSWV5IJB.mjs} +140 -41
  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 +332 -58
  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 +159 -46
  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 +141 -34
  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 +260 -37
  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 +142 -35
  76. package/dist/vite.cjs.map +1 -1
  77. package/dist/vite.mjs +8 -8
  78. package/package.json +1 -1
  79. package/types/client.d.ts +115 -4
  80. package/dist/chunk-32W4QEJP.mjs.map +0 -1
  81. package/dist/chunk-65A7QIKI.mjs.map +0 -1
  82. package/dist/chunk-B232I2GP.mjs.map +0 -1
  83. package/dist/chunk-PFE6GMNE.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-Z3YG4OZT.mjs.map +0 -1
  88. /package/dist/{chunk-JDEOUK5V.mjs.map → chunk-6YXKHAFU.mjs.map} +0 -0
  89. /package/dist/{chunk-Z5CQMP54.mjs.map → chunk-ARRYKOI5.mjs.map} +0 -0
  90. /package/dist/{chunk-KLA67WKG.mjs.map → chunk-B3FFOIWS.mjs.map} +0 -0
  91. /package/dist/{chunk-OPHK6OJN.mjs.map → chunk-SLDBGSC3.mjs.map} +0 -0
  92. /package/dist/{chunk-L2PE36GQ.mjs.map → chunk-T2KL7VEL.mjs.map} +0 -0
  93. /package/dist/{chunk-H3TE3LOV.mjs.map → chunk-XMFTIVJH.mjs.map} +0 -0
  94. /package/dist/{devtools-GAZ7F3KL.mjs.map → devtools-E4YNCY5J.mjs.map} +0 -0
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  FARM_SERVER_QUERY_SYMBOL,
3
3
  createServerQuery
4
- } from "./chunk-65A7QIKI.mjs";
5
- import "./chunk-VY2UYN5R.mjs";
4
+ } from "./chunk-UMVLB3PN.mjs";
5
+ import "./chunk-VPCFICID.mjs";
6
6
  import "./chunk-SCFX4UTD.mjs";
7
- import "./chunk-UB5UOSHB.mjs";
7
+ import "./chunk-ZVMV3THA.mjs";
8
8
  import "./chunk-LM2YNO4U.mjs";
9
9
  import "./chunk-V3XURYJO.mjs";
10
10
  import "./chunk-WZ5QFROO.mjs";
package/dist/server.cjs CHANGED
@@ -1919,6 +1919,47 @@ var init_cache_invalidation = __esm({
1919
1919
  }
1920
1920
  });
1921
1921
 
1922
+ // src/server-fn-error.ts
1923
+ function isServerFnFailure(value) {
1924
+ if (!value || typeof value !== "object") return false;
1925
+ const candidate = value;
1926
+ 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;
1927
+ }
1928
+ function serializeServerFnFailure(value) {
1929
+ if (!isServerFnFailure(value)) return null;
1930
+ return {
1931
+ name: "ServerFnFailure",
1932
+ message: value.message,
1933
+ code: value.code,
1934
+ status: value.status,
1935
+ data: value.data
1936
+ };
1937
+ }
1938
+ var FARM_SERVER_FN_FAILURE_SYMBOL, _ServerFnFailure, ServerFnFailure;
1939
+ var init_server_fn_error = __esm({
1940
+ "src/server-fn-error.ts"() {
1941
+ "use strict";
1942
+ FARM_SERVER_FN_FAILURE_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn.failure");
1943
+ _ServerFnFailure = class _ServerFnFailure extends Error {
1944
+ constructor(code, data, options) {
1945
+ super(options.message);
1946
+ this.name = "ServerFnFailure";
1947
+ this.code = code;
1948
+ this.data = data;
1949
+ this.status = options.status;
1950
+ Object.defineProperty(this, FARM_SERVER_FN_FAILURE_SYMBOL, {
1951
+ value: true,
1952
+ enumerable: false
1953
+ });
1954
+ }
1955
+ };
1956
+ __name(_ServerFnFailure, "ServerFnFailure");
1957
+ ServerFnFailure = _ServerFnFailure;
1958
+ __name(isServerFnFailure, "isServerFnFailure");
1959
+ __name(serializeServerFnFailure, "serializeServerFnFailure");
1960
+ }
1961
+ });
1962
+
1922
1963
  // src/server-action-security.ts
1923
1964
  function resolveServerActionsConfig(config) {
1924
1965
  const allowedOrigins = (config?.allowedOrigins ?? []).map(normalizeAllowedOriginPattern);
@@ -2005,7 +2046,9 @@ function createServerActionRequestErrorResponse(error) {
2005
2046
  headers
2006
2047
  });
2007
2048
  }
2008
- function sanitizeServerActionError(_error) {
2049
+ function sanitizeServerActionError(error) {
2050
+ const declaredFailure = serializeServerFnFailure(error);
2051
+ if (declaredFailure) return declaredFailure;
2009
2052
  return {
2010
2053
  name: "ServerActionError",
2011
2054
  message: "Server function failed"
@@ -2304,6 +2347,7 @@ var init_server_action_security = __esm({
2304
2347
  "use strict";
2305
2348
  import_node_async_hooks = require("async_hooks");
2306
2349
  init_cache_invalidation();
2350
+ init_server_fn_error();
2307
2351
  DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT = 1e6;
2308
2352
  _ServerActionRequestError = class _ServerActionRequestError extends Error {
2309
2353
  constructor(code, status, message) {
@@ -22961,6 +23005,15 @@ function routePatternToRouteLiteral(pattern) {
22961
23005
  return JSON.stringify(pattern);
22962
23006
  }
22963
23007
  __name(routePatternToRouteLiteral, "routePatternToRouteLiteral");
23008
+ function renderTypeUnion(values) {
23009
+ return values.length <= 1 ? values[0] || "never" : `
23010
+ | ${values.join("\n | ")}`;
23011
+ }
23012
+ __name(renderTypeUnion, "renderTypeUnion");
23013
+ function renderTypeAlias(name, value) {
23014
+ return `export type ${name} =${value.startsWith("\n") ? "" : " "}${value};`;
23015
+ }
23016
+ __name(renderTypeAlias, "renderTypeAlias");
22964
23017
  function createRoutePattern(route) {
22965
23018
  if (route.segments.length === 0) return "/";
22966
23019
  return "/" + route.segments.map((seg) => {
@@ -22986,39 +23039,48 @@ async function createRouteTypeDeclarations(options, outPath) {
22986
23039
  const { root, srcDir = "src", extraRoutes = [], suppressLintOnLink = false } = options;
22987
23040
  const sourceRoots = options.sourceRoots ?? [{ name: "project", root, srcDir, layer: false }];
22988
23041
  const patterns = /* @__PURE__ */ new Set();
23042
+ const routeModulePatterns = /* @__PURE__ */ new Set();
22989
23043
  const glob = await import("fast-glob");
22990
23044
  for (const source of sourceRoots) {
22991
23045
  const appDir = path14.join(source.root, source.srcDir, "app");
22992
23046
  if (fs5.existsSync(appDir)) {
22993
- const pageFiles = await glob.default("**/page.{ts,tsx,js,jsx,md,mdx}", {
22994
- cwd: appDir,
22995
- absolute: false
22996
- });
22997
- for (const file of pageFiles) {
23047
+ const routeModuleFiles = await glob.default(
23048
+ "**/{page,layout,loading,error}.{ts,tsx,js,jsx,md,mdx}",
23049
+ {
23050
+ cwd: appDir,
23051
+ absolute: false
23052
+ }
23053
+ );
23054
+ for (const file of routeModuleFiles) {
22998
23055
  if (parseRouteSlotFile(file)) continue;
22999
23056
  const route = parseRoutePath(file);
23057
+ const pattern = createRoutePattern(route);
23058
+ routeModulePatterns.add(pattern);
23000
23059
  if (route.type === "page") {
23001
- const pattern = createRoutePattern(route);
23002
23060
  patterns.add(pattern);
23003
23061
  }
23004
23062
  }
23005
23063
  }
23006
23064
  for (const route of await discoverProgrammaticRoutePaths(source.root, source.srcDir)) {
23007
23065
  patterns.add(route);
23066
+ routeModulePatterns.add(route);
23008
23067
  }
23009
23068
  }
23010
23069
  for (const route of extraRoutes) {
23011
23070
  if (route.startsWith("/")) {
23012
23071
  patterns.add(route);
23072
+ routeModulePatterns.add(route);
23013
23073
  }
23014
23074
  }
23015
23075
  const sortedPatterns = Array.from(patterns).sort();
23016
23076
  const typeLiterals = Array.from(new Set(sortedPatterns.flatMap(routePatternToTsTypeLiterals)));
23017
23077
  const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
23018
- const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
23019
- const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
23078
+ const routeModulePatternLiterals = Array.from(routeModulePatterns).sort().map(routePatternToRouteLiteral);
23079
+ const routePathType = suppressLintOnLink ? "string" : renderTypeUnion(typeLiterals);
23080
+ const routePatternType = suppressLintOnLink ? "string" : renderTypeUnion(patternLiterals);
23081
+ const routeModulePatternType = renderTypeUnion(routeModulePatternLiterals);
23020
23082
  const routeTypesImportPath = `./${path14.basename(outPath).replace(/\.d\.ts$/, "")}`;
23021
- const augmentationBlock = suppressLintOnLink ? "" : `
23083
+ const linkAugmentationBlock = suppressLintOnLink ? "" : `
23022
23084
  declare module "@farm.js/core/client" {
23023
23085
  interface LinkDefaultRoute {
23024
23086
  _: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
@@ -23042,14 +23104,25 @@ declare module "@farm.js/core/dist/client.js" {
23042
23104
  pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
23043
23105
  }
23044
23106
  }
23107
+ `;
23108
+ const routeModuleAugmentationBlock = `
23109
+ declare global {
23110
+ namespace FarmJS {
23111
+ interface RouteRegistry {
23112
+ pattern: import(${JSON.stringify(routeTypesImportPath)}).RouteModulePattern;
23113
+ }
23114
+ }
23115
+ }
23045
23116
  `;
23046
23117
  const content = `/**
23047
23118
  * Auto-generated route types from src/app.
23048
- * Link href is typed automatically via module augmentation. Regenerated on dev start and when routes change.
23119
+ * Link href and route component props are typed automatically from generated declarations.
23120
+ * Regenerated on dev start and when routes change.
23049
23121
  * Set suppressLintOnLink: true in farm.config.ts to accept any string on Link href.
23050
23122
  */
23051
- export type RoutePath = ${routePathType};
23052
- export type RoutePattern = ${routePatternType};${augmentationBlock}
23123
+ ${renderTypeAlias("RoutePath", routePathType)}
23124
+ ${renderTypeAlias("RoutePattern", routePatternType)}
23125
+ ${renderTypeAlias("RouteModulePattern", routeModulePatternType)}${linkAugmentationBlock}${routeModuleAugmentationBlock}
23053
23126
  `;
23054
23127
  return content;
23055
23128
  }
@@ -23331,7 +23404,8 @@ async function generateFarmTypeArtifacts(options) {
23331
23404
  const sourceRoots = getFarmSourceRoots({ root, srcDir, layers: options.layers });
23332
23405
  const appDirs = getFarmAppDirectories({ root, srcDir, layers: options.layers });
23333
23406
  const result = {
23334
- apiRoutes: []
23407
+ apiRoutes: [],
23408
+ stalePaths: []
23335
23409
  };
23336
23410
  const unifiedTypesPath = (0, import_path8.join)(root, srcDir, "farm.d.ts");
23337
23411
  const shouldRefreshUnifiedTypes = shouldGenerateRoutes && !options.routeTypesOutFile || shouldGenerateEnv && !options.envTypesOutFile || shouldGenerateI18n && !options.i18nTypesOutFile;
@@ -23347,22 +23421,29 @@ async function generateFarmTypeArtifacts(options) {
23347
23421
  unifiedSections.push(await createRouteTypeDeclarations(routeOptions, unifiedTypesPath));
23348
23422
  result.routeTypesPath = unifiedTypesPath;
23349
23423
  } else if (shouldGenerateRoutes) {
23350
- result.routeTypesPath = await generateRouteTypes({
23424
+ const routeOptions = {
23351
23425
  root,
23352
23426
  srcDir,
23353
23427
  outFile: options.routeTypesOutFile,
23354
23428
  extraRoutes: options.extraRoutes || [],
23355
23429
  suppressLintOnLink: options.suppressLintOnLink,
23356
23430
  sourceRoots
23357
- });
23431
+ };
23432
+ if (options.check) {
23433
+ const routeTypesPath = resolveGeneratedPath(root, srcDir, options.routeTypesOutFile);
23434
+ const content = await createRouteTypeDeclarations(routeOptions, routeTypesPath);
23435
+ checkGeneratedFile(routeTypesPath, content, result.stalePaths);
23436
+ result.routeTypesPath = routeTypesPath;
23437
+ } else {
23438
+ result.routeTypesPath = await generateRouteTypes(routeOptions);
23439
+ }
23358
23440
  }
23359
23441
  if (shouldGenerateApi) {
23360
23442
  const generator = new APITypeGenerator(appDirs);
23361
23443
  const apiRoutes = generator.scanAPIRoutes();
23362
23444
  const apiTypesPath = options.apiTypesOutFile ? (0, import_path8.resolve)(root, options.apiTypesOutFile) : (0, import_path8.join)(root, srcDir, "lib", "api.generated.ts");
23363
23445
  const content = generator.generateAPIRouter(apiRoutes, { outFile: apiTypesPath });
23364
- (0, import_fs4.mkdirSync)((0, import_path8.dirname)(apiTypesPath), { recursive: true });
23365
- writeFileIfChanged(apiTypesPath, content);
23446
+ writeOrCheckGeneratedFile(apiTypesPath, content, options.check, result.stalePaths);
23366
23447
  result.apiTypesPath = apiTypesPath;
23367
23448
  result.apiRoutes = apiRoutes;
23368
23449
  }
@@ -23380,36 +23461,63 @@ async function generateFarmTypeArtifacts(options) {
23380
23461
  );
23381
23462
  result.envTypesPath = unifiedTypesPath;
23382
23463
  } else if (shouldGenerateEnv) {
23383
- result.envTypesPath = await generateEnvTypes({
23464
+ const envOptions = {
23384
23465
  root,
23385
23466
  srcDir,
23386
23467
  outFile: options.envTypesOutFile,
23387
23468
  configPath: options.configPath,
23388
23469
  layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
23389
- });
23470
+ };
23471
+ if (options.check) {
23472
+ const envTypesPath = resolveGeneratedPath(root, srcDir, options.envTypesOutFile);
23473
+ checkGeneratedFile(
23474
+ envTypesPath,
23475
+ createEnvTypeDeclarations(envOptions, envTypesPath),
23476
+ result.stalePaths
23477
+ );
23478
+ result.envTypesPath = envTypesPath;
23479
+ } else {
23480
+ result.envTypesPath = await generateEnvTypes(envOptions);
23481
+ }
23390
23482
  }
23391
23483
  if (shouldGenerateImages && options.imageTypesOutFile) {
23392
- result.imageTypesPath = generateFarmImageTypes({
23393
- root,
23394
- srcDir,
23395
- outFile: options.imageTypesOutFile
23396
- });
23484
+ const imageTypesPath = resolveGeneratedPath(root, srcDir, options.imageTypesOutFile, false);
23485
+ if (options.check) {
23486
+ checkGeneratedFile(imageTypesPath, createFarmImageTypeDeclarations(), result.stalePaths);
23487
+ result.imageTypesPath = imageTypesPath;
23488
+ } else {
23489
+ result.imageTypesPath = generateFarmImageTypes({
23490
+ root,
23491
+ srcDir,
23492
+ outFile: options.imageTypesOutFile
23493
+ });
23494
+ }
23397
23495
  }
23398
23496
  if (shouldRefreshUnifiedTypes && options.i18nConfig?.enabled && !options.i18nTypesOutFile) {
23399
23497
  const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
23400
23498
  unifiedSections.push(renderFarmI18nTypes(options.i18nConfig.locales, signatures));
23401
23499
  result.i18nTypesPath = unifiedTypesPath;
23402
23500
  } else if (shouldGenerateI18n && options.i18nConfig) {
23403
- result.i18nTypesPath = await generateFarmI18nTypes({
23404
- root,
23405
- srcDir,
23406
- config: options.i18nConfig,
23407
- outFile: options.i18nTypesOutFile
23408
- });
23501
+ if (options.check) {
23502
+ const i18nTypesPath = resolveGeneratedPath(root, srcDir, options.i18nTypesOutFile, false);
23503
+ const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
23504
+ checkGeneratedFile(
23505
+ i18nTypesPath,
23506
+ renderFarmI18nTypes(options.i18nConfig.locales, signatures),
23507
+ result.stalePaths
23508
+ );
23509
+ result.i18nTypesPath = i18nTypesPath;
23510
+ } else {
23511
+ result.i18nTypesPath = await generateFarmI18nTypes({
23512
+ root,
23513
+ srcDir,
23514
+ config: options.i18nConfig,
23515
+ outFile: options.i18nTypesOutFile
23516
+ });
23517
+ }
23409
23518
  }
23410
23519
  if (shouldRefreshUnifiedTypes) {
23411
- (0, import_fs4.mkdirSync)((0, import_path8.dirname)(unifiedTypesPath), { recursive: true });
23412
- writeFileIfChanged(
23520
+ writeOrCheckGeneratedFile(
23413
23521
  unifiedTypesPath,
23414
23522
  `/**
23415
23523
  * Generated by Farm.js. Do not edit.
@@ -23418,14 +23526,41 @@ async function generateFarmTypeArtifacts(options) {
23418
23526
 
23419
23527
  import "@farm.js/core/image";
23420
23528
 
23421
- ${unifiedSections.join("\n")}`
23529
+ ${unifiedSections.map((section) => section.trimEnd()).join("\n\n")}
23530
+ `,
23531
+ options.check,
23532
+ result.stalePaths
23422
23533
  );
23423
23534
  result.typesPath = unifiedTypesPath;
23424
- removeLegacyTypeArtifacts(root, srcDir);
23535
+ if (options.check) {
23536
+ collectLegacyTypeArtifacts(root, srcDir, result.stalePaths);
23537
+ } else {
23538
+ removeLegacyTypeArtifacts(root, srcDir);
23539
+ }
23425
23540
  }
23426
23541
  return result;
23427
23542
  }
23428
23543
  __name(generateFarmTypeArtifacts, "generateFarmTypeArtifacts");
23544
+ function resolveGeneratedPath(root, srcDir, outFile, relativeToSrc = true) {
23545
+ if ((0, import_path8.isAbsolute)(outFile)) return (0, import_path8.resolve)(outFile);
23546
+ return (0, import_path8.resolve)(root, relativeToSrc ? (0, import_path8.join)(srcDir, outFile) : outFile);
23547
+ }
23548
+ __name(resolveGeneratedPath, "resolveGeneratedPath");
23549
+ function writeOrCheckGeneratedFile(filePath, content, check, stalePaths) {
23550
+ if (check) {
23551
+ checkGeneratedFile(filePath, content, stalePaths);
23552
+ return;
23553
+ }
23554
+ (0, import_fs4.mkdirSync)((0, import_path8.dirname)(filePath), { recursive: true });
23555
+ writeFileIfChanged(filePath, content);
23556
+ }
23557
+ __name(writeOrCheckGeneratedFile, "writeOrCheckGeneratedFile");
23558
+ function checkGeneratedFile(filePath, content, stalePaths) {
23559
+ if (!(0, import_fs4.existsSync)(filePath) || (0, import_fs4.readFileSync)(filePath, "utf8") !== content) {
23560
+ stalePaths.push(filePath);
23561
+ }
23562
+ }
23563
+ __name(checkGeneratedFile, "checkGeneratedFile");
23429
23564
  var LEGACY_TYPE_ARTIFACTS = [
23430
23565
  ["farm-routes.d.ts", "Auto-generated route types"],
23431
23566
  ["farm-env.d.ts", "Auto-generated env types"],
@@ -23443,6 +23578,14 @@ function removeLegacyTypeArtifacts(root, srcDir) {
23443
23578
  }
23444
23579
  }
23445
23580
  __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
23581
+ function collectLegacyTypeArtifacts(root, srcDir, stalePaths) {
23582
+ for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
23583
+ const filePath = (0, import_path8.join)(root, srcDir, fileName);
23584
+ if (!(0, import_fs4.existsSync)(filePath)) continue;
23585
+ if ((0, import_fs4.readFileSync)(filePath, "utf8").includes(marker)) stalePaths.push(filePath);
23586
+ }
23587
+ }
23588
+ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
23446
23589
 
23447
23590
  // src/vite.ts
23448
23591
  init_markdown();
@@ -23798,7 +23941,7 @@ function transformError(id, message) {
23798
23941
  __name(transformError, "transformError");
23799
23942
 
23800
23943
  // package.json
23801
- var version = "0.1.0-beta.13";
23944
+ var version = "0.1.0-beta.16";
23802
23945
 
23803
23946
  // src/version.ts
23804
23947
  var FARM_VERSION = version;
@@ -27960,6 +28103,8 @@ init_server_action_security();
27960
28103
 
27961
28104
  // src/server-fn.ts
27962
28105
  init_server_action_security();
28106
+ init_server_fn_error();
28107
+ init_server_fn_error();
27963
28108
  var FARM_SERVER_FN_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn");
27964
28109
  var UNSAFE_FORM_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
27965
28110
  function createServerFn(options) {
@@ -27967,6 +28112,8 @@ function createServerFn(options) {
27967
28112
  throw new TypeError("createServerFn requires a handler function");
27968
28113
  }
27969
28114
  const middleware = resolveServerFnMiddleware(options.middleware);
28115
+ const errors = normalizeServerFnErrors(options.errors);
28116
+ const error = createServerFnErrorHandler(errors);
27970
28117
  const serverFn = /* @__PURE__ */ __name(async (value) => {
27971
28118
  const formData = isFormData(value) ? value : void 0;
27972
28119
  const rawInput = formData ? formDataToObject2(formData) : value;
@@ -27984,7 +28131,7 @@ function createServerFn(options) {
27984
28131
  let resolvedContext = Object.freeze(/* @__PURE__ */ Object.create(null));
27985
28132
  const result = await runServerFnMiddleware(middleware, handlerContext, async (context) => {
27986
28133
  resolvedContext = context.context;
27987
- return options.handler(context);
28134
+ return options.handler({ ...context, error });
27988
28135
  });
27989
28136
  const parsedResult = await _parseServerFnSchema(options.output, result, "output");
27990
28137
  if (options.invalidates) {
@@ -28014,6 +28161,10 @@ function createServerFn(options) {
28014
28161
  value: options.output,
28015
28162
  enumerable: false
28016
28163
  },
28164
+ __farmServerFnError: {
28165
+ value: void 0,
28166
+ enumerable: false
28167
+ },
28017
28168
  __farmServerFnMiddleware: {
28018
28169
  value: middleware,
28019
28170
  enumerable: false
@@ -28052,6 +28203,78 @@ async function runServerFnMiddleware(middleware, handlerContext, handler) {
28052
28203
  return dispatch(0, Object.freeze(/* @__PURE__ */ Object.create(null)));
28053
28204
  }
28054
28205
  __name(runServerFnMiddleware, "runServerFnMiddleware");
28206
+ function normalizeServerFnErrors(definitions) {
28207
+ if (definitions === void 0) return Object.freeze({});
28208
+ if (!isPlainServerFnObject(definitions)) {
28209
+ throw new TypeError("createServerFn errors must be an object");
28210
+ }
28211
+ const normalized = /* @__PURE__ */ Object.create(null);
28212
+ for (const [code, definition] of Object.entries(definitions)) {
28213
+ if (!code.trim()) {
28214
+ throw new TypeError("Server function error codes cannot be empty");
28215
+ }
28216
+ if (!definition || typeof definition !== "object") {
28217
+ throw new TypeError(`Server function error "${code}" must be an object`);
28218
+ }
28219
+ if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
28220
+ throw new TypeError(
28221
+ `Server function error "${code}" status must be an integer between 400 and 599`
28222
+ );
28223
+ }
28224
+ if (!definition.data || typeof definition.data.parse !== "function" && typeof definition.data.safeParse !== "function") {
28225
+ throw new TypeError(
28226
+ `Server function error "${code}" data must provide synchronous parse() or safeParse()`
28227
+ );
28228
+ }
28229
+ if (definition.message !== void 0 && typeof definition.message !== "string") {
28230
+ throw new TypeError(`Server function error "${code}" message must be a string`);
28231
+ }
28232
+ normalized[code] = Object.freeze({ ...definition });
28233
+ }
28234
+ return Object.freeze(normalized);
28235
+ }
28236
+ __name(normalizeServerFnErrors, "normalizeServerFnErrors");
28237
+ function createServerFnErrorHandler(definitions) {
28238
+ return ((code, data) => {
28239
+ const definition = definitions[code];
28240
+ if (!definition) {
28241
+ throw new TypeError(`Server function error "${code}" is not declared`);
28242
+ }
28243
+ const parsed = parseServerFnFailureData(code, definition.data, data);
28244
+ throw new ServerFnFailure(code, parsed, {
28245
+ status: definition.status,
28246
+ message: definition.message ?? "Server function failed"
28247
+ });
28248
+ });
28249
+ }
28250
+ __name(createServerFnErrorHandler, "createServerFnErrorHandler");
28251
+ function parseServerFnFailureData(code, schema, value) {
28252
+ if (typeof schema.safeParse === "function") {
28253
+ const result2 = schema.safeParse(value);
28254
+ if (isPromiseLike2(result2)) {
28255
+ throw new TypeError(`Server function error "${code}" data schema must parse synchronously`);
28256
+ }
28257
+ return unwrapSafeParseResult(result2);
28258
+ }
28259
+ const result = schema.parse(value);
28260
+ if (isPromiseLike2(result)) {
28261
+ throw new TypeError(`Server function error "${code}" data schema must parse synchronously`);
28262
+ }
28263
+ return result;
28264
+ }
28265
+ __name(parseServerFnFailureData, "parseServerFnFailureData");
28266
+ function isPlainServerFnObject(value) {
28267
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
28268
+ const prototype = Object.getPrototypeOf(value);
28269
+ return prototype === Object.prototype || prototype === null;
28270
+ }
28271
+ __name(isPlainServerFnObject, "isPlainServerFnObject");
28272
+ function isPromiseLike2(value) {
28273
+ return Boolean(
28274
+ value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function"
28275
+ );
28276
+ }
28277
+ __name(isPromiseLike2, "isPromiseLike");
28055
28278
  function resolveServerFnMiddleware(middleware) {
28056
28279
  const resolved = [];
28057
28280
  const seen = /* @__PURE__ */ new Set();