@valbuild/shared 0.97.0 → 0.97.4

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.
@@ -758,6 +758,7 @@ export declare const Api: {
758
758
  validate_sources: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>> & z.ZodType<"true" | "false", string[], z.core.$ZodTypeInternals<"true" | "false", string[]>>, z.ZodTransform<boolean, "true" | "false">>>;
759
759
  validate_binary_files: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>> & z.ZodType<"true" | "false", string[], z.core.$ZodTypeInternals<"true" | "false", string[]>>, z.ZodTransform<boolean, "true" | "false">>>;
760
760
  exclude_patches: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>> & z.ZodType<"true" | "false", string[], z.core.$ZodTypeInternals<"true" | "false", string[]>>, z.ZodTransform<boolean, "true" | "false">>>;
761
+ apply_patches: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodArray<z.ZodString>, z.ZodTransform<string, string[]>> & z.ZodType<"true" | "false", string[], z.core.$ZodTypeInternals<"true" | "false", string[]>>, z.ZodTransform<boolean, "true" | "false">>>;
761
762
  };
762
763
  cookies: {
763
764
  val_session: z.ZodOptional<z.ZodString>;
@@ -1,6 +1,6 @@
1
1
  import { ValConfig } from "@valbuild/core";
2
2
  import { z } from "zod";
3
- export declare const SharedValConfig: z.ZodSchema<ValConfig & {
3
+ export declare const SharedValConfig: z.ZodSchema<Omit<ValConfig, "files"> & {
4
4
  contentHostUrl?: string;
5
5
  }>;
6
6
  /**
@@ -12,5 +12,6 @@ export * from "./getSitemapTree.js";
12
12
  export * from "./parseRoutePattern.js";
13
13
  export * from "./getNextAppRouterSourceFolder.js";
14
14
  export * from "./routeValidation.js";
15
+ export * from "./resolveSchemaSourceFixes.js";
15
16
  export * from "./getErrorMessageFromUnknownJson.js";
16
17
  export * from "./zod/SerializedSchema.js";
@@ -0,0 +1,42 @@
1
+ import { type Json, type ModuleFilePath, type SerializedSchema, type SourcePath, type ValidationError } from "@valbuild/core";
2
+ export type SchemaSourceSnapshot = {
3
+ schemas: Record<ModuleFilePath, SerializedSchema>;
4
+ sources: Record<ModuleFilePath, Json>;
5
+ };
6
+ export type RouteInfo = {
7
+ route: string;
8
+ moduleFilePath: ModuleFilePath;
9
+ };
10
+ export declare function getRoutesWithModulePaths(schemas: Record<ModuleFilePath, SerializedSchema>, sources: Record<ModuleFilePath, Json>): RouteInfo[];
11
+ export declare function getRoutesOf(schemas: Record<ModuleFilePath, SerializedSchema>, sources: Record<ModuleFilePath, Json>): string[];
12
+ export declare const levenshtein: (a: string, b: string) => number;
13
+ export declare function findSimilar(key: string, targets: string[]): {
14
+ target: string;
15
+ distance: number;
16
+ }[];
17
+ export type ResolvedFix = {
18
+ status: "resolved";
19
+ } | {
20
+ status: "remaining";
21
+ error: ValidationError;
22
+ };
23
+ /**
24
+ * Resolves a single `keyof:check-keys` or `router:check-route` error against
25
+ * the given schema/source snapshot. Returns:
26
+ * - null if the error is not one of these fixes (caller should pass through)
27
+ * - { status: "resolved" } if the referenced key/route is valid (drop error)
28
+ * - { status: "remaining"; error } if invalid (rewritten error to surface)
29
+ */
30
+ export declare function resolveSchemaSourceFixForError(error: ValidationError, snapshot: SchemaSourceSnapshot): ResolvedFix | null;
31
+ /**
32
+ * Apply schema/source fix resolution across a map of validation errors.
33
+ *
34
+ * Errors with `keyof:check-keys` or `router:check-route` are resolved against
35
+ * the in-memory schema/source snapshot — valid references drop the error,
36
+ * invalid ones are rewritten with a "did you mean…" message and have their
37
+ * `fixes` cleared (so downstream code reports them as plain validation errors).
38
+ * All other errors pass through untouched.
39
+ *
40
+ * Source paths with no remaining errors are removed from the result.
41
+ */
42
+ export declare function resolveSchemaSourceFixes(validationErrors: Record<SourcePath, ValidationError[]>, snapshot: SchemaSourceSnapshot): Record<SourcePath, ValidationError[]>;
@@ -1841,7 +1841,8 @@ var Api = {
1841
1841
  query: {
1842
1842
  validate_sources: onlyOneBooleanQueryParam.optional(),
1843
1843
  validate_binary_files: onlyOneBooleanQueryParam.optional(),
1844
- exclude_patches: onlyOneBooleanQueryParam.optional()
1844
+ exclude_patches: onlyOneBooleanQueryParam.optional(),
1845
+ apply_patches: onlyOneBooleanQueryParam.optional()
1845
1846
  },
1846
1847
  cookies: {
1847
1848
  val_session: zod.z.string().optional()
@@ -1878,7 +1879,7 @@ var Api = {
1878
1879
  source: zod.z.any().optional(),
1879
1880
  //.optional(), // TODO: Json zod type
1880
1881
  baseSource: zod.z.any().optional(),
1881
- // pre-patch source for compare view; set only when the module has pending patches
1882
+ // pre-patch source for compare view; only set when the server applies patches (apply_patches=true) and the module has pending patches
1882
1883
  patches: zod.z.object({
1883
1884
  applied: zod.z.array(PatchId),
1884
1885
  skipped: zod.z.array(PatchId).optional(),
@@ -2491,9 +2492,6 @@ var SharedValConfig = zod.z.object({
2491
2492
  appHostUrl: zod.z.string().optional(),
2492
2493
  project: zod.z.string().optional(),
2493
2494
  root: zod.z.string().optional(),
2494
- files: zod.z.object({
2495
- directory: zod.z.literal("/public/val")
2496
- }).optional(),
2497
2495
  gitCommit: zod.z.string().optional(),
2498
2496
  gitBranch: zod.z.string().optional(),
2499
2497
  defaultTheme: zod.z["enum"](["dark", "light"]).optional(),
@@ -2794,6 +2792,381 @@ function createRegExpFromPattern(pattern) {
2794
2792
  }
2795
2793
  }
2796
2794
 
2795
+ var TYPE_ERROR_MESSAGE = "This is most likely a Val version mismatch or Val bug.";
2796
+ function getRoutesWithModulePaths(schemas, sources) {
2797
+ var routeMap = new Map();
2798
+ for (var moduleFilePathS in schemas) {
2799
+ var moduleFilePath = moduleFilePathS;
2800
+ var schema = schemas[moduleFilePath];
2801
+ var source = sources[moduleFilePath];
2802
+ if (schema && schema.type === "record" && schema.router && source && _typeof(source) === "object" && !Array.isArray(source)) {
2803
+ for (var key in source) {
2804
+ if (!routeMap.has(key)) {
2805
+ routeMap.set(key, moduleFilePath);
2806
+ }
2807
+ }
2808
+ }
2809
+ }
2810
+ var routes = Array.from(routeMap.entries()).map(function (_ref) {
2811
+ var _ref2 = _slicedToArray(_ref, 2),
2812
+ route = _ref2[0],
2813
+ moduleFilePath = _ref2[1];
2814
+ return {
2815
+ route: route,
2816
+ moduleFilePath: moduleFilePath
2817
+ };
2818
+ });
2819
+ return routes.sort(function (a, b) {
2820
+ return a.route.localeCompare(b.route);
2821
+ });
2822
+ }
2823
+ function getRoutesOf(schemas, sources) {
2824
+ return getRoutesWithModulePaths(schemas, sources).map(function (r) {
2825
+ return r.route;
2826
+ });
2827
+ }
2828
+
2829
+ // GPT generated levenshtein distance algorithm
2830
+ var levenshtein = function levenshtein(a, b) {
2831
+ var _ref3 = [a.length, b.length],
2832
+ m = _ref3[0],
2833
+ n = _ref3[1];
2834
+ if (!m || !n) return Math.max(m, n);
2835
+ var dp = Array.from({
2836
+ length: m + 1
2837
+ }, function (_, i) {
2838
+ return i;
2839
+ });
2840
+ for (var j = 1; j <= n; j++) {
2841
+ var prev = dp[0];
2842
+ dp[0] = j;
2843
+ for (var i = 1; i <= m; i++) {
2844
+ var temp = dp[i];
2845
+ dp[i] = a[i - 1] === b[j - 1] ? prev : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
2846
+ prev = temp;
2847
+ }
2848
+ }
2849
+ return dp[m];
2850
+ };
2851
+ function findSimilar(key, targets) {
2852
+ return targets.map(function (target) {
2853
+ return {
2854
+ target: target,
2855
+ distance: levenshtein(key, target)
2856
+ };
2857
+ }).sort(function (a, b) {
2858
+ return a.distance - b.distance;
2859
+ });
2860
+ }
2861
+ function getKeyOfRecordAt(sourcePath, snapshot) {
2862
+ var _Internal$splitModule = core.Internal.splitModuleFilePathAndModulePath(sourcePath),
2863
+ _Internal$splitModule2 = _slicedToArray(_Internal$splitModule, 2),
2864
+ moduleFilePath = _Internal$splitModule2[0],
2865
+ modulePath = _Internal$splitModule2[1];
2866
+ var moduleSource = snapshot.sources[moduleFilePath];
2867
+ var moduleSchema = snapshot.schemas[moduleFilePath];
2868
+ if (!moduleSchema || moduleSource === undefined) {
2869
+ return {
2870
+ source: undefined,
2871
+ schema: undefined
2872
+ };
2873
+ }
2874
+ if (!modulePath) {
2875
+ return {
2876
+ source: moduleSource,
2877
+ schema: moduleSchema
2878
+ };
2879
+ }
2880
+ // Walk both schema and source. This intentionally only follows the
2881
+ // patterns produced by keyOf().sourcePath — typically a top-level record or
2882
+ // an object property pointing at a record. The walk is best-effort and
2883
+ // returns undefined source on any mismatch.
2884
+ var source = moduleSource;
2885
+ var schema = moduleSchema;
2886
+ var _iterator = _createForOfIteratorHelper(core.Internal.splitModulePath(modulePath)),
2887
+ _step;
2888
+ try {
2889
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
2890
+ var part = _step.value;
2891
+ if (source && _typeof(source) === "object" && !Array.isArray(source) && part in source) {
2892
+ source = source[part];
2893
+ } else {
2894
+ source = undefined;
2895
+ }
2896
+ if (schema && schema.type === "object" && schema.items[part]) {
2897
+ schema = schema.items[part];
2898
+ } else if (schema && schema.type === "record") {
2899
+ schema = schema.item;
2900
+ } else {
2901
+ schema = undefined;
2902
+ }
2903
+ }
2904
+ } catch (err) {
2905
+ _iterator.e(err);
2906
+ } finally {
2907
+ _iterator.f();
2908
+ }
2909
+ return {
2910
+ source: source,
2911
+ schema: schema
2912
+ };
2913
+ }
2914
+ function checkKeyIsValid(key, sourcePath, snapshot) {
2915
+ var _getKeyOfRecordAt = getKeyOfRecordAt(sourcePath, snapshot),
2916
+ keyOfModuleSource = _getKeyOfRecordAt.source,
2917
+ keyOfModuleSchema = _getKeyOfRecordAt.schema;
2918
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
2919
+ return {
2920
+ error: true,
2921
+ message: "Expected key at ".concat(sourcePath, " to be of type 'record'")
2922
+ };
2923
+ }
2924
+ if (keyOfModuleSource && _typeof(keyOfModuleSource) === "object" && !Array.isArray(keyOfModuleSource) && key in keyOfModuleSource) {
2925
+ return {
2926
+ error: false
2927
+ };
2928
+ }
2929
+ if (!keyOfModuleSource || _typeof(keyOfModuleSource) !== "object" || Array.isArray(keyOfModuleSource)) {
2930
+ return {
2931
+ error: true,
2932
+ message: "Expected ".concat(sourcePath, " to be a truthy object")
2933
+ };
2934
+ }
2935
+ var alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
2936
+ if (alternatives.length === 0) {
2937
+ return {
2938
+ error: true,
2939
+ message: "Key '".concat(key, "' does not exist in ").concat(sourcePath, ".")
2940
+ };
2941
+ }
2942
+ return {
2943
+ error: true,
2944
+ message: "Key '".concat(key, "' does not exist in ").concat(sourcePath, ". Closest match: '").concat(alternatives[0].target, "'. Other similar: ").concat(alternatives.slice(1, 4).map(function (a) {
2945
+ return "'".concat(a.target, "'");
2946
+ }).join(", ")).concat(alternatives.length > 4 ? ", ..." : "")
2947
+ };
2948
+ }
2949
+ function checkRouteIsValid(route, includePattern, excludePattern, snapshot) {
2950
+ var routerModules = {};
2951
+ for (var moduleFilePathS in snapshot.schemas) {
2952
+ var moduleFilePath = moduleFilePathS;
2953
+ var schema = snapshot.schemas[moduleFilePath];
2954
+ if ((schema === null || schema === void 0 ? void 0 : schema.type) === "record" && schema.router) {
2955
+ var source = snapshot.sources[moduleFilePath];
2956
+ if (source && _typeof(source) === "object" && !Array.isArray(source)) {
2957
+ routerModules[moduleFilePath] = Object.keys(source);
2958
+ }
2959
+ }
2960
+ }
2961
+ var moduleEntries = Object.entries(routerModules);
2962
+ var foundInModule = null;
2963
+ for (var _i = 0, _moduleEntries = moduleEntries; _i < _moduleEntries.length; _i++) {
2964
+ var _moduleEntries$_i = _slicedToArray(_moduleEntries[_i], 2),
2965
+ _moduleFilePath = _moduleEntries$_i[0],
2966
+ routes = _moduleEntries$_i[1];
2967
+ if (routes.includes(route)) {
2968
+ foundInModule = _moduleFilePath;
2969
+ break;
2970
+ }
2971
+ }
2972
+ if (!foundInModule) {
2973
+ var allRoutes = moduleEntries.flatMap(function (_ref4) {
2974
+ var _ref5 = _slicedToArray(_ref4, 2),
2975
+ routes = _ref5[1];
2976
+ return routes;
2977
+ });
2978
+ if (allRoutes.length === 0) {
2979
+ return {
2980
+ error: true,
2981
+ message: "Route '".concat(route, "' could not be validated: No router modules found in the project. Use s.record(...).router(...) to define router modules.")
2982
+ };
2983
+ }
2984
+ allRoutes = filterRoutesByPatterns(allRoutes, includePattern, excludePattern);
2985
+ var alternatives = findSimilar(route, allRoutes);
2986
+ return {
2987
+ error: true,
2988
+ message: "Route '".concat(route, "' does not exist in any router module. ").concat(alternatives.length > 0 ? "Closest match: '".concat(alternatives[0].target, "'. Other similar: ").concat(alternatives.slice(1, 4).map(function (a) {
2989
+ return "'".concat(a.target, "'");
2990
+ }).join(", ")).concat(alternatives.length > 4 ? ", ..." : "") : "No similar routes found.")
2991
+ };
2992
+ }
2993
+ var patternValidation = validateRoutePatterns(route, includePattern, excludePattern);
2994
+ if (!patternValidation.valid) {
2995
+ return {
2996
+ error: true,
2997
+ message: patternValidation.message
2998
+ };
2999
+ }
3000
+ return {
3001
+ error: false
3002
+ };
3003
+ }
3004
+ /**
3005
+ * Resolves a single `keyof:check-keys` or `router:check-route` error against
3006
+ * the given schema/source snapshot. Returns:
3007
+ * - null if the error is not one of these fixes (caller should pass through)
3008
+ * - { status: "resolved" } if the referenced key/route is valid (drop error)
3009
+ * - { status: "remaining"; error } if invalid (rewritten error to surface)
3010
+ */
3011
+ function resolveSchemaSourceFixForError(error, snapshot) {
3012
+ var _error$fixes;
3013
+ var fixes = (_error$fixes = error.fixes) !== null && _error$fixes !== void 0 ? _error$fixes : [];
3014
+ if (fixes.includes("keyof:check-keys")) {
3015
+ if (!error.value) {
3016
+ return {
3017
+ status: "remaining",
3018
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3019
+ message: "Could not find a value for keyOf. ".concat(TYPE_ERROR_MESSAGE),
3020
+ typeError: true,
3021
+ fixes: undefined
3022
+ })
3023
+ };
3024
+ }
3025
+ if (_typeof(error.value) !== "object") {
3026
+ return {
3027
+ status: "remaining",
3028
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3029
+ message: "Expected keyOf validation error to have a 'value' property of type 'object'. Found: ".concat(_typeof(error.value), ". ").concat(TYPE_ERROR_MESSAGE),
3030
+ typeError: true,
3031
+ fixes: undefined
3032
+ })
3033
+ };
3034
+ }
3035
+ var valueObj = error.value;
3036
+ var key = valueObj.key;
3037
+ var valueSourcePath = valueObj.sourcePath;
3038
+ if (typeof key !== "string") {
3039
+ return {
3040
+ status: "remaining",
3041
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3042
+ message: "Expected keyOf validation error 'value' to have property 'key' of type 'string'. Found: ".concat(_typeof(key), ". ").concat(TYPE_ERROR_MESSAGE),
3043
+ typeError: true,
3044
+ fixes: undefined
3045
+ })
3046
+ };
3047
+ }
3048
+ if (typeof valueSourcePath !== "string") {
3049
+ return {
3050
+ status: "remaining",
3051
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3052
+ message: "Expected keyOf validation error 'value' to have property 'sourcePath' of type 'string'. Found: ".concat(_typeof(valueSourcePath), ". ").concat(TYPE_ERROR_MESSAGE),
3053
+ typeError: true,
3054
+ fixes: undefined
3055
+ })
3056
+ };
3057
+ }
3058
+ var res = checkKeyIsValid(key, valueSourcePath, snapshot);
3059
+ if (res.error) {
3060
+ return {
3061
+ status: "remaining",
3062
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3063
+ message: res.message,
3064
+ fixes: undefined
3065
+ })
3066
+ };
3067
+ }
3068
+ return {
3069
+ status: "resolved"
3070
+ };
3071
+ }
3072
+ if (fixes.includes("router:check-route")) {
3073
+ if (!error.value) {
3074
+ return {
3075
+ status: "remaining",
3076
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3077
+ message: "Could not find a value for route. ".concat(TYPE_ERROR_MESSAGE),
3078
+ typeError: true,
3079
+ fixes: undefined
3080
+ })
3081
+ };
3082
+ }
3083
+ if (_typeof(error.value) !== "object") {
3084
+ return {
3085
+ status: "remaining",
3086
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3087
+ message: "Expected route validation error to have a 'value' property of type 'object'. Found: ".concat(_typeof(error.value), ". ").concat(TYPE_ERROR_MESSAGE),
3088
+ typeError: true,
3089
+ fixes: undefined
3090
+ })
3091
+ };
3092
+ }
3093
+ var _valueObj = error.value;
3094
+ var route = _valueObj.route;
3095
+ if (typeof route !== "string") {
3096
+ return {
3097
+ status: "remaining",
3098
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3099
+ message: "Expected route validation error 'value' to have property 'route' of type 'string'. Found: ".concat(_typeof(route), ". ").concat(TYPE_ERROR_MESSAGE),
3100
+ typeError: true,
3101
+ fixes: undefined
3102
+ })
3103
+ };
3104
+ }
3105
+ var include = asRegExpPattern(_valueObj.include);
3106
+ var exclude = asRegExpPattern(_valueObj.exclude);
3107
+ var _res = checkRouteIsValid(route, include, exclude, snapshot);
3108
+ if (_res.error) {
3109
+ return {
3110
+ status: "remaining",
3111
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3112
+ message: _res.message,
3113
+ fixes: undefined
3114
+ })
3115
+ };
3116
+ }
3117
+ return {
3118
+ status: "resolved"
3119
+ };
3120
+ }
3121
+ return null;
3122
+ }
3123
+ function asRegExpPattern(value) {
3124
+ if (value && _typeof(value) === "object" && "source" in value && "flags" in value && typeof value.source === "string" && typeof value.flags === "string") {
3125
+ return value;
3126
+ }
3127
+ return undefined;
3128
+ }
3129
+
3130
+ /**
3131
+ * Apply schema/source fix resolution across a map of validation errors.
3132
+ *
3133
+ * Errors with `keyof:check-keys` or `router:check-route` are resolved against
3134
+ * the in-memory schema/source snapshot — valid references drop the error,
3135
+ * invalid ones are rewritten with a "did you mean…" message and have their
3136
+ * `fixes` cleared (so downstream code reports them as plain validation errors).
3137
+ * All other errors pass through untouched.
3138
+ *
3139
+ * Source paths with no remaining errors are removed from the result.
3140
+ */
3141
+ function resolveSchemaSourceFixes(validationErrors, snapshot) {
3142
+ var result = {};
3143
+ for (var sourcePathS in validationErrors) {
3144
+ var sourcePath = sourcePathS;
3145
+ var remaining = [];
3146
+ var _iterator2 = _createForOfIteratorHelper(validationErrors[sourcePath]),
3147
+ _step2;
3148
+ try {
3149
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
3150
+ var error = _step2.value;
3151
+ var resolved = resolveSchemaSourceFixForError(error, snapshot);
3152
+ if (resolved === null) {
3153
+ remaining.push(error);
3154
+ } else if (resolved.status === "remaining") {
3155
+ remaining.push(resolved.error);
3156
+ }
3157
+ }
3158
+ } catch (err) {
3159
+ _iterator2.e(err);
3160
+ } finally {
3161
+ _iterator2.f();
3162
+ }
3163
+ if (remaining.length > 0) {
3164
+ result[sourcePath] = remaining;
3165
+ }
3166
+ }
3167
+ return result;
3168
+ }
3169
+
2797
3170
  exports.Api = Api;
