zodvex 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +75 -0
  2. package/dist/__type-tests__/infer-returns.d.ts +2 -0
  3. package/dist/__type-tests__/infer-returns.d.ts.map +1 -0
  4. package/dist/__type-tests__/zodTable-inference.d.ts +2 -0
  5. package/dist/__type-tests__/zodTable-inference.d.ts.map +1 -0
  6. package/dist/builders.d.ts +173 -0
  7. package/dist/builders.d.ts.map +1 -0
  8. package/dist/codec.d.ts +11 -0
  9. package/dist/codec.d.ts.map +1 -0
  10. package/dist/custom.d.ts +147 -0
  11. package/dist/custom.d.ts.map +1 -0
  12. package/dist/ids.d.ts +23 -0
  13. package/dist/ids.d.ts.map +1 -0
  14. package/dist/index.d.ts +11 -599
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +203 -58
  17. package/dist/index.js.map +1 -1
  18. package/dist/mapping/core.d.ts +5 -0
  19. package/dist/mapping/core.d.ts.map +1 -0
  20. package/dist/mapping/handlers/enum.d.ts +4 -0
  21. package/dist/mapping/handlers/enum.d.ts.map +1 -0
  22. package/dist/mapping/handlers/index.d.ts +5 -0
  23. package/dist/mapping/handlers/index.d.ts.map +1 -0
  24. package/dist/mapping/handlers/nullable.d.ts +7 -0
  25. package/dist/mapping/handlers/nullable.d.ts.map +1 -0
  26. package/dist/mapping/handlers/record.d.ts +4 -0
  27. package/dist/mapping/handlers/record.d.ts.map +1 -0
  28. package/dist/mapping/handlers/union.d.ts +5 -0
  29. package/dist/mapping/handlers/union.d.ts.map +1 -0
  30. package/dist/mapping/index.d.ts +4 -0
  31. package/dist/mapping/index.d.ts.map +1 -0
  32. package/dist/mapping/types.d.ts +43 -0
  33. package/dist/mapping/types.d.ts.map +1 -0
  34. package/dist/mapping/utils.d.ts +6 -0
  35. package/dist/mapping/utils.d.ts.map +1 -0
  36. package/dist/registry.d.ts +110 -0
  37. package/dist/registry.d.ts.map +1 -0
  38. package/dist/results.d.ts +126 -0
  39. package/dist/results.d.ts.map +1 -0
  40. package/dist/tables.d.ts +214 -0
  41. package/dist/tables.d.ts.map +1 -0
  42. package/dist/transform/index.d.ts +26 -0
  43. package/dist/transform/index.d.ts.map +1 -0
  44. package/dist/transform/index.js +442 -0
  45. package/dist/transform/index.js.map +1 -0
  46. package/dist/transform/transform.d.ts +47 -0
  47. package/dist/transform/transform.d.ts.map +1 -0
  48. package/dist/transform/traverse.d.ts +62 -0
  49. package/dist/transform/traverse.d.ts.map +1 -0
  50. package/dist/transform/types.d.ts +115 -0
  51. package/dist/transform/types.d.ts.map +1 -0
  52. package/dist/types.d.ts +29 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/utils.d.ts +55 -0
  55. package/dist/utils.d.ts.map +1 -0
  56. package/dist/wrappers.d.ts +22 -0
  57. package/dist/wrappers.d.ts.map +1 -0
  58. package/package.json +13 -6
  59. package/src/__type-tests__/infer-returns.ts +24 -0
  60. package/src/__type-tests__/zodTable-inference.ts +5 -5
  61. package/src/custom.ts +205 -28
  62. package/src/index.ts +1 -0
  63. package/src/mapping/core.ts +23 -11
  64. package/src/mapping/types.ts +6 -2
  65. package/src/results.ts +110 -0
  66. package/src/tables.ts +306 -28
  67. package/src/transform/index.ts +38 -0
  68. package/src/transform/transform.ts +409 -0
  69. package/src/transform/traverse.ts +320 -0
  70. package/src/transform/types.ts +128 -0
  71. package/src/types.ts +3 -2
  72. package/src/utils.ts +35 -0
  73. package/src/wrappers.ts +10 -19
package/dist/index.js CHANGED
@@ -388,16 +388,25 @@ function zodToConvexInternal(zodValidator, visited = /* @__PURE__ */ new Set())
388
388
  }
389
389
  case "transform":
