arri 0.12.0 → 0.12.2

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 CHANGED
@@ -1,6 +1,42 @@
1
1
  # Arri RPC
2
2
 
3
- ## Installation
3
+ Typescript implementation of Arri RPC. It's built on top of [H3](https://github.com/unjs/h3) and uses [esbuild](https://esbuild.github.io/) for bundling.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Quickstart](#quickstart)
8
+ - [Manual Setup](#manual-setup)
9
+ - [Install Dependencies](#install-dependencies)
10
+ - [Scaffold Your Project](#scaffold-your-project)
11
+ - [Usage](#usage)
12
+ - [File-Based Routing](#file-based-routing)
13
+ - [Manual Routing](#manual-routing)
14
+ - [Adding Non-RPC Routes](#adding-non-rpc-routes)
15
+ - [Adding Middleware](#adding-middleware)
16
+ - [Key Concepts](#key-concepts)
17
+ - [Arri Definition File](#arri-definition-file)
18
+ - [How Procedures Map To Endpoints](#how-procedures-map-to-endpoints)
19
+ - [Arri CLI](#arri-cli)
20
+
21
+ ## Quickstart
22
+
23
+ ```bash
24
+ # npm
25
+ npx arri init [project-name]
26
+ cd [project-name]
27
+ npm install
28
+ npm run dev
29
+
30
+ # pnpm
31
+ pnpm dlx arri init [project-name]
32
+ cd [project-name]
33
+ pnpm install
34
+ pnpm run dev
35
+ ```
36
+
37
+ ## Manual Setup
38
+
39
+ ### Install Dependencies
4
40
 
5
41
  ```bash
6
42
  # npm
@@ -10,7 +46,32 @@ npm install arri arri-validate
10
46
  pnpm install arri arri-validate
11
47
  ```
12
48
 
13
- ## Basic Setup Example
49
+ ### Scaffold Your Project
50
+
51
+ A basic Arri app directory looks something like this:
52
+
53
+ ```fs
54
+ |-- project-dir
55
+ |-- .arri // temp files go here
56
+ |-- .output // final bundle goes here
57
+ |-- src
58
+ |-- procedures // .rpc.ts files go here
59
+ |-- app.ts
60
+ |-- arri.config.ts
61
+ |-- package.json
62
+ |-- tsconfig.json
63
+ |
64
+ ```
65
+
66
+ Both `.arri` and `.output` should be added to your `.gitignore` file
67
+
68
+ ```txt
69
+ .arri
70
+ .output
71
+ node_modules
72
+ ```
73
+
74
+ #### Configuration File
14
75
 
15
76
  Create an `arri.config.ts` in the project directory
16
77
 
@@ -37,7 +98,9 @@ export default defineConfig({
37
98
  });
38
99
  ```
39
100
 
40
- Create an `app.ts` file in the source directory
101
+ ##### App Entry
102
+
103
+ Create an app entry file in your src directory. The name of the file must match whatever you put as the `entry` in your `arri.config.ts`.
41
104
 
42
105
  ```ts
43
106
  // ./src/app.ts
@@ -63,24 +126,30 @@ app.rpc("sayHello", {
63
126
  export default app;
64
127
  ```
65
128
 
129
+ ##### Package.json
130
+
66
131
  Setup your npm scripts:
67
132
 
68
133
  ```json
69
134
  {
135
+ "name": "my-arri-app",
136
+ "type": "module",
70
137
  "scripts": {
71
138
  "dev": "arri dev",
72
139
  "build": "arri build"
140
+ },
141
+ "dependencies": {
142
+ ...
143
+ },
144
+ "devDependencies": {
145
+ ...
73
146
  }
74
147
  }
75
148
  ```
76
149
 
77
- Start the dev server:
78
-
79
- ```bash
80
- npm run dev
81
- ```
150
+ ## Usage
82
151
 
83
- ## File Based Routing
152
+ ### File Based Routing
84
153
 
85
154
  Arri RPC comes with an optional file based router that will automatically register functions in the `./procedures` directory that end with the `.rpc.ts` file extension.
86
155
 
@@ -115,7 +184,7 @@ export default defineRpc({
115
184
  });
116
185
  ```
117
186
 
118
- ### Customizing the File Based Router
187
+ #### Customizing the File Based Router
119
188
 
120
189
  ```ts
121
190
  export default defineConfig({
@@ -125,9 +194,27 @@ export default defineConfig({
125
194
  });
126
195
  ```
127
196
 
128
- ## Adding Non-RPC Endpoints
197
+ ### Manual Routing
198
+
199
+ ```ts
200
+ // using the app instance
201
+ const app = new ArriApp()
202
+ app.rpc('sayHello', {...})
203
+
204
+ // using a sub-router
205
+ const app = new ArriApp();
206
+ const router = new ArriRoute();
207
+ router.rpc('sayHello', {...})
208
+ app.use(router)
209
+ ```
210
+
211
+ ### Adding Non-RPC Routes
212
+
213
+ You can also add generic endpoints for instances when a message-based RPC endpoint doesn't fit.
129
214
 
130
215
  ```ts
216
+ // using the app instance
217
+ const app = new ArriApp();
131
218
  app.route({
132
219
  method: "get",
133
220
  path: "/hello-world",
@@ -135,25 +222,192 @@ app.route({
135
222
  return "hello world";
136
223
  },
137
224
  });
225
+
226
+ // using a sub-router
227
+ const app = new ArriApp();
228
+ const router = new ArriRouter();
229
+ router.route({
230
+ method: "get",
231
+ path: "/hello-world",
232
+ handler(event) {
233
+ return "hello world",
234
+ }
235
+ })
236
+ app.use(router)
138
237
  ```
139
238
 
140
- ## Creating sub routers
239
+ ### Adding Middleware
141
240
 
142
241
  ```ts
143
- import { ArriApp, ArriRouter } from "arri";
144
-
145
242
  const app = new ArriApp();
146
- const router = new ArriRouter();
147
243
 
148
- router.rpc({
149
- // rpc config
244
+ const requestLoggerMiddleware = defineMiddleware((event) => {
245
+ console.log(`new request at ${event.path}`);
150
246
  });
151
247
 
152
- router.route({
153
- // route config
248
+ app.use(requestLoggerMiddleware);
249
+ ```
250
+
251
+ #### Adding to the RPC Context
252
+
253
+ Any values added to `event.context` will become available in the rpc instance
254
+
255
+ ```ts
256
+ const authMiddleware = defineMiddleware(async (event) => {
257
+ // assume you did something to get the user from the request
258
+ event.context.user = {
259
+ id: 1,
260
+ name: "John Doe",
261
+ email: "johndoe@gmail.com",
262
+ };
263
+ });
264
+
265
+ app.rpc("sayHello", {
266
+ params: undefined,
267
+ response: a.object({
268
+ message: a.string(),
269
+ }),
270
+ // user is available here
271
+ handler({ user }) {
272
+ return {
273
+ message: `Hello ${user.name}`,
274
+ };
275
+ },
154
276
  });
277
+ ```
278
+
279
+ To get type safety for these new properties create a `.d.ts` file and augment the `EventContext` provided by `H3`
280
+
281
+ ```ts
282
+ import "h3";
283
+
284
+ declare module "h3" {
285
+ interface H3EventContext {
286
+ user?: {
287
+ id: number;
288
+ name: string;
289
+ email: string;
290
+ };
291
+ }
292
+ }
293
+ ```
294
+
295
+ ### Adding Client Generators
296
+
297
+ Right now Arri RPC has client generators for the following languages:
298
+
299
+ - typescript
300
+ - dart
301
+
302
+ ```ts
303
+ // arri.config.ts
304
+ import { defineConfig } from "arri";
305
+ import { typescriptClientGenerator, dartClientGenerator } from "arri/dist/codegen";
306
+
307
+ export default defineConfig({
308
+ // rest of config
309
+ clientGenerators: [
310
+ typescriptClientGenerator({...}),
311
+ dartClientGenerator({...})
312
+ ]
313
+ });
314
+ ```
315
+
316
+ ## Key Concepts
317
+
318
+ ### Arri Definition File
319
+
320
+ The server generates a `__definition.json` file that acts as a schema for all of the procedures and models in the API. By default this schema is viewable from `/__definition` when the server is running, but it can be modified. The endpoint is also relative to the `rpcRoutePrefix` option.
321
+
322
+ It looks something like this:
323
+
324
+ ```json
325
+ {
326
+ "procedures": {
327
+ "sayHello": {
328
+ "path": "/say-hello",
329
+ "method": "post",
330
+ "params": "SayHelloParams",
331
+ "response": "SayHelloResponse"
332
+ }
333
+ // rest of procedures
334
+ },
335
+ "models": {
336
+ "SayHelloParams": {
337
+ "properties": {
338
+ "name": {
339
+ "type": "string"
340
+ }
341
+ }
342
+ },
343
+ "SayHelloResponse": {
344
+ "properties": {
345
+ "message": {
346
+ "type": "string"
347
+ }
348
+ }
349
+ }
350
+ // rest of models
351
+ }
352
+ }
353
+ ```
354
+
355
+ Arri is able to use this schema file to automatically generate clients in multiple languages. In this way it works similarly to an Open API schema, but with much better code-generation support. I've made a lot of deliberate choices in designing this schema to make code-generation easier and more consistent across languages. For example, Arri schemas use a superset of [JSON Type Definition](https://jsontypedef.com/) for their models instead of JSON Schema.
356
+
357
+ ### How Procedures Map To Endpoints
358
+
359
+ Every procedure maps to a different url based on it's name. For example given the following file structure:
360
+
361
+ ```fs
362
+ |--src
363
+ |--procedures
364
+ |--getStatus.rpc.ts
365
+ |--users
366
+ |--getUser.rpc.ts
367
+ |--updateUser.rpc.ts
368
+ ```
369
+
370
+ We will get the following endpoints:
371
+
372
+ ```txt
373
+ POST /get-status
374
+ POST /users/get-user
375
+ POST /users/update-user
376
+
377
+ (Note: these will always be relative to the `rpcRoutePrefix` option)
378
+ ```
379
+
380
+ By default all procedures will become post requests, but you can change this when creating a procedure:
381
+
382
+ ```ts
383
+ // procedures/users/getUser.rpc.ts
384
+ export default defineRpc({
385
+ method: "get",
386
+ // rest of config
387
+ });
388
+ ```
389
+
390
+ The supported HTTP methods are as follows:
391
+
392
+ - post
393
+ - get
394
+ - delete
395
+ - patch
396
+ - put
397
+
398
+ When using a get method the RPC params will be mapped as query parameters which will be coerced into their type using the `a.coerce` method from `arri-validate`. Get methods support all basic scalar types however arrays and nested objects are not supported.
399
+
400
+ ## Arri CLI
401
+
402
+ ```bash
403
+ # start the dev server
404
+ arri dev [flags]
405
+
406
+ # create a production build
407
+ arri build [flags]
155
408
 
156
- app.use(router);
409
+ # create a new project
410
+ arri init [dir]
157
411
  ```
158
412
 
159
413
  ## Developing
package/dist/cli.cjs CHANGED
@@ -45,6 +45,10 @@ const prettier__default = /*#__PURE__*/_interopDefaultCompat(prettier);
45
45
  const chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
46
46
  const Degit__default = /*#__PURE__*/_interopDefaultCompat(Degit);
47
47
 
48
+ const DEFAULT_SERVER_ENTRY_FILE = "__default_arri_server.js";
49
+ const DEFAULT_CODEGEN_FILE = "__default_arri_codegen.js";
50
+ const SERVER_ENTRY_OUTPUT = "server.js";
51
+ const CODEGEN_OUTPUT = "codegen.js";
48
52
  async function setupWorkingDir(config) {
49
53
  const arriDir = path__default.resolve(config.rootDir, config.buildDir);
50
54
  const outDir = path__default.resolve(config.rootDir, ".output");
@@ -202,10 +206,14 @@ async function startBuild(config, skipCodeGen = false) {
202
206
  await bundleFiles(config);
203
207
  logger$2.log("Finished bundling");
204
208
  const clientCount = config.clientGenerators.length;
205
- const codegenModule = path__default.resolve(config.rootDir, ".output", "codegen.js");
209
+ const codegenModule = path__default.resolve(
210
+ config.rootDir,
211
+ ".output",
212
+ CODEGEN_OUTPUT
213
+ );
206
214
  if (clientCount > 0 && !skipCodeGen) {
207
215
  logger$2.log("Generating clients");
208
- node_child_process.execSync(`node ${codegenModule}`);
216
+ node_child_process.execSync(`node ${codegenModule}`, { env: process.env });
209
217
  const defJson = path__default.resolve(
210
218
  config.rootDir,
211
219
  ".output",
@@ -224,11 +232,9 @@ async function startBuild(config, skipCodeGen = false) {
224
232
  logger$2.log("Cleaning up files");
225
233
  await fs__default.rm(codegenModule);
226
234
  logger$2.log(
227
- `Build finished! You can start your server by running "node .output/server.js"`
235
+ `Build finished! You can start your server by running "node .output/${SERVER_ENTRY_OUTPUT}"`
228
236
  );
229
237
  }
230
- const BUILD_ENTRY_DEFAULT_FILE = "__default_arri_server.js";
231
- const CODEGEN_DEFAULT_FILE = "__default_arri_codegen.js";
232
238
  async function bundleFiles(config, allowCodegen = true) {
233
239
  if (allowCodegen) {
234
240
  await esbuild.build({
@@ -237,26 +243,26 @@ async function bundleFiles(config, allowCodegen = true) {
237
243
  path__default.resolve(
238
244
  config.rootDir,
239
245
  config.buildDir,
240
- CODEGEN_DEFAULT_FILE
246
+ DEFAULT_CODEGEN_FILE
241
247
  )
242
248
  ],
243
249
  platform: config.esbuild.platform ?? "node",
244
- target: config.esbuild.target ?? "node18",
250
+ target: config.esbuild.target ?? "node20",
245
251
  bundle: true,
246
252
  format: "esm",
247
253
  sourcemap: false,
248
- minifyWhitespace: true,
254
+ minifyWhitespace: false,
249
255
  banner: {
250
256
  js: `import { createRequire as topLevelCreateRequire } from 'module';
251
257
  const require = topLevelCreateRequire(import.meta.url);`
252
258
  },
253
- outfile: path__default.resolve(config.rootDir, ".output", "codegen.js")
259
+ outfile: path__default.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
254
260
  });
255
261
  }
256
262
  let buildEntry = path__default.resolve(
257
263
  config.rootDir,
258
264
  config.buildDir,
259
- BUILD_ENTRY_DEFAULT_FILE
265
+ DEFAULT_SERVER_ENTRY_FILE
260
266
  );
261
267
  if (config.buildEntry) {
262
268
  const parts = config.buildEntry.split(".");
@@ -279,7 +285,7 @@ async function bundleFiles(config, allowCodegen = true) {
279
285
  const require = topLevelCreateRequire(import.meta.url);`
280
286
  },
281
287
  allowOverwrite: true,
282
- outfile: path__default.resolve(config.rootDir, ".output", "server.js")
288
+ outfile: path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
283
289
  });
284
290
  }
285
291
  async function createBuildEntryModule(config) {
@@ -310,7 +316,11 @@ void listen(toNodeListener(app.h3App), {
310
316
  public: true,
311
317
  });`;
312
318
  await fs__default.writeFile(
313
- path__default.resolve(config.rootDir, config.buildDir, BUILD_ENTRY_DEFAULT_FILE),
319
+ path__default.resolve(
320
+ config.rootDir,
321
+ config.buildDir,
322
+ DEFAULT_SERVER_ENTRY_FILE
323
+ ),
314
324
  virtualEntry
315
325
  );
316
326
  }
@@ -346,7 +356,7 @@ async function createBuildCodegenModule(config) {
346
356
  { tabWidth: 4, parser: "typescript" }
347
357
  );
348
358
  await fs__default.writeFile(
349
- path__default.resolve(config.rootDir, config.buildDir, CODEGEN_DEFAULT_FILE),
359
+ path__default.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
350
360
  virtualModule
351
361
  );
352
362
  }
@@ -448,19 +458,26 @@ const dev = citty.defineCommand({
448
458
  await startDevServer(config$1);
449
459
  }
450
460
  });
451
- const startListener = (config, showQr = false) => listhen.listenAndWatch(path__default.resolve(config.rootDir, ".output", "server.js"), {
452
- public: true,
453
- port: config.port,
454
- logger: logger$1,
455
- qr: showQr
456
- });
461
+ const startListener = (config, showQr = false) => listhen.listenAndWatch(
462
+ path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
463
+ {
464
+ public: true,
465
+ port: config.port,
466
+ logger: logger$1,
467
+ qr: showQr
468
+ }
469
+ );
457
470
  async function bundleFilesContext(config) {
458
471
  return await esbuild__namespace.context({
459
472
  ...config.esbuild,
460
473
  entryPoints: [
461
- path__default.resolve(config.rootDir, config.buildDir, "entry.js")
474
+ path__default.resolve(
475
+ config.rootDir,
476
+ config.buildDir,
477
+ DEFAULT_SERVER_ENTRY_FILE
478
+ )
462
479
  ],
463
- outfile: path__default.resolve(config.rootDir, ".output", "server.js"),
480
+ outfile: path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
464
481
  format: "esm",
465
482
  bundle: true,
466
483
  sourcemap: true,
@@ -581,7 +598,11 @@ for (const route of routes) {
581
598
 
582
599
  export default app.h3App;`;
583
600
  await fs__default.writeFile(
584
- path__default.resolve(config.rootDir, config.buildDir, "entry.js"),
601
+ path__default.resolve(
602
+ config.rootDir,
603
+ config.buildDir,
604
+ DEFAULT_SERVER_ENTRY_FILE
605
+ ),
585
606
  virtualEntry
586
607
  );
587
608
  }
package/dist/cli.mjs CHANGED
@@ -21,6 +21,10 @@ import Degit from 'degit';
21
21
  import 'h3';
22
22
  import 'arri-validate';
23
23
 
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";
24
28
  async function setupWorkingDir(config) {
25
29
  const arriDir = path.resolve(config.rootDir, config.buildDir);
26
30
  const outDir = path.resolve(config.rootDir, ".output");
@@ -178,10 +182,14 @@ async function startBuild(config, skipCodeGen = false) {
178
182
  await bundleFiles(config);
179
183
  logger$2.log("Finished bundling");
180
184
  const clientCount = config.clientGenerators.length;
181
- const codegenModule = path.resolve(config.rootDir, ".output", "codegen.js");
185
+ const codegenModule = path.resolve(
186
+ config.rootDir,
187
+ ".output",
188
+ CODEGEN_OUTPUT
189
+ );
182
190
  if (clientCount > 0 && !skipCodeGen) {
183
191
  logger$2.log("Generating clients");
184
- execSync(`node ${codegenModule}`);
192
+ execSync(`node ${codegenModule}`, { env: process.env });
185
193
  const defJson = path.resolve(
186
194
  config.rootDir,
187
195
  ".output",
@@ -200,11 +208,9 @@ async function startBuild(config, skipCodeGen = false) {
200
208
  logger$2.log("Cleaning up files");
201
209
  await fs.rm(codegenModule);
202
210
  logger$2.log(
203
- `Build finished! You can start your server by running "node .output/server.js"`
211
+ `Build finished! You can start your server by running "node .output/${SERVER_ENTRY_OUTPUT}"`
204
212
  );
205
213
  }
206
- const BUILD_ENTRY_DEFAULT_FILE = "__default_arri_server.js";
207
- const CODEGEN_DEFAULT_FILE = "__default_arri_codegen.js";
208
214
  async function bundleFiles(config, allowCodegen = true) {
209
215
  if (allowCodegen) {
210
216
  await build$1({
@@ -213,26 +219,26 @@ async function bundleFiles(config, allowCodegen = true) {
213
219
  path.resolve(
214
220
  config.rootDir,
215
221
  config.buildDir,
216
- CODEGEN_DEFAULT_FILE
222
+ DEFAULT_CODEGEN_FILE
217
223
  )
218
224
  ],
219
225
  platform: config.esbuild.platform ?? "node",
220
- target: config.esbuild.target ?? "node18",
226
+ target: config.esbuild.target ?? "node20",
221
227
  bundle: true,
222
228
  format: "esm",
223
229
  sourcemap: false,
224
- minifyWhitespace: true,
230
+ minifyWhitespace: false,
225
231
  banner: {
226
232
  js: `import { createRequire as topLevelCreateRequire } from 'module';
227
233
  const require = topLevelCreateRequire(import.meta.url);`
228
234
  },
229
- outfile: path.resolve(config.rootDir, ".output", "codegen.js")
235
+ outfile: path.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
230
236
  });
231
237
  }
232
238
  let buildEntry = path.resolve(
233
239
  config.rootDir,
234
240
  config.buildDir,
235
- BUILD_ENTRY_DEFAULT_FILE
241
+ DEFAULT_SERVER_ENTRY_FILE
236
242
  );
237
243
  if (config.buildEntry) {
238
244
  const parts = config.buildEntry.split(".");
@@ -255,7 +261,7 @@ async function bundleFiles(config, allowCodegen = true) {
255
261
  const require = topLevelCreateRequire(import.meta.url);`
256
262
  },
257
263
  allowOverwrite: true,
258
- outfile: path.resolve(config.rootDir, ".output", "server.js")
264
+ outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
259
265
  });
260
266
  }
261
267
  async function createBuildEntryModule(config) {
@@ -286,7 +292,11 @@ void listen(toNodeListener(app.h3App), {
286
292
  public: true,
287
293
  });`;
288
294
  await fs.writeFile(
289
- path.resolve(config.rootDir, config.buildDir, BUILD_ENTRY_DEFAULT_FILE),
295
+ path.resolve(
296
+ config.rootDir,
297
+ config.buildDir,
298
+ DEFAULT_SERVER_ENTRY_FILE
299
+ ),
290
300
  virtualEntry
291
301
  );
292
302
  }
@@ -322,7 +332,7 @@ async function createBuildCodegenModule(config) {
322
332
  { tabWidth: 4, parser: "typescript" }
323
333
  );
324
334
  await fs.writeFile(
325
- path.resolve(config.rootDir, config.buildDir, CODEGEN_DEFAULT_FILE),
335
+ path.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
326
336
  virtualModule
327
337
  );
328
338
  }
@@ -424,19 +434,26 @@ const dev = defineCommand({
424
434
  await startDevServer(config);
425
435
  }
426
436
  });
427
- const startListener = (config, showQr = false) => listenAndWatch(path.resolve(config.rootDir, ".output", "server.js"), {
428
- public: true,
429
- port: config.port,
430
- logger: logger$1,
431
- qr: showQr
432
- });
437
+ const startListener = (config, showQr = false) => listenAndWatch(
438
+ path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
439
+ {
440
+ public: true,
441
+ port: config.port,
442
+ logger: logger$1,
443
+ qr: showQr
444
+ }
445
+ );
433
446
  async function bundleFilesContext(config) {
434
447
  return await esbuild.context({
435
448
  ...config.esbuild,
436
449
  entryPoints: [
437
- path.resolve(config.rootDir, config.buildDir, "entry.js")
450
+ path.resolve(
451
+ config.rootDir,
452
+ config.buildDir,
453
+ DEFAULT_SERVER_ENTRY_FILE
454
+ )
438
455
  ],
439
- outfile: path.resolve(config.rootDir, ".output", "server.js"),
456
+ outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
440
457
  format: "esm",
441
458
  bundle: true,
442
459
  sourcemap: true,
@@ -557,7 +574,11 @@ for (const route of routes) {
557
574
 
558
575
  export default app.h3App;`;
559
576
  await fs.writeFile(
560
- path.resolve(config.rootDir, config.buildDir, "entry.js"),
577
+ path.resolve(
578
+ config.rootDir,
579
+ config.buildDir,
580
+ DEFAULT_SERVER_ENTRY_FILE
581
+ ),
561
582
  virtualEntry
562
583
  );
563
584
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arri",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -30,10 +30,10 @@
30
30
  "pathe": "^1.1.1",
31
31
  "prettier": "^3.0.3",
32
32
  "scule": "^1.0.0",
33
- "arri-codegen-dart": "0.12.0",
34
- "arri-codegen-ts": "0.12.0",
35
- "arri-codegen-utils": "0.12.0",
36
- "arri-validate": "0.12.0"
33
+ "arri-codegen-dart": "0.12.2",
34
+ "arri-codegen-utils": "0.12.2",
35
+ "arri-codegen-ts": "0.12.2",
36
+ "arri-validate": "0.12.2"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "listhen": "1.x"