2798
3171
  exports.DEFAULT_ERROR_MESSAGE = DEFAULT_ERROR_MESSAGE;
2799
3172
  exports.DateOptions = DateOptions;
@@ -2843,12 +3216,18 @@ exports.ValDeployment = ValDeployment;
2843
3216
  exports.createRegExpFromPattern = createRegExpFromPattern;
2844
3217
  exports.createValClient = createValClient;
2845
3218
  exports.filterRoutesByPatterns = filterRoutesByPatterns;
3219
+ exports.findSimilar = findSimilar;
2846
3220
  exports.getErrorMessageFromUnknownJson = getErrorMessageFromUnknownJson;
2847
3221
  exports.getNextAppRouterSitemapTree = getNextAppRouterSitemapTree;
2848
3222
  exports.getNextAppRouterSourceFolder = getNextAppRouterSourceFolder;
2849
3223
  exports.getPatternFromModuleFilePath = getPatternFromModuleFilePath;
3224
+ exports.getRoutesOf = getRoutesOf;
3225
+ exports.getRoutesWithModulePaths = getRoutesWithModulePaths;
3226
+ exports.levenshtein = levenshtein;
2850
3227
  exports.parseRoutePattern = parseRoutePattern;
2851
3228
  exports.remirrorToRichTextSource = remirrorToRichTextSource;
