arri 0.34.0 → 0.36.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/README.md +32 -0
- package/dist/cli.cjs +12 -6
- package/dist/cli.mjs +12 -6
- package/dist/index.cjs +4 -2
- package/dist/index.d.cts +39 -29
- package/dist/index.d.mts +39 -29
- package/dist/index.d.ts +39 -29
- package/dist/index.mjs +2 -1
- package/dist/shared/{arri.0dce1db1.cjs → arri.8e96548e.cjs} +153 -98
- package/dist/shared/{arri.1b62504f.mjs → arri.b1ff441a.mjs} +149 -99
- package/package.json +5 -5
|
@@ -1,23 +1,45 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const arriCodegenUtils = require('arri-codegen-utils');
|
|
4
|
+
const consola = require('consola');
|
|
4
5
|
const h3 = require('h3');
|
|
5
6
|
const arriValidate = require('arri-validate');
|
|
6
7
|
const h3Sse = require('h3-sse');
|
|
7
8
|
const scule = require('scule');
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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);
|
|
18
|
+
return value;
|
|
19
|
+
};
|
|
20
|
+
class ArriServerError extends Error {
|
|
21
|
+
constructor(err) {
|
|
22
|
+
super(err.message);
|
|
23
|
+
__publicField$3(this, "code");
|
|
24
|
+
__publicField$3(this, "data");
|
|
25
|
+
this.code = err.code;
|
|
26
|
+
this.data = err.data;
|
|
27
|
+
if (err.stack) {
|
|
28
|
+
this.stack = err.stack;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const ArriServerErrorResponse = arriValidate.a.object({
|
|
33
|
+
code: arriValidate.a.int16(),
|
|
34
|
+
message: arriValidate.a.string(),
|
|
35
|
+
stack: arriValidate.a.optional(arriValidate.a.array(arriValidate.a.string())),
|
|
13
36
|
data: arriValidate.a.optional(arriValidate.a.any())
|
|
14
37
|
});
|
|
15
38
|
function defineError(statusCode, input = {}) {
|
|
16
39
|
const defaultVals = errorResponseDefaults[statusCode];
|
|
17
|
-
return
|
|
18
|
-
statusCode,
|
|
19
|
-
|
|
20
|
-
stack: input.stack ?? "",
|
|
40
|
+
return new ArriServerError({
|
|
41
|
+
code: statusCode,
|
|
42
|
+
message: input.message ?? defaultVals?.message ?? "An unknown error occurred",
|
|
21
43
|
data: input.data
|
|
22
44
|
});
|
|
23
45
|
}
|
|
@@ -25,7 +47,7 @@ function errorResponseFromValidationErrors(errors, prefixText = `Missing or inva
|
|
|
25
47
|
const errorParts = [];
|
|
26
48
|
for (const err of errors) {
|
|
27
49
|
const propName = err.instancePath?.split("/") ?? [];
|
|
28
|
-
if (propName.length) {
|
|
50
|
+
if (propName.length > 0) {
|
|
29
51
|
propName.shift();
|
|
30
52
|
}
|
|
31
53
|
if (!errorParts.includes(propName.join("."))) {
|
|
@@ -33,7 +55,7 @@ function errorResponseFromValidationErrors(errors, prefixText = `Missing or inva
|
|
|
33
55
|
}
|
|
34
56
|
}
|
|
35
57
|
throw defineError(400, {
|
|
36
|
-
|
|
58
|
+
message: `${prefixText}: [${errorParts.join(",")}]`,
|
|
37
59
|
data: errors
|
|
38
60
|
});
|
|
39
61
|
}
|
|
@@ -187,28 +209,55 @@ const errorResponseDefaults = {
|
|
|
187
209
|
message: "Network Authentication Required"
|
|
188
210
|
}
|
|
189
211
|
};
|
|
190
|
-
async function handleH3Error(err, event, onError) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
212
|
+
async function handleH3Error(err, event, onError, debug) {
|
|
213
|
+
let arriErr;
|
|
214
|
+
if (err instanceof ArriServerError) {
|
|
215
|
+
arriErr = err;
|
|
216
|
+
} else if (h3.isError(err)) {
|
|
217
|
+
arriErr = new ArriServerError({
|
|
218
|
+
code: err.statusCode,
|
|
219
|
+
message: err.message,
|
|
220
|
+
stack: err.stack,
|
|
221
|
+
data: err.data
|
|
222
|
+
});
|
|
223
|
+
} else if (err instanceof Error) {
|
|
224
|
+
arriErr = new ArriServerError({
|
|
225
|
+
code: 500,
|
|
226
|
+
message: err.message,
|
|
227
|
+
data: err,
|
|
228
|
+
stack: err.stack
|
|
229
|
+
});
|
|
230
|
+
} else {
|
|
231
|
+
arriErr = new ArriServerError({
|
|
232
|
+
code: 500,
|
|
233
|
+
message: `An unknown error occurred`,
|
|
234
|
+
data: err
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
if (!arriErr) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
h3.setResponseStatus(event, arriErr.code);
|
|
197
241
|
if (onError) {
|
|
198
|
-
await onError(
|
|
242
|
+
await onError(arriErr, event);
|
|
199
243
|
}
|
|
200
244
|
if (event.handled) {
|
|
201
245
|
return;
|
|
202
246
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
)
|
|
247
|
+
return sendArriError(event, arriErr, debug);
|
|
248
|
+
}
|
|
249
|
+
async function sendArriError(event, error, debug) {
|
|
250
|
+
const payload = {
|
|
251
|
+
code: error.code,
|
|
252
|
+
message: error.message,
|
|
253
|
+
data: error.data
|
|
254
|
+
};
|
|
255
|
+
if (debug) {
|
|
256
|
+
payload.stack = error.stack?.split("\n").map((l) => l.trim());
|
|
257
|
+
}
|
|
258
|
+
h3.setResponseHeader(event, "Content-Type", "application/json");
|
|
259
|
+
h3.setResponseStatus(event, error.code);
|
|
260
|
+
return h3.send(event, JSON.stringify(payload));
|
|
212
261
|
}
|
|
213
262
|
|
|
214
263
|
function isRpcParamSchema(input) {
|
|
@@ -321,7 +370,7 @@ function registerRpc(router, path, procedure, opts) {
|
|
|
321
370
|
if (!responseValidator?.validate(response)) {
|
|
322
371
|
const errors = arriValidate.a.errors(procedure.response, response);
|
|
323
372
|
throw defineError(500, {
|
|
324
|
-
|
|
373
|
+
message: "Failed to serialize response. Response does not match specified schema",
|
|
325
374
|
data: errors
|
|
326
375
|
});
|
|
327
376
|
}
|
|
@@ -344,7 +393,7 @@ function registerRpc(router, path, procedure, opts) {
|
|
|
344
393
|
);
|
|
345
394
|
}
|
|
346
395
|
} catch (err) {
|
|
347
|
-
await handleH3Error(err, event, opts.onError);
|
|
396
|
+
await handleH3Error(err, event, opts.onError, opts.debug ?? false);
|
|
348
397
|
}
|
|
349
398
|
return "";
|
|
350
399
|
});
|
|
@@ -390,7 +439,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
|
|
|
390
439
|
", "
|
|
391
440
|
)}]`;
|
|
392
441
|
throw defineError(400, {
|
|
393
|
-
|
|
442
|
+
message,
|
|
394
443
|
data: parsedParams.error
|
|
395
444
|
});
|
|
396
445
|
}
|
|
@@ -403,7 +452,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
|
|
|
403
452
|
const body = await h3.readRawBody(event);
|
|
404
453
|
if (!body) {
|
|
405
454
|
throw defineError(400, {
|
|
406
|
-
|
|
455
|
+
message: `Invalid request body. Expected object. Got undefined.`
|
|
407
456
|
});
|
|
408
457
|
}
|
|
409
458
|
const parsedParams = arriValidate.a.safeParse(schema, body);
|
|
@@ -417,7 +466,7 @@ async function validateRpcRequestInput(event, httpMethod, schema) {
|
|
|
417
466
|
}
|
|
418
467
|
}
|
|
419
468
|
throw defineError(400, {
|
|
420
|
-
|
|
469
|
+
message: `Invalid request body. Affected properties [${errorParts.join(
|
|
421
470
|
", "
|
|
422
471
|
)}]`,
|
|
423
472
|
data: parsedParams.error
|
|
@@ -490,11 +539,10 @@ class EventStreamConnection {
|
|
|
490
539
|
continue;
|
|
491
540
|
}
|
|
492
541
|
const errors2 = this.validationErrors(item);
|
|
493
|
-
const errorResponse2 = {
|
|
494
|
-
|
|
495
|
-
statusMessage: "Failed to serialize response. Response does not match specified schema.",
|
|
542
|
+
const errorResponse2 = defineError(500, {
|
|
543
|
+
message: "Failed to serialize response. Response does not match specified schema.",
|
|
496
544
|
data: errors2
|
|
497
|
-
};
|
|
545
|
+
});
|
|
498
546
|
events.push({
|
|
499
547
|
id: eventId,
|
|
500
548
|
event: "error",
|
|
@@ -513,11 +561,10 @@ class EventStreamConnection {
|
|
|
513
561
|
return;
|
|
514
562
|
}
|
|
515
563
|
const errors = this.validationErrors(data);
|
|
516
|
-
const errorResponse = {
|
|
517
|
-
|
|
518
|
-
statusMessage: "Failed to serialize response. Response does not match specified schema.",
|
|
564
|
+
const errorResponse = defineError(500, {
|
|
565
|
+
message: "Failed to serialize response. Response does not match specified schema.",
|
|
519
566
|
data: errors
|
|
520
|
-
};
|
|
567
|
+
});
|
|
521
568
|
await this.eventStream.push({
|
|
522
569
|
id: eventId,
|
|
523
570
|
event: "error",
|
|
@@ -603,9 +650,12 @@ function registerEventStreamRpc(router, path, procedure, opts) {
|
|
|
603
650
|
validator: responseValidator?.validate ?? function() {
|
|
604
651
|
return true;
|
|
605
652
|
},
|
|
606
|
-
serializer:
|
|
607
|
-
|
|
608
|
-
|
|
653
|
+
serializer: (
|
|
654
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
655
|
+
responseValidator?.serialize ?? function(_) {
|
|
656
|
+
return "";
|
|
657
|
+
}
|
|
658
|
+
),
|
|
609
659
|
validationErrors(input) {
|
|
610
660
|
if (procedure.response) {
|
|
611
661
|
return arriValidate.a.errors(procedure.response, input);
|
|
@@ -622,7 +672,7 @@ function registerEventStreamRpc(router, path, procedure, opts) {
|
|
|
622
672
|
stream.send();
|
|
623
673
|
}
|
|
624
674
|
} catch (err) {
|
|
625
|
-
await handleH3Error(err, event, opts.onError);
|
|
675
|
+
await handleH3Error(err, event, opts.onError, opts.debug ?? false);
|
|
626
676
|
}
|
|
627
677
|
return "";
|
|
628
678
|
});
|
|
@@ -689,7 +739,7 @@ function handleRoute(router, method, route, opts) {
|
|
|
689
739
|
", "
|
|
690
740
|
)}]`;
|
|
691
741
|
throw defineError(400, {
|
|
692
|
-
|
|
742
|
+
message
|
|
693
743
|
});
|
|
694
744
|
}
|
|
695
745
|
event.context.query = parsedQuery.value;
|
|
@@ -713,7 +763,7 @@ function handleRoute(router, method, route, opts) {
|
|
|
713
763
|
}
|
|
714
764
|
}
|
|
715
765
|
throw defineError(400, {
|
|
716
|
-
|
|
766
|
+
message: `Invalid request body. Affected properties [${errorParts.join(
|
|
717
767
|
", "
|
|
718
768
|
)}]`,
|
|
719
769
|
data: parsedBody.error
|
|
@@ -741,7 +791,7 @@ function handleRoute(router, method, route, opts) {
|
|
|
741
791
|
await route.postHandler(event);
|
|
742
792
|
}
|
|
743
793
|
} catch (err) {
|
|
744
|
-
await handleH3Error(err, event, opts.onError);
|
|
794
|
+
await handleH3Error(err, event, opts.onError, opts.debug ?? false);
|
|
745
795
|
}
|
|
746
796
|
return "";
|
|
747
797
|
});
|
|
@@ -815,32 +865,39 @@ class ArriApp {
|
|
|
815
865
|
__publicField(this, "__isArri__", true);
|
|
816
866
|
__publicField(this, "h3App");
|
|
817
867
|
__publicField(this, "h3Router", h3.createRouter());
|
|
818
|
-
__publicField(this, "
|
|
819
|
-
__publicField(this, "
|
|
868
|
+
__publicField(this, "_rpcDefinitionPath");
|
|
869
|
+
__publicField(this, "_rpcRoutePrefix");
|
|
820
870
|
__publicField(this, "appInfo");
|
|
821
|
-
__publicField(this, "
|
|
822
|
-
__publicField(this, "
|
|
823
|
-
__publicField(this, "
|
|
824
|
-
__publicField(this, "
|
|
825
|
-
__publicField(this, "
|
|
826
|
-
__publicField(this, "
|
|
827
|
-
__publicField(this, "
|
|
871
|
+
__publicField(this, "_procedures", {});
|
|
872
|
+
__publicField(this, "_models", {});
|
|
873
|
+
__publicField(this, "_middlewares", []);
|
|
874
|
+
__publicField(this, "_onRequest");
|
|
875
|
+
__publicField(this, "_onAfterResponse");
|
|
876
|
+
__publicField(this, "_onBeforeResponse");
|
|
877
|
+
__publicField(this, "_onError");
|
|
878
|
+
__publicField(this, "_debug");
|
|
879
|
+
__publicField(this, "definitionPath");
|
|
828
880
|
this.appInfo = opts?.appInfo;
|
|
829
881
|
this.h3App = h3.createApp({
|
|
830
882
|
debug: opts?.debug
|
|
831
883
|
});
|
|
832
|
-
this.
|
|
833
|
-
this.
|
|
834
|
-
this.
|
|
835
|
-
this.
|
|
836
|
-
this.
|
|
837
|
-
this.
|
|
884
|
+
this._debug = opts.debug ?? false;
|
|
885
|
+
this._onRequest = opts.onRequest;
|
|
886
|
+
this._onError = opts.onError;
|
|
887
|
+
this._onAfterResponse = opts.onAfterResponse;
|
|
888
|
+
this._onBeforeResponse = opts.onBeforeResponse;
|
|
889
|
+
this._rpcRoutePrefix = opts?.rpcRoutePrefix ?? "";
|
|
890
|
+
this._rpcDefinitionPath = opts?.rpcDefinitionPath ?? "__definition";
|
|
838
891
|
this.h3App.use(this.h3Router);
|
|
892
|
+
this.definitionPath = this._rpcRoutePrefix ? `/${this._rpcRoutePrefix}/${this._rpcDefinitionPath}`.split("//").join("/") : `/${this._rpcDefinitionPath}`;
|
|
839
893
|
this.h3Router.get(
|
|
840
|
-
this.
|
|
894
|
+
this.definitionPath,
|
|
841
895
|
h3.eventHandler(() => this.getAppDefinition())
|
|
842
896
|
);
|
|
843
897
|
if (process.env.ARRI_DEV_MODE === "true") {
|
|
898
|
+
consola__default.info(
|
|
899
|
+
`Arri definition available at \`http://<host>${this.definitionPath}\``
|
|
900
|
+
);
|
|
844
901
|
this.h3Router.get(
|
|
845
902
|
DEV_DEFINITION_ENDPOINT,
|
|
846
903
|
h3.eventHandler(() => this.getAppDefinition())
|
|
@@ -852,22 +909,16 @@ class ArriApp {
|
|
|
852
909
|
h3.setResponseStatus(event, 404);
|
|
853
910
|
const error = defineError(404);
|
|
854
911
|
try {
|
|
855
|
-
if (this.
|
|
856
|
-
await this.
|
|
912
|
+
if (this._onRequest) {
|
|
913
|
+
await this._onRequest(event);
|
|
857
914
|
}
|
|
858
915
|
} catch (err) {
|
|
859
|
-
await handleH3Error(err, event, this.
|
|
916
|
+
await handleH3Error(err, event, this._onError, this._debug);
|
|
860
917
|
}
|
|
861
918
|
if (event.handled) {
|
|
862
919
|
return;
|
|
863
920
|
}
|
|
864
|
-
|
|
865
|
-
await this.onError(error, event);
|
|
866
|
-
}
|
|
867
|
-
if (event.handled) {
|
|
868
|
-
return;
|
|
869
|
-
}
|
|
870
|
-
h3.sendError(event, error);
|
|
921
|
+
return handleH3Error(error, event, this._onError, this._debug);
|
|
871
922
|
})
|
|
872
923
|
);
|
|
873
924
|
}
|
|
@@ -882,11 +933,11 @@ class ArriApp {
|
|
|
882
933
|
this.registerModels(input.getModels());
|
|
883
934
|
return;
|
|
884
935
|
}
|
|
885
|
-
this.
|
|
936
|
+
this._middlewares.push(input);
|
|
886
937
|
}
|
|
887
938
|
rpc(procedure) {
|
|
888
|
-
const path = procedure.path ?? getRpcPath(procedure.name, this.
|
|
889
|
-
this.
|
|
939
|
+
const path = procedure.path ?? getRpcPath(procedure.name, this._rpcRoutePrefix);
|
|
940
|
+
this._procedures[procedure.name] = createHttpRpcDefinition(
|
|
890
941
|
procedure.name,
|
|
891
942
|
path,
|
|
892
943
|
procedure
|
|
@@ -894,45 +945,48 @@ class ArriApp {
|
|
|
894
945
|
if (isRpcParamSchema(procedure.params)) {
|
|
895
946
|
const paramName = getRpcParamName(procedure.name, procedure);
|
|
896
947
|
if (paramName) {
|
|
897
|
-
this.
|
|
948
|
+
this._models[paramName] = procedure.params;
|
|
898
949
|
}
|
|
899
950
|
}
|
|
900
951
|
if (isRpcParamSchema(procedure.response)) {
|
|
901
952
|
const responseName = getRpcResponseName(procedure.name, procedure);
|
|
902
953
|
if (responseName) {
|
|
903
|
-
this.
|
|
954
|
+
this._models[responseName] = procedure.response;
|
|
904
955
|
}
|
|
905
956
|
}
|
|
906
957
|
if (isEventStreamRpc(procedure)) {
|
|
907
958
|
registerEventStreamRpc(this.h3Router, path, procedure, {
|
|
908
|
-
middleware: this.
|
|
909
|
-
onRequest: this.
|
|
910
|
-
onError: this.
|
|
911
|
-
onAfterResponse: this.
|
|
912
|
-
onBeforeResponse: this.
|
|
959
|
+
middleware: this._middlewares,
|
|
960
|
+
onRequest: this._onRequest,
|
|
961
|
+
onError: this._onError,
|
|
962
|
+
onAfterResponse: this._onAfterResponse,
|
|
963
|
+
onBeforeResponse: this._onBeforeResponse,
|
|
964
|
+
debug: this._debug
|
|
913
965
|
});
|
|
914
966
|
return;
|
|
915
967
|
}
|
|
916
968
|
registerRpc(this.h3Router, path, procedure, {
|
|
917
|
-
middleware: this.
|
|
918
|
-
onRequest: this.
|
|
919
|
-
onError: this.
|
|
920
|
-
onAfterResponse: this.
|
|
921
|
-
onBeforeResponse: this.
|
|
969
|
+
middleware: this._middlewares,
|
|
970
|
+
onRequest: this._onRequest,
|
|
971
|
+
onError: this._onError,
|
|
972
|
+
onAfterResponse: this._onAfterResponse,
|
|
973
|
+
onBeforeResponse: this._onBeforeResponse,
|
|
974
|
+
debug: this._debug
|
|
922
975
|
});
|
|
923
976
|
}
|
|
924
977
|
route(route) {
|
|
925
978
|
registerRoute(this.h3Router, route, {
|
|
926
|
-
middleware: this.
|
|
927
|
-
onRequest: this.
|
|
928
|
-
onError: this.
|
|
929
|
-
onAfterResponse: this.
|
|
930
|
-
onBeforeResponse: this.
|
|
979
|
+
middleware: this._middlewares,
|
|
980
|
+
onRequest: this._onRequest,
|
|
981
|
+
onError: this._onError,
|
|
982
|
+
onAfterResponse: this._onAfterResponse,
|
|
983
|
+
onBeforeResponse: this._onBeforeResponse,
|
|
984
|
+
debug: this._debug
|
|
931
985
|
});
|
|
932
986
|
}
|
|
933
987
|
registerModels(models) {
|
|
934
988
|
for (const key of Object.keys(models)) {
|
|
935
|
-
this.
|
|
989
|
+
this._models[key] = models[key];
|
|
936
990
|
}
|
|
937
991
|
}
|
|
938
992
|
getAppDefinition() {
|
|
@@ -940,10 +994,10 @@ class ArriApp {
|
|
|
940
994
|
arriSchemaVersion: arriCodegenUtils.SCHEMA_VERSION,
|
|
941
995
|
info: this.appInfo,
|
|
942
996
|
procedures: {},
|
|
943
|
-
models: this.
|
|
997
|
+
models: this._models
|
|
944
998
|
};
|
|
945
|
-
for (const key of Object.keys(this.
|
|
946
|
-
const rpc = this.
|
|
999
|
+
for (const key of Object.keys(this._procedures)) {
|
|
1000
|
+
const rpc = this._procedures[key];
|
|
947
1001
|
appDef.procedures[key] = rpc;
|
|
948
1002
|
}
|
|
949
1003
|
return appDef;
|
|
@@ -1011,9 +1065,10 @@ function defineConfig(config) {
|
|
|
1011
1065
|
|
|
1012
1066
|
exports.ArriApp = ArriApp;
|
|
1013
1067
|
exports.ArriRouter = ArriRouter;
|
|
1068
|
+
exports.ArriServerError = ArriServerError;
|
|
1069
|
+
exports.ArriServerErrorResponse = ArriServerErrorResponse;
|
|
1014
1070
|
exports.DEV_DEFINITION_ENDPOINT = DEV_DEFINITION_ENDPOINT;
|
|
1015
1071
|
exports.DEV_ENDPOINT_ROOT = DEV_ENDPOINT_ROOT;
|
|
1016
|
-
exports.ErrorResponse = ErrorResponse;
|
|
1017
1072
|
exports.EventStreamConnection = EventStreamConnection;
|
|
1018
1073
|
exports.createAppDefinition = createAppDefinition;
|
|
1019
1074
|
exports.createHttpRpcDefinition = createHttpRpcDefinition;
|