arri 0.0.28 → 0.0.30

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,5 +1,5 @@
1
1
  import { Type, TypeGuard } from '@sinclair/typebox';
2
- import { createError, eventHandler, isPreflightRequest, readValidatedBody, getValidatedQuery, setResponseHeader, send, createRouter, createApp, sendError } from 'h3';
2
+ import { createError, eventHandler, isPreflightRequest, readValidatedBody, getValidatedQuery, setResponseHeader, send, createRouter, createApp, getQuery, readBody, sendError } from 'h3';
3
3
  import { ValueErrorType } from '@sinclair/typebox/errors';
4
4
  import { Value } from '@sinclair/typebox/value';
5
5
 
@@ -519,95 +519,110 @@ function getRpcResponseDefinition(rpcName, procedure) {
519
519
  }
520
520
  return name;
521
521
  }
522
- function registerRpc(router, path, procedure, middleware) {
522
+ function registerRpc(router, path, procedure, middleware, opts) {
523
523
  const httpMethod = procedure.method ?? "post";
524
524
  const handler = eventHandler(async (event) => {
525
525
  const context = {
526
- event
526
+ type: "procedure",
527
+ params: void 0
527
528
  };
528
529
  if (isPreflightRequest(event)) {
529
530
  return "ok";
530
531
  }
531
- if (middleware.length) {
532
- await Promise.all(middleware.map((m) => m(context)));
533
- }
534
- if (procedure.params) {
535
- switch (httpMethod) {
536
- case "get":
537
- case "head": {
538
- const parsedParams = await getValidatedQuery(
539
- event,
540
- typeboxSafeValidate(procedure.params, true)
541
- );
542
- if (!parsedParams.success) {
543
- const errorParts = [];
544
- for (const err of parsedParams.errors) {
545
- const propName = err.path.split("/");
546
- propName.shift();
547
- if (!errorParts.includes(propName.join("."))) {
548
- errorParts.push(propName.join("."));
532
+ try {
533
+ if (middleware.length) {
534
+ await Promise.all(middleware.map((m) => m(context, event)));
535
+ }
536
+ if (procedure.params) {
537
+ switch (httpMethod) {
538
+ case "get":
539
+ case "head": {
540
+ const parsedParams = await getValidatedQuery(
541
+ event,
542
+ typeboxSafeValidate(procedure.params, true)
543
+ );
544
+ if (!parsedParams.success) {
545
+ const errorParts = [];
546
+ for (const err of parsedParams.errors) {
547
+ const propName = err.path.split("/");
548
+ propName.shift();
549
+ if (!errorParts.includes(propName.join("."))) {
550
+ errorParts.push(propName.join("."));
551
+ }
549
552
  }
553
+ throw defineError(400, {
554
+ statusMessage: `Missing or invalid url query parameters: [${errorParts.join(
555
+ ","
556
+ )}]`,
557
+ data: parsedParams.errors
558
+ });
550
559
  }
551
- throw defineError(400, {
552
- statusMessage: `Missing or invalid url query parameters: [${errorParts.join(
553
- ","
554
- )}]`,
555
- data: parsedParams.errors
556
- });
560
+ context.params = parsedParams.value;
561
+ break;
557
562
  }
558
- context.params = parsedParams.value;
559
- break;
560
- }
561
- case "delete":
562
- case "patch":
563
- case "post":
564
- case "put": {
565
- const parsedParams = await readValidatedBody(
566
- event,
567
- typeboxSafeValidate(procedure.params)
568
- );
569
- if (!parsedParams.success) {
570
- let isObjectError = false;
571
- const errorParts = [];
572
- for (const err of parsedParams.errors) {
573
- if (err.type === ValueErrorType.Object) {
574
- isObjectError = true;
563
+ case "delete":
564
+ case "patch":
565
+ case "post":
566
+ case "put": {
567
+ const parsedParams = await readValidatedBody(
568
+ event,
569
+ typeboxSafeValidate(procedure.params)
570
+ );
571
+ if (!parsedParams.success) {
572
+ let isObjectError = false;
573
+ const errorParts = [];
574
+ for (const err of parsedParams.errors) {
575
+ if (err.type === ValueErrorType.Object) {
576
+ isObjectError = true;
577
+ }
578
+ const propName = err.path.split("/");
579
+ propName.shift();
580
+ if (!errorParts.includes(propName.join("."))) {
581
+ errorParts.push(propName.join("."));
582
+ }
575
583
  }
576
- const propName = err.path.split("/");
577
- propName.shift();
578
- if (!errorParts.includes(propName.join("."))) {
579
- errorParts.push(propName.join("."));
584
+ if (isObjectError) {
585
+ throw defineError(400, {
586
+ statusMessage: `Invalid request body. Expected object.`
587
+ });
580
588
  }
581
- }
582
- if (isObjectError) {
583
589
  throw defineError(400, {
584
- statusMessage: `Invalid request body. Expected object.`
590
+ statusMessage: `Invalid request body. Affected properties [${errorParts.join(
591
+ ", "
592
+ )}]`,
593
+ data: parsedParams.errors
585
594
  });
586
595
  }
587
- throw defineError(400, {
588
- statusMessage: `Invalid request body. Affected properties [${errorParts.join(
589
- ", "
590
- )}]`,
591
- data: parsedParams.errors
592
- });
596
+ context.params = parsedParams.value;
597
+ break;
593
598
  }
594
- context.params = parsedParams.value;
595
- break;
599
+ default:
600
+ break;
596
601
  }
597
602
  }
598
- }
599
- const response = await procedure.handler(context);
600
- if (typeof response === "object") {
601
- setResponseHeader(event, "Content-Type", "application/json");
602
- await send(event, JSON.stringify(response));
603
- } else {
604
- await send(event, response);
605
- }
606
- if (procedure.postHandler) {
603
+ const response = await procedure.handler(context, event);
607
604
  context.response = response;
608
- await procedure.postHandler(context);
605
+ if (opts.onBeforeResponse) {
606
+ await opts.onBeforeResponse(context, event);
607
+ }
608
+ if (typeof response === "object") {
609
+ setResponseHeader(event, "Content-Type", "application/json");
610
+ await send(event, JSON.stringify(response));
611
+ } else {
612
+ await send(event, response ?? "");
613
+ }
614
+ if (opts.onAfterResponse) {
615
+ await opts.onAfterResponse(context, event);
616
+ }
617
+ if (procedure.postHandler) {
618
+ await procedure.postHandler(context, event);
619
+ }
620
+ } catch (err) {
621
+ if (opts.onError) {
622
+ await opts.onError(err, context, event);
623
+ }
609
624
  }
610
- return null;
625
+ return "";
611
626
  });
612
627
  switch (httpMethod) {
613
628
  case "get":
@@ -636,55 +651,70 @@ function defineRoute(config) {
636
651
  return config;
637
652
  }
638
653
  const defineMiddleware = (middleware) => middleware;
639
- function registerRoute(router, route, middleware, prefix) {
640
- const handler = async (event) => {
654
+ function registerRoute(router, route, middleware, prefix, opts) {
655
+ const handler = eventHandler(async (event) => {
641
656
  const context = {
642
- event
657
+ type: "route",
658
+ params: event.context.params,
659
+ query: void 0,
660
+ body: void 0
643
661
  };
644
- if (middleware.length) {
645
- for (const m of middleware) {
646
- await m(context);
662
+ try {
663
+ if (middleware.length) {
664
+ for (const m of middleware) {
665
+ await m(context, event);
666
+ }
647
667
  }
648
- }
649
- if (route.query) {
650
- const result = await getValidatedQuery(
651
- event,
652
- typeboxSafeValidate(route.query)
653
- );
654
- if (!result.success) {
655
- throw errorResponseFromValidationErrors(
656
- result.errors,
657
- "Missing or invalid query parameters"
668
+ if (route.query) {
669
+ const result = await getValidatedQuery(
670
+ event,
671
+ typeboxSafeValidate(route.query)
658
672
  );
673
+ if (!result.success) {
674
+ throw errorResponseFromValidationErrors(
675
+ result.errors,
676
+ "Missing or invalid query parameters"
677
+ );
678
+ }
679
+ context.query = result.value;
659
680
  }
660
- context.query = result.value;
661
- }
662
- if (route.body && route.method !== "get" && route.method !== "head") {
663
- const result = await readValidatedBody(
664
- event,
665
- typeboxSafeValidate(route.body)
666
- );
667
- if (!result.success) {
668
- throw errorResponseFromValidationErrors(
669
- result.errors,
670
- "Missing or invalid body parameters"
681
+ if (route.body && route.method !== "get" && route.method !== "head") {
682
+ const result = await readValidatedBody(
683
+ event,
684
+ typeboxSafeValidate(route.body)
671
685
  );
686
+ if (!result.success) {
687
+ throw errorResponseFromValidationErrors(
688
+ result.errors,
689
+ "Missing or invalid body parameters"
690
+ );
691
+ }
692
+ context.body = result.value;
672
693
  }
673
- context.body = result.value;
674
- }
675
- const response = await route.handler(context);
676
- if (typeof response === "object") {
677
- setResponseHeader(event, "Content-Type", "application/json");
678
- await send(event, JSON.stringify(response));
679
- } else {
680
- await send(event, response);
681
- }
682
- if (route.postHandler) {
694
+ const response = await route.handler(context, event);
683
695
  context.response = response;
684
- await route.postHandler(context);
696
+ if (opts?.onBeforeResponse) {
697
+ await opts.onBeforeResponse(context, event);
698
+ }
699
+ if (typeof response === "object") {
700
+ setResponseHeader(event, "Content-Type", "application/json");
701
+ await send(event, JSON.stringify(response));
702
+ } else {
703
+ await send(event, response ?? "");
704
+ }
705
+ if (opts?.onAfterResponse) {
706
+ await opts.onAfterResponse(context, event);
707
+ }
708
+ if (route.postHandler) {
709
+ await route.postHandler(context, event);
710
+ }
711
+ } catch (err) {
712
+ if (opts?.onError) {
713
+ await opts.onError(err, context, event);
714
+ }
685
715
  }
686
- return null;
687
- };
716
+ return "";
717
+ });
688
718
  const finalPath = (prefix ? `/${prefix}${route.path}` : route.path).split("//").join("/");
689
719
  switch (route.method) {
690
720
  case "get":
@@ -717,7 +747,7 @@ var __publicField = (obj, key, value) => {
717
747
  const DEV_ENDPOINT_ROOT = `/__arri_dev__`;
718
748
  const DEV_DEFINITION_ENDPOINT = `${DEV_ENDPOINT_ROOT}/definition`;
719
749
  class Arri {
720
- constructor(opts) {
750
+ constructor(opts = {}) {
721
751
  __publicField(this, "__isArri__", true);
722
752
  __publicField(this, "h3App");
723
753
  __publicField(this, "h3Router", createRouter());
@@ -727,36 +757,71 @@ class Arri {
727
757
  __publicField(this, "procedures", {});
728
758
  __publicField(this, "models", {});
729
759
  __publicField(this, "middlewares", []);
760
+ __publicField(this, "onAfterResponse");
761
+ __publicField(this, "onBeforeResponse");
762
+ __publicField(this, "onError");
730
763
  this.appInfo = opts?.appInfo;
731
764
  this.h3App = createApp({
732
765
  debug: opts?.debug,
733
- onAfterResponse: opts?.onAfterResponse,
734
- onBeforeResponse: opts?.onBeforeResponse,
735
- onError: async (err, event) => {
736
- if (opts?.onError) {
737
- await opts.onError(err, event);
738
- }
739
- sendError(event, err);
740
- },
741
- onRequest: async (event) => {
742
- if (opts?.onRequest) {
743
- await opts.onRequest(event);
744
- }
745
- }
766
+ onRequest: opts?.onRequest
746
767
  });
768
+ this.onError = opts.onError;
769
+ this.onAfterResponse = opts.onAfterResponse;
770
+ this.onBeforeResponse = opts.onBeforeResponse;
747
771
  this.rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
748
772
  this.rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
749
- this.h3Router.get(
750
- this.rpcRoutePrefix ? `/${this.rpcRoutePrefix}/${this.rpcDefinitionPath}`.split("//").join("/") : `/${this.rpcDefinitionPath}`,
751
- eventHandler((_) => this.getAppDefinition())
752
- );
753
773
  this.h3App.use(this.h3Router);
774
+ this.registerRoute({
775
+ path: this.rpcRoutePrefix ? `/${this.rpcRoutePrefix}/${this.rpcDefinitionPath}`.split("//").join("/") : `/${this.rpcDefinitionPath}`,
776
+ method: "get",
777
+ handler: () => this.getAppDefinition()
778
+ });
754
779
  if (process.env.ARRI_DEV_MODE === "true") {
755
- this.h3Router.get(
756
- DEV_DEFINITION_ENDPOINT,
757
- eventHandler((_) => this.getAppDefinition())
758
- );
780
+ this.registerRoute({
781
+ path: DEV_DEFINITION_ENDPOINT,
782
+ method: "get",
783
+ handler: () => this.getAppDefinition()
784
+ });
759
785
  }
786
+ this.h3Router.use(
787
+ "/**",
788
+ eventHandler(async (event) => {
789
+ const error = defineError(404);
790
+ const query = getQuery(event);
791
+ const disallowedBodyMethods = ["GET", "HEAD", "OPTION"];
792
+ const canBody = !disallowedBodyMethods.includes(event.method);
793
+ const context = {
794
+ type: "route",
795
+ params: event.context.params,
796
+ query,
797
+ // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
798
+ body: canBody ? await readBody(event).catch((_) => void 0) : void 0
799
+ };
800
+ try {
801
+ if (this.middlewares.length) {
802
+ for (const m of this.middlewares) {
803
+ await m(context, event);
804
+ }
805
+ }
806
+ } catch (_) {
807
+ }
808
+ if (this.onError) {
809
+ await this.onError(
810
+ error,
811
+ {
812
+ type: "route",
813
+ params: void 0,
814
+ query: void 0,
815
+ body: void 0
816
+ },
817
+ event
818
+ );
819
+ }
820
+ if (!event.handled) {
821
+ sendError(event, error);
822
+ }
823
+ })
824
+ );
760
825
  }
761
826
  registerMiddleware(middleware) {
762
827
  this.middlewares.push(middleware);
@@ -776,7 +841,11 @@ class Arri {
776
841
  this.models[responseName] = procedure.response;
777
842
  }
778
843
  }
779
- registerRpc(this.h3Router, path, procedure, this.middlewares);
844
+ registerRpc(this.h3Router, path, procedure, this.middlewares, {
845
+ onError: this.onError,
846
+ onAfterResponse: this.onAfterResponse,
847
+ onBeforeResponse: this.onBeforeResponse
848
+ });
780
849
  }
781
850
  registerRoute(route) {
782
851
  registerRoute(this.h3Router, route, this.middlewares);
@@ -1,6 +1,6 @@
1
1
  import { execSync } from 'child_process';
2
2
  import { writeFileSync } from 'fs';
3
- import { h as unflattenProcedures, i as isServiceDef, p as pascalCase, j as camelCase, a as isProcedureDef, d as isJsonSchemaObject, f as isJsonSchemaEnum, c as isJsonSchemaNullType, b as isJsonSchemaScalarType, e as isJsonSchemaRecord, g as isJsonSchemaArray } from './arri.74885d3a.mjs';
3
+ import { h as unflattenProcedures, i as isServiceDef, p as pascalCase, j as camelCase, a as isProcedureDef, d as isJsonSchemaObject, f as isJsonSchemaEnum, c as isJsonSchemaNullType, b as isJsonSchemaScalarType, e as isJsonSchemaRecord, g as isJsonSchemaArray } from './arri.7d8427d5.mjs';
4
4
 
5
5
  function defineClientGeneratorPlugin(plugin) {
6
6
  return plugin;