arri 0.36.1 → 0.37.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.
package/dist/index.mjs CHANGED
@@ -1,7 +1,6 @@
1
- export { A as ArriApp, t as ArriRouter, j as ArriServerError, k as ArriServerErrorResponse, a as DEV_DEFINITION_ENDPOINT, D as DEV_ENDPOINT_ROOT, E as EventStreamConnection, c as createAppDefinition, e as createHttpRpcDefinition, q as defaultConfig, s as defineConfig, l as defineError, y as defineEventStreamRpc, u as defineRoute, d as defineRpc, m as errorResponseFromValidationErrors, f as getRpcParamName, g as getRpcPath, h as getRpcResponseName, n as handleH3Error, x as handleRoute, o as isArriConfig, z as isEventStreamRpc, p as isResolvedArriConfig, b as isRpc, i as isRpcParamSchema, B as registerEventStreamRpc, w as registerRoute, r as registerRpc, v as validateRpcRequestInput } from './shared/arri.b1ff441a.mjs';
1
+ export { A as ArriApp, t as ArriRouter, j as ArriServerError, k as ArriServerErrorResponse, a as DEV_DEFINITION_ENDPOINT, D as DEV_ENDPOINT_ROOT, E as EventStreamConnection, W as WsPeer, c as createAppDefinition, e as createHttpRpcDefinition, G as createWsRpcDefinition, q as defaultConfig, s as defineConfig, l as defineError, y as defineEventStreamRpc, u as defineRoute, d as defineRpc, C as defineWebsocketRpc, m as errorResponseFromValidationErrors, f as getRpcParamName, g as getRpcPath, h as getRpcResponseName, n as handleH3Error, x as handleRoute, o as isArriConfig, z as isEventStreamRpc, p as isResolvedArriConfig, b as isRpc, i as isRpcParamSchema, B as registerEventStreamRpc, w as registerRoute, r as registerRpc, F as registerWebsocketRpc, v as validateRpcRequestInput } from './shared/arri.37a5d932.mjs';
2
2
  export * from 'h3';
3
3
  import 'arri-codegen-utils';
4
- import 'consola';
5
4
  import 'arri-validate';
6
5
  import 'h3-sse';
7
6
  import 'scule';
@@ -1,21 +1,20 @@
1
1
  import { isRpcHttpMethod, removeDisallowedChars, SCHEMA_VERSION } from 'arri-codegen-utils';
2
- import consola from 'consola';
3
- import { isError, setResponseStatus, setResponseHeader, send, eventHandler, isPreflightRequest, readRawBody, getValidatedQuery, defineEventHandler, getQuery, setHeader, createRouter, createApp } from 'h3';
2
+ import { isError, setResponseStatus, setResponseHeader, send, eventHandler, isPreflightRequest, readRawBody, getValidatedQuery, defineEventHandler, getQuery, setHeader, defineWebSocketHandler, createRouter, createApp } from 'h3';
4
3
  import { a, isAObjectSchema, isADiscriminatorSchema } from 'arri-validate';
5
4
  import { createEventStream } from 'h3-sse';
6
5
  import { kebabCase, pascalCase } from 'scule';
7
6
 
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);
7
+ var __defProp$4 = Object.defineProperty;
8
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __publicField$4 = (obj, key, value) => {
10
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
12
11
  return value;
13
12
  };