3229
+ exports.resolveSchemaSourceFixForError = resolveSchemaSourceFixForError;
3230
+ exports.resolveSchemaSourceFixes = resolveSchemaSourceFixes;
2852
3231
  exports.richTextToRemirror = richTextToRemirror;
2853
3232
  exports.urlOf = urlOf;
2854
3233
  exports.validateRoutePatterns = validateRoutePatterns;
@@ -1841,7 +1841,8 @@ var Api = {
1841
1841
  query: {
1842
1842
  validate_sources: onlyOneBooleanQueryParam.optional(),
1843
1843
  validate_binary_files: onlyOneBooleanQueryParam.optional(),
1844
- exclude_patches: onlyOneBooleanQueryParam.optional()
1844
+ exclude_patches: onlyOneBooleanQueryParam.optional(),
1845
+ apply_patches: onlyOneBooleanQueryParam.optional()
1845
1846
  },
1846
1847
  cookies: {
1847
1848
  val_session: zod.z.string().optional()
@@ -1878,7 +1879,7 @@ var Api = {
1878
1879
  source: zod.z.any().optional(),
1879
1880
  //.optional(), // TODO: Json zod type
1880
1881
  baseSource: zod.z.any().optional(),
1881
- // pre-patch source for compare view; set only when the module has pending patches
1882
+ // pre-patch source for compare view; only set when the server applies patches (apply_patches=true) and the module has pending patches
1882
1883
  patches: zod.z.object({
1883
1884
  applied: zod.z.array(PatchId),
1884
1885
  skipped: zod.z.array(PatchId).optional(),
@@ -2491,9 +2492,6 @@ var SharedValConfig = zod.z.object({
2491
2492
  appHostUrl: zod.z.string().optional(),
2492
2493
  project: zod.z.string().optional(),
2493
2494
  root: zod.z.string().optional(),
2494
- files: zod.z.object({
2495
- directory: zod.z.literal("/public/val")
2496
- }).optional(),
2497
2495
  gitCommit: zod.z.string().optional(),
2498
2496
  gitBranch: zod.z.string().optional(),
2499
2497
  defaultTheme: zod.z["enum"](["dark", "light"]).optional(),
@@ -2794,6 +2792,381 @@ function createRegExpFromPattern(pattern) {
2794
2792
  }
2795
2793
  }
2796
2794
 
2795
+ var TYPE_ERROR_MESSAGE = "This is most likely a Val version mismatch or Val bug.";
2796
+ function getRoutesWithModulePaths(schemas, sources) {
2797
+ var routeMap = new Map();
2798
+ for (var moduleFilePathS in schemas) {
2799
+ var moduleFilePath = moduleFilePathS;
2800
+ var schema = schemas[moduleFilePath];
2801
+ var source = sources[moduleFilePath];
2802
+ if (schema && schema.type === "record" && schema.router && source && _typeof(source) === "object" && !Array.isArray(source)) {
2803
+ for (var key in source) {
2804
+ if (!routeMap.has(key)) {
2805
+ routeMap.set(key, moduleFilePath);
2806
+ }
2807
+ }
2808
+ }
2809
+ }
2810
+ var routes = Array.from(routeMap.entries()).map(function (_ref) {
2811
+ var _ref2 = _slicedToArray(_ref, 2),
2812
+ route = _ref2[0],
2813
+ moduleFilePath = _ref2[1];
2814
+ return {
2815
+ route: route,
2816
+ moduleFilePath: moduleFilePath
2817
+ };
2818
+ });
2819
+ return routes.sort(function (a, b) {
2820
+ return a.route.localeCompare(b.route);
2821
+ });
2822
+ }
2823
+ function getRoutesOf(schemas, sources) {
2824
+ return getRoutesWithModulePaths(schemas, sources).map(function (r) {
2825
+ return r.route;
2826
+ });
2827
+ }
2828
+
2829
+ // GPT generated levenshtein distance algorithm
2830
+ var levenshtein = function levenshtein(a, b) {
2831
+ var _ref3 = [a.length, b.length],
2832
+ m = _ref3[0],
2833
+ n = _ref3[1];
2834
+ if (!m || !n) return Math.max(m, n);
2835
+ var dp = Array.from({
2836
+ length: m + 1
2837
+ }, function (_, i) {
2838
+ return i;
2839
+ });
2840
+ for (var j = 1; j <= n; j++) {
2841
+ var prev = dp[0];
2842
+ dp[0] = j;
2843
+ for (var i = 1; i <= m; i++) {
2844
+ var temp = dp[i];
2845
+ dp[i] = a[i - 1] === b[j - 1] ? prev : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
2846
+ prev = temp;
2847
+ }
2848
+ }
2849
+ return dp[m];
2850
+ };
2851
+ function findSimilar(key, targets) {
2852
+ return targets.map(function (target) {
2853
+ return {
2854
+ target: target,
2855
+ distance: levenshtein(key, target)
2856
+ };
2857
+ }).sort(function (a, b) {
2858
+ return a.distance - b.distance;
2859
+ });
2860
+ }
2861
+ function getKeyOfRecordAt(sourcePath, snapshot) {
2862
+ var _Internal$splitModule = core.Internal.splitModuleFilePathAndModulePath(sourcePath),
2863
+ _Internal$splitModule2 = _slicedToArray(_Internal$splitModule, 2),
2864
+ moduleFilePath = _Internal$splitModule2[0],
2865
+ modulePath = _Internal$splitModule2[1];
2866
+ var moduleSource = snapshot.sources[moduleFilePath];
2867
+ var moduleSchema = snapshot.schemas[moduleFilePath];
2868
+ if (!moduleSchema || moduleSource === undefined) {
2869
+ return {
2870
+ source: undefined,
2871
+ schema: undefined
2872
+ };
2873
+ }
2874
+ if (!modulePath) {
2875
+ return {
2876
+ source: moduleSource,
2877
+ schema: moduleSchema
2878
+ };
2879
+ }
2880
+ // Walk both schema and source. This intentionally only follows the
2881
+ // patterns produced by keyOf().sourcePath — typically a top-level record or
2882
+ // an object property pointing at a record. The walk is best-effort and
2883
+ // returns undefined source on any mismatch.
2884
+ var source = moduleSource;
2885
+ var schema = moduleSchema;
2886
+ var _iterator = _createForOfIteratorHelper(core.Internal.splitModulePath(modulePath)),
2887
+ _step;
2888
+ try {
2889
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
2890
+ var part = _step.value;
2891
+ if (source && _typeof(source) === "object" && !Array.isArray(source) && part in source) {
2892
+ source = source[part];
2893
+ } else {
2894
+ source = undefined;
2895
+ }
2896
+ if (schema && schema.type === "object" && schema.items[part]) {
2897
+ schema = schema.items[part];
2898
+ } else if (schema && schema.type === "record") {
2899
+ schema = schema.item;
2900
+ } else {
2901
+ schema = undefined;
2902
+ }
2903
+ }
2904
+ } catch (err) {
2905
+ _iterator.e(err);
2906
+ } finally {
2907
+ _iterator.f();
2908
+ }
2909
+ return {
2910
+ source: source,
2911
+ schema: schema
2912
+ };
2913
+ }
2914
+ function checkKeyIsValid(key, sourcePath, snapshot) {
2915
+ var _getKeyOfRecordAt = getKeyOfRecordAt(sourcePath, snapshot),
2916
+ keyOfModuleSource = _getKeyOfRecordAt.source,
2917
+ keyOfModuleSchema = _getKeyOfRecordAt.schema;
2918
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
2919
+ return {
2920
+ error: true,
2921
+ message: "Expected key at ".concat(sourcePath, " to be of type 'record'")
2922
+ };
2923
+ }
2924
+ if (keyOfModuleSource && _typeof(keyOfModuleSource) === "object" && !Array.isArray(keyOfModuleSource) && key in keyOfModuleSource) {
2925
+ return {
2926
+ error: false
2927
+ };
2928
+ }
2929
+ if (!keyOfModuleSource || _typeof(keyOfModuleSource) !== "object" || Array.isArray(keyOfModuleSource)) {
2930
+ return {
2931
+ error: true,
2932
+ message: "Expected ".concat(sourcePath, " to be a truthy object")
2933
+ };
2934
+ }
2935
+ var alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
2936
+ if (alternatives.length === 0) {
2937
+ return {
2938
+ error: true,
2939
+ message: "Key '".concat(key, "' does not exist in ").concat(sourcePath, ".")
2940
+ };
2941
+ }
2942
+ return {
2943
+ error: true,
2944
+ message: "Key '".concat(key, "' does not exist in ").concat(sourcePath, ". Closest match: '").concat(alternatives[0].target, "'. Other similar: ").concat(alternatives.slice(1, 4).map(function (a) {
2945
+ return "'".concat(a.target, "'");
2946
+ }).join(", ")).concat(alternatives.length > 4 ? ", ..." : "")
2947
+ };
2948
+ }
2949
+ function checkRouteIsValid(route, includePattern, excludePattern, snapshot) {
2950
+ var routerModules = {};
2951
+ for (var moduleFilePathS in snapshot.schemas) {
2952
+ var moduleFilePath = moduleFilePathS;
2953
+ var schema = snapshot.schemas[moduleFilePath];
2954
+ if ((schema === null || schema === void 0 ? void 0 : schema.type) === "record" && schema.router) {
2955
+ var source = snapshot.sources[moduleFilePath];
2956
+ if (source && _typeof(source) === "object" && !Array.isArray(source)) {
2957
+ routerModules[moduleFilePath] = Object.keys(source);
2958
+ }
2959
+ }
2960
+ }
2961
+ var moduleEntries = Object.entries(routerModules);
2962
+ var foundInModule = null;
2963
+ for (var _i = 0, _moduleEntries = moduleEntries; _i < _moduleEntries.length; _i++) {
2964
+ var _moduleEntries$_i = _slicedToArray(_moduleEntries[_i], 2),
2965
+ _moduleFilePath = _moduleEntries$_i[0],
2966
+ routes = _moduleEntries$_i[1];
2967
+ if (routes.includes(route)) {
2968
+ foundInModule = _moduleFilePath;
2969
+ break;
2970
+ }
2971
+ }
2972
+ if (!foundInModule) {
2973
+ var allRoutes = moduleEntries.flatMap(function (_ref4) {
2974
+ var _ref5 = _slicedToArray(_ref4, 2),
2975
+ routes = _ref5[1];
2976
+ return routes;
2977
+ });
2978
+ if (allRoutes.length === 0) {
2979
+ return {
2980
+ error: true,
2981
+ message: "Route '".concat(route, "' could not be validated: No router modules found in the project. Use s.record(...).router(...) to define router modules.")
2982
+ };
2983
+ }
2984
+ allRoutes = filterRoutesByPatterns(allRoutes, includePattern, excludePattern);
2985
+ var alternatives = findSimilar(route, allRoutes);
2986
+ return {
2987
+ error: true,
2988
+ message: "Route '".concat(route, "' does not exist in any router module. ").concat(alternatives.length > 0 ? "Closest match: '".concat(alternatives[0].target, "'. Other similar: ").concat(alternatives.slice(1, 4).map(function (a) {
2989
+ return "'".concat(a.target, "'");
2990
+ }).join(", ")).concat(alternatives.length > 4 ? ", ..." : "") : "No similar routes found.")
2991
+ };
2992
+ }
2993
+ var patternValidation = validateRoutePatterns(route, includePattern, excludePattern);
2994
+ if (!patternValidation.valid) {
2995
+ return {
2996
+ error: true,
2997
+ message: patternValidation.message
2998
+ };
2999
+ }
3000
+ return {
3001
+ error: false
3002
+ };
3003
+ }
3004
+ /**
3005
+ * Resolves a single `keyof:check-keys` or `router:check-route` error against
3006
+ * the given schema/source snapshot. Returns:
3007
+ * - null if the error is not one of these fixes (caller should pass through)
3008
+ * - { status: "resolved" } if the referenced key/route is valid (drop error)
3009
+ * - { status: "remaining"; error } if invalid (rewritten error to surface)
3010
+ */
3011
+ function resolveSchemaSourceFixForError(error, snapshot) {
3012
+ var _error$fixes;
3013
+ var fixes = (_error$fixes = error.fixes) !== null && _error$fixes !== void 0 ? _error$fixes : [];
3014
+ if (fixes.includes("keyof:check-keys")) {
3015
+ if (!error.value) {
3016
+ return {
3017
+ status: "remaining",
3018
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3019
+ message: "Could not find a value for keyOf. ".concat(TYPE_ERROR_MESSAGE),
3020
+ typeError: true,
3021
+ fixes: undefined
3022
+ })
3023
+ };
3024
+ }
3025
+ if (_typeof(error.value) !== "object") {
3026
+ return {
3027
+ status: "remaining",
3028
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3029
+ message: "Expected keyOf validation error to have a 'value' property of type 'object'. Found: ".concat(_typeof(error.value), ". ").concat(TYPE_ERROR_MESSAGE),
3030
+ typeError: true,
3031
+ fixes: undefined
3032
+ })
3033
+ };
3034
+ }
3035
+ var valueObj = error.value;
3036
+ var key = valueObj.key;
3037
+ var valueSourcePath = valueObj.sourcePath;
3038
+ if (typeof key !== "string") {
3039
+ return {
3040
+ status: "remaining",
3041
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3042
+ message: "Expected keyOf validation error 'value' to have property 'key' of type 'string'. Found: ".concat(_typeof(key), ". ").concat(TYPE_ERROR_MESSAGE),
3043
+ typeError: true,
3044
+ fixes: undefined
3045
+ })
3046
+ };
3047
+ }
3048
+ if (typeof valueSourcePath !== "string") {
3049
+ return {
3050
+ status: "remaining",
3051
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3052
+ message: "Expected keyOf validation error 'value' to have property 'sourcePath' of type 'string'. Found: ".concat(_typeof(valueSourcePath), ". ").concat(TYPE_ERROR_MESSAGE),
3053
+ typeError: true,
3054
+ fixes: undefined
3055
+ })
3056
+ };
3057
+ }
3058
+ var res = checkKeyIsValid(key, valueSourcePath, snapshot);
3059
+ if (res.error) {
3060
+ return {
3061
+ status: "remaining",
3062
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3063
+ message: res.message,
3064
+ fixes: undefined
3065
+ })
3066
+ };
3067
+ }
3068
+ return {
3069
+ status: "resolved"
3070
+ };
3071
+ }
3072
+ if (fixes.includes("router:check-route")) {
3073
+ if (!error.value) {
3074
+ return {
3075
+ status: "remaining",
3076
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3077
+ message: "Could not find a value for route. ".concat(TYPE_ERROR_MESSAGE),
3078
+ typeError: true,
3079
+ fixes: undefined
3080
+ })
3081
+ };
3082
+ }
3083
+ if (_typeof(error.value) !== "object") {
3084
+ return {
3085
+ status: "remaining",
3086
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3087
+ message: "Expected route validation error to have a 'value' property of type 'object'. Found: ".concat(_typeof(error.value), ". ").concat(TYPE_ERROR_MESSAGE),
3088
+ typeError: true,
3089
+ fixes: undefined
3090
+ })
3091
+ };
3092
+ }
3093
+ var _valueObj = error.value;
3094
+ var route = _valueObj.route;
3095
+ if (typeof route !== "string") {
3096
+ return {
3097
+ status: "remaining",
3098
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3099
+ message: "Expected route validation error 'value' to have property 'route' of type 'string'. Found: ".concat(_typeof(route), ". ").concat(TYPE_ERROR_MESSAGE),
3100
+ typeError: true,
3101
+ fixes: undefined
3102
+ })
3103
+ };
3104
+ }
3105
+ var include = asRegExpPattern(_valueObj.include);
3106
+ var exclude = asRegExpPattern(_valueObj.exclude);
3107
+ var _res = checkRouteIsValid(route, include, exclude, snapshot);
3108
+ if (_res.error) {
3109
+ return {
3110
+ status: "remaining",
3111
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3112
+ message: _res.message,
3113
+ fixes: undefined
3114
+ })
3115
+ };
3116
+ }
3117
+ return {
3118
+ status: "resolved"
3119
+ };
3120
+ }
3121
+ return null;
3122
+ }
3123
+ function asRegExpPattern(value) {
3124
+ if (value && _typeof(value) === "object" && "source" in value && "flags" in value && typeof value.source === "string" && typeof value.flags === "string") {
3125
+ return value;
3126
+ }
3127
+ return undefined;
3128
+ }
3129
+
3130
+ /**
3131
+ * Apply schema/source fix resolution across a map of validation errors.
3132
+ *
3133
+ * Errors with `keyof:check-keys` or `router:check-route` are resolved against
3134
+ * the in-memory schema/source snapshot — valid references drop the error,
3135
+ * invalid ones are rewritten with a "did you mean…" message and have their
3136
+ * `fixes` cleared (so downstream code reports them as plain validation errors).
3137
+ * All other errors pass through untouched.
3138
+ *
3139
+ * Source paths with no remaining errors are removed from the result.
3140
+ */
3141
+ function resolveSchemaSourceFixes(validationErrors, snapshot) {
3142
+ var result = {};
3143
+ for (var sourcePathS in validationErrors) {
3144
+ var sourcePath = sourcePathS;
3145
+ var remaining = [];
3146
+ var _iterator2 = _createForOfIteratorHelper(validationErrors[sourcePath]),
3147
+ _step2;
3148
+ try {
3149
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
3150
+ var error = _step2.value;
3151
+ var resolved = resolveSchemaSourceFixForError(error, snapshot);
3152
+ if (resolved === null) {
3153
+ remaining.push(error);
3154
+ } else if (resolved.status === "remaining") {
3155
+ remaining.push(resolved.error);
3156
+ }
3157
+ }
3158
+ } catch (err) {
3159
+ _iterator2.e(err);
3160
+ } finally {
3161
+ _iterator2.f();
3162
+ }
3163
+ if (remaining.length > 0) {
3164
+ result[sourcePath] = remaining;
3165
+ }
3166
+ }
3167
+ return result;
3168
+ }
3169
+
2797
3170
  exports.Api = Api;
