arri 0.36.0 → 0.37.0
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/README.md +32 -15
- package/dist/cli.cjs +22 -6
- package/dist/cli.mjs +22 -6
- package/dist/index.cjs +6 -1
- package/dist/index.d.cts +66 -11
- package/dist/index.d.mts +66 -11
- package/dist/index.d.ts +66 -11
- package/dist/index.mjs +2 -1
- package/dist/shared/{arri.087dabd0.cjs → arri.1ce0fa20.cjs} +227 -42
- package/dist/shared/{arri.b0950dad.mjs → arri.90dd1716.mjs} +221 -44
- package/package.json +6 -5
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { isRpcHttpMethod, removeDisallowedChars, SCHEMA_VERSION } from 'arri-codegen-utils';
|
|
2
|
-
import
|
|
2
|
+
import consola from 'consola';
|
|
3
|
+
import { isError, setResponseStatus, setResponseHeader, send, eventHandler, isPreflightRequest, readRawBody, getValidatedQuery, defineEventHandler, getQuery, setHeader, defineWebSocketHandler, 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
|
-
var __defProp$
|
|
8
|
-
var __defNormalProp$
|
|
9
|
-
var __publicField$
|
|
10
|
-
__defNormalProp$
|
|
8
|
+
var __defProp$4 = Object.defineProperty;
|
|
9
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __publicField$4 = (obj, key, value) => {
|
|
11
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
11
12
|
return value;
|
|
12
13
|
};
|
|
13
14
|
class ArriServerError extends Error {
|
|
14
15
|
constructor(err) {
|
|
15
16
|
super(err.message);
|
|
16
|
-
__publicField$
|
|
17
|
-
__publicField$
|
|
17
|
+
__publicField$4(this, "code");
|
|
18
|
+
__publicField$4(this, "data");
|
|
18
19
|
this.code = err.code;
|
|
19
20
|
this.data = err.data;
|
|
20
21
|
if (err.stack) {
|
|
@@ -260,6 +261,7 @@ function isRpc(input) {
|
|
|
260
261
|
return typeof input === "object" && input !== null && "method" in input && isRpcHttpMethod(input.method) && "handler" in input && typeof input.handler === "function";
|
|
261
262
|
}
|
|
262
263
|
function defineRpc(config) {
|
|
264
|
+
config.transport = "http";
|
|
263
265
|
return config;
|
|
264
266
|
}
|
|
265
267
|
function createHttpRpcDefinition(rpcName, httpPath, procedure) {
|
|
@@ -471,17 +473,18 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
|
|
|
471
473
|
}
|
|
472
474
|
}
|
|
473
475
|
|
|
474
|
-
var __defProp$
|
|
475
|
-
var __defNormalProp$
|
|
476
|
-
var __publicField$
|
|
477
|
-
__defNormalProp$
|
|
476
|
+
var __defProp$3 = Object.defineProperty;
|
|
477
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
478
|
+
var __publicField$3 = (obj, key, value) => {
|
|
479
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
478
480
|
return value;
|
|
479
481
|
};
|
|
480
482
|
function defineEventStreamRpc(config) {
|
|
481
483
|
return {
|
|
482
484
|
...config,
|
|
483
485
|
method: config.method ?? "get",
|
|
484
|
-
isEventStream: true
|
|
486
|
+
isEventStream: true,
|
|
487
|
+
transport: "http"
|
|
485
488
|
};
|
|
486
489
|
}
|
|
487
490
|
function isEventStreamRpc(input) {
|
|
@@ -489,14 +492,14 @@ function isEventStreamRpc(input) {
|
|
|
489
492
|
}
|
|
490
493
|
class EventStreamConnection {
|
|
491
494
|
constructor(event, opts) {
|
|
492
|
-
__publicField$
|
|
493
|
-
__publicField$
|
|
494
|
-
__publicField$
|
|
495
|
-
__publicField$
|
|
495
|
+
__publicField$3(this, "lastEventId");
|
|
496
|
+
__publicField$3(this, "validationErrors");
|
|
497
|
+
__publicField$3(this, "validator");
|
|
498
|
+
__publicField$3(this, "serializer");
|
|
496
499
|
// for some reason Rollup cannot output DTS when this is set to NodeJS.Timeout
|
|
497
|
-
__publicField$
|
|
498
|
-
__publicField$
|
|
499
|
-
__publicField$
|
|
500
|
+
__publicField$3(this, "pingInterval");
|
|
501
|
+
__publicField$3(this, "pingIntervalMs");
|
|
502
|
+
__publicField$3(this, "eventStream");
|
|
500
503
|
this.eventStream = createEventStream(event);
|
|
501
504
|
this.lastEventId = this.eventStream.lastEventId;
|
|
502
505
|
this.pingIntervalMs = opts.pingInterval ?? 6e4;
|
|
@@ -810,19 +813,24 @@ function handleRoute(router, method, route, opts) {
|
|
|
810
813
|
}
|
|
811
814
|
}
|
|
812
815
|
|
|
813
|
-
var __defProp$
|
|
814
|
-
var __defNormalProp$
|
|
815
|
-
var __publicField$
|
|
816
|
-
__defNormalProp$
|
|
816
|
+
var __defProp$2 = Object.defineProperty;
|
|
817
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
818
|
+
var __publicField$2 = (obj, key, value) => {
|
|
819
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
817
820
|
return value;
|
|
818
821
|
};
|
|
819
822
|
class ArriRouter {
|
|
820
823
|
constructor() {
|
|
821
|
-
__publicField$
|
|
822
|
-
__publicField$
|
|
823
|
-
__publicField$
|
|
824
|
+
__publicField$2(this, "procedures", []);
|
|
825
|
+
__publicField$2(this, "routes", []);
|
|
826
|
+
__publicField$2(this, "models", {});
|
|
824
827
|
}
|
|
825
828
|
rpc(procedure) {
|
|
829
|
+
procedure.transport = "http";
|
|
830
|
+
this.procedures.push(procedure);
|
|
831
|
+
}
|
|
832
|
+
wsRpc(procedure) {
|
|
833
|
+
procedure.transport = "ws";
|
|
826
834
|
this.procedures.push(procedure);
|
|
827
835
|
}
|
|
828
836
|
route(route) {
|
|
@@ -844,6 +852,145 @@ class ArriRouter {
|
|
|
844
852
|
}
|
|
845
853
|
}
|
|
846
854
|
|
|
855
|
+
var __defProp$1 = Object.defineProperty;
|
|
856
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
857
|
+
var __publicField$1 = (obj, key, value) => {
|
|
858
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
859
|
+
return value;
|
|
860
|
+
};
|
|
861
|
+
class WsPeer {
|
|
862
|
+
constructor(peer, opts) {
|
|
863
|
+
__publicField$1(this, "_peer");
|
|
864
|
+
__publicField$1(this, "_validator");
|
|
865
|
+
__publicField$1(this, "context");
|
|
866
|
+
__publicField$1(this, "url");
|
|
867
|
+
this._peer = peer;
|
|
868
|
+
this._validator = opts.validator;
|
|
869
|
+
this.url = peer.url;
|
|
870
|
+
this.context = opts.context;
|
|
871
|
+
}
|
|
872
|
+
send(data) {
|
|
873
|
+
if (!this._validator) {
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
if (!this._validator.validate(data)) {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
const payload = this._validator.serialize(data);
|
|
880
|
+
return this._peer.send(`type: message
|
|
881
|
+
data: ${payload}`);
|
|
882
|
+
}
|
|
883
|
+
sendError(err) {
|
|
884
|
+
return this._peer.send(`type: error
|
|
885
|
+
data: ${JSON.stringify(err)}`);
|
|
886
|
+
}
|
|
887
|
+
close() {
|
|
888
|
+
throw new Error("close() is not yet implemented on WsPeer");
|
|
889
|
+
}
|
|
890
|
+
subscribe(channel) {
|
|
891
|
+
this._peer.subscribe(channel);
|
|
892
|
+
}
|
|
893
|
+
unsubscribe(channel) {
|
|
894
|
+
this._peer.unsubscribe(channel);
|
|
895
|
+
}
|
|
896
|
+
publish(channel, message) {
|
|
897
|
+
if (!this._validator) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
if (!this._validator.validate(message)) {
|
|
901
|
+
const err = {
|
|
902
|
+
code: 500,
|
|
903
|
+
message: `Error serializing message on server. The payload doesn't match the specified schema.`,
|
|
904
|
+
data: {
|
|
905
|
+
payload: message
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
this.sendError(err);
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
const payload = this._validator.serialize(message);
|
|
912
|
+
this._peer.publish(channel, payload);
|
|
913
|
+
}
|
|
914
|
+
readyState() {
|
|
915
|
+
return this._peer.readyState;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
function defineWebsocketRpc(def) {
|
|
919
|
+
def.transport = "ws";
|
|
920
|
+
return def;
|
|
921
|
+
}
|
|
922
|
+
function registerWebsocketRpc(router, path, rpc) {
|
|
923
|
+
let responseValidator;
|
|
924
|
+
let paramValidator;
|
|
925
|
+
try {
|
|
926
|
+
responseValidator = rpc.response ? a.compile(rpc.response) : void 0;
|
|
927
|
+
} catch (err) {
|
|
928
|
+
console.error("ERROR COMPILING VALIDATOR", err);
|
|
929
|
+
}
|
|
930
|
+
try {
|
|
931
|
+
paramValidator = rpc.params ? a.compile(rpc.params) : void 0;
|
|
932
|
+
} catch (err) {
|
|
933
|
+
console.error("ERROR COMPILING PARAMS", err);
|
|
934
|
+
}
|
|
935
|
+
const handler = defineWebSocketHandler({
|
|
936
|
+
upgrade(req) {
|
|
937
|
+
},
|
|
938
|
+
open(peer) {
|
|
939
|
+
const urlParts = peer.url.split("?");
|
|
940
|
+
const context = {
|
|
941
|
+
rpcName: rpc.name,
|
|
942
|
+
clientAddress: peer.addr
|
|
943
|
+
};
|
|
944
|
+
if (urlParts.length > 1) {
|
|
945
|
+
urlParts.shift();
|
|
946
|
+
const queryStr = new URLSearchParams(urlParts.join("?"));
|
|
947
|
+
const query = {};
|
|
948
|
+
for (const [key, val] of queryStr.entries()) {
|
|
949
|
+
query[key] = val;
|
|
950
|
+
}
|
|
951
|
+
context.queryParams = query;
|
|
952
|
+
}
|
|
953
|
+
const wsPeer = new WsPeer(peer, {
|
|
954
|
+
validator: responseValidator,
|
|
955
|
+
context
|
|
956
|
+
});
|
|
957
|
+
peer.ctx.__wsPeer = wsPeer;
|
|
958
|
+
rpc.handler.onOpen(peer.ctx.__wsPeer);
|
|
959
|
+
},
|
|
960
|
+
message(peer, message) {
|
|
961
|
+
if (!paramValidator) {
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
const data = paramValidator.safeParse(message.text());
|
|
965
|
+
if (!data.success) {
|
|
966
|
+
const errorResponse = {
|
|
967
|
+
code: 400,
|
|
968
|
+
message: data.error.message,
|
|
969
|
+
data: data.error.errors,
|
|
970
|
+
stack: data.error.stack?.split("\n")
|
|
971
|
+
};
|
|
972
|
+
peer.ctx.__wsPeer.sendError(errorResponse);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
rpc.handler.onMessage(peer.ctx.__wsPeer, data.value);
|
|
976
|
+
},
|
|
977
|
+
close(peer, details) {
|
|
978
|
+
rpc.handler.onClose(peer.ctx.__wsPeer, details);
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
router.use(path, handler);
|
|
982
|
+
}
|
|
983
|
+
function createWsRpcDefinition(rpcName, path, rpc) {
|
|
984
|
+
return {
|
|
985
|
+
transport: "ws",
|
|
986
|
+
path,
|
|
987
|
+
params: getRpcParamName(rpcName, rpc),
|
|
988
|
+
response: getRpcResponseName(rpcName, rpc),
|
|
989
|
+
isDeprecated: rpc.isDeprecated,
|
|
990
|
+
description: rpc.description
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
|
|
847
994
|
var __defProp = Object.defineProperty;
|
|
848
995
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
849
996
|
var __publicField = (obj, key, value) => {
|
|
@@ -869,6 +1016,7 @@ class ArriApp {
|
|
|
869
1016
|
__publicField(this, "_onBeforeResponse");
|
|
870
1017
|
__publicField(this, "_onError");
|
|
871
1018
|
__publicField(this, "_debug");
|
|
1019
|
+
__publicField(this, "definitionPath");
|
|
872
1020
|
this.appInfo = opts?.appInfo;
|
|
873
1021
|
this.h3App = createApp({
|
|
874
1022
|
debug: opts?.debug
|
|
@@ -881,11 +1029,15 @@ class ArriApp {
|
|
|
881
1029
|
this._rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
|
|
882
1030
|
this._rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
|
|
883
1031
|
this.h3App.use(this.h3Router);
|
|
1032
|
+
this.definitionPath = this._rpcRoutePrefix ? `/${this._rpcRoutePrefix}/${this._rpcDefinitionPath}`.split("//").join("/") : `/${this._rpcDefinitionPath}`;
|
|
884
1033
|
this.h3Router.get(
|
|
885
|
-
this.
|
|
1034
|
+
this.definitionPath,
|
|
886
1035
|
eventHandler(() => this.getAppDefinition())
|
|
887
1036
|
);
|
|
888
1037
|
if (process.env.ARRI_DEV_MODE === "true") {
|
|
1038
|
+
consola.info(
|
|
1039
|
+
`Arri definition available at \`http://<host>${this.definitionPath}\``
|
|
1040
|
+
);
|
|
889
1041
|
this.h3Router.get(
|
|
890
1042
|
DEV_DEFINITION_ENDPOINT,
|
|
891
1043
|
eventHandler(() => this.getAppDefinition())
|
|
@@ -916,7 +1068,11 @@ class ArriApp {
|
|
|
916
1068
|
this.route(route);
|
|
917
1069
|
}
|
|
918
1070
|
for (const rpc of input.getProcedures()) {
|
|
919
|
-
|
|
1071
|
+
if (rpc.transport === "http") {
|
|
1072
|
+
this.rpc(rpc);
|
|
1073
|
+
} else {
|
|
1074
|
+
this.wsRpc(rpc);
|
|
1075
|
+
}
|
|
920
1076
|
}
|
|
921
1077
|
this.registerModels(input.getModels());
|
|
922
1078
|
return;
|
|
@@ -924,26 +1080,24 @@ class ArriApp {
|
|
|
924
1080
|
this._middlewares.push(input);
|
|
925
1081
|
}
|
|
926
1082
|
rpc(procedure) {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
if (isRpcParamSchema(procedure.params)) {
|
|
934
|
-
const paramName = getRpcParamName(procedure.name, procedure);
|
|
1083
|
+
procedure.transport = "http";
|
|
1084
|
+
const p = procedure;
|
|
1085
|
+
const path = p.path ?? getRpcPath(p.name, this._rpcRoutePrefix);
|
|
1086
|
+
this._procedures[p.name] = createHttpRpcDefinition(p.name, path, p);
|
|
1087
|
+
if (isRpcParamSchema(p.params)) {
|
|
1088
|
+
const paramName = getRpcParamName(p.name, p);
|
|
935
1089
|
if (paramName) {
|
|
936
|
-
this._models[paramName] =
|
|
1090
|
+
this._models[paramName] = p.params;
|
|
937
1091
|
}
|
|
938
1092
|
}
|
|
939
|
-
if (isRpcParamSchema(
|
|
940
|
-
const responseName = getRpcResponseName(
|
|
1093
|
+
if (isRpcParamSchema(p.response)) {
|
|
1094
|
+
const responseName = getRpcResponseName(p.name, p);
|
|
941
1095
|
if (responseName) {
|
|
942
|
-
this._models[responseName] =
|
|
1096
|
+
this._models[responseName] = p.response;
|
|
943
1097
|
}
|
|
944
1098
|
}
|
|
945
|
-
if (isEventStreamRpc(
|
|
946
|
-
registerEventStreamRpc(this.h3Router, path,
|
|
1099
|
+
if (isEventStreamRpc(p)) {
|
|
1100
|
+
registerEventStreamRpc(this.h3Router, path, p, {
|
|
947
1101
|
middleware: this._middlewares,
|
|
948
1102
|
onRequest: this._onRequest,
|
|
949
1103
|
onError: this._onError,
|
|
@@ -953,7 +1107,7 @@ class ArriApp {
|
|
|
953
1107
|
});
|
|
954
1108
|
return;
|
|
955
1109
|
}
|
|
956
|
-
registerRpc(this.h3Router, path,
|
|
1110
|
+
registerRpc(this.h3Router, path, p, {
|
|
957
1111
|
middleware: this._middlewares,
|
|
958
1112
|
onRequest: this._onRequest,
|
|
959
1113
|
onError: this._onError,
|
|
@@ -962,6 +1116,29 @@ class ArriApp {
|
|
|
962
1116
|
debug: this._debug
|
|
963
1117
|
});
|
|
964
1118
|
}
|
|
1119
|
+
wsRpc(procedure) {
|
|
1120
|
+
procedure.transport = "ws";
|
|
1121
|
+
const p = procedure;
|
|
1122
|
+
const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
|
|
1123
|
+
this._procedures[procedure.name] = createWsRpcDefinition(
|
|
1124
|
+
procedure.name,
|
|
1125
|
+
path,
|
|
1126
|
+
p
|
|
1127
|
+
);
|
|
1128
|
+
if (isRpcParamSchema(procedure.params)) {
|
|
1129
|
+
const paramName = getRpcParamName(procedure.name, p);
|
|
1130
|
+
if (paramName) {
|
|
1131
|
+
this._models[paramName] = procedure.params;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (isRpcParamSchema(procedure.response)) {
|
|
1135
|
+
const responseName = getRpcResponseName(procedure.name, p);
|
|
1136
|
+
if (responseName) {
|
|
1137
|
+
this._models[responseName] = procedure.response;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
registerWebsocketRpc(this.h3Router, path, p);
|
|
1141
|
+
}
|
|
965
1142
|
route(route) {
|
|
966
1143
|
registerRoute(this.h3Router, route, {
|
|
967
1144
|
middleware: this._middlewares,
|
|
@@ -1051,4 +1228,4 @@ function defineConfig(config) {
|
|
|
1051
1228
|
};
|
|
1052
1229
|
}
|
|
1053
1230
|
|
|
1054
|
-
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 };
|
|
1231
|
+
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arri",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
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,10 +44,10 @@
|
|
|
43
44
|
"prettier": "^3.2.5",
|
|
44
45
|
"scule": "^1.3.0",
|
|
45
46
|
"uncrypto": "^0.1.3",
|
|
46
|
-
"arri-codegen-dart": "0.
|
|
47
|
-
"arri-codegen-
|
|
48
|
-
"arri-
|
|
49
|
-
"arri-
|
|
47
|
+
"arri-codegen-dart": "0.37.0",
|
|
48
|
+
"arri-codegen-utils": "0.37.0",
|
|
49
|
+
"arri-validate": "0.37.0",
|
|
50
|
+
"arri-codegen-ts": "0.37.0"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
53
|
"@types/degit": "^2.8.6",
|