14
13
  class ArriServerError extends Error {
15
14
  constructor(err) {
16
15
  super(err.message);
17
- __publicField$3(this, "code");
18
- __publicField$3(this, "data");
16
+ __publicField$4(this, "code");
17
+ __publicField$4(this, "data");
19
18
  this.code = err.code;
20
19
  this.data = err.data;
21
20
  if (err.stack) {
@@ -261,6 +260,7 @@ function isRpc(input) {
261
260
  return typeof input === "object" && input !== null && "method" in input && isRpcHttpMethod(input.method) && "handler" in input && typeof input.handler === "function";
262
261
  }
263
262
  function defineRpc(config) {
263
+ config.transport = "http";
264
264
  return config;
265
265
  }
266
266
  function createHttpRpcDefinition(rpcName, httpPath, procedure) {
@@ -472,17 +472,18 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
472
472
  }
473
473
  }
474
474
 
475
- var __defProp$2 = Object.defineProperty;
476
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
477
- var __publicField$2 = (obj, key, value) => {
478
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
475
+ var __defProp$3 = Object.defineProperty;
476
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
477
+ var __publicField$3 = (obj, key, value) => {
478
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
479
479
  return value;
480
480
  };
481
481
  function defineEventStreamRpc(config) {
482
482
  return {
483
483
  ...config,
484
484
  method: config.method ?? "get",
485
- isEventStream: true
485
+ isEventStream: true,
486
+ transport: "http"
486
487
  };
487
488
  }
488
489
  function isEventStreamRpc(input) {
@@ -490,14 +491,14 @@ function isEventStreamRpc(input) {
490
491
  }
491
492
  class EventStreamConnection {
492
493
  constructor(event, opts) {
493
- __publicField$2(this, "lastEventId");
494
- __publicField$2(this, "validationErrors");
495
- __publicField$2(this, "validator");
496
- __publicField$2(this, "serializer");
494
+ __publicField$3(this, "lastEventId");
495
+ __publicField$3(this, "validationErrors");
496
+ __publicField$3(this, "validator");
497
+ __publicField$3(this, "serializer");
497
498
  // for some reason Rollup cannot output DTS when this is set to NodeJS.Timeout
498
- __publicField$2(this, "pingInterval");
499
- __publicField$2(this, "pingIntervalMs");
500
- __publicField$2(this, "eventStream");
499
+ __publicField$3(this, "pingInterval");
500
+ __publicField$3(this, "pingIntervalMs");
501
+ __publicField$3(this, "eventStream");
501
502
  this.eventStream = createEventStream(event);
502
503
  this.lastEventId = this.eventStream.lastEventId;
503
504
  this.pingIntervalMs = opts.pingInterval ?? 6e4;
@@ -811,19 +812,24 @@ function handleRoute(router, method, route, opts) {
811
812
  }
812
813
  }
813
814
 
814
- var __defProp$1 = Object.defineProperty;
815
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
816
- var __publicField$1 = (obj, key, value) => {
817
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
815
+ var __defProp$2 = Object.defineProperty;
816
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
817
+ var __publicField$2 = (obj, key, value) => {
818
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
818
819
  return value;
819
820
  };
820
821
  class ArriRouter {
821
822
  constructor() {
822
- __publicField$1(this, "procedures", []);
823
- __publicField$1(this, "routes", []);
824
- __publicField$1(this, "models", {});
823
+ __publicField$2(this, "procedures", []);
824
+ __publicField$2(this, "routes", []);
825
+ __publicField$2(this, "models", {});
825
826
  }
826
827
  rpc(procedure) {
828
+ procedure.transport = "http";
829
+ this.procedures.push(procedure);
830
+ }
831
+ wsRpc(procedure) {
832
+ procedure.transport = "ws";
827
833
  this.procedures.push(procedure);
828
834
  }
829
835
  route(route) {
@@ -845,6 +851,145 @@ class ArriRouter {
845
851
  }
846
852
  }
847
853
 
854
+ var __defProp$1 = Object.defineProperty;
855
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
856
+ var __publicField$1 = (obj, key, value) => {
857
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
858
+ return value;
859
+ };
860
+ class WsPeer {
861
+ constructor(peer, opts) {
862
+ __publicField$1(this, "_peer");
863
+ __publicField$1(this, "_validator");
864
+ __publicField$1(this, "context");
865
+ __publicField$1(this, "url");
866
+ this._peer = peer;
867
+ this._validator = opts.validator;
868
+ this.url = peer.url;
869
+ this.context = opts.context;
870
+ }
871
+ send(data) {
872
+ if (!this._validator) {
873
+ return;
874
+ }
875
+ if (!this._validator.validate(data)) {
876
+ return;
877
+ }
878
+ const payload = this._validator.serialize(data);
879
+ return this._peer.send(`type: message
880
+ data: ${payload}`);
881
+ }
882
+ sendError(err) {
883
+ return this._peer.send(`type: error
884
+ data: ${JSON.stringify(err)}`);
885
+ }
886
+ close() {
887
+ throw new Error("close() is not yet implemented on WsPeer");
888
+ }
889
+ subscribe(channel) {
890
+ this._peer.subscribe(channel);
891
+ }
892
+ unsubscribe(channel) {
893
+ this._peer.unsubscribe(channel);
894
+ }
895
+ publish(channel, message) {
896
+ if (!this._validator) {
897
+ return;
898
+ }
899
+ if (!this._validator.validate(message)) {
900
+ const err = {
901
+ code: 500,
902
+ message: `Error serializing message on server. The payload doesn't match the specified schema.`,
903
+ data: {
904
+ payload: message
905
+ }
906
+ };
907
+ this.sendError(err);
908
+ return;
909
+ }
910
+ const payload = this._validator.serialize(message);
911
+ this._peer.publish(channel, payload);
912
+ }
913
+ readyState() {
914
+ return this._peer.readyState;
915
+ }
916
+ }
917
+ function defineWebsocketRpc(def) {
918
+ def.transport = "ws";
919
+ return def;
920
+ }
921
+ function registerWebsocketRpc(router, path, rpc) {
922
+ let responseValidator;
923
+ let paramValidator;
924
+ try {
925
+ responseValidator = rpc.response ? a.compile(rpc.response) : void 0;
926
+ } catch (err) {
927
+ console.error("ERROR COMPILING VALIDATOR", err);
928
+ }
929
+ try {
930
+ paramValidator = rpc.params ? a.compile(rpc.params) : void 0;
931
+ } catch (err) {
932
+ console.error("ERROR COMPILING PARAMS", err);
933
+ }
934
+ const handler = defineWebSocketHandler({
935
+ upgrade(req) {
936
+ },
937
+ open(peer) {
938
+ const urlParts = peer.url.split("?");
939
+ const context = {
940
+ rpcName: rpc.name,
941
+ clientAddress: peer.addr
942
+ };
943
+ if (urlParts.length > 1) {
944
+ urlParts.shift();
945
+ const queryStr = new URLSearchParams(urlParts.join("?"));
946
+ const query = {};
947
+ for (const [key, val] of queryStr.entries()) {
948
+ query[key] = val;
949
+ }
950
+ context.queryParams = query;
951
+ }
952
+ const wsPeer = new WsPeer(peer, {
953
+ validator: responseValidator,
954
+ context
955
+ });
956
+ peer.ctx.__wsPeer = wsPeer;
957
+ rpc.handler.onOpen(peer.ctx.__wsPeer);
958
+ },
959
+ message(peer, message) {
960
+ if (!paramValidator) {
961
+ return;
962
+ }
963
+ const data = paramValidator.safeParse(message.text());
964
+ if (!data.success) {
965
+ const errorResponse = {
966
+ code: 400,
967
+ message: data.error.message,
968
+ data: data.error.errors,
969
+ stack: data.error.stack?.split("\n")
970
+ };
971
+ peer.ctx.__wsPeer.sendError(errorResponse);
972
+ return;
973
+ }
974
+ rpc.handler.onMessage(peer.ctx.__wsPeer, data.value);
975
+ },
976
+ close(peer, details) {
977
+ rpc.handler.onClose(peer.ctx.__wsPeer, details);
978
+ }
979
+ });
980
+ router.use(path, handler);
981
+ }
982
+ function createWsRpcDefinition(rpcName, path, rpc) {
983
+ return {
984
+ transport: "ws",
985
+ path,
986
+ params: getRpcParamName(rpcName, rpc),
987
+ response: getRpcResponseName(rpcName, rpc),
988
+ isDeprecated: rpc.isDeprecated,
989
+ description: rpc.description
990
+ };
991
+ }
992
+
848
993
  var __defProp = Object.defineProperty;
849
994
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
850
995
  var __publicField = (obj, key, value) => {
@@ -888,10 +1033,27 @@ class ArriApp {
888
1033
  this.definitionPath,
889
1034
  eventHandler(() => this.getAppDefinition())
890
1035
  );
1036
+ if (!opts.disableDefaultRoute) {
1037
+ this.route({
1038
+ method: ["get", "head"],
1039
+ path: "/",
1040
+ handler: (_) => {
1041
+ let schemaPath;
1042
+ if (this._rpcRoutePrefix) {
1043
+ schemaPath = `/${this._rpcRoutePrefix}/${this._rpcDefinitionPath}`;
1044
+ } else {
1045
+ schemaPath = `/${this._rpcDefinitionPath}`;
1046
+ }
1047
+ return {
1048
+ title: this.appInfo?.title ?? "Arri-RPC Server",
1049
+ description: this.appInfo?.description ?? "This server utilizes Arri-RPC. Visit the schema path to see all of the available procedures.",
1050
+ schemaPath,
1051
+ ...this.appInfo
1052
+ };
1053
+ }
1054
+ });
1055
+ }
891
1056
  if (process.env.ARRI_DEV_MODE === "true") {
892
- consola.info(
893
- `Arri definition available at \`http://<host>${this.definitionPath}\``
894
- );
895
1057
  this.h3Router.get(
896
1058
  DEV_DEFINITION_ENDPOINT,
897
1059
  eventHandler(() => this.getAppDefinition())
@@ -922,7 +1084,11 @@ class ArriApp {
922
1084
  this.route(route);
923
1085
  }
924
1086
  for (const rpc of input.getProcedures()) {
925
- this.rpc(rpc);
1087
+ if (rpc.transport === "http") {
1088
+ this.rpc(rpc);
1089
+ } else {
1090
+ this.wsRpc(rpc);
1091
+ }
926
1092
  }
927
1093
  this.registerModels(input.getModels());
928
1094
  return;
@@ -930,26 +1096,24 @@ class ArriApp {
930
1096
  this._middlewares.push(input);
931
1097
  }
932
1098
  rpc(procedure) {
933
- const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
934
- this._procedures[procedure.name] = createHttpRpcDefinition(
935
- procedure.name,
936
- path,
937
- procedure
938
- );
939
- if (isRpcParamSchema(procedure.params)) {
940
- const paramName = getRpcParamName(procedure.name, procedure);
1099
+ procedure.transport = "http";
1100
+ const p = procedure;
1101
+ const path = p.path ?? getRpcPath(p.name, this._rpcRoutePrefix);
1102
+ this._procedures[p.name] = createHttpRpcDefinition(p.name, path, p);
1103
+ if (isRpcParamSchema(p.params)) {
1104
+ const paramName = getRpcParamName(p.name, p);
941
1105
  if (paramName) {
942
- this._models[paramName] = procedure.params;
1106
+ this._models[paramName] = p.params;
943
1107
  }
944
1108
  }
945
- if (isRpcParamSchema(procedure.response)) {
946
- const responseName = getRpcResponseName(procedure.name, procedure);
1109
+ if (isRpcParamSchema(p.response)) {
1110
+ const responseName = getRpcResponseName(p.name, p);
947
1111
  if (responseName) {
948
- this._models[responseName] = procedure.response;
1112
+ this._models[responseName] = p.response;
949
1113
  }
950
1114
  }
951
- if (isEventStreamRpc(procedure)) {
952
- registerEventStreamRpc(this.h3Router, path, procedure, {
1115
+ if (isEventStreamRpc(p)) {
1116
+ registerEventStreamRpc(this.h3Router, path, p, {
953
1117
  middleware: this._middlewares,
954
1118
  onRequest: this._onRequest,
955
1119
  onError: this._onError,
@@ -959,7 +1123,7 @@ class ArriApp {
959
1123
  });
960
1124
  return;
961
1125
  }
962
- registerRpc(this.h3Router, path, procedure, {
1126
+ registerRpc(this.h3Router, path, p, {
963
1127
  middleware: this._middlewares,
964
1128
  onRequest: this._onRequest,
965
1129
  onError: this._onError,
@@ -968,6 +1132,29 @@ class ArriApp {
968
1132
  debug: this._debug
969
1133
  });
970
1134
  }
1135
+ wsRpc(procedure) {
1136
+ procedure.transport = "ws";
1137
+ const p = procedure;
1138
+ const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
1139
+ this._procedures[procedure.name] = createWsRpcDefinition(
1140
+ procedure.name,
1141
+ path,
1142
+ p
1143
+ );
1144
+ if (isRpcParamSchema(procedure.params)) {
1145
+ const paramName = getRpcParamName(procedure.name, p);
1146
+ if (paramName) {
1147
+ this._models[paramName] = procedure.params;
1148
+ }
1149
+ }
1150
+ if (isRpcParamSchema(procedure.response)) {
1151
+ const responseName = getRpcResponseName(procedure.name, p);
1152
+ if (responseName) {
1153
+ this._models[responseName] = procedure.response;
1154
+ }
1155
+ }
1156
+ registerWebsocketRpc(this.h3Router, path, p);
1157
+ }
971
1158
  route(route) {
972
1159
  registerRoute(this.h3Router, route, {
973
1160
  middleware: this._middlewares,
@@ -1057,4 +1244,4 @@ function defineConfig(config) {
1057
1244
  };
1058
1245
  }
1059
1246
 
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 };
1247
+ export { ArriApp as A, registerEventStreamRpc as B, defineWebsocketRpc as C, DEV_ENDPOINT_ROOT as D, EventStreamConnection as E, registerWebsocketRpc as F, createWsRpcDefinition as G, WsPeer as W, 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 };