webspresso 0.0.112 → 0.0.114

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 (42) hide show
  1. package/README.md +26 -0
  2. package/bin/commands/admin-password.js +1 -7
  3. package/bin/commands/api.js +1 -7
  4. package/bin/commands/new.js +1 -7
  5. package/bin/commands/page.js +1 -7
  6. package/bin/commands/seed.js +1 -7
  7. package/bin/commands/service.js +1 -7
  8. package/bin/utils/prompt.js +17 -0
  9. package/core/cache/tagged-lru.js +9 -3
  10. package/core/client/adapter/datastar.js +602 -26
  11. package/core/client/api.js +151 -7
  12. package/core/client/controller.js +172 -11
  13. package/core/client/devtool.js +59 -33
  14. package/core/client/forms.js +479 -29
  15. package/core/client/fragments.js +456 -27
  16. package/core/client/index.js +18 -1
  17. package/core/client/server-fragments.js +125 -40
  18. package/core/client/utils.js +72 -17
  19. package/core/console/commands.js +26 -5
  20. package/core/console/repl.js +7 -1
  21. package/core/http/pipeline.js +82 -1
  22. package/core/openapi/build-from-api-routes.js +5 -5
  23. package/core/orm/json-fields.js +7 -6
  24. package/core/orm/schema-helpers.js +18 -15
  25. package/core/orm/utils/nanoid.js +7 -8
  26. package/core/plugins/plugin-manager.js +155 -1
  27. package/core/services/validator.js +12 -1
  28. package/core/validation/apply.js +3 -0
  29. package/core/validation/index.js +25 -0
  30. package/core/validation/zod-introspect.js +187 -0
  31. package/index.d.ts +113 -1
  32. package/package.json +12 -11
  33. package/plugins/mcp/providers/services.js +2 -2
  34. package/src/api/define-api.js +2 -0
  35. package/src/api/validation-i18n.js +6 -2
  36. package/src/bundle/index.js +140 -6
  37. package/src/dev/api-typegen.js +79 -22
  38. package/src/dev/typegen.js +61 -35
  39. package/src/dev-reload/index.js +44 -2
  40. package/src/file-router.js +24 -6
  41. package/src/routing/mount-discovered-routes.js +24 -6
  42. package/src/server.js +59 -3
@@ -3,6 +3,8 @@
3
3
  * @module core/orm/json-fields
4
4
  */
5
5
 
6
+ const { getZodDef, getZodInner, getZodTypeName } = require('../validation/zod-introspect');
7
+
6
8
  /**
7
9
  * Get JSON column names from model
8
10
  * @param {import('./types').ModelDefinition} model - Model definition
@@ -31,16 +33,15 @@ function getJsonColumns(model) {
31
33
  if (model && model.schema && model.schema.shape) {
32
34
  for (const [name, fieldSchema] of Object.entries(model.schema.shape)) {
33
35
  let current = fieldSchema;
34
- while (current && current._def) {
35
- if (current._def.innerType) {
36
- current = current._def.innerType;
37
- } else if (current._def.schema) {
38
- current = current._def.schema;
36
+ while (current && getZodDef(current)) {
37
+ const inner = getZodInner(current);
38
+ if (inner) {
39
+ current = inner;
39
40
  } else {
40
41
  break;
41
42
  }
42
43
  }
43
- const typeName = current?._def?.typeName;
44
+ const typeName = getZodTypeName(current);
44
45
  if (typeName === 'ZodRecord' || typeName === 'ZodObject' || typeName === 'ZodArray') {
45
46
  jsonCols.add(name);
46
47
  }
@@ -5,6 +5,13 @@
5
5
  */
6
6
 
7
7
  const { safeJsonParse } = require('../utils/json');
8
+ const {
9
+ getZodDef,
10
+ getZodTypeName,
11
+ getZodInner,
12
+ getZodEnumValues,
13
+ isZodInt,
14
+ } = require('../validation/zod-introspect');
8
15
 
9
16
  const METADATA_MARKER = '__wdb__';
10
17
  const metaWeakMap = new WeakMap();
