@zenstackhq/server 3.1.0 → 3.2.0

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.
package/dist/api.cjs CHANGED
@@ -38,17 +38,156 @@ module.exports = __toCommonJS(api_exports);
38
38
 
39
39
  // src/api/rest/index.ts
40
40
  var import_common_helpers = require("@zenstackhq/common-helpers");
41
- var import_orm = require("@zenstackhq/orm");
41
+ var import_orm2 = require("@zenstackhq/orm");
42
42
  var import_decimal2 = require("decimal.js");
43
- var import_superjson2 = __toESM(require("superjson"), 1);
43
+ var import_superjson3 = __toESM(require("superjson"), 1);
44
44
  var import_ts_japi = __toESM(require("ts-japi"), 1);
45
45
  var import_ts_pattern2 = require("ts-pattern");
46
46
  var import_url_pattern = __toESM(require("url-pattern"), 1);
47
+ var import_zod2 = __toESM(require("zod"), 1);
48
+ var import_v42 = require("zod-validation-error/v4");
49
+
50
+ // src/api/common/procedures.ts
51
+ var import_orm = require("@zenstackhq/orm");
52
+ var PROCEDURE_ROUTE_PREFIXES = "$procs";
53
+ function getProcedureDef(schema, proc) {
54
+ const procs = schema.procedures ?? {};
55
+ if (!Object.prototype.hasOwnProperty.call(procs, proc)) {
56
+ return void 0;
57
+ }
58
+ return procs[proc];
59
+ }
60
+ __name(getProcedureDef, "getProcedureDef");
61
+ function mapProcedureArgs(procDef, payload) {
62
+ const params = Object.values(procDef.params ?? {});
63
+ if (params.length === 0) {
64
+ if (typeof payload === "undefined") {
65
+ return void 0;
66
+ }
67
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
68
+ const envelope2 = payload;
69
+ const argsPayload2 = Object.prototype.hasOwnProperty.call(envelope2, "args") ? envelope2.args : void 0;
70
+ if (typeof argsPayload2 === "undefined") {
71
+ return payload;
72
+ }
73
+ if (argsPayload2 && typeof argsPayload2 === "object" && !Array.isArray(argsPayload2)) {
74
+ if (Object.keys(argsPayload2).length === 0) {
75
+ return payload;
76
+ }
77
+ }
78
+ }
79
+ throw new Error("procedure does not accept arguments");
80
+ }
81
+ if (typeof payload === "undefined" && params.every((p) => p.optional)) {
82
+ return void 0;
83
+ }
84
+ if (typeof payload === "undefined") {
85
+ throw new Error("missing procedure arguments");
86
+ }
87
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
88
+ throw new Error("procedure payload must be an object");
89
+ }
90
+ const envelope = payload;
91
+ const argsPayload = Object.prototype.hasOwnProperty.call(envelope, "args") ? envelope.args : void 0;
92
+ if (typeof argsPayload === "undefined") {
93
+ if (params.every((p) => p.optional)) {
94
+ return payload;
95
+ }
96
+ throw new Error("missing procedure arguments");
97
+ }
98
+ if (!argsPayload || typeof argsPayload !== "object" || Array.isArray(argsPayload)) {
99
+ throw new Error("procedure `args` must be an object");
100
+ }
101
+ const obj = argsPayload;
102
+ for (const key of Object.keys(obj)) {
103
+ if (!params.some((p) => p.name === key)) {
104
+ throw new Error(`unknown procedure argument: ${key}`);
105
+ }
106
+ }
107
+ for (const p of params) {
108
+ if (!Object.prototype.hasOwnProperty.call(obj, p.name)) {
109
+ if (p.optional) {
110
+ continue;
111
+ }
112
+ throw new Error(`missing procedure argument: ${p.name}`);
113
+ }
114
+ }
115
+ return payload;
116
+ }
117
+ __name(mapProcedureArgs, "mapProcedureArgs");
118
+
119
+ // src/api/common/schemas.ts
47
120
  var import_zod = __toESM(require("zod"), 1);
