@zenstackhq/server 3.0.0-beta.19 → 3.0.0-beta.20

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
@@ -42,6 +42,7 @@ var import_orm = require("@zenstackhq/orm");
42
42
  var import_decimal2 = require("decimal.js");
43
43
  var import_superjson2 = __toESM(require("superjson"), 1);
44
44
  var import_ts_japi = __toESM(require("ts-japi"), 1);
45
+ var import_ts_pattern2 = require("ts-pattern");
45
46
  var import_url_pattern = __toESM(require("url-pattern"), 1);
46
47
  var import_zod = __toESM(require("zod"), 1);
47
48
 
@@ -327,17 +328,17 @@ var RestApiHandler = class {
327
328
  if (!pattern) {
328
329
  throw new InvalidValueError(`Unknown route type: ${routeType}`);
329
330
  }
330
- const match2 = pattern.match(path);
331
- if (!match2) {
331
+ const match4 = pattern.match(path);
332
+ if (!match4) {
332
333
  return;
333
334
  }
334
- if (match2.type in this.modelNameMapping) {
335
- throw new InvalidValueError(`use the mapped model name: ${this.modelNameMapping[match2.type]} and not ${match2.type}`);
335
+ if (match4.type in this.modelNameMapping) {
336
+ throw new InvalidValueError(`use the mapped model name: ${this.modelNameMapping[match4.type]} and not ${match4.type}`);
336
337
  }
337
- if (match2.type in this.reverseModelNameMapping) {
338
- match2.type = this.reverseModelNameMapping[match2.type];
338
+ if (match4.type in this.reverseModelNameMapping) {
339
+ match4.type = this.reverseModelNameMapping[match4.type];
339
340
  }
340
- return match2;
341
+ return match4;
341
342
  }
342
343
  async handleRequest({ client, method, path, query, requestBody }) {
343
344
  method = method.toUpperCase();
@@ -347,21 +348,21 @@ var RestApiHandler = class {
347
348
  try {
348
349
  switch (method) {
349
350
  case "GET": {
350
- let match2 = this.matchUrlPattern(path, "single");
351
- if (match2) {
352
- return await this.processSingleRead(client, match2.type, match2.id, query);
351
+ let match4 = this.matchUrlPattern(path, "single");
352
+ if (match4) {
353
+ return await this.processSingleRead(client, match4.type, match4.id, query);
353
354
  }
354
- match2 = this.matchUrlPattern(path, "fetchRelationship");
355
- if (match2) {
356
- return await this.processFetchRelated(client, match2.type, match2.id, match2.relationship, query);
355
+ match4 = this.matchUrlPattern(path, "fetchRelationship");
356
+ if (match4) {
357
+ return await this.processFetchRelated(client, match4.type, match4.id, match4.relationship, query);
357
358
  }
358
- match2 = this.matchUrlPattern(path, "relationship");
359
- if (match2) {
360
- return await this.processReadRelationship(client, match2.type, match2.id, match2.relationship, query);
359
+ match4 = this.matchUrlPattern(path, "relationship");
360
+ if (match4) {
361
+ return await this.processReadRelationship(client, match4.type, match4.id, match4.relationship, query);
361
362
  }
362
- match2 = this.matchUrlPattern(path, "collection");
363
- if (match2) {
364
- return await this.processCollectionRead(client, match2.type, query);
363
+ match4 = this.matchUrlPattern(path, "collection");
364
+ if (match4) {
365
+ return await this.processCollectionRead(client, match4.type, query);
365
366
  }
366
367
  return this.makeError("invalidPath");
367
368
  }
@@ -369,19 +370,19 @@ var RestApiHandler = class {
369
370
  if (!requestBody) {
370
371
  return this.makeError("invalidPayload");
371
372
  }
372
- let match2 = this.matchUrlPattern(path, "collection");
373
- if (match2) {
373
+ let match4 = this.matchUrlPattern(path, "collection");
374
+ if (match4) {
374
375
  const body = requestBody;
375
376
  const upsertMeta = this.upsertMetaSchema.safeParse(body);
376
377
  if (upsertMeta.success) {
377
- return await this.processUpsert(client, match2.type, query, requestBody);
378
+ return await this.processUpsert(client, match4.type, query, requestBody);
378
379
  } else {
379
- return await this.processCreate(client, match2.type, query, requestBody);
380
+ return await this.processCreate(client, match4.type, query, requestBody);
380
381
  }
381
382
  }
382
- match2 = this.matchUrlPattern(path, "relationship");
383
- if (match2) {
384
- return await this.processRelationshipCRUD(client, "create", match2.type, match2.id, match2.relationship, query, requestBody);
383
+ match4 = this.matchUrlPattern(path, "relationship");
384
+ if (match4) {
385
+ return await this.processRelationshipCRUD(client, "create", match4.type, match4.id, match4.relationship, query, requestBody);
385
386
  }
386
387
  return this.makeError("invalidPath");
387
388
  }
@@ -391,24 +392,24 @@ var RestApiHandler = class {
391
392
  if (!requestBody) {
392
393
  return this.makeError("invalidPayload");
393
394
  }
394
- let match2 = this.matchUrlPattern(path, "single");
395
- if (match2) {
396
- return await this.processUpdate(client, match2.type, match2.id, query, requestBody);
395
+ let match4 = this.matchUrlPattern(path, "single");
396
+ if (match4) {
397
+ return await this.processUpdate(client, match4.type, match4.id, query, requestBody);
397
398
  }
398
- match2 = this.matchUrlPattern(path, "relationship");
399
- if (match2) {
400
- return await this.processRelationshipCRUD(client, "update", match2.type, match2.id, match2.relationship, query, requestBody);
399
+ match4 = this.matchUrlPattern(path, "relationship");
400
+ if (match4) {
401
+ return await this.processRelationshipCRUD(client, "update", match4.type, match4.id, match4.relationship, query, requestBody);
401
402
  }
402
403
  return this.makeError("invalidPath");
403
404
  }
404
405
  case "DELETE": {
405
- let match2 = this.matchUrlPattern(path, "single");
406
- if (match2) {
407
- return await this.processDelete(client, match2.type, match2.id);
406
+ let match4 = this.matchUrlPattern(path, "single");
407
+ if (match4) {
408
+ return await this.processDelete(client, match4.type, match4.id);
408
409
  }
409
- match2 = this.matchUrlPattern(path, "relationship");
410
- if (match2) {
411
- return await this.processRelationshipCRUD(client, "delete", match2.type, match2.id, match2.relationship, query, requestBody);
410
+ match4 = this.matchUrlPattern(path, "relationship");
411
+ if (match4) {
412
+ return await this.processRelationshipCRUD(client, "delete", match4.type, match4.id, match4.relationship, query, requestBody);
412
413
  }
413
414
  return this.makeError("invalidPath");
414
415
  }
@@ -418,8 +419,8 @@ var RestApiHandler = class {
418
419
  } catch (err) {
419
420
  if (err instanceof InvalidValueError) {
420
421
  return this.makeError("invalidValue", err.message);
421
- } else if (err instanceof import_orm.ZenStackError) {
422
- return this.handleZenStackError(err);
422
+ } else if (err instanceof import_orm.ORMError) {
423
+ return this.handleORMError(err);
423
424
  } else {
424
425
  return this.handleGenericError(err);
425
426
  }
@@ -1445,11 +1446,11 @@ ${err.stack}` : "Unknown error");
1445
1446
  if (!value) {
1446
1447
  continue;
1447
1448
  }
1448
- const match2 = key.match(this.filterParamPattern);
1449
- if (!match2 || !match2.groups || !match2.groups["match"]) {
1449
+ const match4 = key.match(this.filterParamPattern);
1450
+ if (!match4 || !match4.groups || !match4.groups["match"]) {
1450
1451
  continue;
1451
1452
  }
1452
- const filterKeys = match2.groups["match"].replaceAll(/[[\]]/g, " ").split(" ").filter((i) => i);
1453
+ const filterKeys = match4.groups["match"].replaceAll(/[[\]]/g, " ").split(" ").filter((i) => i);
1453
1454
  if (!filterKeys.length) {
1454
1455
  continue;
1455
1456
  }
@@ -1772,20 +1773,24 @@ ${err.stack}` : "Unknown error");
1772
1773
  };
1773
1774
  }
1774
1775
  }
1775
- handleZenStackError(err) {
1776
- if (err instanceof import_orm.InputValidationError) {
1777
- return this.makeError("validationError", err.message, 422, err.cause instanceof Error ? err.cause.message : void 0);
1778
- } else if (err instanceof import_orm.RejectedByPolicyError) {
1779
- return this.makeError("forbidden", err.message, 403, err.reason);
1780
- } else if (err instanceof import_orm.NotFoundError) {
1781
- return this.makeError("notFound", err.message);
1782
- } else if (err instanceof import_orm.QueryError) {
1783
- return this.makeError("queryError", err.message, 400, err.cause instanceof Error ? err.cause.message : void 0);
1784
- } else {
1776
+ handleORMError(err) {
1777
+ return (0, import_ts_pattern2.match)(err.reason).with(import_orm.ORMErrorReason.INVALID_INPUT, () => {
1778
+ return this.makeError("validationError", err.message, 422);
1779
+ }).with(import_orm.ORMErrorReason.REJECTED_BY_POLICY, () => {
1780
+ return this.makeError("forbidden", err.message, 403, {
1781
+ reason: err.rejectedByPolicyReason
1782
+ });
1783
+ }).with(import_orm.ORMErrorReason.NOT_FOUND, () => {
1784
+ return this.makeError("notFound", err.message, 404);
1785
+ }).with(import_orm.ORMErrorReason.DB_QUERY_ERROR, () => {
1786
+ return this.makeError("queryError", err.message, 400, {
1787
+ dbErrorCode: err.dbErrorCode
1788
+ });
1789
+ }).otherwise(() => {
1785
1790
  return this.makeError("unknownError", err.message);
1786
- }
1791
+ });
1787
1792
  }
1788
- makeError(code, detail, status, reason) {
1793
+ makeError(code, detail, status, otherFields = {}) {
1789
1794
  status = status ?? this.errors[code]?.status ?? 500;
1790
1795
  const error = {
1791
1796
  status,
@@ -1795,9 +1800,7 @@ ${err.stack}` : "Unknown error");
1795
1800
  if (detail) {
1796
1801
  error.detail = detail;
1797
1802
  }
1798
- if (reason) {
1799
- error.reason = reason;
1800
- }
1803
+ Object.assign(error, otherFields);
1801
1804
  return {
1802
1805
  status,
1803
1806
  body: {
@@ -1819,6 +1822,7 @@ ${err.stack}` : "Unknown error");
1819
1822
  var import_common_helpers2 = require("@zenstackhq/common-helpers");
1820
1823
  var import_orm2 = require("@zenstackhq/orm");
1821
1824
  var import_superjson3 = __toESM(require("superjson"), 1);
1825
+ var import_ts_pattern3 = require("ts-pattern");
1822
1826
  registerCustomSerializers();
1823
1827
  var RPCApiHandler = class {
1824
1828
  static {
@@ -1931,8 +1935,8 @@ var RPCApiHandler = class {
1931
1935
  return response;
1932
1936
  } catch (err) {
1933
1937
  log(this.options.log, "error", `error occurred when handling "${model}.${op}" request`, err);
1934
- if (err instanceof import_orm2.ZenStackError) {
1935
- return this.makeZenStackErrorResponse(err);
1938
+ if (err instanceof import_orm2.ORMError) {
1939
+ return this.makeORMErrorResponse(err);
1936
1940
  } else {
1937
1941
  return this.makeGenericErrorResponse(err);
1938
1942
  }
@@ -1965,27 +1969,29 @@ var RPCApiHandler = class {
1965
1969
  log(this.options.log, "debug", () => `sending error response: ${(0, import_common_helpers2.safeJSONStringify)(resp)}${err instanceof Error ? "\n" + err.stack : ""}`);
1966
1970
  return resp;
1967
1971
  }
1968
- makeZenStackErrorResponse(err) {
1972
+ makeORMErrorResponse(err) {
1969
1973
  let status = 400;
1970
1974
  const error = {
1971
- message: err.message
1975
+ message: err.message,
1976
+ reason: err.reason
1972
1977
  };
1973
- if (err.cause && err.cause instanceof Error) {
1974
- error.cause = err.cause.message;
1975
- }
1976
- if (err instanceof import_orm2.NotFoundError) {
1978
+ (0, import_ts_pattern3.match)(err.reason).with(import_orm2.ORMErrorReason.NOT_FOUND, () => {
1977
1979
  status = 404;
1978
1980
  error.model = err.model;
1979
- } else if (err instanceof import_orm2.InputValidationError) {
1981
+ }).with(import_orm2.ORMErrorReason.INVALID_INPUT, () => {
1980
1982
  status = 422;
1981
1983
  error.rejectedByValidation = true;
1982
1984
  error.model = err.model;
1983
- } else if (err instanceof import_orm2.RejectedByPolicyError) {
1985
+ }).with(import_orm2.ORMErrorReason.REJECTED_BY_POLICY, () => {
1984
1986
  status = 403;
1985
1987
  error.rejectedByPolicy = true;
1986
- error.rejectReason = err.reason;
1988
+ error.rejectReason = err.rejectedByPolicyReason;
1987
1989
  error.model = err.model;
1988
- }
1990
+ }).with(import_orm2.ORMErrorReason.DB_QUERY_ERROR, () => {
1991
+ status = 400;
1992
+ error.dbErrorCode = err.dbErrorCode;
1993
+ }).otherwise(() => {
1994
+ });
1989
1995
  const resp = {
1990
1996
  status,
1991
1997
  body: {