@@ -665,10 +672,7 @@ function createSchemaHelpers(z) {
665
672
  */
666
673
  json(options = {}) {
667
674
  const { nullable = false, ...rest } = options;
668
- let schema = z.unknown();
669
- if (nullable) {
670
- schema = schema.nullable().optional();
671
- }
675
+ let schema = nullable ? z.unknown().nullable().optional() : z.unknown().optional();
672
676
  return createSchemaBuilder(schema, {
673
677
  type: 'json',
674
678
  nullable,
@@ -888,14 +892,14 @@ function extractColumnsFromSchema(schema) {
888
892
  // Unwrap optional/nullable wrappers to get to the base schema
889
893
  let current = schemaToCheck;
890
894
  let isNullable = false;
891
- while (current && current._def) {
892
- if (current._def.typeName === 'ZodNullable' || current._def.typeName === 'ZodOptional') {
895
+ while (current && getZodDef(current)) {
896
+ const currentType = getZodTypeName(current);
897
+ if (currentType === 'ZodNullable' || currentType === 'ZodOptional') {
893
898
  isNullable = true;
894
899
  }
895
- if (current._def.innerType) {
896
- current = current._def.innerType;
897
- } else if (current._def.schema) {
898
- current = current._def.schema;
900
+ const inner = getZodInner(current);
901
+ if (inner) {
902
+ current = inner;
899
903
  } else {
900
904
  break;
901
905
  }
@@ -905,16 +909,15 @@ function extractColumnsFromSchema(schema) {
905
909
  const meta = getColumnMeta(schemaToCheck) || (current ? getColumnMeta(current) : null);
906
910
  if (meta) {
907
911
  columns.set(key, meta);
908
- } else if (current && current._def && current._def.typeName) {
909
- const typeName = current._def.typeName;
912
+ } else if (current && getZodTypeName(current)) {
913
+ const typeName = getZodTypeName(current);
910
914
  let inferred = null;
911
915
  switch (typeName) {
912
916
  case 'ZodString':
913
917
  inferred = { type: 'string', maxLength: 255, nullable: isNullable };
914
918
  break;
915
919
  case 'ZodNumber': {
916
- const isInt = current._def.checks?.some((c) => c.kind === 'int');
917
- inferred = { type: isInt ? 'integer' : 'float', nullable: isNullable };
920
+ inferred = { type: isZodInt(current) ? 'integer' : 'float', nullable: isNullable };
918
921
  break;
919
922
  }
920
923
  case 'ZodBoolean':
@@ -924,7 +927,7 @@ function extractColumnsFromSchema(schema) {
924
927
  inferred = { type: 'timestamp', nullable: isNullable };
925
928
  break;
926
929
  case 'ZodEnum':
927
- inferred = { type: 'enum', enumValues: current._def.values || [], nullable: isNullable };
930
+ inferred = { type: 'enum', enumValues: getZodEnumValues(current), nullable: isNullable };
928
931
  break;
929
932
  case 'ZodArray':
930
933
  inferred = { type: 'files', nullable: isNullable };
@@ -63,14 +63,13 @@ function resolveNanoidSize(arg) {
63
63
  * @param {typeof import('zod').z} zod
64
64
  */
65
65
  function extendZ(zod) {
66
- return new Proxy(zod, {
67
- get(target, prop, receiver) {
68
- if (prop === 'nanoid') {
69
- return function nanoid(arg) {
70
- return zodNanoid(zod, resolveNanoidSize(arg));
71
- };
72
- }
73
- return Reflect.get(target, prop, receiver);
66
+ return Object.create(zod, {
67
+ nanoid: {
68
+ value: function nanoid(arg) {
69
+ return zodNanoid(zod, resolveNanoidSize(arg));
70
+ },
71
+ enumerable: true,
72
+ configurable: true,
74
73
  },
75
74
  });
76
75
  }
@@ -147,6 +147,9 @@ class PluginManager {
147
147
  this.routes = []; // Collected route metadata
148
148
  this.customRoutes = []; // Routes added by plugins
149
149
  this.cspDirectives = new Map(); // directive -> Set of sources (from plugins)
150
+ this.clientControllers = new Map(); // name -> { name, filePath, pluginName }
151
+ this.clientServices = new Map(); // name -> { name, filePath, pluginName }
152
+ this.registeredFragments = new Map(); // name -> { name, def, pluginName }
150
153
  this.disposers = []; // Array<{ name: string, fn: Function }>
151
154
  this._cachedHelpers = null; // Cached helpers object
152
155
  this.pendingAsyncOperations = []; // Track background promises
@@ -271,7 +274,7 @@ class PluginManager {
271
274
 
272
275
  // Build graph
273
276
  for (const plugin of plugins) {
274
- if (!plugin.name) {
277
+ if (!plugin || !plugin.name) {
275
278
  console.warn('[plugin-manager] Skipping plugin without name:', plugin);
276
279
  continue;
277
280
  }
@@ -730,6 +733,33 @@ class PluginManager {
730
733
  */
731
734
  getScriptInjector() {
732
735
  return getCachedScriptInjector();
736
+ },
737
+
738
+ /**
739
+ * Register a client controller entry file (`.client.js` / `.client.ts`) for bundler discovery
740
+ * @param {string} name - Controller name used in `data-w-controller="<name>"`
741
+ * @param {string} filePath - Absolute or project-relative path to the client controller module
742
+ */
743
+ registerClientController(name, filePath) {
744
+ self.registerClientController(name, filePath, pluginName);
745
+ },
746
+
747
+ /**
748
+ * Register a client service module (`defineClientService(...)`) for bundler discovery
749
+ * @param {string} name - Service name used in `ctx.services.get('<name>')`
750
+ * @param {string} filePath - Absolute or project-relative path to the client service module
751
+ */
752
+ registerClientService(name, filePath) {
753
+ self.registerClientService(name, filePath, pluginName);
754
+ },
755
+
756
+ /**
757
+ * Register a reusable SSR fragment (`defineFragment(...)`) usable across pages
758
+ * @param {string} name - Fragment name used in `fsy.fragment('<name>', ...)`
759
+ * @param {Object} fragmentDef - Fragment definition created via `defineFragment(...)`
760
+ */
761
+ registerFragment(name, fragmentDef) {
762
+ self.registerFragment(name, fragmentDef, pluginName);
733
763
  }
734
764
  };
735
765
  }
@@ -808,6 +838,130 @@ class PluginManager {
808
838
  }
809
839
  }
810
840
 
841
+ /**
842
+ * Register a client controller module from a plugin.
843
+ * @param {string} name
844
+ * @param {string} filePath
845
+ * @param {string} [pluginName='unknown']
846
+ */
847
+ registerClientController(name, filePath, pluginName = 'unknown') {
848
+ const cleanName = typeof name === 'string' ? name.trim() : '';
849
+ const cleanPath = typeof filePath === 'string' ? filePath.trim() : '';
850
+ if (!cleanName || !cleanPath) {
851
+ throw new TypeError(`[plugin-manager] registerClientController(name, filePath) requires non-empty strings (plugin "${pluginName}").`);
852
+ }
853
+ const existing = this.clientControllers.get(cleanName);
854
+ if (existing && existing.filePath !== cleanPath) {
855
+ const err = new Error(
856
+ `Client controller name collision: "${cleanName}" is registered by both plugin "${existing.pluginName}" (${existing.filePath}) and "${pluginName}" (${cleanPath}).`
857
+ );
858
+ err.code = 'PLUGIN_CLIENT_CONTROLLER_COLLISION';
859
+ throw err;
860
+ }
861
+ this.clientControllers.set(cleanName, {
862
+ name: cleanName,
863
+ filePath: cleanPath,
864
+ pluginName,
865
+ });
866
+ }
867
+
868
+ /**
869
+ * Register a client service module from a plugin.
870
+ * @param {string} name
871
+ * @param {string} filePath
872
+ * @param {string} [pluginName='unknown']
873
+ */
874
+ registerClientService(name, filePath, pluginName = 'unknown') {
875
+ const cleanName = typeof name === 'string' ? name.trim() : '';
876
+ const cleanPath = typeof filePath === 'string' ? filePath.trim() : '';
877
+ if (!cleanName || !cleanPath) {
878
+ throw new TypeError(`[plugin-manager] registerClientService(name, filePath) requires non-empty strings (plugin "${pluginName}").`);
879
+ }
880
+ const existing = this.clientServices.get(cleanName);
881
+ if (existing && existing.filePath !== cleanPath) {
882
+ const err = new Error(
883
+ `Client service name collision: "${cleanName}" is registered by both plugin "${existing.pluginName}" (${existing.filePath}) and "${pluginName}" (${cleanPath}).`
884
+ );
885
+ err.code = 'PLUGIN_CLIENT_SERVICE_COLLISION';
886
+ throw err;
887
+ }
888
+ this.clientServices.set(cleanName, {
889
+ name: cleanName,
890
+ filePath: cleanPath,
891
+ pluginName,
892
+ });
893
+ }
894
+
895
+ /**
896
+ * Register a reusable SSR fragment definition from a plugin.
897
+ * @param {string} name
898
+ * @param {Object} fragmentDef
899
+ * @param {string} [pluginName='unknown']
900
+ */
901
+ registerFragment(name, fragmentDef, pluginName = 'unknown') {
902
+ const cleanName = typeof name === 'string' ? name.trim() : '';
903
+ if (!cleanName || !fragmentDef || typeof fragmentDef !== 'object') {
904
+ throw new TypeError(`[plugin-manager] registerFragment(name, fragmentDef) requires a valid fragment name and definition (plugin "${pluginName}").`);
905
+ }
906
+ if (this.registeredFragments.has(cleanName)) {
907
+ console.warn(`[plugin-manager] Fragment "${cleanName}" is already registered (registered by "${pluginName}" overwrites existing fragment).`);
908
+ }
909
+ this.registeredFragments.set(cleanName, {
910
+ name: cleanName,
911
+ def: fragmentDef,
912
+ pluginName,
913
+ });
914
+ }
915
+
916
+ /**
917
+ * Get all client controllers registered by plugins.
918
+ * @returns {Array<{ name: string, filePath: string, pluginName: string }>}
919
+ */
920
+ getClientControllers() {
921
+ return Array.from(this.clientControllers.values());
922
+ }
923
+
924
+ /**
925
+ * Get all client services registered by plugins.
926
+ * @returns {Array<{ name: string, filePath: string, pluginName: string }>}
927
+ */
928
+ getClientServices() {
929
+ return Array.from(this.clientServices.values());
930
+ }
931
+
932
+ /**
933
+ * Look up a plugin-registered fragment definition by name.
934
+ * @param {string} name
935
+ * @returns {Object|null}
936
+ */
937
+ getFragment(name) {
938
+ const entry = this.registeredFragments.get(name);
939
+ return entry ? entry.def : null;
940
+ }
941
+
942
+ /**
943
+ * Get all plugin-registered fragments as a plain map `{ [name]: fragmentDef }`.
944
+ * @returns {Record<string, Object>}
945
+ */
946
+ getFragments() {
947
+ const out = {};
948
+ for (const [name, entry] of this.registeredFragments) {
949
+ out[name] = entry.def;
950
+ }
951
+ return out;
952
+ }
953
+
954
+ /**
955
+ * Get combined client manifest of controllers, services, and fragment names registered by plugins.
956
+ */
957
+ getClientManifest() {
958
+ return {
959
+ controllers: this.getClientControllers(),
960
+ services: this.getClientServices(),
961
+ fragments: Array.from(this.registeredFragments.keys()),
962
+ };
963
+ }
964
+
811
965
  /**
812
966
  * Register a request-scoped helper provider (called on each SSR request)
813
967
  * @param {Function} fn - (req) => Record<string, any>
@@ -293,7 +293,18 @@ function validateServiceInput(schema, input, serviceName, options = {}) {
293
293
  // 1. Zod schema validation
294
294
  if (compiled instanceof z.ZodType || typeof compiled.safeParse === 'function') {
295
295
  try {
296
- const result = compiled.safeParse(sanitized);
296
+ let result;
297
+ if (compiled._zod && typeof compiled._zod.run === 'function') {
298
+ const rawRun = compiled._zod.run({ value: sanitized, issues: [] }, { async: true });
299
+ if (rawRun instanceof Promise) {
300
+ // Attach no-op catch so async refinements rejected during sync preflight don't emit UnhandledRejection
301
+ rawRun.catch(() => {});
302
+ throw new Error('Encountered Promise during synchronous parse');
303
+ }
304
+ result = rawRun.issues.length ? compiled.safeParse(sanitized) : { success: true, data: rawRun.value };
305
+ } else {
306
+ result = compiled.safeParse(sanitized);
307
+ }
297
308
  if (!result.success) {
298
309
  const { message, fields, fieldErrors } = formatZodErrors(result.error, serviceName);
299
310
  throw createServiceValidationError(message, {
@@ -6,6 +6,9 @@
6
6
  * @module core/validation/apply
7
7
  */
8
8
 
9
+ const { ensureZodCompat } = require('./zod-introspect');
10
+ ensureZodCompat();
11
+
9
12
  const EMPTY_INPUT = Object.freeze({
10
13
  body: undefined,
11
14
  params: undefined,
@@ -28,6 +28,31 @@ if (z.ZodType && z.ZodType.prototype && typeof z.ZodType.prototype._refinement =
28
28
  };
29
29
  wrappedRefinement.__webspresso_wrapped = true;
30
30
  z.ZodType.prototype._refinement = wrappedRefinement;
31
+ } else if (z.ZodType && z.ZodType.prototype && typeof z.ZodType.prototype.refine === 'function' && !z.ZodType.prototype.refine.__webspresso_wrapped) {
32
+ const origRefine = z.ZodType.prototype.refine;
33
+ const wrappedRefine = function (check, params) {
34
+ const wrappedCheck = typeof check === 'function'
35
+ ? (val) => {
36
+ const res = check(val);
37
+ if (res && typeof res.catch === 'function') {
38
+ res.catch(() => {});
39
+ }
40
+ return res;
41
+ }
42
+ : check;
43
+ return origRefine.call(this, wrappedCheck, params);
44
+ };
45
+ wrappedRefine.__webspresso_wrapped = true;
46
+ z.ZodType.prototype.refine = wrappedRefine;
47
+ }
48
+
49
+ if (z.ZodError && z.ZodError.prototype && !Object.getOwnPropertyDescriptor(z.ZodError.prototype, 'errors')) {
50
+ Object.defineProperty(z.ZodError.prototype, 'errors', {
51
+ get() {
52
+ return this.issues;
53
+ },
54
+ configurable: true,
55
+ });
31
56
  }
32
57
 
33
58
  /**
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Zod v3 & v4 Introspection Helpers
3
+ * Provides a unified abstraction over Zod v3 (`_def.typeName`) and Zod v4 (`_zod.def.type`)
4
+ * for ORM column inference, TypeGen, API TypeGen, and OpenAPI/MCP JSON Schema generation.
5
+ * @module core/validation/zod-introspect
6
+ */
7
+
8
+ const z = require('zod');
9
+
10
+ const V4_TYPE_MAP = Object.freeze({
11
+ string: 'ZodString',
12
+ number: 'ZodNumber',
13
+ boolean: 'ZodBoolean',
14
+ date: 'ZodDate',
15
+ bigint: 'ZodBigInt',
16
+ any: 'ZodAny',
17
+ unknown: 'ZodUnknown',
18
+ never: 'ZodNever',
19
+ undefined: 'ZodUndefined',
20
+ void: 'ZodVoid',
21
+ null: 'ZodNull',
22
+ literal: 'ZodLiteral',
23
+ enum: 'ZodEnum',
24
+ array: 'ZodArray',
25
+ optional: 'ZodOptional',
26
+ nullable: 'ZodNullable',
27
+ default: 'ZodDefault',
28
+ prefault: 'ZodDefault',
29
+ transform: 'ZodEffects',
30
+ pipe: 'ZodPipeline',
31
+ union: 'ZodUnion',
32
+ object: 'ZodObject',
33
+ record: 'ZodRecord',
34
+ tuple: 'ZodTuple',
35
+ set: 'ZodSet',
36
+ map: 'ZodMap',
37
+ nonoptional: 'ZodNonOptional',
38
+ readonly: 'ZodReadonly',
39
+ catch: 'ZodCatch',
40
+ });
41
+
42
+ function getZodDef(schema) {
43
+ if (!schema || typeof schema !== 'object') return null;
44
+ return (schema._zod && schema._zod.def) || schema._def || null;
45
+ }
46
+
47
+ function getZodTypeName(schema) {
48
+ const def = getZodDef(schema);
49
+ if (!def) return null;
50
+ if (def.typeName) return def.typeName;
51
+ if (typeof def.type === 'string') {
52
+ return V4_TYPE_MAP[def.type] || null;
53
+ }
54
+ return null;
55
+ }
56
+
57
+ function isZodSchema(val) {
58
+ return Boolean(val && typeof val === 'object' && (val._zod || val._def) && typeof val.safeParse === 'function');
59
+ }
60
+
61
+ function getZodInner(schema) {
62
+ const def = getZodDef(schema);
63
+ if (!def) return null;
64
+ return def.innerType || def.schema || def.in || null;
65
+ }
66
+
67
+ function getZodPipeOut(schema) {
68
+ const def = getZodDef(schema);
69
+ if (!def) return null;
70
+ return def.out || null;
71
+ }
72
+
73
+ function getZodArrayElement(schema) {
74
+ const def = getZodDef(schema);
75
+ if (!def) return null;
76
+ if (def.element) return def.element;
77
+ if (def.type && typeof def.type === 'object') return def.type;
78
+ return null;
79
+ }
80
+
81
+ function getZodObjectShape(schema) {
82
+ if (!schema || typeof schema !== 'object') return {};
83
+ if (typeof schema.shape === 'object' && schema.shape !== null) return schema.shape;
84
+ const def = getZodDef(schema);
85
+ if (!def) return {};
86
+ if (typeof def.shape === 'function') return def.shape() || {};
87
+ if (typeof def.shape === 'object' && def.shape !== null) return def.shape;
88
+ return {};
89
+ }
90
+
91
+ function getZodEnumValues(schema) {
92
+ const def = getZodDef(schema);
93
+ if (!def) return [];
94
+ if (Array.isArray(def.values)) return def.values;
95
+ if (def.entries && typeof def.entries === 'object') return Object.values(def.entries);
96
+ if (def.values && typeof def.values === 'object') return Object.values(def.values);
97
+ return [];
98
+ }
99
+
100
+ function getZodLiteralValue(schema) {
101
+ const def = getZodDef(schema);
102
+ if (!def) return undefined;
103
+ if (def.value !== undefined) return def.value;
104
+ if (Array.isArray(def.values)) return def.values[0];
105
+ return undefined;
106
+ }
107
+
108
+ function isZodInt(schema) {
109
+ const def = getZodDef(schema);
110
+ if (!def) return false;
111
+ if (def.format === 'safeint' || def.format === 'int32' || def.format === 'uint32') return true;
112
+ if (!Array.isArray(def.checks)) return false;
113
+ return def.checks.some((c) => {
114
+ if (!c) return false;
115
+ if (c.kind === 'int') return true;
116
+ const cDef = c._zod && c._zod.def;
117
+ return Boolean(cDef && cDef.check === 'number_format' && (cDef.format === 'safeint' || cDef.format === 'int32'));
118
+ });
119
+ }
120
+
121
+ function isZodCoerced(schema) {
122
+ const def = getZodDef(schema);
123
+ return Boolean(def && def.coerce);
124
+ }
125
+
126
+ function zodToJsonSchemaCompat(schema, options = {}) {
127
+ if (typeof z.toJSONSchema === 'function') {
128
+ try {
129
+ const target = options.target === 'openApi3' ? 'openapi-3.0' : (options.target || 'draft-7');
130
+ const jsonSchema = z.toJSONSchema(schema, {
131
+ target,
132
+ unrepresentable: 'any',
133
+ });
134
+ if (jsonSchema && typeof jsonSchema === 'object') {
135
+ delete jsonSchema.$schema;
136
+ }
137
+ return jsonSchema;
138
+ } catch (_) {
139
+ // Fall through to legacy helper if needed
140
+ }
141
+ }
142
+ const { zodToJsonSchema } = require('zod-to-json-schema');
143
+ return zodToJsonSchema(schema, options);
144
+ }
145
+
146
+ /**
147
+ * Apply Zod v3 compatibility shims onto Zod v4 prototypes (idempotent).
148
+ * - Exposes `ZodError.prototype.errors` -> `this.issues`
149
+ */
150
+ function ensureZodCompat(zodModule = z) {
151
+ if (!zodModule) return;
152
+
153
+ const sampleError = typeof zodModule.string === 'function'
154
+ ? zodModule.string().safeParse(123)?.error
155
+ : null;
156
+ const errProtos = [
157
+ sampleError ? Object.getPrototypeOf(sampleError) : null,
158
+ zodModule.ZodError?.prototype,
159
+ ];
160
+ for (const errProto of errProtos) {
161
+ if (errProto && !Object.getOwnPropertyDescriptor(errProto, 'errors')) {
162
+ Object.defineProperty(errProto, 'errors', {
163
+ get() {
164
+ return this.issues;
165
+ },
166
+ configurable: true,
167
+ });
168
+ }
169
+ }
170
+ }
171
+
172
+ module.exports = {
173
+ getZodDef,
174
+ getZodTypeName,
175
+ isZodSchema,
176
+ getZodInner,
177
+ getZodPipeOut,
178
+ getZodArrayElement,
179
+ getZodObjectShape,
180
+ getZodEnumValues,
181
+ getZodLiteralValue,
182
+ isZodInt,
183
+ isZodCoerced,
184
+ zodToJsonSchemaCompat,
185
+ ensureZodCompat,
186
+ };
187
+