121
+ var loggerSchema = import_zod.default.union([
122
+ import_zod.default.enum([
123
+ "debug",
124
+ "info",
125
+ "warn",
126
+ "error"
127
+ ]).array(),
128
+ import_zod.default.function()
129
+ ]);
130
+
131
+ // src/api/common/utils.ts
132
+ var import_superjson = __toESM(require("superjson"), 1);
133
+ async function processSuperJsonRequestPayload(payload) {
134
+ if (!payload || typeof payload !== "object" || Array.isArray(payload) || !("meta" in payload)) {
135
+ return {
136
+ result: payload,
137
+ error: void 0
138
+ };
139
+ }
140
+ const { meta, ...rest } = payload;
141
+ if (meta?.serialization) {
142
+ try {
143
+ return {
144
+ result: import_superjson.default.deserialize({
145
+ json: rest,
146
+ meta: meta.serialization
147
+ }),
148
+ error: void 0
149
+ };
150
+ } catch (err) {
151
+ return {
152
+ result: void 0,
153
+ error: `failed to deserialize request payload: ${err.message}`
154
+ };
155
+ }
156
+ }
157
+ return {
158
+ result: rest,
159
+ error: void 0
160
+ };
161
+ }
162
+ __name(processSuperJsonRequestPayload, "processSuperJsonRequestPayload");
163
+ function unmarshalQ(value, meta) {
164
+ let parsedValue;
165
+ try {
166
+ parsedValue = JSON.parse(value);
167
+ } catch {
168
+ throw new Error('invalid "q" query parameter');
169
+ }
170
+ if (meta) {
171
+ let parsedMeta;
172
+ try {
173
+ parsedMeta = JSON.parse(meta);
174
+ } catch {
175
+ throw new Error('invalid "meta" query parameter');
176
+ }
177
+ if (parsedMeta.serialization) {
178
+ return import_superjson.default.deserialize({
179
+ json: parsedValue,
180
+ meta: parsedMeta.serialization
181
+ });
182
+ }
183
+ }
184
+ return parsedValue;
185
+ }
186
+ __name(unmarshalQ, "unmarshalQ");
48
187
 
49
188
  // src/api/utils.ts
50
189
  var import_decimal = require("decimal.js");
51
- var import_superjson = __toESM(require("superjson"), 1);
190
+ var import_superjson2 = __toESM(require("superjson"), 1);
52
191
  var import_ts_pattern = require("ts-pattern");
53
192
  var import_v3 = require("zod-validation-error/v3");
54
193
  var import_v4 = require("zod-validation-error/v4");
@@ -67,13 +206,13 @@ ${error}` : ""}`);
67
206
  }
68
207
  __name(log, "log");
