typed-bridge 2.1.1 → 2.1.2

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.
@@ -166,6 +166,63 @@ declare const _default: {
166
166
  updatedAt: import("zod").ZodDate;
167
167
  }, import("zod/v4/core").$strip>>>;
168
168
  'order.list': () => Promise<order.Order[]>;
169
+ 'order.resolve': (args: import("zod").infer<import("zod").ZodObject<{
170
+ id: import("zod").ZodNumber;
171
+ }, import("zod/v4/core").$strip>>, context: {
172
+ requestedAt: number;
173
+ userId: number;
174
+ }) => Promise<import("zod").infer<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
175
+ status: import("zod").ZodLiteral<"found">;
176
+ order: import("zod").ZodObject<{
177
+ id: import("zod").ZodNumber;
178
+ customerName: import("zod").ZodString;
179
+ orderStatus: import("zod").ZodEnum<{
180
+ pending: "pending";
181
+ confirmed: "confirmed";
182
+ shipped: "shipped";
183
+ delivered: "delivered";
184
+ cancelled: "cancelled";
185
+ }>;
186
+ total: import("zod").ZodNumber;
187
+ }, import("zod/v4/core").$strip>;
188
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
189
+ status: import("zod").ZodLiteral<"not_found">;
190
+ }, import("zod/v4/core").$strip>], "status">>>;
191
+ 'order.statusFilter': (args: import("zod").infer<import("zod").ZodObject<{
192
+ status: import("zod").ZodEnum<{
193
+ pending: "pending";
194
+ confirmed: "confirmed";
195
+ shipped: "shipped";
196
+ delivered: "delivered";
197
+ cancelled: "cancelled";
198
+ }>;
199
+ }, import("zod/v4/core").$strip>>, context: {
200
+ requestedAt: number;
201
+ userId: number;
202
+ }) => Promise<import("zod").infer<import("zod").ZodObject<{
203
+ orders: import("zod").ZodArray<import("zod").ZodObject<{
204
+ id: import("zod").ZodNumber;
205
+ status: import("zod").ZodEnum<{
206
+ pending: "pending";
207
+ confirmed: "confirmed";
208
+ shipped: "shipped";
209
+ delivered: "delivered";
210
+ cancelled: "cancelled";
211
+ }>;
212
+ total: import("zod").ZodNumber;
213
+ }, import("zod/v4/core").$strip>>;
214
+ }, import("zod/v4/core").$strip>>>;
215
+ 'order.tag': (args: import("zod").infer<import("zod").ZodObject<{
216
+ orderId: import("zod").ZodNumber;
217
+ tag: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber]>;
218
+ }, import("zod/v4/core").$strip>>, context: {
219
+ requestedAt: number;
220
+ userId: number;
221
+ }) => Promise<import("zod").infer<import("zod").ZodObject<{
222
+ orderId: import("zod").ZodNumber;
223
+ tag: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber]>;
224
+ appliedAt: import("zod").ZodDate;
225
+ }, import("zod/v4/core").$strip>>>;
169
226
  'order.primitives': (args: import("zod").infer<import("zod").ZodObject<{
170
227
  key: import("zod").ZodString;
171
228
  }, import("zod/v4/core").$strip>>) => Promise<import("zod").infer<import("zod").ZodObject<{
@@ -49,5 +49,8 @@ exports.default = {
49
49
  'order.fetch': order.fetch,
50
50
  'order.update': order.update,
51
51
  'order.list': order.list,
52
+ 'order.resolve': order.resolve,
53
+ 'order.statusFilter': order.statusFilter,
54
+ 'order.tag': order.tag,
52
55
  'order.primitives': order.primitives
53
56
  };
@@ -35,5 +35,8 @@ export declare const create: (args: $z.infer<typeof types.create.args>, context:
35
35
  export declare const fetch: (args: $z.infer<typeof types.fetch.args>, context: Context) => Promise<$z.infer<typeof types.fetch.res>>;
36
36
  export declare const update: (args: $z.infer<typeof types.update.args>, context: Context) => Promise<$z.infer<typeof types.update.res>>;
37
37
  export declare const list: () => Promise<Order[]>;
38
+ export declare const resolve: (args: $z.infer<typeof types.resolve.args>, context: Context) => Promise<$z.infer<typeof types.resolve.res>>;
39
+ export declare const statusFilter: (args: $z.infer<typeof types.statusFilter.args>, context: Context) => Promise<$z.infer<typeof types.statusFilter.res>>;
40
+ export declare const tag: (args: $z.infer<typeof types.tag.args>, context: Context) => Promise<$z.infer<typeof types.tag.res>>;
38
41
  export declare const primitives: (args: $z.infer<typeof types.primitives.args>) => Promise<$z.infer<typeof types.primitives.res>>;
39
42
  export {};
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.primitives = exports.list = exports.update = exports.fetch = exports.create = void 0;
36
+ exports.primitives = exports.tag = exports.statusFilter = exports.resolve = exports.list = exports.update = exports.fetch = exports.create = void 0;
37
37
  const types = __importStar(require("./types"));
38
38
  let nextId = 1;
39
39
  const orders = [];
@@ -94,6 +94,43 @@ const list = async () => {
94
94
  return orders;
95
95
  };
96
96
  exports.list = list;
97
+ const resolve = async (args, context) => {
98
+ args = types.resolve.args.parse(args);
99
+ const order = orders.find(o => o.id === args.id);
100
+ if (!order)
101
+ return { status: 'not_found' };
102
+ return {
103
+ status: 'found',
104
+ order: {
105
+ id: order.id,
106
+ customerName: `Customer #${order.customerId}`,
107
+ orderStatus: order.status,
108
+ total: order.total
109
+ }
110
+ };
111
+ };
112
+ exports.resolve = resolve;
113
+ const statusFilter = async (args, context) => {
114
+ args = types.statusFilter.args.parse(args);
115
+ return {
116
+ orders: orders
117
+ .filter(o => o.status === args.status)
118
+ .map(o => ({ id: o.id, status: o.status, total: o.total }))
119
+ };
120
+ };
121
+ exports.statusFilter = statusFilter;
122
+ const orderTags = new Map();
123
+ const tag = async (args, context) => {
124
+ args = types.tag.args.parse(args);
125
+ const order = orders.find(o => o.id === args.orderId);
126
+ if (!order)
127
+ throw new Error(`Order with ID ${args.orderId} not found`);
128
+ const tags = orderTags.get(args.orderId) || [];
129
+ tags.push(args.tag);
130
+ orderTags.set(args.orderId, tags);
131
+ return { orderId: args.orderId, tag: args.tag, appliedAt: new Date() };
132
+ };
133
+ exports.tag = tag;
97
134
  const primitives = async (args) => {
98
135
  args = types.primitives.args.parse(args);
99
136
  return {
@@ -97,6 +97,63 @@ export declare const update: {
97
97
  updatedAt: $z.ZodDate;
98
98
  }, $z.core.$strip>;
99
99
  };
100
+ export declare const resolve: {
101
+ args: $z.ZodObject<{
102
+ id: $z.ZodNumber;
103
+ }, $z.core.$strip>;
104
+ res: $z.ZodDiscriminatedUnion<[$z.ZodObject<{
105
+ status: $z.ZodLiteral<"found">;
106
+ order: $z.ZodObject<{
107
+ id: $z.ZodNumber;
108
+ customerName: $z.ZodString;
109
+ orderStatus: $z.ZodEnum<{
110
+ pending: "pending";
111
+ confirmed: "confirmed";
112
+ shipped: "shipped";
113
+ delivered: "delivered";
114
+ cancelled: "cancelled";
115
+ }>;
116
+ total: $z.ZodNumber;
117
+ }, $z.core.$strip>;
118
+ }, $z.core.$strip>, $z.ZodObject<{
119
+ status: $z.ZodLiteral<"not_found">;
120
+ }, $z.core.$strip>], "status">;
121
+ };
122
+ export declare const statusFilter: {
123
+ args: $z.ZodObject<{
124
+ status: $z.ZodEnum<{
125
+ pending: "pending";
126
+ confirmed: "confirmed";
127
+ shipped: "shipped";
128
+ delivered: "delivered";
129
+ cancelled: "cancelled";
130
+ }>;
131
+ }, $z.core.$strip>;
132
+ res: $z.ZodObject<{
133
+ orders: $z.ZodArray<$z.ZodObject<{
134
+ id: $z.ZodNumber;
135
+ status: $z.ZodEnum<{
136
+ pending: "pending";
137
+ confirmed: "confirmed";
138
+ shipped: "shipped";
139
+ delivered: "delivered";
140
+ cancelled: "cancelled";
141
+ }>;
142
+ total: $z.ZodNumber;
143
+ }, $z.core.$strip>>;
144
+ }, $z.core.$strip>;
145
+ };
146
+ export declare const tag: {
147
+ args: $z.ZodObject<{
148
+ orderId: $z.ZodNumber;
149
+ tag: $z.ZodUnion<readonly [$z.ZodString, $z.ZodNumber]>;
150
+ }, $z.core.$strip>;
151
+ res: $z.ZodObject<{
152
+ orderId: $z.ZodNumber;
153
+ tag: $z.ZodUnion<readonly [$z.ZodString, $z.ZodNumber]>;
154
+ appliedAt: $z.ZodDate;
155
+ }, $z.core.$strip>;
156
+ };
100
157
  export declare const primitives: {
101
158
  args: $z.ZodObject<{
102
159
  key: $z.ZodString;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.primitives = exports.update = exports.fetch = exports.create = void 0;
3
+ exports.primitives = exports.tag = exports.statusFilter = exports.resolve = exports.update = exports.fetch = exports.create = void 0;
4
4
  const __1 = require("../../..");
5
5
  // --- Reusable schemas ---
6
6
  const addressSchema = __1.$z.object({
@@ -70,6 +70,52 @@ exports.update = {
70
70
  updatedAt: __1.$z.date()
71
71
  })
72
72
  };
73
+ // --- resolve: exercises ZodDiscriminatedUnion + ZodLiteral + ZodEnum ---
74
+ const orderStatusEnum = __1.$z.enum(['pending', 'confirmed', 'shipped', 'delivered', 'cancelled']);
75
+ exports.resolve = {
76
+ args: __1.$z.object({
77
+ id: __1.$z.number().min(1)
78
+ }),
79
+ res: __1.$z.discriminatedUnion('status', [
80
+ __1.$z.object({
81
+ status: __1.$z.literal('found'),
82
+ order: __1.$z.object({
83
+ id: __1.$z.number(),
84
+ customerName: __1.$z.string(),
85
+ orderStatus: orderStatusEnum,
86
+ total: __1.$z.number()
87
+ })
88
+ }),
89
+ __1.$z.object({
90
+ status: __1.$z.literal('not_found')
91
+ })
92
+ ])
93
+ };
94
+ // --- statusFilter: exercises ZodEnum in args and response ---
95
+ exports.statusFilter = {
96
+ args: __1.$z.object({
97
+ status: orderStatusEnum
98
+ }),
99
+ res: __1.$z.object({
100
+ orders: __1.$z.array(__1.$z.object({
101
+ id: __1.$z.number(),
102
+ status: orderStatusEnum,
103
+ total: __1.$z.number()
104
+ }))
105
+ })
106
+ };
107
+ // --- tag: exercises ZodUnion ---
108
+ exports.tag = {
109
+ args: __1.$z.object({
110
+ orderId: __1.$z.number().min(1),
111
+ tag: __1.$z.union([__1.$z.string(), __1.$z.number()])
112
+ }),
113
+ res: __1.$z.object({
114
+ orderId: __1.$z.number(),
115
+ tag: __1.$z.union([__1.$z.string(), __1.$z.number()]),
116
+ appliedAt: __1.$z.date()
117
+ })
118
+ };
73
119
  // --- primitives: exercises all remaining keyword types ---
74
120
  exports.primitives = {
75
121
  args: __1.$z.object({
@@ -59,9 +59,7 @@ export default typedBridge
59
59
  `;
60
60
  /**
61
61
  * Transformer #1:
62
- * Resolve zod types to plain TypeScript types, and remove zod imports.
63
- * Handles both Zod 3 (zod.TypeOf<ZodObject<S,UK,CA,Output,Input>>) and
64
- * Zod 4 (zod.infer<ZodObject<Shape, UK>>) patterns.
62
+ * Resolve Zod 4 types to plain TypeScript types, and remove zod imports.
65
63
  */
66
64
  const resolveZodTypesTransformer = context => {
67
65
  return sourceFile => {
@@ -74,23 +72,32 @@ const resolveZodTypesTransformer = context => {
74
72
  ZodVoid: typescript_1.default.SyntaxKind.VoidKeyword,
75
73
  ZodAny: typescript_1.default.SyntaxKind.AnyKeyword,
76
74
  ZodUnknown: typescript_1.default.SyntaxKind.UnknownKeyword,
77
- ZodNever: typescript_1.default.SyntaxKind.NeverKeyword,
75
+ ZodNever: typescript_1.default.SyntaxKind.NeverKeyword
78
76
  };
79
77
  function getZodRef(node) {
80
78
  if (typescript_1.default.isTypeReferenceNode(node) &&
81
79
  typescript_1.default.isQualifiedName(node.typeName) &&
82
80
  typescript_1.default.isIdentifier(node.typeName.left) &&
83
- (node.typeName.left.text === 'zod' || node.typeName.left.text.startsWith('zod_'))) {
81
+ (node.typeName.left.text === 'z' ||
82
+ node.typeName.left.text === 'zod' ||
83
+ node.typeName.left.text.startsWith('zod_'))) {
84
84
  return { name: node.typeName.right.text, typeArgs: node.typeArguments };
85
85
  }
86
86
  return null;
87
87
  }
88
+ function unwrapReadonlyTuple(node) {
89
+ if (typescript_1.default.isTupleTypeNode(node))
90
+ return node;
91
+ if (typescript_1.default.isTypeOperatorNode(node) && node.operator === typescript_1.default.SyntaxKind.ReadonlyKeyword && typescript_1.default.isTupleTypeNode(node.type))
92
+ return node.type;
93
+ return null;
94
+ }
88
95
  function resolveZodType(node) {
89
96
  const ref = getZodRef(node);
90
97
  if (!ref)
91
98
  return node;
92
99
  const { name, typeArgs } = ref;
93
- if ((name === 'infer' || name === 'TypeOf') && typeArgs?.length === 1)
100
+ if (name === 'infer' && typeArgs?.length === 1)
94
101
  return resolveZodType(typeArgs[0]);
95
102
  const keyword = zodKeywordMap[name];
96
103
  if (keyword !== undefined)
@@ -99,12 +106,8 @@ const resolveZodTypesTransformer = context => {
99
106
  return typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createNull());
100
107
  if (name === 'ZodDate')
101
108
  return typescript_1.default.factory.createTypeReferenceNode('Date');
102
- if (name === 'ZodObject' && typeArgs) {
103
- if (typeArgs.length >= 4)
104
- return resolveZodType(typeArgs[3]);
105
- if (typeArgs.length >= 1 && typescript_1.default.isTypeLiteralNode(typeArgs[0]))
106
- return resolveShape(typeArgs[0]);
107
- }
109
+ if (name === 'ZodObject' && typeArgs && typeArgs.length >= 1 && typescript_1.default.isTypeLiteralNode(typeArgs[0]))
110
+ return resolveShape(typeArgs[0]);
108
111
  if (name === 'ZodArray' && typeArgs && typeArgs.length >= 1)
109
112
  return typescript_1.default.factory.createArrayTypeNode(resolveZodType(typeArgs[0]));
110
113
  if (name === 'ZodOptional' && typeArgs && typeArgs.length >= 1)
@@ -119,6 +122,30 @@ const resolveZodTypesTransformer = context => {
119
122
  ]);
120
123
  if (name === 'ZodDefault' && typeArgs && typeArgs.length >= 1)
121
124
  return resolveZodType(typeArgs[0]);
125
+ if (name === 'ZodLiteral' && typeArgs && typeArgs.length >= 1)
126
+ return typeArgs[0];
127
+ // v4: ZodEnum<{pending: "pending", confirmed: "confirmed", ...}>
128
+ if (name === 'ZodEnum' && typeArgs && typeArgs.length >= 1 && typescript_1.default.isTypeLiteralNode(typeArgs[0])) {
129
+ const types = [];
130
+ for (const member of typeArgs[0].members) {
131
+ if (typescript_1.default.isPropertySignature(member) && member.type)
132
+ types.push(member.type);
133
+ }
134
+ if (types.length > 0)
135
+ return typescript_1.default.factory.createUnionTypeNode(types);
136
+ }
137
+ // v4: ZodDiscriminatedUnion<[ZodObject<...>, ...], "disc">
138
+ if (name === 'ZodDiscriminatedUnion' && typeArgs && typeArgs.length >= 1) {
139
+ const tuple = unwrapReadonlyTuple(typeArgs[0]);
140
+ if (tuple)
141
+ return typescript_1.default.factory.createUnionTypeNode(tuple.elements.map(e => resolveZodType(e)));
142
+ }
143
+ // v4: ZodUnion<readonly [ZodString, ZodNumber]>
144
+ if (name === 'ZodUnion' && typeArgs && typeArgs.length >= 1) {
145
+ const tuple = unwrapReadonlyTuple(typeArgs[0]);
146
+ if (tuple)
147
+ return typescript_1.default.factory.createUnionTypeNode(tuple.elements.map(e => resolveZodType(e)));
148
+ }
122
149
  return node;
123
150
  }
124
151
  function resolveShape(shape) {
@@ -137,7 +164,7 @@ const resolveZodTypesTransformer = context => {
137
164
  function typeVisitor(node) {
138
165
  if (typescript_1.default.isTypeNode(node)) {
139
166
  const ref = getZodRef(node);
140
- if (ref && (ref.name === 'infer' || ref.name === 'TypeOf'))
167
+ if (ref)
141
168
  return resolveZodType(node);
142
169
  }
143
170
  return typescript_1.default.visitEachChild(node, typeVisitor, context);
@@ -205,11 +232,15 @@ const removeDefaultExportTransformer = context => {
205
232
  * 3. Writes the final file output.
206
233
  */
207
234
  function cleanTsFile(src) {
208
- let sourceCode = fs_1.default.readFileSync(src, 'utf-8');
235
+ const sourceCode = fs_1.default.readFileSync(src, 'utf-8');
209
236
  // Parse the source
210
237
  const sourceFile = typescript_1.default.createSourceFile(path_1.default.basename(src), sourceCode, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TS);
211
238
  // Run the transformers
212
- const result = typescript_1.default.transform(sourceFile, [resolveZodTypesTransformer, removeSecondParamTransformer, removeDefaultExportTransformer]);
239
+ const result = typescript_1.default.transform(sourceFile, [
240
+ resolveZodTypesTransformer,
241
+ removeSecondParamTransformer,
242
+ removeDefaultExportTransformer
243
+ ]);
213
244
  // Print final code
214
245
  const eslintDisable = `/* eslint-disable */`;
215
246
  const printer = typescript_1.default.createPrinter();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typed-bridge",
3
3
  "description": "Strictly typed server functions for typescript apps",
4
- "version": "2.1.1",
4
+ "version": "2.1.2",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "author": "neilveil",
package/test/bridge.ts CHANGED
@@ -174,6 +174,36 @@ declare const _default: {
174
174
  updatedAt: Date;
175
175
  }>;
176
176
  'order.list': () => Promise<Order[]>;
177
+ 'order.resolve': (args: {
178
+ id: number;
179
+ }) => Promise<{
180
+ status: "found";
181
+ order: {
182
+ id: number;
183
+ customerName: string;
184
+ orderStatus: "pending" | "confirmed" | "shipped" | "delivered" | "cancelled";
185
+ total: number;
186
+ };
187
+ } | {
188
+ status: "not_found";
189
+ }>;
190
+ 'order.statusFilter': (args: {
191
+ status: "pending" | "confirmed" | "shipped" | "delivered" | "cancelled";
192
+ }) => Promise<{
193
+ orders: {
194
+ id: number;
195
+ status: "pending" | "confirmed" | "shipped" | "delivered" | "cancelled";
196
+ total: number;
197
+ }[];
198
+ }>;
199
+ 'order.tag': (args: {
200
+ orderId: number;
201
+ tag: string | number;
202
+ }) => Promise<{
203
+ orderId: number;
204
+ tag: string | number;
205
+ appliedAt: Date;
206
+ }>;
177
207
  'order.primitives': (args: {
178
208
  key: string;
179
209
  }) => Promise<{