arri 0.34.0 → 0.36.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.
@@ -1,23 +1,45 @@
1
1
  'use strict';
2
2
 
3
3
  const arriCodegenUtils = require('arri-codegen-utils');
4
+ const consola = require('consola');
4
5
  const h3 = require('h3');
5
6
  const arriValidate = require('arri-validate');
6
7
  const h3Sse = require('h3-sse');
7
8
  const scule = require('scule');
8
9
 
9
- const ErrorResponse = arriValidate.a.object({
10
- statusCode: arriValidate.a.int8(),
11
- statusMessage: arriValidate.a.string(),
12
- stack: arriValidate.a.optional(arriValidate.a.string()),
10
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
+
12
+ const consola__default = /*#__PURE__*/_interopDefaultCompat(consola);
13
+
14
+ var __defProp$3 = Object.defineProperty;
15
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
16
+ var __publicField$3 = (obj, key, value) => {
17
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
18
+ return value;
19
+ };
20
+ class ArriServerError extends Error {
21
+ constructor(err) {
22
+ super(err.message);
23
+ __publicField$3(this, "code");
24
+ __publicField$3(this, "data");
25
+ this.code = err.code;
26
+ this.data = err.data;
27
+ if (err.stack) {
28
+ this.stack = err.stack;
29
+ }
30
+ }
31
+ }
32
+ const ArriServerErrorResponse = arriValidate.a.object({
33
+ code: arriValidate.a.int16(),
34
+ message: arriValidate.a.string(),
35
+ stack: arriValidate.a.optional(arriValidate.a.array(arriValidate.a.string())),
13
36
  data: arriValidate.a.optional(arriValidate.a.any())
14
37
  });
15
38
  function defineError(statusCode, input = {}) {
16
39
  const defaultVals = errorResponseDefaults[statusCode];
17
- return h3.createError({
18
- statusCode,
19
- statusMessage: input.statusMessage ?? defaultVals.message ?? "An unknown error occurred",
20
- stack: input.stack ?? "",
40
+ return new ArriServerError({
41
+ code: statusCode,
42
+ message: input.message ?? defaultVals?.message ?? "An unknown error occurred",
21
43
  data: input.data
22
44
  });
23
45
  }
@@ -25,7 +47,7 @@ function errorResponseFromValidationErrors(errors, prefixText = `Missing or inva
25
47
  const errorParts = [];
26
48
  for (const err of errors) {
27
49
  const propName = err.instancePath?.split("/") ?? [];
28
- if (propName.length) {
50
+ if (propName.length > 0) {
29
51
  propName.shift();
30
52
  }
31
53
  if (!errorParts.includes(propName.join("."))) {
@@ -33,7 +55,7 @@ function errorResponseFromValidationErrors(errors, prefixText = `Missing or inva
33
55
  }
34
56
  }
35
57
  throw defineError(400, {
36
- statusMessage: `${prefixText}: [${errorParts.join(",")}]`,
58
+ message: `${prefixText}: [${errorParts.join(",")}]`,
37
59
  data: errors
38
60
  });
39
61
  }
@@ -187,28 +209,55 @@ const errorResponseDefaults = {
187
209
  message: "Network Authentication Required"
188
210
  }
189
211
  };
190
- async function handleH3Error(err, event, onError) {
191
- const error = h3.isError(err) ? err : defineError(500, {
192
- statusMessage: typeof err === "object" && err != null && "message" in err && typeof err.message === "string" ? err.message : void 0,
193
- data: err,
194
- stack: `${err}`
195
- });
196
- h3.setResponseStatus(event, error.statusCode);
212
+ async function handleH3Error(err, event, onError, debug) {
213
+ let arriErr;
214
+ if (err instanceof ArriServerError) {
215
+ arriErr = err;
216
+ } else if (h3.isError(err)) {
217
+ arriErr = new ArriServerError({
218
+ code: err.statusCode,
219
+ message: err.message,
220
+ stack: err.stack,
221
+ data: err.data
222
+ });
223
+ } else if (err instanceof Error) {
224
+ arriErr = new ArriServerError({
225
+ code: 500,
226
+ message: err.message,
227
+ data: err,
228
+ stack: err.stack
229
+ });
230
+ } else {
231
+ arriErr = new ArriServerError({
232
+ code: 500,
233
+ message: `An unknown error occurred`,
234
+ data: err
235
+ });
236
+ }
237
+ if (!arriErr) {
238
+ return;
239
+ }
240
+ h3.setResponseStatus(event, arriErr.code);
197
241
  if (onError) {
198
- await onError(error, event);
242
+ await onError(arriErr, event);
199
243
  }
200
244
  if (event.handled) {
201
245
  return;
202
246
  }
203
- await h3.send(
204
- event,
205
- JSON.stringify({
206
- statusCode: error.statusCode,
207
- statusMessage: error.statusMessage,
208
- data: error.data,
209
- stack: error.stack
210
- })
211
- );
247
+ return sendArriError(event, arriErr, debug);
248
+ }
249
+ async function sendArriError(event, error, debug) {
250
+ const payload = {
251
+ code: error.code,
252
+ message: error.message,
253
+ data: error.data
254
+ };
255
+ if (debug) {
256
+ payload.stack = error.stack?.split("\n").map((l) => l.trim());
257
+ }
258
+ h3.setResponseHeader(event, "Content-Type", "application/json");
259
+ h3.setResponseStatus(event, error.code);
260
+ return h3.send(event, JSON.stringify(payload));
212
261
  }
213
262
 
214
263
  function isRpcParamSchema(input) {
@@ -321,7 +370,7 @@ function registerRpc(router, path, procedure, opts) {
321
370
  if (!responseValidator?.validate(response)) {
322
371
  const errors = arriValidate.a.errors(procedure.response, response);
323
372
  throw defineError(500, {
324
- statusMessage: "Failed to serialize response. Response does not match specified schema",
373
+ message: "Failed to serialize response. Response does not match specified schema",
325
374
  data: errors
326
375
  });
327
376
  }
@@ -344,7 +393,7 @@ function registerRpc(router, path, procedure, opts) {
344
393
  );
345
394
  }
346
395
  } catch (err) {
347
- await handleH3Error(err, event, opts.onError);
396
+ await handleH3Error(err, event, opts.onError, opts.debug ?? false);
348
397
  }
349
398
  return "";
350
399
  });