2798
3171
  exports.DEFAULT_ERROR_MESSAGE = DEFAULT_ERROR_MESSAGE;
2799
3172
  exports.DateOptions = DateOptions;
@@ -2843,12 +3216,18 @@ exports.ValDeployment = ValDeployment;
2843
3216
  exports.createRegExpFromPattern = createRegExpFromPattern;
2844
3217
  exports.createValClient = createValClient;
2845
3218
  exports.filterRoutesByPatterns = filterRoutesByPatterns;
3219
+ exports.findSimilar = findSimilar;
2846
3220
  exports.getErrorMessageFromUnknownJson = getErrorMessageFromUnknownJson;
2847
3221
  exports.getNextAppRouterSitemapTree = getNextAppRouterSitemapTree;
2848
3222
  exports.getNextAppRouterSourceFolder = getNextAppRouterSourceFolder;
2849
3223
  exports.getPatternFromModuleFilePath = getPatternFromModuleFilePath;
3224
+ exports.getRoutesOf = getRoutesOf;
3225
+ exports.getRoutesWithModulePaths = getRoutesWithModulePaths;
3226
+ exports.levenshtein = levenshtein;
2850
3227
  exports.parseRoutePattern = parseRoutePattern;
2851
3228
  exports.remirrorToRichTextSource = remirrorToRichTextSource;
