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,21 +1,39 @@
1
1
  import { isRpcHttpMethod, removeDisallowedChars, SCHEMA_VERSION } from 'arri-codegen-utils';
2
- import { createError, isError, setResponseStatus, send, eventHandler, isPreflightRequest, setResponseHeader, readRawBody, getValidatedQuery, defineEventHandler, getQuery, setHeader, createRouter, createApp, sendError } from 'h3';
2
+ import consola from 'consola';
3
+ import { isError, setResponseStatus, setResponseHeader, send, eventHandler, isPreflightRequest, readRawBody, getValidatedQuery, defineEventHandler, getQuery, setHeader, createRouter, createApp } from 'h3';
3
4
  import { a, isAObjectSchema, isADiscriminatorSchema } from 'arri-validate';
4
5
  import { createEventStream } from 'h3-sse';
5
6
  import { kebabCase, pascalCase } from 'scule';
6
7
 
7
- const ErrorResponse = a.object({
8
- statusCode: a.int8(),
9
- statusMessage: a.string(),
10
- stack: a.optional(a.string()),
8
+ var __defProp$3 = Object.defineProperty;
9
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __publicField$3 = (obj, key, value) => {
11
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
12
+ return value;
13
+ };
14
+ class ArriServerError extends Error {
15
+ constructor(err) {
16
+ super(err.message);
17
+ __publicField$3(this, "code");
18
+ __publicField$3(this, "data");
19
+ this.code = err.code;
20
+ this.data = err.data;
21
+ if (err.stack) {
22
+ this.stack = err.stack;
23
+ }
24
+ }
25
+ }
26
+ const ArriServerErrorResponse = a.object({
27
+ code: a.int16(),
28
+ message: a.string(),
29
+ stack: a.optional(a.array(a.string())),
11
30
  data: a.optional(a.any())
12
31
  });
13
32
  function defineError(statusCode, input = {}) {
14
33
  const defaultVals = errorResponseDefaults[statusCode];
15
- return createError({
16
- statusCode,
17
- statusMessage: input.statusMessage ?? defaultVals.message ?? "An unknown error occurred",
18
- stack: input.stack ?? "",
34
+ return new ArriServerError({
35
+ code: statusCode,
36
+ message: input.message ?? defaultVals?.message ?? "An unknown error occurred",
19
37
  data: input.data
20
38
  });
21
39
  }
@@ -23,7 +41,7 @@ function errorResponseFromValidationErrors(errors, prefixText = `Missing or inva
23
41
  const errorParts = [];
24
42
  for (const err of errors) {
25
43
  const propName = err.instancePath?.split("/") ?? [];
26
- if (propName.length) {
44
+ if (propName.length > 0) {
27
45
  propName.shift();
28
46
  }
29
47
  if (!errorParts.includes(propName.join("."))) {
@@ -31,7 +49,7 @@ function errorResponseFromValidationErrors(errors, prefixText = `Missing or inva
31
49
  }
32
50
  }
33
51
  throw defineError(400, {
34
- statusMessage: `${prefixText}: [${errorParts.join(",")}]`,
52
+ message: `${prefixText}: [${errorParts.join(",")}]`,
35
53
  data: errors
36
54
  });
37
55
  }
@@ -185,28 +203,55 @@ const errorResponseDefaults = {
185
203
  message: "Network Authentication Required"
186
204
  }
187
205
  };
188
- async function handleH3Error(err, event, onError) {
189
- const error = isError(err) ? err : defineError(500, {
190
- statusMessage: typeof err === "object" && err != null && "message" in err && typeof err.message === "string" ? err.message : void 0,
191
- data: err,
192
- stack: `${err}`
193
- });
194
- setResponseStatus(event, error.statusCode);
206
+ async function handleH3Error(err, event, onError, debug) {
207
+ let arriErr;
208
+ if (err instanceof ArriServerError) {
209
+ arriErr = err;
210
+ } else if (isError(err)) {
211
+ arriErr = new ArriServerError({
212
+ code: err.statusCode,
213
+ message: err.message,
214
+ stack: err.stack,
215
+ data: err.data
216
+ });
217
+ } else if (err instanceof Error) {
218
+ arriErr = new ArriServerError({
219
+ code: 500,
220
+ message: err.message,
221
+ data: err,
222
+ stack: err.stack
223
+ });
224
+ } else {
225
+ arriErr = new ArriServerError({
226
+ code: 500,
227
+ message: `An unknown error occurred`,
228
+ data: err
229
+ });
230
+ }
231
+ if (!arriErr) {
232
+ return;
233
+ }
234
+ setResponseStatus(event, arriErr.code);
195
235
  if (onError) {
196
- await onError(error, event);
236
+ await onError(arriErr, event);
197
237
  }
198
238
  if (event.handled) {
199
239
  return;
200
240
  }
201
- await send(
202
- event,
203
- JSON.stringify({
204
- statusCode: error.statusCode,
205
- statusMessage: error.statusMessage,
206
- data: error.data,
207
- stack: error.stack
208
- })
209
- );
241
+ return sendArriError(event, arriErr, debug);
242
+ }
243
+ async function sendArriError(event, error, debug) {
244
+ const payload = {
245
+ code: error.code,
246
+ message: error.message,
247
+ data: error.data
248
+ };
249
+ if (debug) {
250
+ payload.stack = error.stack?.split("\n").map((l) => l.trim());
251
+ }
252
+ setResponseHeader(event, "Content-Type", "application/json");
253
+ setResponseStatus(event, error.code);
254
+ return send(event, JSON.stringify(payload));
210
255
  }
211
256
 
212
257
  function isRpcParamSchema(input) {
@@ -319,7 +364,7 @@ function registerRpc(router, path, procedure, opts) {
319
364
  if (!responseValidator?.validate(response)) {
320
365
  const errors = a.errors(procedure.response, response);
321
366
  throw defineError(500, {
322
- statusMessage: "Failed to serialize response. Response does not match specified schema",
367
+ message: "Failed to serialize response. Response does not match specified schema",
323
368
  data: errors
324
369
  });
325
370
  }
@@ -342,7 +387,7 @@ function registerRpc(router, path, procedure, opts) {
342
387
  );
343
388
  }
344
389
  } catch (err) {
345
- await handleH3Error(err, event, opts.onError);
390
+ await handleH3Error(err, event, opts.onError, opts.debug ?? false);
346
391
  }
347
392
  return "";
348
393
  });
