arri 0.12.8 → 0.15.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/cli.mjs CHANGED
@@ -8,9 +8,10 @@ import { loadConfig } from 'c12';
8
8
  import consola, { createConsola } from 'consola';
9
9
  import * as esbuild from 'esbuild';
10
10
  import { build as build$1 } from 'esbuild';
11
+ import { replace } from 'esbuild-plugin-replace';
11
12
  import path from 'pathe';
12
13
  import prettier from 'prettier';
13
- import { n as defaultConfig, m as isResolvedArriConfig, a as DEV_DEFINITION_ENDPOINT } from './shared/arri.4d91d9b0.mjs';
14
+ import { n as defaultConfig, m as isResolvedArriConfig, a as DEV_DEFINITION_ENDPOINT } from './shared/arri.28516ef9.mjs';
14
15
  import { globby } from 'globby';
15
16
  import { camelCase, kebabCase } from 'scule';
16
17
  import { dartClientGenerator } from 'arri-codegen-dart';
@@ -21,10 +22,11 @@ import Degit from 'degit';
21
22
  import 'h3';
22
23
  import 'arri-validate';
23
24
 
24
- const DEFAULT_SERVER_ENTRY_FILE = "__default_arri_server.js";
25
- const DEFAULT_CODEGEN_FILE = "__default_arri_codegen.js";
26
- const SERVER_ENTRY_OUTPUT = "server.js";
27
- const CODEGEN_OUTPUT = "codegen.js";
25
+ const GEN_APP_FILE = "__arri_app.js";
26
+ const GEN_SERVER_ENTRY_FILE = "__arri_server.js";
27
+ const OUT_APP_FILE = "app.js";
28
+ const OUT_SERVER_ENTRY = "server.js";
29
+ const OUT_CODEGEN = "codegen.js";
28
30
  async function setupWorkingDir(config) {
29
31
  const arriDir = path.resolve(config.rootDir, config.buildDir);
30
32
  const outDir = path.resolve(config.rootDir, ".output");
@@ -37,12 +39,15 @@ async function setupWorkingDir(config) {
37
39
  await fs.mkdir(arriDir);
38
40
  await fs.mkdir(outDir);
39
41
  }
40
- async function createRoutesModule(config) {
42
+ async function createAppWithRoutesModule(config) {
43
+ const appModule = path.resolve(config.rootDir, config.srcDir, config.entry);
44
+ const appImportParts = path.relative(path.resolve(config.rootDir, config.srcDir), appModule).split(".");
45
+ appImportParts.pop();
41
46
  const routes = [];
42
47
  const existingRoutes = [];
43
48
  await Promise.all(
44
49
  config.procedureGlobPatterns.map(async (pattern) => {
45
- const results = await getVirtualRouteBatch(pattern, config);
50
+ const results = await getFsRouteBatch(pattern, config);
46
51
  for (const result of results) {
47
52
  if (!existingRoutes.includes(result.name)) {
48
53
  routes.push(result);
@@ -53,22 +58,29 @@ async function createRoutesModule(config) {
53
58
  );
54
59
  routes.sort((a, b) => a.name < b.name ? -1 : 1);
55
60
  const module = await prettier.format(
56
- `${routes.map(
61
+ `import app from './${appImportParts.join(".")}';
62
+ ${routes.map(
57
63
  (route) => `import ${route.importName} from '${route.importPath}';`
58
64
  ).join("\n")}
59
65
  const routes = [${routes.map(
60
66
  (route) => `{ id: '${route.name}', route: ${route.importName} }`
61
67
  ).join(",\n")}
62
68
  ];
63
- export default routes`,
69
+ for(const route of routes) {
70
+ app.rpc({
71
+ name: route.id,
72
+ ...route.route,
73
+ });
74
+ }
75
+ export default app`,
64
76
  { parser: "typescript", tabWidth: 4 }
65
77
  );
66
78
  await fs.writeFile(
67
- path.resolve(config.rootDir, config.buildDir, "routes.js"),
79
+ path.resolve(config.rootDir, config.buildDir, GEN_APP_FILE),
68
80
  module
69
81
  );
70
82
  }
71
- async function getVirtualRouteBatch(globPattern, config) {
83
+ async function getFsRouteBatch(globPattern, config) {
72
84
  if (!config.procedureDir) {
73
85
  return [];
74
86
  }
@@ -174,19 +186,15 @@ async function startBuild(config, skipCodeGen = false) {
174
186
  logger$2.log("Bundling server....");
175
187
  await setupWorkingDir(config);
176
188
  await Promise.all([
177
- createRoutesModule(config),
178
- createBuildEntryModule(config),
179
- createBuildCodegenModule(config)
189
+ createAppWithRoutesModule(config),
190
+ createServerEntryFile(config),
191
+ createCodegenEntryFile(config),
192
+ transpileFiles(config)
180
193
  ]);
181
- await transpileFiles(config);
182
- await bundleFiles(config);
194
+ await bundleAppEntry(config);
183
195
  logger$2.log("Finished bundling");
184
196
  const clientCount = config.clientGenerators.length;
185
- const codegenModule = path.resolve(
186
- config.rootDir,
187
- ".output",
188
- CODEGEN_OUTPUT
189
- );
197
+ const codegenModule = path.resolve(config.rootDir, ".output", OUT_CODEGEN);
190
198
  if (!skipCodeGen) {
191
199
  logger$2.log("Generating Arri app definition (__definition.json)");
192
200
  execSync(`node ${codegenModule}`, { env: process.env });
@@ -213,48 +221,18 @@ async function startBuild(config, skipCodeGen = false) {
213
221
  logger$2.log("Cleaning up files");
214
222
  await fs.rm(codegenModule);
215
223
  logger$2.success(
216
- `Build finished! You can start your server by running "node .output/${SERVER_ENTRY_OUTPUT}"`
224
+ `Build finished! You can start your server by running "node .output/${OUT_SERVER_ENTRY}"`
217
225
  );
218
226
  }
219
- async function bundleFiles(config, allowCodegen = true) {
220
- if (allowCodegen) {
221
- await build$1({
222
- ...config.esbuild,
223
- entryPoints: [
224
- path.resolve(
225
- config.rootDir,
226
- config.buildDir,
227
- DEFAULT_CODEGEN_FILE
228
- )
229
- ],
230
- platform: config.esbuild.platform ?? "node",
231
- target: config.esbuild.target ?? "node20",
232
- packages: "external",
233
- bundle: true,
234
- format: "esm",
235
- sourcemap: false,
236
- minifyWhitespace: false,
237
- banner: {
238
- js: `import { createRequire as topLevelCreateRequire } from 'module';
239
- const require = topLevelCreateRequire(import.meta.url);`
240
- },
241
- outfile: path.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
242
- });
243
- }
244
- let buildEntry = path.resolve(
227
+ async function bundleAppEntry(config, allowCodegen = true) {
228
+ const appEntry = path.resolve(
245
229
  config.rootDir,
246
230
  config.buildDir,
247
- DEFAULT_SERVER_ENTRY_FILE
231
+ GEN_APP_FILE
248
232
  );
249
- if (config.buildEntry) {
250
- const parts = config.buildEntry.split(".");
251
- parts.pop();
252
- const mergedParts = `${parts.join(".")}.js`;
253
- buildEntry = path.resolve(config.rootDir, config.buildDir, mergedParts);
254
- }
255
233
  await build$1({
256
234
  ...config.esbuild,
257
- entryPoints: [buildEntry],
235
+ entryPoints: [appEntry],
258
236
  platform: config.esbuild.platform ?? "node",
259
237
  target: config.esbuild.target ?? "node20",
260
238
  bundle: true,
@@ -267,11 +245,34 @@ const require = topLevelCreateRequire(import.meta.url);`
267
245
  const require = topLevelCreateRequire(import.meta.url);`
268
246
  },
269
247
  allowOverwrite: true,
270
- outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
248
+ outfile: path.resolve(config.rootDir, ".output", OUT_APP_FILE)
271
249
  });
272
250
  }
273
- async function createBuildEntryModule(config) {
274
- if (config.buildEntry) {
251
+ async function createServerEntryFile(config) {
252
+ if (config.serverEntry) {
253
+ const buildEntry = path.resolve(
254
+ config.rootDir,
255
+ config.srcDir,
256
+ config.serverEntry
257
+ );
258
+ await build$1({
259
+ ...config.esbuild,
260
+ entryPoints: [buildEntry],
261
+ platform: config.esbuild.platform ?? "node",
262
+ target: config.esbuild.target ?? "node20",
263
+ bundle: false,
264
+ packages: "external",
265
+ format: "esm",
266
+ sourcemap: true,
267
+ minifyWhitespace: true,
268
+ banner: {
269
+ js: `import { createRequire as topLevelCreateRequire } from 'module';
270
+ const require = topLevelCreateRequire(import.meta.url);`
271
+ },
272
+ plugins: [replace({ "virtual:arri/app": "./app.js" })],
273
+ allowOverwrite: true,
274
+ outfile: path.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY)
275
+ });
275
276
  return;
276
277
  }
277
278
  const appModule = path.resolve(config.rootDir, config.srcDir, config.entry);
@@ -279,34 +280,18 @@ async function createBuildEntryModule(config) {
279
280
  appImportParts.pop();
280
281
  const virtualEntry = `import { toNodeListener } from 'arri';
281
282
  import { listen } from 'listhen';
282
- import routes from './routes.js';
283
- import app from './${appImportParts.join(".")}.js';
284
-
285
- for (const route of routes) {
286
- app.rpc({
287
- name: route.id,
288
- method: route.route.method,
289
- params: route.route.params,
290
- response: route.route.response,
291
- handler: route.route.handler,
292
- postHandler: route.route.postHandler,
293
- });
294
- }
283
+ import app from './${OUT_APP_FILE}';
295
284
 
296
285
  void listen(toNodeListener(app.h3App), {
297
286
  port: process.env.PORT ?? ${config.port},
298
287
  public: true,
299
288
  });`;
300
289
  await fs.writeFile(
301
- path.resolve(
302
- config.rootDir,
303
- config.buildDir,
304
- DEFAULT_SERVER_ENTRY_FILE
305
- ),
290
+ path.resolve(config.rootDir, ".output", GEN_SERVER_ENTRY_FILE),
306
291
  virtualEntry
307
292
  );
308
293
  }
309
- async function createBuildCodegenModule(config) {
294
+ async function createCodegenEntryFile(config) {
310
295
  const appModule = path.resolve(config.rootDir, config.srcDir, config.entry);
311
296
  const appImportParts = path.relative(path.resolve(config.rootDir, config.srcDir), appModule).split(".");
312
297
  appImportParts.pop();
@@ -314,20 +299,7 @@ async function createBuildCodegenModule(config) {
314
299
  `
315
300
  import { writeFileSync } from 'node:fs';
316
301
  import path from 'pathe';
317
- import app from './${appImportParts.join(".")}.js';
318
- import routes from './routes.js';
319
-
320
- for (const route of routes) {
321
- app.rpc({
322
- name: route.id,
323
- method: route.route.method,
324
- path: route.route.path,
325
- params: route.route.params,
326
- response: route.route.response,
327
- handler: route.route.handler,
328
- postHandler: route.route.postHandler,
329
- });
330
- }
302
+ import app from './${OUT_APP_FILE}';
331
303
 
332
304
  const __dirname = new URL(".", import.meta.url).pathname;
333
305
  const def = app.getAppDefinition();
@@ -338,7 +310,7 @@ async function createBuildCodegenModule(config) {
338
310
  { tabWidth: 4, parser: "typescript" }
339
311
  );
340
312
  await fs.writeFile(
341
- path.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
313
+ path.resolve(config.rootDir, ".output", OUT_CODEGEN),
342
314
  virtualModule
343
315
  );
344
316
  }
@@ -440,26 +412,26 @@ const dev = defineCommand({
440
412
  await startDevServer(config);
441
413
  }
442
414
  });
443
- const startListener = (config, showQr = false) => listenAndWatch(
444
- path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
445
- {
446
- public: true,
447
- port: config.port,
448
- logger: logger$1,
449
- qr: showQr
450
- }
451
- );
415
+ const startListener = (config, showQr = false) => listenAndWatch(path.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY), {
416
+ public: true,
417
+ port: config.port,
418
+ logger: logger$1,
419
+ qr: showQr
420
+ });
452
421
  async function bundleFilesContext(config) {
422
+ const serverContent = `import app from './${OUT_APP_FILE}';
423
+
424
+ export default app.h3App;`;
425
+ await fs.writeFile(
426
+ path.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY),
427
+ serverContent
428
+ );
453
429
  return await esbuild.context({
454
430
  ...config.esbuild,
455
431
  entryPoints: [
456
- path.resolve(
457
- config.rootDir,
458
- config.buildDir,
459
- DEFAULT_SERVER_ENTRY_FILE
460
- )
432
+ path.resolve(config.rootDir, config.buildDir, GEN_APP_FILE)
461
433
  ],
462
- outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
434
+ outfile: path.resolve(config.rootDir, ".output", OUT_APP_FILE),
463
435
  format: "esm",
464
436
  bundle: true,
465
437
  sourcemap: true,
@@ -471,8 +443,11 @@ async function bundleFilesContext(config) {
471
443
  async function startDevServer(config) {
472
444
  await setupWorkingDir(config);
473
445
  let fileWatcher;
474
- await Promise.all([createRoutesModule(config), createEntryModule(config)]);
475
- await transpileFiles(config);
446
+ await Promise.all([
447
+ createEntryModule(config),
448
+ createAppWithRoutesModule(config),
449
+ transpileFiles(config)
450
+ ]);
476
451
  const bundleFiles = await bundleFilesContext(config);
477
452
  await bundleFiles.rebuild();
478
453
  const listener = await startListener(config, true);
@@ -510,7 +485,7 @@ async function startDevServer(config) {
510
485
  if (event === "add" || event === "addDir") {
511
486
  return;
512
487
  }
513
- await createRoutesModule(config);
488
+ await createAppWithRoutesModule(config);
514
489
  let bundleCreated = false;
515
490
  try {
516
491
  logger$1.log(
@@ -563,28 +538,11 @@ async function createEntryModule(config) {
563
538
  appImportParts.pop();
564
539
  const virtualEntry = `import { toNodeListener } from 'h3';
565
540
  import { listen } from 'listhen';
566
- import routes from './routes';
567
- import app from './${appImportParts.join(".")}';
568
-
569
- for (const route of routes) {
570
- app.rpc({
571
- name: route.id,
572
- method: route.route.method,
573
- path: route.route.path,
574
- params: route.route.params,
575
- response: route.route.response,
576
- handler: route.route.handler,
577
- postHandler: route.route.postHandler,
578
- });
579
- }
541
+ import app from './${GEN_APP_FILE}';
580
542
 
581
543
  export default app.h3App;`;
582
544
  await fs.writeFile(
583
- path.resolve(
584
- config.rootDir,
585
- config.buildDir,
586
- DEFAULT_SERVER_ENTRY_FILE
587
- ),
545
+ path.resolve(config.rootDir, config.buildDir, GEN_SERVER_ENTRY_FILE),
588
546
  virtualEntry
589
547
  );
590
548
  }
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const config = require('./shared/arri.fa32b1ba.cjs');
3
+ const config = require('./shared/arri.2eb37786.cjs');
4
4
  const h3 = require('h3');
5
5
  require('arri-validate');
6
6
  require('arri-codegen-utils');
@@ -13,24 +13,32 @@ exports.ArriRouter = config.ArriRouter;
13
13
  exports.DEV_DEFINITION_ENDPOINT = config.DEV_DEFINITION_ENDPOINT;
14
14
  exports.DEV_ENDPOINT_ROOT = config.DEV_ENDPOINT_ROOT;
15
15
  exports.ErrorResponse = config.ErrorResponse;
16
+ exports.EventStreamConnection = config.EventStreamConnection;
16
17
  exports.createRpcDefinition = config.createRpcDefinition;
17
18
  exports.defaultConfig = config.defaultConfig;
18
19
  exports.defineConfig = config.defineConfig;
19
20
  exports.defineError = config.defineError;
21
+ exports.defineEventStreamRpc = config.defineEventStreamRpc;
20
22
  exports.defineRoute = config.defineRoute;
21
23
  exports.defineRpc = config.defineRpc;
22
24
  exports.errorResponseFromValidationErrors = config.errorResponseFromValidationErrors;
25
+ exports.formatSse = config.formatSse;
26
+ exports.formatSseList = config.formatSseList;
23
27
  exports.getRpcParamName = config.getRpcParamName;
24
28
  exports.getRpcPath = config.getRpcPath;
25
29
  exports.getRpcResponseName = config.getRpcResponseName;
26
30
  exports.handleH3Error = config.handleH3Error;
27
31
  exports.handleRoute = config.handleRoute;
28
32
  exports.isArriConfig = config.isArriConfig;
33
+ exports.isEventStreamRpc = config.isEventStreamRpc;
29
34
  exports.isResolvedArriConfig = config.isResolvedArriConfig;
30
35
  exports.isRpc = config.isRpc;
31
36
  exports.isRpcParamSchema = config.isRpcParamSchema;
37
+ exports.registerEventStreamRpc = config.registerEventStreamRpc;
32
38
  exports.registerRoute = config.registerRoute;
33
39
  exports.registerRpc = config.registerRpc;
40
+ exports.setSseHeaders = config.setSseHeaders;
41
+ exports.validateRpcRequestInput = config.validateRpcRequestInput;
34
42
  exports.defineMiddleware = defineMiddleware;
35
43
  Object.keys(h3).forEach(function (k) {
36
44
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = h3[k];
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { HttpMethod, RpcHttpMethod, RpcDefinition, AppDefinition, ClientGenerator } from 'arri-codegen-utils';
2
- import { AObjectSchema, ASchema, InferType, ARecordSchema, ADiscriminatorSchema, a, ValidationError } from 'arri-validate';
3
- import { H3EventContext, H3Event, Router, App, H3Error } from 'h3';
1
+ import { HttpMethod, RpcHttpMethod, RpcDefinition, SchemaFormProperties, SchemaFormDiscriminator, SchemaFormValues, AppDefinition, ClientGenerator } from 'arri-codegen-utils';
2
+ import { AObjectSchema, ASchema, InferType, a, ValidationError, ARecordSchema, ADiscriminatorSchema } from 'arri-validate';
3
+ import { H3EventContext, H3Event, Router, H3Error, App } from 'h3';
4
4
  export * from 'h3';
5
5
  import { BuildOptions } from 'esbuild';
6
6
 
@@ -44,20 +44,103 @@ type RouteOptions = Pick<ArriOptions, "onAfterResponse" | "onBeforeResponse" | "
44
44
  declare function registerRoute(router: Router, route: ArriRoute<any>, opts: RouteOptions): void;
45
45
  declare function handleRoute(router: Router, method: HttpMethod, route: ArriRoute<any>, opts: RouteOptions): void;
46
46
 
47
+ declare const ErrorResponse: AObjectSchema<{
48
+ statusCode: number;
49
+ statusMessage: string;
50
+ stack?: string | undefined;
51
+ data?: any;
52
+ }, false>;
53
+ type ErrorResponse = a.infer<typeof ErrorResponse>;
54
+ declare function defineError(statusCode: StatusCode, input?: Partial<Omit<ErrorResponse, "statusCode" | "stack">> & {
55
+ stack?: string;
56
+ }): H3Error;
57
+ declare function errorResponseFromValidationErrors(errors: ValidationError["errors"], prefixText?: string): H3Error;
58
+ type StatusCode = number | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 507 | 511;
59
+ declare function handleH3Error(err: unknown, event: H3Event, onError: ArriOptions["onError"]): Promise<void>;
60
+
61
+ declare function setSseHeaders(event: H3Event): void;
62
+ declare function defineEventStreamRpc<TParams extends RpcParamSchema | undefined = undefined, TResponse extends RpcParamSchema | undefined | never = undefined>(config: Omit<EventStreamRpc<TParams, TResponse>, "isEventStream">): EventStreamRpc<TParams, TResponse>;
63
+ declare function isEventStreamRpc(input: unknown): input is EventStreamRpc<any, any>;
64
+ interface EventStreamRpc<TParams extends RpcParamSchema | undefined = undefined, TResponse extends RpcParamSchema | undefined = undefined> extends Omit<Rpc<true, TParams, TResponse>, "handler" | "postHandler"> {
65
+ isEventStream: true;
66
+ handler: EventStreamRpcHandler<TParams extends RpcParamSchema ? InferType<TParams> : undefined, TResponse extends RpcParamSchema ? InferType<TResponse> : undefined>;
67
+ }
68
+ type EventStreamRpcHandler<TParams, TResponse> = (context: EventStreamRpcHandlerContext<TParams, TResponse>, event: EventStreamRpcEvent<TParams, TResponse>) => void | Promise<void>;
69
+ interface EventStreamRpcEvent<TParams, TResponse> extends RpcEvent<TParams> {
70
+ connection: EventStreamConnection<TResponse>;
71
+ }
72
+ interface EventStreamRpcHandlerContext<TParams = any, TResponse = any> extends RpcHandlerContext<TParams> {
73
+ connection: EventStreamConnection<TResponse>;
74
+ }
75
+ interface EventStreamConnectionOptions<TData> {
76
+ serializer: (input: TData) => string;
77
+ pingInterval?: number;
78
+ }
79
+ /**
80
+ * A server sent event
81
+ */
82
+ interface Sse {
83
+ id?: string;
84
+ event?: string;
85
+ data: string;
86
+ }
87
+ declare function formatSse({ id, data, event }: Sse): string;
88
+ declare function formatSseList(events: Sse[]): string;
89
+ declare class EventStreamConnection<TData> {
90
+ lastEventId: string | undefined;
91
+ private readonly writable;
92
+ private readonly readable;
93
+ private readonly writer;
94
+ private readonly encoder;
95
+ private readonly serializer;
96
+ private readonly h3Event;
97
+ private pingInterval;
98
+ private readonly pingIntervalMs;
99
+ constructor(event: H3Event, opts: EventStreamConnectionOptions<TData>);
100
+ /**
101
+ * Start sending the event stream to the client
102
+ */
103
+ start(): void;
104
+ /**
105
+ * Publish a new event. Events published with this hook will trigger the `onData()` hooks of any connected clients.
106
+ */
107
+ push(data: TData[], eventId?: string): Promise<void>;
108
+ push(data: TData, eventId?: string): Promise<void>;
109
+ /**
110
+ * Publish an error event. This will trigger the `onError` hooks of any connected clients.
111
+ */
112
+ pushError(error: ErrorResponse, eventId?: string): Promise<void>;
113
+ private publishEvents;
114
+ private publishEvent;
115
+ private cleanup;
116
+ /**
117
+ * Tell clients that the stream has ended and close the connection.
118
+ */
119
+ end(): Promise<void>;
120
+ on(event: "disconnect", callback: () => any): void;
121
+ on(event: "end", callback: () => any): void;
122
+ }
123
+ declare function registerEventStreamRpc(router: Router, path: string, procedure: EventStreamRpc<any, any> & {
124
+ name: string;
125
+ }, opts: RouteOptions): void;
126
+
47
127
  type RpcParamSchema<TObjectInner = any, TRecordInner extends ASchema = any, TDiscriminatorInner = any> = AObjectSchema<TObjectInner> | ARecordSchema<TRecordInner> | ADiscriminatorSchema<TDiscriminatorInner>;
48
128
  declare function isRpcParamSchema(input: unknown): input is RpcParamSchema;
49
- interface ArriProcedure<TParams extends RpcParamSchema | undefined, TResponse extends RpcParamSchema | undefined> {
50
- description?: string;
129
+ interface NamedRpc<TIsEventStream extends boolean = false, TParams extends RpcParamSchema | undefined = undefined, TResponse extends RpcParamSchema | undefined = undefined> extends Rpc<TIsEventStream, TParams, TResponse> {
130
+ name: string;
131
+ }
132
+ interface Rpc<TIsEventStream extends boolean = false, TParams extends RpcParamSchema | undefined = undefined, TResponse extends RpcParamSchema | undefined = undefined> {
51
133
  method?: RpcHttpMethod;
52
134
  path?: string;
135
+ description?: string;
53
136
  params: TParams;
54
137
  response: TResponse;
55
- handler: ArriProcedureHandler<TParams extends RpcParamSchema ? InferType<TParams> : undefined, TResponse extends RpcParamSchema ? InferType<TResponse> : void>;
56
- postHandler?: ArriProcedurePostHandler<TParams extends RpcParamSchema ? InferType<TParams> : undefined, TResponse extends RpcParamSchema ? InferType<TResponse> : undefined>;
57
- }
58
- interface ArriNamedProcedure<TParams extends RpcParamSchema | undefined, TResponse extends RpcParamSchema | undefined> extends ArriProcedure<TParams, TResponse> {
59
- name: string;
138
+ isEventStream?: TIsEventStream;
139
+ pingInterval?: TIsEventStream extends true ? number : undefined;
140
+ handler: TIsEventStream extends true ? EventStreamRpcHandler<TParams extends RpcParamSchema ? InferType<TParams> : undefined, TResponse extends RpcParamSchema ? InferType<TResponse> : undefined> : RpcHandler<TParams extends RpcParamSchema ? InferType<TParams> : undefined, TResponse extends RpcParamSchema ? InferType<TResponse> : void>;
141
+ postHandler?: TIsEventStream extends true ? undefined : RpcPostHandler<TParams extends RpcParamSchema ? InferType<TParams> : undefined, TResponse extends RpcParamSchema ? InferType<TResponse> : undefined>;
60
142
  }
143
+ type HttpRpc<TParams extends RpcParamSchema | undefined, TResponse extends RpcParamSchema | undefined> = Omit<Rpc<false, TParams, TResponse>, "isEventStream">;
61
144
  type HandlerContext = Record<string, any>;
62
145
  interface RpcHandlerContext<TParams = undefined> extends HandlerContext, Omit<H3EventContext, "params"> {
63
146
  rpcName: string;
@@ -72,31 +155,37 @@ interface RpcEvent<TParams = undefined> extends Omit<H3Event, "context"> {
72
155
  interface RpcPostEvent<TParams = undefined, TResponse = undefined> extends Omit<H3Event, "context"> {
73
156
  context: RpcPostHandlerContext<TParams, TResponse>;
74
157
  }
75
- type ArriProcedureHandler<TParams, TResponse> = (context: RpcHandlerContext<TParams>, event: RpcEvent<TParams>) => TResponse | Promise<TResponse>;
76
- type ArriProcedurePostHandler<TParams, TResponse> = (context: RpcPostHandlerContext<TParams, TResponse>, event: RpcPostEvent<TParams, TResponse>) => any;
77
- declare function isRpc(input: any): input is ArriProcedure<any, any>;
78
- declare function defineRpc<TParams extends RpcParamSchema | undefined = undefined, TResponse extends RpcParamSchema | undefined | never = undefined>(config: ArriProcedure<TParams, TResponse>): ArriProcedure<TParams, TResponse>;
79
- declare function createRpcDefinition(rpcName: string, httpPath: string, procedure: ArriProcedure<any, any>): RpcDefinition;
158
+ type RpcHandler<TParams, TResponse> = (context: RpcHandlerContext<TParams>, event: RpcEvent<TParams>) => TResponse | Promise<TResponse>;
159
+ type RpcPostHandler<TParams, TResponse> = (context: RpcPostHandlerContext<TParams, TResponse>, event: RpcPostEvent<TParams, TResponse>) => any;
160
+ declare function isRpc(input: unknown): input is Rpc<any, any>;
161
+ declare function defineRpc<TParams extends RpcParamSchema | undefined = undefined, TResponse extends RpcParamSchema | undefined | never = undefined>(config: HttpRpc<TParams, TResponse>): Rpc<false, TParams, TResponse>;
162
+ declare function createRpcDefinition(rpcName: string, httpPath: string, procedure: Rpc<any, any, any>): RpcDefinition;
80
163
  declare function getRpcPath(rpcName: string, prefix?: string): string;
81
- declare function getRpcParamName(rpcName: string, procedure: ArriProcedure<any, any>): string | undefined;
82
- declare function getRpcResponseName(rpcName: string, procedure: ArriProcedure<any, any>): string | undefined;
83
- declare function registerRpc(router: Router, path: string, procedure: ArriNamedProcedure<any, any>, opts: RouteOptions): void;
164
+ declare function getRpcParamName(rpcName: string, procedure: Rpc<any, any, any>): string | undefined;
165
+ declare function getRpcResponseName(rpcName: string, procedure: Rpc<any, any, any>): string | undefined;
166
+ declare function registerRpc(router: Router, path: string, procedure: NamedRpc<any, any, any>, opts: RouteOptions): void;
167
+ declare function validateRpcRequestInput(event: H3Event, httpMethod: RpcHttpMethod, schema: ASchema): Promise<void>;
84
168
 
85
169
  interface ArriRouterBase {
86
- rpc: <TParams extends AObjectSchema<any, any> | undefined, TResponse extends AObjectSchema<any, any> | undefined>(procedure: ArriNamedProcedure<TParams, TResponse>) => void;
170
+ rpc: <TIsEventStream extends boolean, TParams extends AObjectSchema<any, any> | undefined, TResponse extends AObjectSchema<any, any> | undefined>(procedure: NamedRpc<TIsEventStream, TParams, TResponse>) => void;
87
171
  route: <TPath extends string, TQuery extends AObjectSchema<any, any> = any, TBody extends ASchema<any> = any, TResponse = any>(route: ArriRoute<TPath, TQuery, TBody, TResponse>) => void;
172
+ registerModels: (models: ModelMap) => void;
88
173
  }
89
174
  declare class ArriRouter implements ArriRouterBase {
90
175
  private readonly procedures;
91
176
  private readonly routes;
92
- rpc<TParams extends AObjectSchema<any, any> | undefined, TResponse extends AObjectSchema<any, any> | undefined>(procedure: ArriNamedProcedure<TParams, TResponse>): void;
177
+ private readonly models;
178
+ rpc<TIsEventStream extends boolean = false, TParams extends AObjectSchema<any, any> | undefined = undefined, TResponse extends AObjectSchema<any, any> | undefined = undefined>(procedure: NamedRpc<TIsEventStream, TParams, TResponse>): void;
93
179
  route<TPath extends string, TQuery extends AObjectSchema<any, any> = any, TBody extends ASchema<any> = any, TResponse = any>(route: ArriRoute<TPath, TQuery, TBody, TResponse>): void;
94
- getProcedures(): ArriNamedProcedure<any, any>[];
180
+ registerModels(models: ModelMap): void;
181
+ getProcedures(): NamedRpc<any, any, any>[];
95
182
  getRoutes(): ArriRoute<any, any, any, any>[];
183
+ getModels(): ModelMap;
96
184
  }
97
185
 
98
186
  declare const DEV_ENDPOINT_ROOT = "/__arri_dev__";
99
187
  declare const DEV_DEFINITION_ENDPOINT = "/__arri_dev__/__definition";
188
+ type ModelMap = Record<string, SchemaFormProperties | SchemaFormDiscriminator | SchemaFormValues>;
100
189
  declare class ArriApp implements ArriRouterBase {
101
190
  __isArri__: boolean;
102
191
  readonly h3App: App;
@@ -113,8 +202,9 @@ declare class ArriApp implements ArriRouterBase {
113
202
  private readonly onError;
114
203
  constructor(opts?: ArriOptions);
115
204
  use(input: Middleware | ArriRouter): void;
116
- rpc<TParams extends AObjectSchema<any, any> | undefined, TResponse extends AObjectSchema<any, any> | undefined>(procedure: ArriNamedProcedure<TParams, TResponse>): void;
205
+ rpc<TIsEventStream extends boolean = false, TParams extends AObjectSchema<any, any> | undefined = undefined, TResponse extends AObjectSchema<any, any> | undefined = undefined>(procedure: NamedRpc<TIsEventStream, TParams, TResponse>): void;
117
206
  route<TPath extends string, TQuery extends AObjectSchema<any, any>, TBody extends ASchema<any>, TResponse = any>(route: ArriRoute<TPath, TQuery, TBody, TResponse>): void;
207
+ registerModels(models: ModelMap): void;
118
208
  getAppDefinition(): AppDefinition;
119
209
  }
120
210
  interface ArriOptions {
@@ -135,24 +225,10 @@ interface ArriOptions {
135
225
  onError?: (error: H3Error, event: MiddlewareEvent) => void | Promise<void>;
136
226
  }
137
227
 
138
- declare const ErrorResponse: AObjectSchema<{
139
- statusCode: number;
140
- statusMessage: string;
141
- stack?: string | undefined;
142
- data?: any;
143
- }, false>;
144
- type ErrorResponse = a.infer<typeof ErrorResponse>;
145
- declare function defineError(statusCode: StatusCode, input?: Partial<Omit<ErrorResponse, "statusCode" | "stack">> & {
146
- stack?: string;
147
- }): H3Error;
148
- declare function errorResponseFromValidationErrors(errors: ValidationError["errors"], prefixText?: string): H3Error;
149
- type StatusCode = number | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 507 | 511;
150
- declare function handleH3Error(err: unknown, event: H3Event, onError: ArriOptions["onError"]): Promise<void>;
151
-
152
228
  interface ArriConfig {
153
229
  port: number;
154
230
  entry: string;
155
- buildEntry?: string;
231
+ serverEntry?: string;
156
232
  rootDir?: string;
157
233
  srcDir?: string;
158
234
  procedureDir?: string | false;
@@ -170,4 +246,4 @@ type ResolvedArriConfig = Required<ArriConfig>;
170
246
  declare const defaultConfig: Required<ArriConfig>;
171
247
  declare function defineConfig(config: ArriConfig): ResolvedArriConfig;
172
248
 
173
- export { ArriApp, type ArriConfig, type ArriNamedProcedure, type ArriOptions, type ArriProcedure, type ArriProcedureHandler, type ArriProcedurePostHandler, type ArriRoute, ArriRouter, type ArriRouterBase, DEV_DEFINITION_ENDPOINT, DEV_ENDPOINT_ROOT, ErrorResponse, type ExtractParam, type ExtractParams, type HandlerContext, type Middleware, type MiddlewareEvent, type MiddlewareEventContext, type PostRouteEvent, type PostRouteEventContext, type ResolvedArriConfig, type RouteEvent, type RouteEventContext, type RouteOptions, type RpcEvent, type RpcHandlerContext, type RpcParamSchema, type RpcPostEvent, type RpcPostHandlerContext, type StatusCode, createRpcDefinition, defaultConfig, defineConfig, defineError, defineMiddleware, defineRoute, defineRpc, errorResponseFromValidationErrors, getRpcParamName, getRpcPath, getRpcResponseName, handleH3Error, handleRoute, isArriConfig, isResolvedArriConfig, isRpc, isRpcParamSchema, registerRoute, registerRpc };
249
+ export { ArriApp, type ArriConfig, type ArriOptions, type ArriRoute, ArriRouter, type ArriRouterBase, DEV_DEFINITION_ENDPOINT, DEV_ENDPOINT_ROOT, ErrorResponse, EventStreamConnection, type EventStreamConnectionOptions, type EventStreamRpc, type EventStreamRpcEvent, type EventStreamRpcHandler, type EventStreamRpcHandlerContext, type ExtractParam, type ExtractParams, type HandlerContext, type HttpRpc, type Middleware, type MiddlewareEvent, type MiddlewareEventContext, type ModelMap, type NamedRpc, type PostRouteEvent, type PostRouteEventContext, type ResolvedArriConfig, type RouteEvent, type RouteEventContext, type RouteOptions, type Rpc, type RpcEvent, type RpcHandler, type RpcHandlerContext, type RpcParamSchema, type RpcPostEvent, type RpcPostHandler, type RpcPostHandlerContext, type Sse, type StatusCode, createRpcDefinition, defaultConfig, defineConfig, defineError, defineEventStreamRpc, defineMiddleware, defineRoute, defineRpc, errorResponseFromValidationErrors, formatSse, formatSseList, getRpcParamName, getRpcPath, getRpcResponseName, handleH3Error, handleRoute, isArriConfig, isEventStreamRpc, isResolvedArriConfig, isRpc, isRpcParamSchema, registerEventStreamRpc, registerRoute, registerRpc, setSseHeaders, validateRpcRequestInput };