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