@@ -390,7 +439,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
390
439
  ", "
391
440
  )}]`;
392
441
  throw defineError(400, {
393
- statusMessage: message,
442
+ message,
394
443
  data: parsedParams.error
395
444
  });
396
445
  }
@@ -403,7 +452,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
403
452
  const body = await h3.readRawBody(event);
404
453
  if (!body) {
405
454
  throw defineError(400, {
406
- statusMessage: `Invalid request body. Expected object. Got undefined.`
455
+ message: `Invalid request body. Expected object. Got undefined.`
407
456
  });
408
457
  }
409
458
  const parsedParams = arriValidate.a.safeParse(schema, body);
@@ -417,7 +466,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
417
466
  }
418
467
  }
419
468
  throw defineError(400, {
420
- statusMessage: `Invalid request body. Affected properties [${errorParts.join(
469
+ message: `Invalid request body. Affected properties [${errorParts.join(
421
470
  ", "
422
471
  )}]`,
423
472
  data: parsedParams.error
@@ -490,11 +539,10 @@ class EventStreamConnection {
490
539
  continue;
491
540
  }
492
541
  const errors2 = this.validationErrors(item);
493
- const errorResponse2 = {
494
- statusCode: 500,
495
- statusMessage: "Failed to serialize response. Response does not match specified schema.",
542
+ const errorResponse2 = defineError(500, {
543
+ message: "Failed to serialize response. Response does not match specified schema.",
496
544
  data: errors2
497
- };
545
+ });
498
546
  events.push({
499
547
  id: eventId,
500
548
  event: "error",
@@ -513,11 +561,10 @@ class EventStreamConnection {
513
561
  return;
514
562
  }
515
563
  const errors = this.validationErrors(data);
516
- const errorResponse = {
517
- statusCode: 500,
518
- statusMessage: "Failed to serialize response. Response does not match specified schema.",
564
+ const errorResponse = defineError(500, {
565
+ message: "Failed to serialize response. Response does not match specified schema.",
519
566
  data: errors
520
- };
567
+ });
521
568
  await this.eventStream.push({
522
569
  id: eventId,
523
570
  event: "error",
@@ -603,9 +650,12 @@ function registerEventStreamRpc(router, path, procedure, opts) {
603
650
  validator: responseValidator?.validate ?? function() {
604
651
  return true;
605
652
  },
606
- serializer: responseValidator?.serialize ?? function(_) {
607
- return "";
608
- },
653
+ serializer: (
654
+ // eslint-disable-next-line @typescript-eslint/unbound-method
655
+ responseValidator?.serialize ?? function(_) {
656
+ return "";
657
+ }
658
+ ),
609
659
  validationErrors(input) {
610
660
  if (procedure.response) {
611
661
  return arriValidate.a.errors(procedure.response, input);
@@ -622,7 +672,7 @@ function registerEventStreamRpc(router, path, procedure, opts) {
622
672
  stream.send();
623
673
  }
624
674
  } catch (err) {
625
- await handleH3Error(err, event, opts.onError);
675
+ await handleH3Error(err, event, opts.onError, opts.debug ?? false);
626
676
  }
627
677
  return "";
628
678
  });
@@ -689,7 +739,7 @@ function handleRoute(router, method, route, opts) {
689
739
  ", "
690
740
  )}]`;
691
741
  throw defineError(400, {
692
- statusMessage: message
742
+ message
693
743
  });
694
744
  }
695
745
  event.context.query = parsedQuery.value;
@@ -713,7 +763,7 @@ function handleRoute(router, method, route, opts) {
713
763
  }
714
764
  }
715
765
  throw defineError(400, {
716
- statusMessage: `Invalid request body. Affected properties [${errorParts.join(
766
+ message: `Invalid request body. Affected properties [${errorParts.join(
717
767
  ", "
718
768
  )}]`,
719
769
  data: parsedBody.error
@@ -741,7 +791,7 @@ function handleRoute(router, method, route, opts) {
741
791
  await route.postHandler(event);
742
792
  }
743
793
  } catch (err) {
744
- await handleH3Error(err, event, opts.onError);
794
+ await handleH3Error(err, event, opts.onError, opts.debug ?? false);
745
795
  }
746
796
  return "";
747
797
  });
@@ -815,32 +865,39 @@ class ArriApp {
815
865
  __publicField(this, "__isArri__", true);
816
866
  __publicField(this, "h3App");
817
867
  __publicField(this, "h3Router", h3.createRouter());
818
- __publicField(this, "rpcDefinitionPath");
819
- __publicField(this, "rpcRoutePrefix");
868
+ __publicField(this, "_rpcDefinitionPath");
869
+ __publicField(this, "_rpcRoutePrefix");
820
870
  __publicField(this, "appInfo");
821
- __publicField(this, "procedures", {});
822
- __publicField(this, "models", {});
823
- __publicField(this, "middlewares", []);
824
- __publicField(this, "onRequest");
825
- __publicField(this, "onAfterResponse");
826
- __publicField(this, "onBeforeResponse");
827
- __publicField(this, "onError");
871
+ __publicField(this, "_procedures", {});
872
+ __publicField(this, "_models", {});
873
+ __publicField(this, "_middlewares", []);
874
+ __publicField(this, "_onRequest");
875
+ __publicField(this, "_onAfterResponse");
876
+ __publicField(this, "_onBeforeResponse");
877
+ __publicField(this, "_onError");
878
+ __publicField(this, "_debug");
879
+ __publicField(this, "definitionPath");
828
880
  this.appInfo = opts?.appInfo;
829
881
  this.h3App = h3.createApp({
830
882
  debug: opts?.debug
831
883
  });
832
- this.onRequest = opts.onRequest;
833
- this.onError = opts.onError;
834
- this.onAfterResponse = opts.onAfterResponse;
835
- this.onBeforeResponse = opts.onBeforeResponse;
836
- this.rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
837
- this.rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
884
+ this._debug = opts.debug ?? false;
885
+ this._onRequest = opts.onRequest;
886
+ this._onError = opts.onError;
887
+ this._onAfterResponse = opts.onAfterResponse;
888
+ this._onBeforeResponse = opts.onBeforeResponse;
889
+ this._rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
890
+ this._rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
838
891
  this.h3App.use(this.h3Router);
892
+ this.definitionPath = this._rpcRoutePrefix ? `/${this._rpcRoutePrefix}/${this._rpcDefinitionPath}`.split("//").join("/") : `/${this._rpcDefinitionPath}`;
839
893
  this.h3Router.get(
840
- this.rpcRoutePrefix ? `/${this.rpcRoutePrefix}/${this.rpcDefinitionPath}`.split("//").join("/") : `/${this.rpcDefinitionPath}`,
894
+ this.definitionPath,
841
895
  h3.eventHandler(() => this.getAppDefinition())
842
896
  );
843
897
  if (process.env.ARRI_DEV_MODE === "true") {
898
+ consola__default.info(
899
+ `Arri definition available at \`http://<host>${this.definitionPath}\``
900
+ );
844
901
  this.h3Router.get(
845
902
  DEV_DEFINITION_ENDPOINT,
846
903
  h3.eventHandler(() => this.getAppDefinition())
@@ -852,22 +909,16 @@ class ArriApp {
852
909
  h3.setResponseStatus(event, 404);
853
910
  const error = defineError(404);
854
911
  try {
855
- if (this.onRequest) {
856
- await this.onRequest(event);
912
+ if (this._onRequest) {
913
+ await this._onRequest(event);
857
914
  }
858
915
  } catch (err) {
859
- await handleH3Error(err, event, this.onError);
916
+ await handleH3Error(err, event, this._onError, this._debug);
860
917
  }
861
918
  if (event.handled) {
862
919
  return;
863
920
  }
864
- if (this.onError) {
865
- await this.onError(error, event);
866
- }
867
- if (event.handled) {
868
- return;
869
- }
870
- h3.sendError(event, error);
921
+ return handleH3Error(error, event, this._onError, this._debug);
871
922
  })
872
923
  );
873
924
  }
@@ -882,11 +933,11 @@ class ArriApp {
882
933
  this.registerModels(input.getModels());
883
934
  return;
884
935
  }
885
- this.middlewares.push(input);
936
+ this._middlewares.push(input);
886
937
  }
887
938
  rpc(procedure) {
888
- const path = procedure.path ?? getRpcPath(procedure.name, this.rpcRoutePrefix);
889
- this.procedures[procedure.name] = createHttpRpcDefinition(
939
+ const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
940
+ this._procedures[procedure.name] = createHttpRpcDefinition(
890
941
  procedure.name,
891
942
  path,
892
943
  procedure
@@ -894,45 +945,48 @@ class ArriApp {
894
945
  if (isRpcParamSchema(procedure.params)) {
895
946
  const paramName = getRpcParamName(procedure.name, procedure);
896
947
  if (paramName) {
897
- this.models[paramName] = procedure.params;
948
+ this._models[paramName] = procedure.params;
898
949
  }
899
950
  }
900
951
  if (isRpcParamSchema(procedure.response)) {
901
952
  const responseName = getRpcResponseName(procedure.name, procedure);
902
953
  if (responseName) {
903
- this.models[responseName] = procedure.response;
954
+ this._models[responseName] = procedure.response;
904
955
  }
905
956
  }
906
957
  if (isEventStreamRpc(procedure)) {
907
958
  registerEventStreamRpc(this.h3Router, path, procedure, {
908
- middleware: this.middlewares,
909
- onRequest: this.onRequest,
910
- onError: this.onError,
911
- onAfterResponse: this.onAfterResponse,
912
- onBeforeResponse: this.onBeforeResponse
959
+ middleware: this._middlewares,
960
+ onRequest: this._onRequest,
961
+ onError: this._onError,
962
+ onAfterResponse: this._onAfterResponse,
963
+ onBeforeResponse: this._onBeforeResponse,
964
+ debug: this._debug
913
965
  });
914
966
  return;
915
967
  }
916
968
  registerRpc(this.h3Router, path, procedure, {
917
- middleware: this.middlewares,
918
- onRequest: this.onRequest,
919
- onError: this.onError,
920
- onAfterResponse: this.onAfterResponse,
921
- onBeforeResponse: this.onBeforeResponse
969
+ middleware: this._middlewares,
970
+ onRequest: this._onRequest,
971
+ onError: this._onError,
972
+ onAfterResponse: this._onAfterResponse,
973
+ onBeforeResponse: this._onBeforeResponse,
974
+ debug: this._debug
922
975
  });
923
976
  }
924
977
  route(route) {
925
978
  registerRoute(this.h3Router, route, {
926
- middleware: this.middlewares,
927
- onRequest: this.onRequest,
928
- onError: this.onError,
929
- onAfterResponse: this.onAfterResponse,
930
- onBeforeResponse: this.onBeforeResponse
979
+ middleware: this._middlewares,
980
+ onRequest: this._onRequest,
981
+ onError: this._onError,
982
+ onAfterResponse: this._onAfterResponse,
983
+ onBeforeResponse: this._onBeforeResponse,
984
+ debug: this._debug
931
985
  });
932
986
  }
933
987
  registerModels(models) {
934
988
  for (const key of Object.keys(models)) {
935
- this.models[key] = models[key];
989
+ this._models[key] = models[key];
936
990
  }
937
991
  }
938
992
  getAppDefinition() {
@@ -940,10 +994,10 @@ class ArriApp {
940
994
  arriSchemaVersion: arriCodegenUtils.SCHEMA_VERSION,
941
995
  info: this.appInfo,
942
996
  procedures: {},
943
- models: this.models
997
+ models: this._models
944
998
  };
945
- for (const key of Object.keys(this.procedures)) {
946
- const rpc = this.procedures[key];
999
+ for (const key of Object.keys(this._procedures)) {
1000
+ const rpc = this._procedures[key];
947
1001
  appDef.procedures[key] = rpc;
948
1002
  }
949
1003
  return appDef;
@@ -1011,9 +1065,10 @@ function defineConfig(config) {
1011
1065
 
1012
1066
  exports.ArriApp = ArriApp;
1013
1067
  exports.ArriRouter = ArriRouter;
1068
+ exports.ArriServerError = ArriServerError;
1069
+ exports.ArriServerErrorResponse = ArriServerErrorResponse;
1014
1070
  exports.DEV_DEFINITION_ENDPOINT = DEV_DEFINITION_ENDPOINT;
1015
1071
  exports.DEV_ENDPOINT_ROOT = DEV_ENDPOINT_ROOT;
1016
- exports.ErrorResponse = ErrorResponse;
1017
1072
  exports.EventStreamConnection = EventStreamConnection;
1018
1073
  exports.createAppDefinition = createAppDefinition;
1019
1074
  exports.createHttpRpcDefinition = createHttpRpcDefinition;