3229
+ exports.resolveSchemaSourceFixForError = resolveSchemaSourceFixForError;
3230
+ exports.resolveSchemaSourceFixes = resolveSchemaSourceFixes;
2852
3231
  exports.richTextToRemirror = richTextToRemirror;
2853
3232
  exports.urlOf = urlOf;
2854
3233
  exports.validateRoutePatterns = validateRoutePatterns;
@@ -1837,7 +1837,8 @@ var Api = {
1837
1837
  query: {
1838
1838
  validate_sources: onlyOneBooleanQueryParam.optional(),
1839
1839
  validate_binary_files: onlyOneBooleanQueryParam.optional(),
1840
- exclude_patches: onlyOneBooleanQueryParam.optional()
1840
+ exclude_patches: onlyOneBooleanQueryParam.optional(),
1841
+ apply_patches: onlyOneBooleanQueryParam.optional()
1841
1842
  },
1842
1843
  cookies: {
1843
1844
  val_session: z.string().optional()
@@ -1874,7 +1875,7 @@ var Api = {
1874
1875
  source: z.any().optional(),
1875
1876
  //.optional(), // TODO: Json zod type
1876
1877
  baseSource: z.any().optional(),
1877
- // pre-patch source for compare view; set only when the module has pending patches
1878
+ // pre-patch source for compare view; only set when the server applies patches (apply_patches=true) and the module has pending patches
1878
1879
  patches: z.object({
1879
1880
  applied: z.array(PatchId),
1880
1881
  skipped: z.array(PatchId).optional(),
@@ -2487,9 +2488,6 @@ var SharedValConfig = z.object({
2487
2488
  appHostUrl: z.string().optional(),
2488
2489
  project: z.string().optional(),
2489
2490
  root: z.string().optional(),
2490
- files: z.object({
2491
- directory: z.literal("/public/val")
2492
- }).optional(),
2493
2491
  gitCommit: z.string().optional(),
2494
2492
  gitBranch: z.string().optional(),
2495
2493
  defaultTheme: z["enum"](["dark", "light"]).optional(),
@@ -2790,4 +2788,379 @@ function createRegExpFromPattern(pattern) {
2790
2788
  }
2791
2789
  }
2792
2790
 
2793
- export { Api, DEFAULT_ERROR_MESSAGE, DateOptions, FileOptions, ImageOptions, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RichTextOptions, SerializedArraySchema, SerializedBooleanSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedStringSchema, SerializedUnionSchema, SharedValConfig, VAL_CONFIG_SESSION_STORAGE_KEY, VAL_ENABLE_COOKIE_NAME, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_THEME_SESSION_STORAGE_KEY, ValCommit, ValDeployment, createRegExpFromPattern, createValClient, filterRoutesByPatterns, getErrorMessageFromUnknownJson, getNextAppRouterSitemapTree, getNextAppRouterSourceFolder, getPatternFromModuleFilePath, parseRoutePattern, remirrorToRichTextSource, richTextToRemirror, urlOf, validateRoutePatterns };
2791
+ var TYPE_ERROR_MESSAGE = "This is most likely a Val version mismatch or Val bug.";
2792
+ function getRoutesWithModulePaths(schemas, sources) {
2793
+ var routeMap = new Map();
2794
+ for (var moduleFilePathS in schemas) {
2795
+ var moduleFilePath = moduleFilePathS;
2796
+ var schema = schemas[moduleFilePath];
2797
+ var source = sources[moduleFilePath];
2798
+ if (schema && schema.type === "record" && schema.router && source && _typeof(source) === "object" && !Array.isArray(source)) {
2799
+ for (var key in source) {
2800
+ if (!routeMap.has(key)) {
2801
+ routeMap.set(key, moduleFilePath);
2802
+ }
2803
+ }
2804
+ }
2805
+ }
2806
+ var routes = Array.from(routeMap.entries()).map(function (_ref) {
2807
+ var _ref2 = _slicedToArray(_ref, 2),
2808
+ route = _ref2[0],
2809
+ moduleFilePath = _ref2[1];
2810
+ return {
2811
+ route: route,
2812
+ moduleFilePath: moduleFilePath
2813
+ };
2814
+ });
2815
+ return routes.sort(function (a, b) {
2816
+ return a.route.localeCompare(b.route);
2817
+ });
2818
+ }
2819
+ function getRoutesOf(schemas, sources) {
2820
+ return getRoutesWithModulePaths(schemas, sources).map(function (r) {
2821
+ return r.route;
2822
+ });
2823
+ }
2824
+
2825
+ // GPT generated levenshtein distance algorithm
2826
+ var levenshtein = function levenshtein(a, b) {
2827
+ var _ref3 = [a.length, b.length],
2828
+ m = _ref3[0],
2829
+ n = _ref3[1];
2830
+ if (!m || !n) return Math.max(m, n);
2831
+ var dp = Array.from({
2832
+ length: m + 1
2833
+ }, function (_, i) {
2834
+ return i;
2835
+ });
2836
+ for (var j = 1; j <= n; j++) {
2837
+ var prev = dp[0];
2838
+ dp[0] = j;
2839
+ for (var i = 1; i <= m; i++) {
2840
+ var temp = dp[i];
2841
+ dp[i] = a[i - 1] === b[j - 1] ? prev : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
2842
+ prev = temp;
2843
+ }
2844
+ }
2845
+ return dp[m];
2846
+ };
2847
+ function findSimilar(key, targets) {
2848
+ return targets.map(function (target) {
2849
+ return {
2850
+ target: target,
2851
+ distance: levenshtein(key, target)
2852
+ };
2853
+ }).sort(function (a, b) {
2854
+ return a.distance - b.distance;
2855
+ });
2856
+ }
2857
+ function getKeyOfRecordAt(sourcePath, snapshot) {
2858
+ var _Internal$splitModule = Internal.splitModuleFilePathAndModulePath(sourcePath),
2859
+ _Internal$splitModule2 = _slicedToArray(_Internal$splitModule, 2),
2860
+ moduleFilePath = _Internal$splitModule2[0],
2861
+ modulePath = _Internal$splitModule2[1];
2862
+ var moduleSource = snapshot.sources[moduleFilePath];
2863
+ var moduleSchema = snapshot.schemas[moduleFilePath];
2864
+ if (!moduleSchema || moduleSource === undefined) {
2865
+ return {
2866
+ source: undefined,
2867
+ schema: undefined
2868
+ };
2869
+ }
2870
+ if (!modulePath) {
2871
+ return {
2872
+ source: moduleSource,
2873
+ schema: moduleSchema
2874
+ };
2875
+ }
2876
+ // Walk both schema and source. This intentionally only follows the
2877
+ // patterns produced by keyOf().sourcePath — typically a top-level record or
2878
+ // an object property pointing at a record. The walk is best-effort and
2879
+ // returns undefined source on any mismatch.
2880
+ var source = moduleSource;
2881
+ var schema = moduleSchema;
2882
+ var _iterator = _createForOfIteratorHelper(Internal.splitModulePath(modulePath)),
2883
+ _step;
2884
+ try {
2885
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
2886
+ var part = _step.value;
2887
+ if (source && _typeof(source) === "object" && !Array.isArray(source) && part in source) {
2888
+ source = source[part];
2889
+ } else {
2890
+ source = undefined;
2891
+ }
2892
+ if (schema && schema.type === "object" && schema.items[part]) {
2893
+ schema = schema.items[part];
2894
+ } else if (schema && schema.type === "record") {
2895
+ schema = schema.item;
2896
+ } else {
2897
+ schema = undefined;
2898
+ }
2899
+ }
2900
+ } catch (err) {
2901
+ _iterator.e(err);
2902
+ } finally {
2903
+ _iterator.f();
2904
+ }
2905
+ return {
2906
+ source: source,
2907
+ schema: schema
2908
+ };
2909
+ }
2910
+ function checkKeyIsValid(key, sourcePath, snapshot) {
2911
+ var _getKeyOfRecordAt = getKeyOfRecordAt(sourcePath, snapshot),
2912
+ keyOfModuleSource = _getKeyOfRecordAt.source,
2913
+ keyOfModuleSchema = _getKeyOfRecordAt.schema;
2914
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
2915
+ return {
2916
+ error: true,
2917
+ message: "Expected key at ".concat(sourcePath, " to be of type 'record'")
2918
+ };
2919
+ }
2920
+ if (keyOfModuleSource && _typeof(keyOfModuleSource) === "object" && !Array.isArray(keyOfModuleSource) && key in keyOfModuleSource) {
2921
+ return {
2922
+ error: false
2923
+ };
2924
+ }
2925
+ if (!keyOfModuleSource || _typeof(keyOfModuleSource) !== "object" || Array.isArray(keyOfModuleSource)) {
2926
+ return {
2927
+ error: true,
2928
+ message: "Expected ".concat(sourcePath, " to be a truthy object")
2929
+ };
2930
+ }
2931
+ var alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
2932
+ if (alternatives.length === 0) {
2933
+ return {
2934
+ error: true,
2935
+ message: "Key '".concat(key, "' does not exist in ").concat(sourcePath, ".")
2936
+ };
2937
+ }
2938
+ return {
2939
+ error: true,
2940
+ message: "Key '".concat(key, "' does not exist in ").concat(sourcePath, ". Closest match: '").concat(alternatives[0].target, "'. Other similar: ").concat(alternatives.slice(1, 4).map(function (a) {
2941
+ return "'".concat(a.target, "'");
2942
+ }).join(", ")).concat(alternatives.length > 4 ? ", ..." : "")
2943
+ };
2944
+ }
2945
+ function checkRouteIsValid(route, includePattern, excludePattern, snapshot) {
2946
+ var routerModules = {};
2947
+ for (var moduleFilePathS in snapshot.schemas) {
2948
+ var moduleFilePath = moduleFilePathS;
2949
+ var schema = snapshot.schemas[moduleFilePath];
2950
+ if ((schema === null || schema === void 0 ? void 0 : schema.type) === "record" && schema.router) {
2951
+ var source = snapshot.sources[moduleFilePath];
2952
+ if (source && _typeof(source) === "object" && !Array.isArray(source)) {
2953
+ routerModules[moduleFilePath] = Object.keys(source);
2954
+ }
2955
+ }
2956
+ }
2957
+ var moduleEntries = Object.entries(routerModules);
2958
+ var foundInModule = null;
2959
+ for (var _i = 0, _moduleEntries = moduleEntries; _i < _moduleEntries.length; _i++) {
2960
+ var _moduleEntries$_i = _slicedToArray(_moduleEntries[_i], 2),
2961
+ _moduleFilePath = _moduleEntries$_i[0],
2962
+ routes = _moduleEntries$_i[1];
2963
+ if (routes.includes(route)) {
2964
+ foundInModule = _moduleFilePath;
2965
+ break;
2966
+ }
2967
+ }
2968
+ if (!foundInModule) {
2969
+ var allRoutes = moduleEntries.flatMap(function (_ref4) {
2970
+ var _ref5 = _slicedToArray(_ref4, 2),
2971
+ routes = _ref5[1];
2972
+ return routes;
2973
+ });
2974
+ if (allRoutes.length === 0) {
2975
+ return {
2976
+ error: true,
2977
+ message: "Route '".concat(route, "' could not be validated: No router modules found in the project. Use s.record(...).router(...) to define router modules.")
2978
+ };
2979
+ }
2980
+ allRoutes = filterRoutesByPatterns(allRoutes, includePattern, excludePattern);
2981
+ var alternatives = findSimilar(route, allRoutes);
2982
+ return {
2983
+ error: true,
2984
+ message: "Route '".concat(route, "' does not exist in any router module. ").concat(alternatives.length > 0 ? "Closest match: '".concat(alternatives[0].target, "'. Other similar: ").concat(alternatives.slice(1, 4).map(function (a) {
2985
+ return "'".concat(a.target, "'");
2986
+ }).join(", ")).concat(alternatives.length > 4 ? ", ..." : "") : "No similar routes found.")
2987
+ };
2988
+ }
2989
+ var patternValidation = validateRoutePatterns(route, includePattern, excludePattern);
2990
+ if (!patternValidation.valid) {
2991
+ return {
2992
+ error: true,
2993
+ message: patternValidation.message
2994
+ };
2995
+ }
2996
+ return {
2997
+ error: false
2998
+ };
2999
+ }
3000
+ /**
3001
+ * Resolves a single `keyof:check-keys` or `router:check-route` error against
3002
+ * the given schema/source snapshot. Returns:
3003
+ * - null if the error is not one of these fixes (caller should pass through)
3004
+ * - { status: "resolved" } if the referenced key/route is valid (drop error)
3005
+ * - { status: "remaining"; error } if invalid (rewritten error to surface)
3006
+ */
3007
+ function resolveSchemaSourceFixForError(error, snapshot) {
3008
+ var _error$fixes;
3009
+ var fixes = (_error$fixes = error.fixes) !== null && _error$fixes !== void 0 ? _error$fixes : [];
3010
+ if (fixes.includes("keyof:check-keys")) {
3011
+ if (!error.value) {
3012
+ return {
3013
+ status: "remaining",
3014
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3015
+ message: "Could not find a value for keyOf. ".concat(TYPE_ERROR_MESSAGE),
3016
+ typeError: true,
3017
+ fixes: undefined
3018
+ })
3019
+ };
3020
+ }
3021
+ if (_typeof(error.value) !== "object") {
3022
+ return {
3023
+ status: "remaining",
3024
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3025
+ message: "Expected keyOf validation error to have a 'value' property of type 'object'. Found: ".concat(_typeof(error.value), ". ").concat(TYPE_ERROR_MESSAGE),
3026
+ typeError: true,
3027
+ fixes: undefined
3028
+ })
3029
+ };
3030
+ }
3031
+ var valueObj = error.value;
3032
+ var key = valueObj.key;
3033
+ var valueSourcePath = valueObj.sourcePath;
3034
+ if (typeof key !== "string") {
3035
+ return {
3036
+ status: "remaining",
3037
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3038
+ message: "Expected keyOf validation error 'value' to have property 'key' of type 'string'. Found: ".concat(_typeof(key), ". ").concat(TYPE_ERROR_MESSAGE),
3039
+ typeError: true,
3040
+ fixes: undefined
3041
+ })
3042
+ };
3043
+ }
3044
+ if (typeof valueSourcePath !== "string") {
3045
+ return {
3046
+ status: "remaining",
3047
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3048
+ message: "Expected keyOf validation error 'value' to have property 'sourcePath' of type 'string'. Found: ".concat(_typeof(valueSourcePath), ". ").concat(TYPE_ERROR_MESSAGE),
3049
+ typeError: true,
3050
+ fixes: undefined
3051
+ })
3052
+ };
3053
+ }
3054
+ var res = checkKeyIsValid(key, valueSourcePath, snapshot);
3055
+ if (res.error) {
3056
+ return {
3057
+ status: "remaining",
3058
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3059
+ message: res.message,
3060
+ fixes: undefined
3061
+ })
3062
+ };
3063
+ }
3064
+ return {
3065
+ status: "resolved"
3066
+ };
3067
+ }
3068
+ if (fixes.includes("router:check-route")) {
3069
+ if (!error.value) {
3070
+ return {
3071
+ status: "remaining",
3072
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3073
+ message: "Could not find a value for route. ".concat(TYPE_ERROR_MESSAGE),
3074
+ typeError: true,
3075
+ fixes: undefined
3076
+ })
3077
+ };
3078
+ }
3079
+ if (_typeof(error.value) !== "object") {
3080
+ return {
3081
+ status: "remaining",
3082
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3083
+ message: "Expected route validation error to have a 'value' property of type 'object'. Found: ".concat(_typeof(error.value), ". ").concat(TYPE_ERROR_MESSAGE),
3084
+ typeError: true,
3085
+ fixes: undefined
3086
+ })
3087
+ };
3088
+ }
3089
+ var _valueObj = error.value;
3090
+ var route = _valueObj.route;
3091
+ if (typeof route !== "string") {
3092
+ return {
3093
+ status: "remaining",
3094
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3095
+ message: "Expected route validation error 'value' to have property 'route' of type 'string'. Found: ".concat(_typeof(route), ". ").concat(TYPE_ERROR_MESSAGE),
3096
+ typeError: true,
3097
+ fixes: undefined
3098
+ })
3099
+ };
3100
+ }
3101
+ var include = asRegExpPattern(_valueObj.include);
3102
+ var exclude = asRegExpPattern(_valueObj.exclude);
3103
+ var _res = checkRouteIsValid(route, include, exclude, snapshot);
3104
+ if (_res.error) {
3105
+ return {
3106
+ status: "remaining",
3107
+ error: _objectSpread2(_objectSpread2({}, error), {}, {
3108
+ message: _res.message,
3109
+ fixes: undefined
3110
+ })
3111
+ };
3112
+ }
3113
+ return {
3114
+ status: "resolved"
3115
+ };
3116
+ }
3117
+ return null;
3118
+ }
3119
+ function asRegExpPattern(value) {
3120
+ if (value && _typeof(value) === "object" && "source" in value && "flags" in value && typeof value.source === "string" && typeof value.flags === "string") {
3121
+ return value;
3122
+ }
3123
+ return undefined;
3124
+ }
3125
+
3126
+ /**
3127
+ * Apply schema/source fix resolution across a map of validation errors.
3128
+ *
3129
+ * Errors with `keyof:check-keys` or `router:check-route` are resolved against
3130
+ * the in-memory schema/source snapshot — valid references drop the error,
3131
+ * invalid ones are rewritten with a "did you mean…" message and have their
3132
+ * `fixes` cleared (so downstream code reports them as plain validation errors).
3133
+ * All other errors pass through untouched.
3134
+ *
3135
+ * Source paths with no remaining errors are removed from the result.
3136
+ */
3137
+ function resolveSchemaSourceFixes(validationErrors, snapshot) {
3138
+ var result = {};
3139
+ for (var sourcePathS in validationErrors) {
3140
+ var sourcePath = sourcePathS;
3141
+ var remaining = [];
3142
+ var _iterator2 = _createForOfIteratorHelper(validationErrors[sourcePath]),
3143
+ _step2;
3144
+ try {
3145
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
3146
+ var error = _step2.value;
3147
+ var resolved = resolveSchemaSourceFixForError(error, snapshot);
3148
+ if (resolved === null) {
3149
+ remaining.push(error);
3150
+ } else if (resolved.status === "remaining") {
3151
+ remaining.push(resolved.error);
3152
+ }
3153
+ }
3154
+ } catch (err) {
3155
+ _iterator2.e(err);
3156
+ } finally {
3157
+ _iterator2.f();
3158
+ }
3159
+ if (remaining.length > 0) {
3160
+ result[sourcePath] = remaining;
3161
+ }
3162
+ }
3163
+ return result;
3164
+ }
3165
+
3166
+ export { Api, DEFAULT_ERROR_MESSAGE, DateOptions, FileOptions, ImageOptions, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RichTextOptions, SerializedArraySchema, SerializedBooleanSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedStringSchema, SerializedUnionSchema, SharedValConfig, VAL_CONFIG_SESSION_STORAGE_KEY, VAL_ENABLE_COOKIE_NAME, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_THEME_SESSION_STORAGE_KEY, ValCommit, ValDeployment, createRegExpFromPattern, createValClient, filterRoutesByPatterns, findSimilar, getErrorMessageFromUnknownJson, getNextAppRouterSitemapTree, getNextAppRouterSourceFolder, getPatternFromModuleFilePath, getRoutesOf, getRoutesWithModulePaths, levenshtein, parseRoutePattern, remirrorToRichTextSource, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, richTextToRemirror, urlOf, validateRoutePatterns };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/shared",
3
- "version": "0.97.0",
3
+ "version": "0.97.4",
4
4
  "private": false,
5
5
  "description": "Val shared types and utilities",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "zod": "^4.3.5",
33
33
  "zod-validation-error": "^5.0.0",
34
- "@valbuild/core": "0.97.0"
34
+ "@valbuild/core": "0.97.4"
35
35
  },
36
36
  "files": [
37
37
  "dist",