390
390
  case "pipe": {
391
- const codec = findBaseCodec(actualValidator);
392
- if (codec) {
393
- convexValidator = codec.toValidator(actualValidator);
394
- } else {
395
- const metadata2 = registryHelpers.getMetadata(actualValidator);
396
- if (metadata2?.brand && metadata2?.originalSchema) {
397
- convexValidator = zodToConvexInternal(metadata2.originalSchema, visited);
391
+ if (actualValidator instanceof z.ZodCodec) {
392
+ const inputSchema = actualValidator.def?.in;
393
+ if (inputSchema && inputSchema instanceof z.ZodType) {
394
+ convexValidator = zodToConvexInternal(inputSchema, visited);
398
395
  } else {
399
396
  convexValidator = v.any();
400
397
  }
398
+ } else {
399
+ const codec = findBaseCodec(actualValidator);
400
+ if (codec) {
401
+ convexValidator = codec.toValidator(actualValidator);
402
+ } else {
403
+ const metadata2 = registryHelpers.getMetadata(actualValidator);
404
+ if (metadata2?.brand && metadata2?.originalSchema) {
405
+ convexValidator = zodToConvexInternal(metadata2.originalSchema, visited);
406
+ } else {
407
+ convexValidator = v.any();
408
+ }
409
+ }
401
410
  }
402
411
  break;
403
412
  }
@@ -675,6 +684,21 @@ function handleZodValidationError(e, context) {
675
684
  }
676
685
  throw e;
677
686
  }
687
+ function validateReturns(schema, value) {
688
+ try {
689
+ return z.encode(schema, value);
690
+ } catch (e) {
691
+ if (e?.message?.includes("unidirectional transform")) {
692
+ try {
693
+ return schema.parse(value);
694
+ } catch (parseError) {
695
+ handleZodValidationError(parseError, "returns");
696
+ }
697
+ }
698
+ handleZodValidationError(e, "returns");
699
+ }
700
+ throw new Error("Unreachable");
701
+ }
678
702
  function zPaginated(item) {
679
703
  return z.object({
680
704
  page: z.array(item),
@@ -725,6 +749,20 @@ function safeOmit(schema, mask) {
725
749
  }
726
750
 
727
751
  // src/custom.ts
752
+ function customCtxWithHooks(fn) {
753
+ return {
754
+ args: {},
755
+ input: async (ctx) => {
756
+ const result = await fn(ctx);
757
+ return {
758
+ ctx: result.ctx ?? {},
759
+ args: result.args ?? {},
760
+ hooks: result.hooks,
761
+ transforms: result.transforms
762
+ };
763
+ }
764
+ };
765
+ }
728
766
  function customFnBuilder(builder, customization) {
729
767
  const customInput = customization.input ?? NoOp.input;
730
768
  const inputArgs = customization.args ?? NoOp.args;
@@ -768,17 +806,16 @@ function customFnBuilder(builder, customization) {
768
806
  const finalCtx = { ...ctx, ...added?.ctx ?? {} };
769
807
  const baseArgs = parsed.data;
770
808
  const addedArgs = added?.args ?? {};
771
- const finalArgs = { ...baseArgs, ...addedArgs };
809
+ let finalArgs = { ...baseArgs, ...addedArgs };
810
+ if (added?.transforms?.input) {
811
+ finalArgs = await added.transforms.input(finalArgs, argsSchema);
812
+ }
772
813
  const ret = await handler(finalCtx, finalArgs);
773
814
  if (returns) {
774
- let validated;
775
- try {
776
- validated = returns.parse(ret);
777
- } catch (e) {
778
- handleZodValidationError(e, "returns");
779
- }
780
- if (added?.onSuccess) {
781
- await added.onSuccess({
815
+ const preTransformed = added?.transforms?.output ? await added.transforms.output(ret, returns) : ret;
816
+ const validated = validateReturns(returns, preTransformed);
817
+ if (added?.hooks?.onSuccess) {
818
+ await added.hooks.onSuccess({
782
819
  ctx,
783
820
  args: parsed.data,
784
821
  result: validated
@@ -786,8 +823,8 @@ function customFnBuilder(builder, customization) {
786
823
  }
787
824
  return toConvexJS(returns, validated);
788
825
  }
789
- if (added?.onSuccess) {
790
- await added.onSuccess({ ctx, args: parsed.data, result: ret });
826
+ if (added?.hooks?.onSuccess) {
827
+ await added.hooks.onSuccess({ ctx, args: parsed.data, result: ret });
791
828
  }
792
829
  return ret;
793
830
  }
@@ -805,22 +842,21 @@ function customFnBuilder(builder, customization) {
805
842
  const finalCtx = { ...ctx, ...added?.ctx ?? {} };
806
843
  const baseArgs = allArgs;
807
844
  const addedArgs = added?.args ?? {};
808
- const finalArgs = { ...baseArgs, ...addedArgs };
845
+ let finalArgs = { ...baseArgs, ...addedArgs };
846
+ if (added?.transforms?.input) {
847
+ finalArgs = await added.transforms.input(finalArgs, z.unknown());
848
+ }
809
849
  const ret = await handler(finalCtx, finalArgs);
810
850
  if (returns) {
811
- let validated;
812
- try {
813
- validated = returns.parse(ret);
814
- } catch (e) {
815
- handleZodValidationError(e, "returns");
816
- }
817
- if (added?.onSuccess) {
818
- await added.onSuccess({ ctx, args: allArgs, result: validated });
851
+ const preTransformed = added?.transforms?.output ? await added.transforms.output(ret, returns) : ret;
852
+ const validated = validateReturns(returns, preTransformed);
853
+ if (added?.hooks?.onSuccess) {
854
+ await added.hooks.onSuccess({ ctx, args: allArgs, result: validated });
819
855
  }
820
856
  return toConvexJS(returns, validated);
821
857
  }
822
- if (added?.onSuccess) {
823
- await added.onSuccess({ ctx, args: allArgs, result: ret });
858
+ if (added?.hooks?.onSuccess) {
859
+ await added.hooks.onSuccess({ ctx, args: allArgs, result: ret });
824
860
  }
825
861
  return ret;
826
862
  }
@@ -896,12 +932,8 @@ function zQuery(query, input, handler, options) {
896
932
  }
897
933
  const raw = await handler(ctx, parsed);
898
934
  if (options?.returns) {
899
- try {
900
- const validated = options.returns.parse(raw);
901
- return toConvexJS(options.returns, validated);
902
- } catch (e) {
903
- handleZodValidationError(e, "returns");
904
- }
935
+ const validated = validateReturns(options.returns, raw);
936
+ return toConvexJS(options.returns, validated);
905
937
  }
906
938
  return toConvexJS(raw);
907
939
  }
@@ -935,12 +967,8 @@ function zMutation(mutation, input, handler, options) {
935
967
  }
936
968
  const raw = await handler(ctx, parsed);
937
969
  if (options?.returns) {
938
- try {
939
- const validated = options.returns.parse(raw);
940
- return toConvexJS(options.returns, validated);
941
- } catch (e) {
942
- handleZodValidationError(e, "returns");
943
- }
970
+ const validated = validateReturns(options.returns, raw);
971
+ return toConvexJS(options.returns, validated);
944
972
  }
945
973
  return toConvexJS(raw);
946
974
  }
@@ -974,12 +1002,8 @@ function zAction(action, input, handler, options) {
974
1002
  }
975
1003
  const raw = await handler(ctx, parsed);
976
1004
  if (options?.returns) {
977
- try {
978
- const validated = options.returns.parse(raw);
979
- return toConvexJS(options.returns, validated);
980
- } catch (e) {
981
- handleZodValidationError(e, "returns");
982
- }
1005
+ const validated = validateReturns(options.returns, raw);
1006
+ return toConvexJS(options.returns, validated);
983
1007
  }
984
1008
  return toConvexJS(raw);
985
1009
  }
@@ -1026,9 +1050,48 @@ function zCustomActionBuilder(action, customization) {
1026
1050
  customization
1027
1051
  );
1028
1052
  }
1053
+ var success = (data) => ({ success: true, data });
1054
+ var failure = (error) => ({ success: false, error });
1055
+ var ok = () => ({ success: true });
1056
+ var formSuccess = (data) => ({ success: true, data });
1057
+ var formFailure = (data, error) => ({ success: false, data, error });
1058
+ var zMutationResult = (dataSchema) => z.discriminatedUnion("success", [
1059
+ z.object({ success: z.literal(true), data: dataSchema }),
1060
+ z.object({ success: z.literal(false), error: z.string() })
1061
+ ]);
1062
+ var zVoidMutationResult = z.discriminatedUnion("success", [
1063
+ z.object({ success: z.literal(true) }),
1064
+ z.object({ success: z.literal(false), error: z.string() })
1065
+ ]);
1066
+ var zFormError = z.object({
1067
+ formErrors: z.array(z.string()),
1068
+ fieldErrors: z.record(z.string(), z.array(z.string()))
1069
+ });
1070
+ var zFormResult = (dataSchema) => z.discriminatedUnion("success", [
1071
+ z.object({ success: z.literal(true), data: dataSchema }),
1072
+ z.object({ success: z.literal(false), data: dataSchema, error: zFormError })
1073
+ ]);
1074
+ function isZodUnion(schema) {
1075
+ return schema instanceof z.ZodUnion || schema instanceof z.ZodDiscriminatedUnion;
1076
+ }
1077
+ function getUnionOptions(schema) {
1078
+ return schema.options;
1079
+ }
1080
+ function assertUnionOptions(options) {
1081
+ if (options.length < 2) {
1082
+ throw new Error(
1083
+ `z.union() requires at least 2 options, but received ${options.length}. This indicates an invalid union schema was passed to zodTable().`
1084
+ );
1085
+ }
1086
+ }
1087
+ function createUnionFromOptions(options) {
1088
+ assertUnionOptions(options);
1089
+ return z.union(options);
1090
+ }
1029
1091
  function addSystemFields(tableName, schema) {
1030
- if (schema instanceof z.ZodUnion || schema instanceof z.ZodDiscriminatedUnion) {
1031
- const options = schema.options.map((variant) => {
1092
+ if (isZodUnion(schema)) {
1093
+ const originalOptions = getUnionOptions(schema);
1094
+ const extendedOptions = originalOptions.map((variant) => {
1032
1095
  if (variant instanceof z.ZodObject) {
1033
1096
  return variant.extend({
1034
1097
  _id: zid(tableName),
@@ -1037,7 +1100,7 @@ function addSystemFields(tableName, schema) {
1037
1100
  }
1038
1101
  return variant;
1039
1102
  });
1040
- return z.union(options);
1103
+ return createUnionFromOptions(extendedOptions);
1041
1104
  }
1042
1105
  if (schema instanceof z.ZodObject) {
1043
1106
  return schema.extend({
@@ -1047,6 +1110,9 @@ function addSystemFields(tableName, schema) {
1047
1110
  }
1048
1111
  return schema;
1049
1112
  }
1113
+ function asTableValidator(validator) {
1114
+ return validator;
1115
+ }
1050
1116
  function zodDoc(tableName, schema) {
1051
1117
  return schema.extend({
1052
1118
  _id: zid(tableName),
@@ -1076,28 +1142,107 @@ function zodTable(name, schemaOrShape) {
1076
1142
  );
1077
1143
  const zDoc = zodDoc(name, z.object(shape));
1078
1144
  const docArray = z.array(zDoc);
1079
- return Object.assign(table, {
1145
+ const baseSchema = z.object(shape);
1146
+ const partialShape = {};
1147
+ for (const [key, value] of Object.entries(shape)) {
1148
+ partialShape[key] = value.optional();
1149
+ }
1150
+ const updateSchema = z.object({
1151
+ _id: zid(name),
1152
+ _creationTime: z.number().optional(),
1153
+ ...partialShape
1154
+ });
1155
+ const schema = {
1156
+ doc: zDoc,
1157
+ docArray,
1158
+ base: baseSchema,
1159
+ insert: baseSchema,
1160
+ // alias for base
1161
+ update: updateSchema
1162
+ };
1163
+ const warned = { zDoc: false, docArray: false };
1164
+ const result = Object.assign(table, {
1080
1165
  shape,
1081
- zDoc,
1082
- docArray
1166
+ schema
1167
+ });
1168
+ Object.defineProperty(result, "zDoc", {
1169
+ get() {
1170
+ if (!warned.zDoc) {
1171
+ console.warn("zodvex: `zDoc` is deprecated, use `schema.doc` instead");
1172
+ warned.zDoc = true;
1173
+ }
1174
+ return schema.doc;
1175
+ },
1176
+ enumerable: true
1177
+ });
1178
+ Object.defineProperty(result, "docArray", {
1179
+ get() {
1180
+ if (!warned.docArray) {
1181
+ console.warn("zodvex: `docArray` is deprecated, use `schema.docArray` instead");
1182
+ warned.docArray = true;
1183
+ }
1184
+ return schema.docArray;
1185
+ },
1186
+ enumerable: true
1083
1187
  });
1188
+ return result;
1084
1189
  } else {
1085
1190
  const schema = schemaOrShape;
1086
1191
  const convexValidator = zodToConvex(schema);
1087
- const table = defineTable(convexValidator);
1088
- const withFields = addSystemFields(name, schema);
1089
- const docArray = z.array(withFields);
1192
+ const table = defineTable(asTableValidator(convexValidator));
1193
+ const docSchema = addSystemFields(name, schema);
1194
+ const docArray = z.array(docSchema);
1195
+ let updateSchema;
1196
+ if (isZodUnion(schema)) {
1197
+ const originalOptions = getUnionOptions(schema);
1198
+ const updateOptions = originalOptions.map((variant) => {
1199
+ if (variant instanceof z.ZodObject) {
1200
+ const partialShape = {};
1201
+ for (const [key, value] of Object.entries(variant.shape)) {
1202
+ partialShape[key] = value.optional();
1203
+ }
1204
+ return z.object({
1205
+ _id: zid(name),
1206
+ _creationTime: z.number().optional(),
1207
+ ...partialShape
1208
+ });
1209
+ }
1210
+ return variant;
1211
+ });
1212
+ updateSchema = createUnionFromOptions(updateOptions);
1213
+ } else if (schema instanceof z.ZodObject) {
1214
+ const partialShape = {};
1215
+ for (const [key, value] of Object.entries(schema.shape)) {
1216
+ partialShape[key] = value.optional();
1217
+ }
1218
+ updateSchema = z.object({
1219
+ _id: zid(name),
1220
+ _creationTime: z.number().optional(),
1221
+ ...partialShape
1222
+ });
1223
+ } else {
1224
+ updateSchema = schema;
1225
+ }
1226
+ const schemaNamespace = {
1227
+ doc: docSchema,
1228
+ docArray,
1229
+ base: schema,
1230
+ insert: schema,
1231
+ // alias for base
1232
+ update: updateSchema
1233
+ };
1090
1234
  return {
1091
1235
  table,
1092
1236
  tableName: name,
1093
1237
  validator: convexValidator,
1094
- schema,
1238
+ schema: schemaNamespace,
1095
1239
  docArray,
1240
+ // deprecated
1096
1241
  withSystemFields: () => addSystemFields(name, schema)
1097
1242
  };
1098
1243
  }
1099
1244
  }
1100
1245
 
1101
- export { addSystemFields, composeOverrides, convexCodec, customFnBuilder, findBaseCodec, formatZodIssues, fromConvexJS, getObjectShape, getZidTableName, handleZodValidationError, isDateSchema, isZidSchema, makeUnion, mapDateFieldToNumber, pick, pickShape, registerBaseCodec, registryHelpers, returnsAs, safeOmit, safePick, toConvexJS, toJSONSchema, zActionBuilder, zCustomAction, zCustomActionBuilder, zCustomMutation, zCustomMutationBuilder, zCustomQuery, zCustomQueryBuilder, zMutationBuilder, zPaginated, zQueryBuilder, zid, zodDoc, zodDocOrNull, zodTable, zodToConvex, zodToConvexFields, zodvexJSONSchemaOverride };
1246
+ export { addSystemFields, assertUnionOptions, composeOverrides, convexCodec, createUnionFromOptions, customCtxWithHooks, customFnBuilder, failure, findBaseCodec, formFailure, formSuccess, formatZodIssues, fromConvexJS, getObjectShape, getUnionOptions, getZidTableName, handleZodValidationError, isDateSchema, isZidSchema, isZodUnion, makeUnion, mapDateFieldToNumber, ok, pick, pickShape, registerBaseCodec, registryHelpers, returnsAs, safeOmit, safePick, success, toConvexJS, toJSONSchema, validateReturns, zActionBuilder, zCustomAction, zCustomActionBuilder, zCustomMutation, zCustomMutationBuilder, zCustomQuery, zCustomQueryBuilder, zFormError, zFormResult, zMutationBuilder, zMutationResult, zPaginated, zQueryBuilder, zVoidMutationResult, zid, zodDoc, zodDocOrNull, zodTable, zodToConvex, zodToConvexFields, zodvexJSONSchemaOverride };
1102
1247
  //# sourceMappingURL=index.js.map
1103
1248
  //# sourceMappingURL=index.js.map