69
208
  function registerCustomSerializers() {
70
- import_superjson.default.registerCustom({
209
+ import_superjson2.default.registerCustom({
71
210
  isApplicable: /* @__PURE__ */ __name((v) => import_decimal.Decimal.isDecimal(v), "isApplicable"),
72
211
  serialize: /* @__PURE__ */ __name((v) => v.toJSON(), "serialize"),
73
212
  deserialize: /* @__PURE__ */ __name((v) => new import_decimal.Decimal(v), "deserialize")
74
213
  }, "Decimal");
75
214
  if (globalThis.Buffer) {
76
- import_superjson.default.registerCustom({
215
+ import_superjson2.default.registerCustom({
77
216
  isApplicable: /* @__PURE__ */ __name((v) => Buffer.isBuffer(v), "isApplicable"),
78
217
  serialize: /* @__PURE__ */ __name((v) => v.toString("base64"), "serialize"),
79
218
  deserialize: /* @__PURE__ */ __name((v) => Buffer.from(v, "base64"), "deserialize")
@@ -205,55 +344,55 @@ var RestApiHandler = class {
205
344
  };
206
345
  filterParamPattern = new RegExp(/^filter(?<match>(\[[^[\]]+\])+)$/);
207
346
  // zod schema for payload of creating and updating a resource
208
- createUpdatePayloadSchema = import_zod.default.object({
209
- data: import_zod.default.object({
210
- type: import_zod.default.string(),
211
- attributes: import_zod.default.object({}).passthrough().optional(),
212
- relationships: import_zod.default.record(import_zod.default.string(), import_zod.default.object({
213
- data: import_zod.default.union([
214
- import_zod.default.object({
215
- type: import_zod.default.string(),
216
- id: import_zod.default.union([
217
- import_zod.default.string(),
218
- import_zod.default.number()
347
+ createUpdatePayloadSchema = import_zod2.default.object({
348
+ data: import_zod2.default.object({
349
+ type: import_zod2.default.string(),
350
+ attributes: import_zod2.default.object({}).passthrough().optional(),
351
+ relationships: import_zod2.default.record(import_zod2.default.string(), import_zod2.default.object({
352
+ data: import_zod2.default.union([
353
+ import_zod2.default.object({
354
+ type: import_zod2.default.string(),
355
+ id: import_zod2.default.union([
356
+ import_zod2.default.string(),
357
+ import_zod2.default.number()
219
358
  ])
220
359
  }),
221
- import_zod.default.array(import_zod.default.object({
222
- type: import_zod.default.string(),
223
- id: import_zod.default.union([
224
- import_zod.default.string(),
225
- import_zod.default.number()
360
+ import_zod2.default.array(import_zod2.default.object({
361
+ type: import_zod2.default.string(),
362
+ id: import_zod2.default.union([
363
+ import_zod2.default.string(),
364
+ import_zod2.default.number()
226
365
  ])
227
366
  }))
228
367
  ])
229
368
  })).optional()
230
369
  }),
231
- meta: import_zod.default.object({}).passthrough().optional()
370
+ meta: import_zod2.default.object({}).passthrough().optional()
232
371
  }).strict();
233
372
  // zod schema for updating a single relationship
234
- updateSingleRelationSchema = import_zod.default.object({
235
- data: import_zod.default.object({
236
- type: import_zod.default.string(),
237
- id: import_zod.default.union([
238
- import_zod.default.string(),
239
- import_zod.default.number()
373
+ updateSingleRelationSchema = import_zod2.default.object({
374
+ data: import_zod2.default.object({
375
+ type: import_zod2.default.string(),
376
+ id: import_zod2.default.union([
377
+ import_zod2.default.string(),
378
+ import_zod2.default.number()
240
379
  ])
241
380
  }).nullable()
242
381
  });
243
382
  // zod schema for updating collection relationship
244
- updateCollectionRelationSchema = import_zod.default.object({
245
- data: import_zod.default.array(import_zod.default.object({
246
- type: import_zod.default.string(),
247
- id: import_zod.default.union([
248
- import_zod.default.string(),
249
- import_zod.default.number()
383
+ updateCollectionRelationSchema = import_zod2.default.object({
384
+ data: import_zod2.default.array(import_zod2.default.object({
385
+ type: import_zod2.default.string(),
386
+ id: import_zod2.default.union([
387
+ import_zod2.default.string(),
388
+ import_zod2.default.number()
250
389
  ])
251
390
  }))
252
391
  });
253
- upsertMetaSchema = import_zod.default.object({
254
- meta: import_zod.default.object({
255
- operation: import_zod.default.literal("upsert"),
256
- matchFields: import_zod.default.array(import_zod.default.string()).min(1)
392
+ upsertMetaSchema = import_zod2.default.object({
393
+ meta: import_zod2.default.object({
394
+ operation: import_zod2.default.literal("upsert"),
395
+ matchFields: import_zod2.default.array(import_zod2.default.string()).min(1)
257
396
  })
258
397
  });
259
398
  // all known types and their metadata
@@ -266,6 +405,7 @@ var RestApiHandler = class {
266
405
  externalIdMapping;
267
406
  constructor(options) {
268
407
  this.options = options;
408
+ this.validateOptions(options);
269
409
  this.idDivider = options.idDivider ?? DEFAULT_ID_DIVIDER;
270
410
  const segmentCharset = options.urlSegmentCharset ?? "a-zA-Z0-9-_~ %";
271
411
  this.modelNameMapping = options.modelNameMapping ?? {};
@@ -286,6 +426,25 @@ var RestApiHandler = class {
286
426
  this.buildTypeMap();
287
427
  this.buildSerializers();
288
428
  }
429
+ validateOptions(options) {
430
+ const schema = import_zod2.default.strictObject({
431
+ schema: import_zod2.default.object(),
432
+ log: loggerSchema.optional(),
433
+ endpoint: import_zod2.default.string().min(1),
434
+ pageSize: import_zod2.default.union([
435
+ import_zod2.default.number().int().positive(),
436
+ import_zod2.default.literal(Infinity)
437
+ ]).optional(),
438
+ idDivider: import_zod2.default.string().min(1).optional(),
439
+ urlSegmentCharset: import_zod2.default.string().min(1).optional(),
440
+ modelNameMapping: import_zod2.default.record(import_zod2.default.string(), import_zod2.default.string()).optional(),
441
+ externalIdMapping: import_zod2.default.record(import_zod2.default.string(), import_zod2.default.string()).optional()
442
+ });
443
+ const parseResult = schema.safeParse(options);
444
+ if (!parseResult.success) {
445
+ throw new Error(`Invalid options: ${(0, import_v42.fromError)(parseResult.error)}`);
446
+ }
447
+ }
289
448
  get schema() {
290
449
  return this.options.schema;
291
450
  }
@@ -346,6 +505,16 @@ var RestApiHandler = class {
346
505
  path = "/" + path;
347
506
  }
348
507
  try {
508
+ if (path.startsWith("/$procs/")) {
509
+ const proc = path.split("/")[2];
510
+ return await this.processProcedureRequest({
511
+ client,
512
+ method,
513
+ proc,
514
+ query,
515
+ requestBody
516
+ });
517
+ }
349
518
  switch (method) {
350
519
  case "GET": {
351
520
  let match4 = this.matchUrlPattern(path, "single");
@@ -419,7 +588,7 @@ var RestApiHandler = class {
419
588
  } catch (err) {
420
589
  if (err instanceof InvalidValueError) {
421
590
  return this.makeError("invalidValue", err.message);
422
- } else if (err instanceof import_orm.ORMError) {
591
+ } else if (err instanceof import_orm2.ORMError) {
423
592
  return this.handleORMError(err);
424
593
  } else {
425
594
  return this.handleGenericError(err);
@@ -430,6 +599,71 @@ var RestApiHandler = class {
430
599
  return this.makeError("unknownError", err instanceof Error ? `${err.message}
431
600
  ${err.stack}` : "Unknown error");
432
601
  }
602
+ async processProcedureRequest({ client, method, proc, query, requestBody }) {
603
+ if (!proc) {
604
+ return this.makeProcBadInputErrorResponse("missing procedure name");
605
+ }
606
+ const procDef = getProcedureDef(this.schema, proc);
607
+ if (!procDef) {
608
+ return this.makeProcBadInputErrorResponse(`unknown procedure: ${proc}`);
609
+ }
610
+ const isMutation = !!procDef.mutation;
611
+ if (isMutation) {
612
+ if (method !== "POST") {
613
+ return this.makeProcBadInputErrorResponse("invalid request method, only POST is supported");
614
+ }
615
+ } else {
616
+ if (method !== "GET") {
617
+ return this.makeProcBadInputErrorResponse("invalid request method, only GET is supported");
618
+ }
619
+ }
620
+ const argsPayload = method === "POST" ? requestBody : query;
621
+ const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload);
622
+ if (error) {
623
+ return this.makeProcBadInputErrorResponse(error);
624
+ }
625
+ let procInput;
626
+ try {
627
+ procInput = mapProcedureArgs(procDef, processedArgsPayload);
628
+ } catch (err) {
629
+ return this.makeProcBadInputErrorResponse(err instanceof Error ? err.message : "invalid procedure arguments");
630
+ }
631
+ try {
632
+ log(this.log, "debug", () => `handling "$procs.${proc}" request`);
633
+ const clientResult = await client.$procs?.[proc](procInput);
634
+ const toSerialize = this.toPlainObject(clientResult);
635
+ const { json, meta } = import_superjson3.default.serialize(toSerialize);
636
+ const responseBody = {
637
+ data: json
638
+ };
639
+ if (meta) {
640
+ responseBody.meta = {
641
+ serialization: meta
642
+ };
643
+ }
644
+ return {
645
+ status: 200,
646
+ body: responseBody
647
+ };
648
+ } catch (err) {
649
+ log(this.log, "error", `error occurred when handling "$procs.${proc}" request`, err);
650
+ if (err instanceof import_orm2.ORMError) {
651
+ throw err;
652
+ }
653
+ return this.makeProcGenericErrorResponse(err);
654
+ }
655
+ }
656
+ makeProcBadInputErrorResponse(message) {
657
+ const resp = this.makeError("invalidPayload", message, 400);
658
+ log(this.log, "debug", () => `sending error response: ${JSON.stringify(resp)}`);
659
+ return resp;
660
+ }
661
+ makeProcGenericErrorResponse(err) {
662
+ const message = err instanceof Error ? err.message : "unknown error";
663
+ const resp = this.makeError("unknownError", message, 500);
664
+ log(this.log, "debug", () => `sending error response: ${JSON.stringify(resp)}`);
665
+ return resp;
666
+ }
433
667
  async processSingleRead(client, type, resourceId, query) {
434
668
  const typeInfo = this.getModelInfo(type);
435
669
  if (!typeInfo) {
@@ -751,7 +985,7 @@ ${err.stack}` : "Unknown error");
751
985
  processRequestBody(requestBody) {
752
986
  let body = requestBody;
753
987
  if (body.meta?.serialization) {
754
- body = import_superjson2.default.deserialize({
988
+ body = import_superjson3.default.deserialize({
755
989
  json: body,
756
990
  meta: body.meta.serialization
757
991
  });
@@ -1195,7 +1429,7 @@ ${err.stack}` : "Unknown error");
1195
1429
  this.injectCompoundId(model, itemsWithId);
1196
1430
  const serialized = await serializer.serialize(itemsWithId, options);
1197
1431
  const plainResult = this.toPlainObject(serialized);
1198
- const { json, meta } = import_superjson2.default.serialize(plainResult);
1432
+ const { json, meta } = import_superjson3.default.serialize(plainResult);
1199
1433
  const result = json;
1200
1434
  if (meta) {
1201
1435
  result.meta = {
@@ -1774,15 +2008,15 @@ ${err.stack}` : "Unknown error");
1774
2008
  }
1775
2009
  }
1776
2010
  handleORMError(err) {
1777
- return (0, import_ts_pattern2.match)(err.reason).with(import_orm.ORMErrorReason.INVALID_INPUT, () => {
2011
+ return (0, import_ts_pattern2.match)(err.reason).with(import_orm2.ORMErrorReason.INVALID_INPUT, () => {
1778
2012
  return this.makeError("validationError", err.message, 422);
1779
- }).with(import_orm.ORMErrorReason.REJECTED_BY_POLICY, () => {
2013
+ }).with(import_orm2.ORMErrorReason.REJECTED_BY_POLICY, () => {
1780
2014
  return this.makeError("forbidden", err.message, 403, {
1781
2015
  reason: err.rejectedByPolicyReason
1782
2016
  });
1783
- }).with(import_orm.ORMErrorReason.NOT_FOUND, () => {
2017
+ }).with(import_orm2.ORMErrorReason.NOT_FOUND, () => {
1784
2018
  return this.makeError("notFound", err.message, 404);
1785
- }).with(import_orm.ORMErrorReason.DB_QUERY_ERROR, () => {
2019
+ }).with(import_orm2.ORMErrorReason.DB_QUERY_ERROR, () => {
1786
2020
  return this.makeError("queryError", err.message, 400, {
1787
2021
  dbErrorCode: err.dbErrorCode
1788
2022
  });
@@ -1820,9 +2054,11 @@ ${err.stack}` : "Unknown error");
1820
2054
 
1821
2055
  // src/api/rpc/index.ts
1822
2056
  var import_common_helpers2 = require("@zenstackhq/common-helpers");
1823
- var import_orm2 = require("@zenstackhq/orm");
1824
- var import_superjson3 = __toESM(require("superjson"), 1);
2057
+ var import_orm3 = require("@zenstackhq/orm");
2058
+ var import_superjson4 = __toESM(require("superjson"), 1);
1825
2059
  var import_ts_pattern3 = require("ts-pattern");
2060
+ var import_zod3 = __toESM(require("zod"), 1);
2061
+ var import_v43 = require("zod-validation-error/v4");
1826
2062
  registerCustomSerializers();
1827
2063
  var RPCApiHandler = class {
1828
2064
  static {
@@ -1831,6 +2067,17 @@ var RPCApiHandler = class {
1831
2067
  options;
1832
2068
  constructor(options) {
1833
2069
  this.options = options;
2070
+ this.validateOptions(options);
2071
+ }
2072
+ validateOptions(options) {
2073
+ const schema = import_zod3.default.strictObject({
2074
+ schema: import_zod3.default.object(),
2075
+ log: loggerSchema.optional()
2076
+ });
2077
+ const parseResult = schema.safeParse(options);
2078
+ if (!parseResult.success) {
2079
+ throw new Error(`Invalid options: ${(0, import_v43.fromError)(parseResult.error)}`);
2080
+ }
1834
2081
  }
1835
2082
  get schema() {
1836
2083
  return this.options.schema;
@@ -1845,6 +2092,15 @@ var RPCApiHandler = class {
1845
2092
  if (parts.length !== 0 || !op || !model) {
1846
2093
  return this.makeBadInputErrorResponse("invalid request path");
1847
2094
  }
2095
+ if (model === PROCEDURE_ROUTE_PREFIXES) {
2096
+ return this.handleProcedureRequest({
2097
+ client,
2098
+ method: method.toUpperCase(),
2099
+ proc: op,
2100
+ query,
2101
+ requestBody
2102
+ });
2103
+ }
1848
2104
  model = (0, import_common_helpers2.lowerCaseFirst)(model);
1849
2105
  method = method.toUpperCase();
1850
2106
  let args;
@@ -1869,11 +2125,12 @@ var RPCApiHandler = class {
1869
2125
  case "aggregate":
1870
2126
  case "groupBy":
1871
2127
  case "count":
2128
+ case "exists":
1872
2129
  if (method !== "GET") {
1873
2130
  return this.makeBadInputErrorResponse("invalid request method, only GET is supported");
1874
2131
  }
1875
2132
  try {
1876
- args = query?.["q"] ? this.unmarshalQ(query["q"], query["meta"]) : {};
2133
+ args = query?.["q"] ? unmarshalQ(query["q"], query["meta"]) : {};
1877
2134
  } catch {
1878
2135
  return this.makeBadInputErrorResponse('invalid "q" query parameter');
1879
2136
  }
@@ -1895,7 +2152,7 @@ var RPCApiHandler = class {
1895
2152
  return this.makeBadInputErrorResponse("invalid request method, only DELETE is supported");
1896
2153
  }
1897
2154
  try {
1898
- args = query?.["q"] ? this.unmarshalQ(query["q"], query["meta"]) : {};
2155
+ args = query?.["q"] ? unmarshalQ(query["q"], query["meta"]) : {};
1899
2156
  } catch (err) {
1900
2157
  return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid "q" query parameter');
1901
2158
  }
@@ -1917,7 +2174,7 @@ var RPCApiHandler = class {
1917
2174
  data: clientResult
1918
2175
  };
1919
2176
  if (clientResult) {
1920
- const { json, meta } = import_superjson3.default.serialize(clientResult);
2177
+ const { json, meta } = import_superjson4.default.serialize(clientResult);
1921
2178
  responseBody = {
1922
2179
  data: json
1923
2180
  };
@@ -1935,13 +2192,75 @@ var RPCApiHandler = class {
1935
2192
  return response;
1936
2193
  } catch (err) {
1937
2194
  log(this.options.log, "error", `error occurred when handling "${model}.${op}" request`, err);
1938
- if (err instanceof import_orm2.ORMError) {
2195
+ if (err instanceof import_orm3.ORMError) {
1939
2196
  return this.makeORMErrorResponse(err);
1940
2197
  } else {
1941
2198
  return this.makeGenericErrorResponse(err);
1942
2199
  }
1943
2200
  }
1944
2201
  }
2202
+ async handleProcedureRequest({ client, method, proc, query, requestBody }) {
2203
+ if (!proc) {
2204
+ return this.makeBadInputErrorResponse("missing procedure name");
2205
+ }
2206
+ const procDef = getProcedureDef(this.options.schema, proc);
2207
+ if (!procDef) {
2208
+ return this.makeBadInputErrorResponse(`unknown procedure: ${proc}`);
2209
+ }
2210
+ const isMutation = !!procDef.mutation;
2211
+ if (isMutation) {
2212
+ if (method !== "POST") {
2213
+ return this.makeBadInputErrorResponse("invalid request method, only POST is supported");
2214
+ }
2215
+ } else {
2216
+ if (method !== "GET") {
2217
+ return this.makeBadInputErrorResponse("invalid request method, only GET is supported");
2218
+ }
2219
+ }
2220
+ let argsPayload = method === "POST" ? requestBody : void 0;
2221
+ if (method === "GET") {
2222
+ try {
2223
+ argsPayload = query?.["q"] ? unmarshalQ(query["q"], query["meta"]) : void 0;
2224
+ } catch (err) {
2225
+ return this.makeBadInputErrorResponse(err instanceof Error ? err.message : 'invalid "q" query parameter');
2226
+ }
2227
+ }
2228
+ const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload);
2229
+ if (error) {
2230
+ return this.makeBadInputErrorResponse(error);
2231
+ }
2232
+ let procInput;
2233
+ try {
2234
+ procInput = mapProcedureArgs(procDef, processedArgsPayload);
2235
+ } catch (err) {
2236
+ return this.makeBadInputErrorResponse(err instanceof Error ? err.message : "invalid procedure arguments");
2237
+ }
2238
+ try {
2239
+ log(this.options.log, "debug", () => `handling "$procs.${proc}" request`);
2240
+ const clientResult = await client.$procs?.[proc](procInput);
2241
+ const { json, meta } = import_superjson4.default.serialize(clientResult);
2242
+ const responseBody = {
2243
+ data: json
2244
+ };
2245
+ if (meta) {
2246
+ responseBody.meta = {
2247
+ serialization: meta
2248
+ };
2249
+ }
2250
+ const response = {
2251
+ status: 200,
2252
+ body: responseBody
2253
+ };
2254
+ log(this.options.log, "debug", () => `sending response for "$procs.${proc}" request: ${(0, import_common_helpers2.safeJSONStringify)(response)}`);
2255
+ return response;
2256
+ } catch (err) {
2257
+ log(this.options.log, "error", `error occurred when handling "$procs.${proc}" request`, err);
2258
+ if (err instanceof import_orm3.ORMError) {
2259
+ return this.makeORMErrorResponse(err);
2260
+ }
2261
+ return this.makeGenericErrorResponse(err);
2262
+ }
2263
+ }
1945
2264
  isValidModel(client, model) {
1946
2265
  return Object.keys(client.$schema.models).some((m) => (0, import_common_helpers2.lowerCaseFirst)(m) === (0, import_common_helpers2.lowerCaseFirst)(model));
1947
2266
  }
@@ -1975,19 +2294,19 @@ var RPCApiHandler = class {
1975
2294
  message: err.message,
1976
2295
  reason: err.reason
1977
2296
  };
1978
- (0, import_ts_pattern3.match)(err.reason).with(import_orm2.ORMErrorReason.NOT_FOUND, () => {
2297
+ (0, import_ts_pattern3.match)(err.reason).with(import_orm3.ORMErrorReason.NOT_FOUND, () => {
1979
2298
  status = 404;
1980
2299
  error.model = err.model;
1981
- }).with(import_orm2.ORMErrorReason.INVALID_INPUT, () => {
2300
+ }).with(import_orm3.ORMErrorReason.INVALID_INPUT, () => {
1982
2301
  status = 422;
1983
2302
  error.rejectedByValidation = true;
1984
2303
  error.model = err.model;
1985
- }).with(import_orm2.ORMErrorReason.REJECTED_BY_POLICY, () => {
2304
+ }).with(import_orm3.ORMErrorReason.REJECTED_BY_POLICY, () => {
1986
2305
  status = 403;
1987
2306
  error.rejectedByPolicy = true;
1988
- error.rejectReason = err.rejectedByPolicyReason;
1989
2307
  error.model = err.model;
1990
- }).with(import_orm2.ORMErrorReason.DB_QUERY_ERROR, () => {
2308
+ error.rejectReason = err.rejectedByPolicyReason;
2309
+ }).with(import_orm3.ORMErrorReason.DB_QUERY_ERROR, () => {
1991
2310
  status = 400;
1992
2311
  error.dbErrorCode = err.dbErrorCode;
1993
2312
  }).otherwise(() => {
@@ -2005,7 +2324,7 @@ var RPCApiHandler = class {
2005
2324
  const { meta, ...rest } = args ?? {};
2006
2325
  if (meta?.serialization) {
2007
2326
  try {
2008
- args = import_superjson3.default.deserialize({
2327
+ args = import_superjson4.default.deserialize({
2009
2328
  json: rest,
2010
2329
  meta: meta.serialization
2011
2330
  });
@@ -2023,29 +2342,6 @@ var RPCApiHandler = class {
2023
2342
  error: void 0
2024
2343
  };
2025
2344
  }
2026
- unmarshalQ(value, meta) {
2027
- let parsedValue;
2028
- try {
2029
- parsedValue = JSON.parse(value);
2030
- } catch {
2031
- throw new Error('invalid "q" query parameter');
2032
- }
2033
- if (meta) {
2034
- let parsedMeta;
2035
- try {
2036
- parsedMeta = JSON.parse(meta);
2037
- } catch {
2038
- throw new Error('invalid "meta" query parameter');
2039
- }
2040
- if (parsedMeta.serialization) {
2041
- return import_superjson3.default.deserialize({
2042
- json: parsedValue,
2043
- meta: parsedMeta.serialization
2044
- });
2045
- }
2046
- }
2047
- return parsedValue;
2048
- }
2049
2345
  };
2050
2346
  // Annotate the CommonJS export names for ESM import in node:
2051
2347
  0 && (module.exports = {