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.
@@ -1,27 +1,22 @@
1
1
  'use strict';
2
2
 
3
3
  const arriCodegenUtils = require('arri-codegen-utils');
4
- const consola = require('consola');
5
4
  const h3 = require('h3');
6
5
  const arriValidate = require('arri-validate');
7
6
  const h3Sse = require('h3-sse');
8
7
  const scule = require('scule');
9
8
 
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);
9
+ var __defProp$4 = Object.defineProperty;
10
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __publicField$4 = (obj, key, value) => {
12
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
18
13
  return value;
19
14
  };
20
15
  class ArriServerError extends Error {
21
16
  constructor(err) {
22
17
  super(err.message);
23
- __publicField$3(this, "code");
24
- __publicField$3(this, "data");
18
+ __publicField$4(this, "code");
19
+ __publicField$4(this, "data");
25
20
  this.code = err.code;
26
21
  this.data = err.data;
27
22
  if (err.stack) {
@@ -267,6 +262,7 @@ function isRpc(input) {
267
262
  return typeof input === "object" && input !== null && "method" in input && arriCodegenUtils.isRpcHttpMethod(input.method) && "handler" in input && typeof input.handler === "function";
268
263
  }
269
264
  function defineRpc(config) {
265
+ config.transport = "http";
270
266
  return config;
271
267
  }
272
268
  function createHttpRpcDefinition(rpcName, httpPath, procedure) {
@@ -478,17 +474,18 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
478
474
  }
479
475
  }
480
476
 
481
- var __defProp$2 = Object.defineProperty;
482
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
483
- var __publicField$2 = (obj, key, value) => {
484
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
477
+ var __defProp$3 = Object.defineProperty;
478
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
479
+ var __publicField$3 = (obj, key, value) => {
480
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
485
481
  return value;
486
482
  };
487
483
  function defineEventStreamRpc(config) {
488
484
  return {
489
485
  ...config,
490
486
  method: config.method ?? "get",
491
- isEventStream: true
487
+ isEventStream: true,
488
+ transport: "http"
492
489
  };
493
490
  }
494
491
  function isEventStreamRpc(input) {
@@ -496,14 +493,14 @@ function isEventStreamRpc(input) {
496
493
  }
497
494
  class EventStreamConnection {
498
495
  constructor(event, opts) {
499
- __publicField$2(this, "lastEventId");
500
- __publicField$2(this, "validationErrors");
501
- __publicField$2(this, "validator");
502
- __publicField$2(this, "serializer");
496
+ __publicField$3(this, "lastEventId");
497
+ __publicField$3(this, "validationErrors");
498
+ __publicField$3(this, "validator");
499
+ __publicField$3(this, "serializer");
503
500
  // for some reason Rollup cannot output DTS when this is set to NodeJS.Timeout
504
- __publicField$2(this, "pingInterval");
505
- __publicField$2(this, "pingIntervalMs");
506
- __publicField$2(this, "eventStream");
501
+ __publicField$3(this, "pingInterval");
502
+ __publicField$3(this, "pingIntervalMs");
503
+ __publicField$3(this, "eventStream");
507
504
  this.eventStream = h3Sse.createEventStream(event);
508
505
  this.lastEventId = this.eventStream.lastEventId;
509
506
  this.pingIntervalMs = opts.pingInterval ?? 6e4;
@@ -817,19 +814,24 @@ function handleRoute(router, method, route, opts) {
817
814
  }
818
815
  }
819
816
 
820
- var __defProp$1 = Object.defineProperty;
821
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
822
- var __publicField$1 = (obj, key, value) => {
823
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
817
+ var __defProp$2 = Object.defineProperty;
818
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
819
+ var __publicField$2 = (obj, key, value) => {
820
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
824
821
  return value;
825
822
  };
826
823
  class ArriRouter {
827
824
  constructor() {
828
- __publicField$1(this, "procedures", []);
829
- __publicField$1(this, "routes", []);
830
- __publicField$1(this, "models", {});
825
+ __publicField$2(this, "procedures", []);
826
+ __publicField$2(this, "routes", []);
827
+ __publicField$2(this, "models", {});
831
828
  }
832
829
  rpc(procedure) {
830
+ procedure.transport = "http";
831
+ this.procedures.push(procedure);
832
+ }
833
+ wsRpc(procedure) {
834
+ procedure.transport = "ws";
833
835
  this.procedures.push(procedure);
834
836
  }
835
837
  route(route) {
@@ -851,6 +853,145 @@ class ArriRouter {
851
853
  }
852
854
  }
853
855
 
856
+ var __defProp$1 = Object.defineProperty;
857
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
858
+ var __publicField$1 = (obj, key, value) => {
859
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
860
+ return value;
861
+ };
862
+ class WsPeer {
863
+ constructor(peer, opts) {
864
+ __publicField$1(this, "_peer");
865
+ __publicField$1(this, "_validator");
866
+ __publicField$1(this, "context");
867
+ __publicField$1(this, "url");
868
+ this._peer = peer;
869
+ this._validator = opts.validator;
870
+ this.url = peer.url;
871
+ this.context = opts.context;
872
+ }
873
+ send(data) {
874
+ if (!this._validator) {
875
+ return;
876
+ }
877
+ if (!this._validator.validate(data)) {
878
+ return;
879
+ }
880
+ const payload = this._validator.serialize(data);
881
+ return this._peer.send(`type: message
882
+ data: ${payload}`);
883
+ }
884
+ sendError(err) {
885
+ return this._peer.send(`type: error
886
+ data: ${JSON.stringify(err)}`);
887
+ }
888
+ close() {
889
+ throw new Error("close() is not yet implemented on WsPeer");
890
+ }
891
+ subscribe(channel) {
892
+ this._peer.subscribe(channel);
893
+ }
894
+ unsubscribe(channel) {
895
+ this._peer.unsubscribe(channel);
896
+ }
897
+ publish(channel, message) {
898
+ if (!this._validator) {
899
+ return;
900
+ }
901
+ if (!this._validator.validate(message)) {
902
+ const err = {
903
+ code: 500,
904
+ message: `Error serializing message on server. The payload doesn't match the specified schema.`,
905
+ data: {
906
+ payload: message
907
+ }
908
+ };
909
+ this.sendError(err);
910
+ return;
911
+ }
912
+ const payload = this._validator.serialize(message);
913
+ this._peer.publish(channel, payload);
914
+ }
915
+ readyState() {
916
+ return this._peer.readyState;
917
+ }
918
+ }
919
+ function defineWebsocketRpc(def) {
920
+ def.transport = "ws";
921
+ return def;
922
+ }
923
+ function registerWebsocketRpc(router, path, rpc) {
924
+ let responseValidator;
925
+ let paramValidator;
926
+ try {
927
+ responseValidator = rpc.response ? arriValidate.a.compile(rpc.response) : void 0;
928
+ } catch (err) {
929
+ console.error("ERROR COMPILING VALIDATOR", err);
930
+ }
931
+ try {
932
+ paramValidator = rpc.params ? arriValidate.a.compile(rpc.params) : void 0;
933
+ } catch (err) {
934
+ console.error("ERROR COMPILING PARAMS", err);
935
+ }
936
+ const handler = h3.defineWebSocketHandler({
937
+ upgrade(req) {
938
+ },
939
+ open(peer) {
940
+ const urlParts = peer.url.split("?");
941
+ const context = {
942
+ rpcName: rpc.name,
943
+ clientAddress: peer.addr
944
+ };
945
+ if (urlParts.length > 1) {
946
+ urlParts.shift();
947
+ const queryStr = new URLSearchParams(urlParts.join("?"));
948
+ const query = {};
949
+ for (const [key, val] of queryStr.entries()) {
950
+ query[key] = val;
951
+ }
952
+ context.queryParams = query;
953
+ }
954
+ const wsPeer = new WsPeer(peer, {
955
+ validator: responseValidator,
956
+ context
957
+ });
958
+ peer.ctx.__wsPeer = wsPeer;
959
+ rpc.handler.onOpen(peer.ctx.__wsPeer);
960
+ },
961
+ message(peer, message) {
962
+ if (!paramValidator) {
963
+ return;
964
+ }
965
+ const data = paramValidator.safeParse(message.text());
966
+ if (!data.success) {
967
+ const errorResponse = {
968
+ code: 400,
969
+ message: data.error.message,
970
+ data: data.error.errors,
971
+ stack: data.error.stack?.split("\n")
972
+ };
973
+ peer.ctx.__wsPeer.sendError(errorResponse);
974
+ return;
975
+ }
976
+ rpc.handler.onMessage(peer.ctx.__wsPeer, data.value);
977
+ },
978
+ close(peer, details) {
979
+ rpc.handler.onClose(peer.ctx.__wsPeer, details);
980
+ }
981
+ });
982
+ router.use(path, handler);
983
+ }
984
+ function createWsRpcDefinition(rpcName, path, rpc) {
985
+ return {
986
+ transport: "ws",
987
+ path,
988
+ params: getRpcParamName(rpcName, rpc),
989
+ response: getRpcResponseName(rpcName, rpc),
990
+ isDeprecated: rpc.isDeprecated,
991
+ description: rpc.description
992
+ };
993
+ }
994
+
854
995
  var __defProp = Object.defineProperty;
855
996
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
856
997
  var __publicField = (obj, key, value) => {
@@ -894,10 +1035,27 @@ class ArriApp {
894
1035
  this.definitionPath,
895
1036
  h3.eventHandler(() => this.getAppDefinition())
896
1037
  );
1038
+ if (!opts.disableDefaultRoute) {
1039
+ this.route({
1040
+ method: ["get", "head"],
1041
+ path: "/",
1042
+ handler: (_) => {
1043
+ let schemaPath;
1044
+ if (this._rpcRoutePrefix) {
1045
+ schemaPath = `/${this._rpcRoutePrefix}/${this._rpcDefinitionPath}`;
1046
+ } else {
1047
+ schemaPath = `/${this._rpcDefinitionPath}`;
1048
+ }
1049
+ return {
1050
+ title: this.appInfo?.title ?? "Arri-RPC Server",
1051
+ description: this.appInfo?.description ?? "This server utilizes Arri-RPC. Visit the schema path to see all of the available procedures.",
1052
+ schemaPath,
1053
+ ...this.appInfo
1054
+ };
1055
+ }
1056
+ });
1057
+ }
897
1058
  if (process.env.ARRI_DEV_MODE === "true") {
898
- consola__default.info(
899
- `Arri definition available at \`http://<host>${this.definitionPath}\``
900
- );
901
1059
  this.h3Router.get(
902
1060
  DEV_DEFINITION_ENDPOINT,
903
1061
  h3.eventHandler(() => this.getAppDefinition())
@@ -928,7 +1086,11 @@ class ArriApp {
928
1086
  this.route(route);
929
1087
  }
930
1088
  for (const rpc of input.getProcedures()) {
931
- this.rpc(rpc);
1089
+ if (rpc.transport === "http") {
1090
+ this.rpc(rpc);
1091
+ } else {
1092
+ this.wsRpc(rpc);
1093
+ }
932
1094
  }
933
1095
  this.registerModels(input.getModels());
934
1096
  return;
@@ -936,26 +1098,24 @@ class ArriApp {
936
1098
  this._middlewares.push(input);
937
1099
  }
938
1100
  rpc(procedure) {
939
- const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
940
- this._procedures[procedure.name] = createHttpRpcDefinition(
941
- procedure.name,
942
- path,
943
- procedure
944
- );
945
- if (isRpcParamSchema(procedure.params)) {
946
- const paramName = getRpcParamName(procedure.name, procedure);
1101
+ procedure.transport = "http";
1102
+ const p = procedure;
1103
+ const path = p.path ?? getRpcPath(p.name, this._rpcRoutePrefix);
1104
+ this._procedures[p.name] = createHttpRpcDefinition(p.name, path, p);
1105
+ if (isRpcParamSchema(p.params)) {
1106
+ const paramName = getRpcParamName(p.name, p);
947
1107
  if (paramName) {
948
- this._models[paramName] = procedure.params;
1108
+ this._models[paramName] = p.params;
949
1109
  }
950
1110
  }
951
- if (isRpcParamSchema(procedure.response)) {
952
- const responseName = getRpcResponseName(procedure.name, procedure);
1111
+ if (isRpcParamSchema(p.response)) {
1112
+ const responseName = getRpcResponseName(p.name, p);
953
1113
  if (responseName) {
954
- this._models[responseName] = procedure.response;
1114
+ this._models[responseName] = p.response;
955
1115
  }
956
1116
  }
957
- if (isEventStreamRpc(procedure)) {
958
- registerEventStreamRpc(this.h3Router, path, procedure, {
1117
+ if (isEventStreamRpc(p)) {
1118
+ registerEventStreamRpc(this.h3Router, path, p, {
959
1119
  middleware: this._middlewares,
960
1120
  onRequest: this._onRequest,
961
1121
  onError: this._onError,
@@ -965,7 +1125,7 @@ class ArriApp {
965
1125
  });
966
1126
  return;
967
1127
  }
968
- registerRpc(this.h3Router, path, procedure, {
1128
+ registerRpc(this.h3Router, path, p, {
969
1129
  middleware: this._middlewares,
970
1130
  onRequest: this._onRequest,
971
1131
  onError: this._onError,
@@ -974,6 +1134,29 @@ class ArriApp {
974
1134
  debug: this._debug
975
1135
  });
976
1136
  }
1137
+ wsRpc(procedure) {
1138
+ procedure.transport = "ws";
1139
+ const p = procedure;
1140
+ const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
1141
+ this._procedures[procedure.name] = createWsRpcDefinition(
1142
+ procedure.name,
1143
+ path,
1144
+ p
1145
+ );
1146
+ if (isRpcParamSchema(procedure.params)) {
1147
+ const paramName = getRpcParamName(procedure.name, p);
1148
+ if (paramName) {
1149
+ this._models[paramName] = procedure.params;
1150
+ }
1151
+ }
1152
+ if (isRpcParamSchema(procedure.response)) {
1153
+ const responseName = getRpcResponseName(procedure.name, p);
1154
+ if (responseName) {
1155
+ this._models[responseName] = procedure.response;
1156
+ }
1157
+ }
1158
+ registerWebsocketRpc(this.h3Router, path, p);
1159
+ }
977
1160
  route(route) {
978
1161
  registerRoute(this.h3Router, route, {
979
1162
  middleware: this._middlewares,
@@ -1070,14 +1253,17 @@ exports.ArriServerErrorResponse = ArriServerErrorResponse;
1070
1253
  exports.DEV_DEFINITION_ENDPOINT = DEV_DEFINITION_ENDPOINT;
1071
1254
  exports.DEV_ENDPOINT_ROOT = DEV_ENDPOINT_ROOT;
1072
1255
  exports.EventStreamConnection = EventStreamConnection;
1256
+ exports.WsPeer = WsPeer;
1073
1257
  exports.createAppDefinition = createAppDefinition;
1074
1258
  exports.createHttpRpcDefinition = createHttpRpcDefinition;
1259
+ exports.createWsRpcDefinition = createWsRpcDefinition;
1075
1260
  exports.defaultConfig = defaultConfig;
1076
1261
  exports.defineConfig = defineConfig;
1077
1262
  exports.defineError = defineError;
1078
1263
  exports.defineEventStreamRpc = defineEventStreamRpc;
1079
1264
  exports.defineRoute = defineRoute;
1080
1265
  exports.defineRpc = defineRpc;
1266
+ exports.defineWebsocketRpc = defineWebsocketRpc;
1081
1267
  exports.errorResponseFromValidationErrors = errorResponseFromValidationErrors;
1082
1268
  exports.getRpcParamName = getRpcParamName;
1083
1269
  exports.getRpcPath = getRpcPath;
@@ -1092,4 +1278,5 @@ exports.isRpcParamSchema = isRpcParamSchema;
1092
1278
  exports.registerEventStreamRpc = registerEventStreamRpc;
1093
1279
  exports.registerRoute = registerRoute;
1094
1280
  exports.registerRpc = registerRpc;
1281
+ exports.registerWebsocketRpc = registerWebsocketRpc;
1095
1282
  exports.validateRpcRequestInput = validateRpcRequestInput;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arri",
3
- "version": "0.36.1",
3
+ "version": "0.37.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -30,6 +30,7 @@
30
30
  "chokidar": "^3.6.0",
31
31
  "citty": "^0.1.6",
32
32
  "consola": "^3.2.3",
33
+ "crossws": "^0.2.4",
33
34
  "degit": "^2.8.4",
34
35
  "enquirer": "^2.4.1",
35
36
  "esbuild": "^0.20.2",
@@ -43,13 +44,13 @@
43
44
  "prettier": "^3.2.5",
44
45
  "scule": "^1.3.0",
45
46
  "uncrypto": "^0.1.3",
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"
47
+ "arri-codegen-dart": "0.37.1",
48
+ "arri-codegen-ts": "0.37.1",
49
+ "arri-validate": "0.37.1",
50
+ "arri-codegen-utils": "0.37.1"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@types/degit": "^2.8.6",
53
- "bun-types": "^1.0.35"
54
+ "bun-types": "^1.1.1"
54
55
  }
55
56
  }