@@ -388,7 +433,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
388
433
  ", "
389
434
  )}]`;
390
435
  throw defineError(400, {
391
- statusMessage: message,
436
+ message,
392
437
  data: parsedParams.error
393
438
  });
394
439
  }
@@ -401,7 +446,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
401
446
  const body = await readRawBody(event);
402
447
  if (!body) {
403
448
  throw defineError(400, {
404
- statusMessage: `Invalid request body. Expected object. Got undefined.`
449
+ message: `Invalid request body. Expected object. Got undefined.`
405
450
  });
406
451
  }
407
452
  const parsedParams = a.safeParse(schema, body);
@@ -415,7 +460,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
415
460
  }
416
461
  }
417
462
  throw defineError(400, {
418
- statusMessage: `Invalid request body. Affected properties [${errorParts.join(
463
+ message: `Invalid request body. Affected properties [${errorParts.join(
419
464
  ", "
420
465
  )}]`,
421
466
  data: parsedParams.error
@@ -488,11 +533,10 @@ class EventStreamConnection {
488
533
  continue;
489
534
  }
490
535
  const errors2 = this.validationErrors(item);
491
- const errorResponse2 = {
492
- statusCode: 500,
493
- statusMessage: "Failed to serialize response. Response does not match specified schema.",
536
+ const errorResponse2 = defineError(500, {
537
+ message: "Failed to serialize response. Response does not match specified schema.",
494
538
  data: errors2
495
- };
539
+ });
496
540
  events.push({
497
541
  id: eventId,
498
542
  event: "error",
@@ -511,11 +555,10 @@ class EventStreamConnection {
511
555
  return;
512
556
  }
513
557
  const errors = this.validationErrors(data);
514
- const errorResponse = {
515
- statusCode: 500,
516
- statusMessage: "Failed to serialize response. Response does not match specified schema.",
558
+ const errorResponse = defineError(500, {
559
+ message: "Failed to serialize response. Response does not match specified schema.",
517
560
  data: errors
518
- };
561
+ });
519
562
  await this.eventStream.push({
520
563
  id: eventId,
521
564
  event: "error",
@@ -601,9 +644,12 @@ function registerEventStreamRpc(router, path, procedure, opts) {
601
644
  validator: responseValidator?.validate ?? function() {
602
645
  return true;
603
646
  },
604
- serializer: responseValidator?.serialize ?? function(_) {
605
- return "";
606
- },
647
+ serializer: (
648
+ // eslint-disable-next-line @typescript-eslint/unbound-method
649
+ responseValidator?.serialize ?? function(_) {
650
+ return "";
651
+ }
652
+ ),
607
653
  validationErrors(input) {
608
654
  if (procedure.response) {
609
655
  return a.errors(procedure.response, input);
@@ -620,7 +666,7 @@ function registerEventStreamRpc(router, path, procedure, opts) {
620
666
  stream.send();
621
667
  }
622
668
  } catch (err) {
623
- await handleH3Error(err, event, opts.onError);
669
+ await handleH3Error(err, event, opts.onError, opts.debug ?? false);
624
670
  }
625
671
  return "";
626
672
  });
@@ -687,7 +733,7 @@ function handleRoute(router, method, route, opts) {
687
733
  ", "
688
734
  )}]`;
689
735
  throw defineError(400, {
690
- statusMessage: message
736
+ message
691
737
  });
692
738
  }
693
739
  event.context.query = parsedQuery.value;
@@ -711,7 +757,7 @@ function handleRoute(router, method, route, opts) {
711
757
  }
712
758
  }
713
759
  throw defineError(400, {
714
- statusMessage: `Invalid request body. Affected properties [${errorParts.join(
760
+ message: `Invalid request body. Affected properties [${errorParts.join(
715
761
  ", "
716
762
  )}]`,
717
763
  data: parsedBody.error
@@ -739,7 +785,7 @@ function handleRoute(router, method, route, opts) {
739
785
  await route.postHandler(event);
740
786
  }
741
787
  } catch (err) {
742
- await handleH3Error(err, event, opts.onError);
788
+ await handleH3Error(err, event, opts.onError, opts.debug ?? false);
743
789
  }
744
790
  return "";
745
791
  });
@@ -813,32 +859,39 @@ class ArriApp {
813
859
  __publicField(this, "__isArri__", true);
814
860
  __publicField(this, "h3App");
815
861
  __publicField(this, "h3Router", createRouter());
816
- __publicField(this, "rpcDefinitionPath");
817
- __publicField(this, "rpcRoutePrefix");
862
+ __publicField(this, "_rpcDefinitionPath");
863
+ __publicField(this, "_rpcRoutePrefix");
818
864
  __publicField(this, "appInfo");
819
- __publicField(this, "procedures", {});
820
- __publicField(this, "models", {});
821
- __publicField(this, "middlewares", []);
822
- __publicField(this, "onRequest");
823
- __publicField(this, "onAfterResponse");
824
- __publicField(this, "onBeforeResponse");
825
- __publicField(this, "onError");
865
+ __publicField(this, "_procedures", {});
866
+ __publicField(this, "_models", {});
867
+ __publicField(this, "_middlewares", []);
868
+ __publicField(this, "_onRequest");
869
+ __publicField(this, "_onAfterResponse");
870
+ __publicField(this, "_onBeforeResponse");
871
+ __publicField(this, "_onError");
872
+ __publicField(this, "_debug");
873
+ __publicField(this, "definitionPath");
826
874
  this.appInfo = opts?.appInfo;
827
875
  this.h3App = createApp({
828
876
  debug: opts?.debug
829
877
  });
830
- this.onRequest = opts.onRequest;
831
- this.onError = opts.onError;
832
- this.onAfterResponse = opts.onAfterResponse;
833
- this.onBeforeResponse = opts.onBeforeResponse;
834
- this.rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
835
- this.rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
878
+ this._debug = opts.debug ?? false;
879
+ this._onRequest = opts.onRequest;
880
+ this._onError = opts.onError;
881
+ this._onAfterResponse = opts.onAfterResponse;
882
+ this._onBeforeResponse = opts.onBeforeResponse;
883
+ this._rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
884
+ this._rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
836
885
  this.h3App.use(this.h3Router);
886
+ this.definitionPath = this._rpcRoutePrefix ? `/${this._rpcRoutePrefix}/${this._rpcDefinitionPath}`.split("//").join("/") : `/${this._rpcDefinitionPath}`;
837
887
  this.h3Router.get(
838
- this.rpcRoutePrefix ? `/${this.rpcRoutePrefix}/${this.rpcDefinitionPath}`.split("//").join("/") : `/${this.rpcDefinitionPath}`,
888
+ this.definitionPath,
839
889
  eventHandler(() => this.getAppDefinition())
840
890
  );
841
891
  if (process.env.ARRI_DEV_MODE === "true") {
892
+ consola.info(
893
+ `Arri definition available at \`http://<host>${this.definitionPath}\``
894
+ );
842
895
  this.h3Router.get(
843
896
  DEV_DEFINITION_ENDPOINT,
844
897
  eventHandler(() => this.getAppDefinition())
@@ -850,22 +903,16 @@ class ArriApp {
850
903
  setResponseStatus(event, 404);
851
904
  const error = defineError(404);
852
905
  try {
853
- if (this.onRequest) {
854
- await this.onRequest(event);
906
+ if (this._onRequest) {
907
+ await this._onRequest(event);
855
908
  }
856
909
  } catch (err) {
857
- await handleH3Error(err, event, this.onError);
910
+ await handleH3Error(err, event, this._onError, this._debug);
858
911
  }
859
912
  if (event.handled) {
860
913
  return;
861
914
  }
862
- if (this.onError) {
863
- await this.onError(error, event);
864
- }
865
- if (event.handled) {
866
- return;
867
- }
868
- sendError(event, error);
915
+ return handleH3Error(error, event, this._onError, this._debug);
869
916
  })
870
917
  );
871
918
  }
@@ -880,11 +927,11 @@ class ArriApp {
880
927
  this.registerModels(input.getModels());
881
928
  return;
882
929
  }
883
- this.middlewares.push(input);
930
+ this._middlewares.push(input);
884
931
  }
885
932
  rpc(procedure) {
886
- const path = procedure.path ?? getRpcPath(procedure.name, this.rpcRoutePrefix);
887
- this.procedures[procedure.name] = createHttpRpcDefinition(
933
+ const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
934
+ this._procedures[procedure.name] = createHttpRpcDefinition(
888
935
  procedure.name,
889
936
  path,
890
937
  procedure
@@ -892,45 +939,48 @@ class ArriApp {
892
939
  if (isRpcParamSchema(procedure.params)) {
893
940
  const paramName = getRpcParamName(procedure.name, procedure);
894
941
  if (paramName) {
895
- this.models[paramName] = procedure.params;
942
+ this._models[paramName] = procedure.params;
896
943
  }
897
944
  }
898
945
  if (isRpcParamSchema(procedure.response)) {
899
946
  const responseName = getRpcResponseName(procedure.name, procedure);
900
947
  if (responseName) {
901
- this.models[responseName] = procedure.response;
948
+ this._models[responseName] = procedure.response;
902
949
  }
903
950
  }
904
951
  if (isEventStreamRpc(procedure)) {
905
952
  registerEventStreamRpc(this.h3Router, path, procedure, {
906
- middleware: this.middlewares,
907
- onRequest: this.onRequest,
908
- onError: this.onError,
909
- onAfterResponse: this.onAfterResponse,
910
- onBeforeResponse: this.onBeforeResponse
953
+ middleware: this._middlewares,
954
+ onRequest: this._onRequest,
955
+ onError: this._onError,
956
+ onAfterResponse: this._onAfterResponse,
957
+ onBeforeResponse: this._onBeforeResponse,
958
+ debug: this._debug
911
959
  });
912
960
  return;
913
961
  }
914
962
  registerRpc(this.h3Router, path, procedure, {
915
- middleware: this.middlewares,
916
- onRequest: this.onRequest,
917
- onError: this.onError,
918
- onAfterResponse: this.onAfterResponse,
919
- onBeforeResponse: this.onBeforeResponse
963
+ middleware: this._middlewares,
964
+ onRequest: this._onRequest,
965
+ onError: this._onError,
966
+ onAfterResponse: this._onAfterResponse,
967
+ onBeforeResponse: this._onBeforeResponse,
968
+ debug: this._debug
920
969
  });
921
970
  }
922
971
  route(route) {
923
972
  registerRoute(this.h3Router, route, {
924
- middleware: this.middlewares,
925
- onRequest: this.onRequest,
926
- onError: this.onError,
927
- onAfterResponse: this.onAfterResponse,
928
- onBeforeResponse: this.onBeforeResponse
973
+ middleware: this._middlewares,
974
+ onRequest: this._onRequest,
975
+ onError: this._onError,
976
+ onAfterResponse: this._onAfterResponse,
977
+ onBeforeResponse: this._onBeforeResponse,
978
+ debug: this._debug
929
979
  });
930
980
  }
931
981
  registerModels(models) {
932
982
  for (const key of Object.keys(models)) {
933
- this.models[key] = models[key];
983
+ this._models[key] = models[key];
934
984
  }
935
985
  }
936
986
  getAppDefinition() {
@@ -938,10 +988,10 @@ class ArriApp {
938
988
  arriSchemaVersion: SCHEMA_VERSION,
939
989
  info: this.appInfo,
940
990
  procedures: {},
941
- models: this.models
991
+ models: this._models
942
992
  };
943
- for (const key of Object.keys(this.procedures)) {
944
- const rpc = this.procedures[key];
993
+ for (const key of Object.keys(this._procedures)) {
994
+ const rpc = this._procedures[key];
945
995
  appDef.procedures[key] = rpc;
946
996
  }
947
997
  return appDef;
@@ -1007,4 +1057,4 @@ function defineConfig(config) {
1007
1057
  };
1008
1058
  }
1009
1059
 
1010
- export { ArriApp as A, DEV_ENDPOINT_ROOT as D, ErrorResponse as E, DEV_DEFINITION_ENDPOINT as a, isRpc as b, createAppDefinition as c, defineRpc as d, createHttpRpcDefinition as e, getRpcParamName as f, getRpcPath as g, getRpcResponseName as h, isRpcParamSchema as i, defineError as j, errorResponseFromValidationErrors as k, handleH3Error as l, isArriConfig as m, isResolvedArriConfig as n, defaultConfig as o, defineConfig as p, ArriRouter as q, registerRpc as r, defineRoute as s, registerRoute as t, handleRoute as u, validateRpcRequestInput as v, defineEventStreamRpc as w, isEventStreamRpc as x, EventStreamConnection as y, registerEventStreamRpc as z };
1060
+ export { ArriApp as A, registerEventStreamRpc as B, DEV_ENDPOINT_ROOT as D, EventStreamConnection as E, DEV_DEFINITION_ENDPOINT as a, isRpc as b, createAppDefinition as c, defineRpc as d, createHttpRpcDefinition as e, getRpcParamName as f, getRpcPath as g, getRpcResponseName as h, isRpcParamSchema as i, ArriServerError as j, ArriServerErrorResponse as k, defineError as l, errorResponseFromValidationErrors as m, handleH3Error as n, isArriConfig as o, isResolvedArriConfig as p, defaultConfig as q, registerRpc as r, defineConfig as s, ArriRouter as t, defineRoute as u, validateRpcRequestInput as v, registerRoute as w, handleRoute as x, defineEventStreamRpc as y, isEventStreamRpc as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arri",
3
- "version": "0.34.0",
3
+ "version": "0.36.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -43,10 +43,10 @@
43
43
  "prettier": "^3.2.5",
44
44
  "scule": "^1.3.0",
45
45
  "uncrypto": "^0.1.3",
46
- "arri-codegen-dart": "0.34.0",
47
- "arri-codegen-ts": "0.34.0",
48
- "arri-validate": "0.34.0",
49
- "arri-codegen-utils": "0.34.0"
46
+ "arri-codegen-utils": "0.36.1",
47
+ "arri-validate": "0.36.1",
48
+ "arri-codegen-ts": "0.36.1",
49
+ "arri-codegen-dart": "0.36.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/degit": "^2.8.6",