arri 0.11.3 → 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 +274 -20
- package/dist/cli.cjs +64 -24
- package/dist/cli.mjs +64 -24
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +1 -1
- package/dist/shared/{arri.537f5e35.mjs → arri.4d91d9b0.mjs} +3 -1
- package/dist/shared/{arri.a90e9723.cjs → arri.fa32b1ba.cjs} +3 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
# Arri RPC
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
npm run dev
|
|
81
|
-
```
|
|
150
|
+
## Usage
|
|
82
151
|
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
244
|
+
const requestLoggerMiddleware = defineMiddleware((event) => {
|
|
245
|
+
console.log(`new request at ${event.path}`);
|
|
150
246
|
});
|
|
151
247
|
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
409
|
+
# create a new project
|
|
410
|
+
arri init [dir]
|
|
157
411
|
```
|
|
158
412
|
|
|
159
413
|
## Developing
|
package/dist/cli.cjs
CHANGED
|
@@ -11,7 +11,7 @@ const consola = require('consola');
|
|
|
11
11
|
const esbuild = require('esbuild');
|
|
12
12
|
const path = require('pathe');
|
|
13
13
|
const prettier = require('prettier');
|
|
14
|
-
const config = require('./shared/arri.
|
|
14
|
+
const config = require('./shared/arri.fa32b1ba.cjs');
|
|
15
15
|
const globby = require('globby');
|
|
16
16
|
const scule = require('scule');
|
|
17
17
|
const arriCodegenDart = require('arri-codegen-dart');
|
|
@@ -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");
|
|
@@ -160,7 +164,7 @@ async function transpileFiles(config) {
|
|
|
160
164
|
outdir: outDir,
|
|
161
165
|
bundle: false,
|
|
162
166
|
format: "esm",
|
|
163
|
-
target: "
|
|
167
|
+
target: "node20",
|
|
164
168
|
platform: "node"
|
|
165
169
|
});
|
|
166
170
|
}
|
|
@@ -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(
|
|
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,7 +232,7 @@ 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
|
|
235
|
+
`Build finished! You can start your server by running "node .output/${SERVER_ENTRY_OUTPUT}"`
|
|
228
236
|
);
|
|
229
237
|
}
|
|
230
238
|
async function bundleFiles(config, allowCodegen = true) {
|
|
@@ -232,26 +240,39 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
232
240
|
await esbuild.build({
|
|
233
241
|
...config.esbuild,
|
|
234
242
|
entryPoints: [
|
|
235
|
-
path__default.resolve(
|
|
243
|
+
path__default.resolve(
|
|
244
|
+
config.rootDir,
|
|
245
|
+
config.buildDir,
|
|
246
|
+
DEFAULT_CODEGEN_FILE
|
|
247
|
+
)
|
|
236
248
|
],
|
|
237
249
|
platform: config.esbuild.platform ?? "node",
|
|
238
|
-
target: config.esbuild.target ?? "
|
|
250
|
+
target: config.esbuild.target ?? "node20",
|
|
239
251
|
bundle: true,
|
|
240
252
|
format: "esm",
|
|
241
253
|
sourcemap: false,
|
|
242
|
-
minifyWhitespace:
|
|
254
|
+
minifyWhitespace: false,
|
|
243
255
|
banner: {
|
|
244
256
|
js: `import { createRequire as topLevelCreateRequire } from 'module';
|
|
245
257
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
246
258
|
},
|
|
247
|
-
|
|
259
|
+
outfile: path__default.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
|
|
248
260
|
});
|
|
249
261
|
}
|
|
262
|
+
let buildEntry = path__default.resolve(
|
|
263
|
+
config.rootDir,
|
|
264
|
+
config.buildDir,
|
|
265
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
266
|
+
);
|
|
267
|
+
if (config.buildEntry) {
|
|
268
|
+
const parts = config.buildEntry.split(".");
|
|
269
|
+
parts.pop();
|
|
270
|
+
const mergedParts = `${parts.join(".")}.js`;
|
|
271
|
+
buildEntry = path__default.resolve(config.rootDir, config.buildDir, mergedParts);
|
|
272
|
+
}
|
|
250
273
|
await esbuild.build({
|
|
251
274
|
...config.esbuild,
|
|
252
|
-
entryPoints: [
|
|
253
|
-
path__default.resolve(config.rootDir, config.buildDir, "server.js")
|
|
254
|
-
],
|
|
275
|
+
entryPoints: [buildEntry],
|
|
255
276
|
platform: config.esbuild.platform ?? "node",
|
|
256
277
|
target: config.esbuild.target ?? "node20",
|
|
257
278
|
bundle: true,
|
|
@@ -264,10 +285,13 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
264
285
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
265
286
|
},
|
|
266
287
|
allowOverwrite: true,
|
|
267
|
-
|
|
288
|
+
outfile: path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
|
|
268
289
|
});
|
|
269
290
|
}
|
|
270
291
|
async function createBuildEntryModule(config) {
|
|
292
|
+
if (config.buildEntry) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
271
295
|
const appModule = path__default.resolve(config.rootDir, config.srcDir, config.entry);
|
|
272
296
|
const appImportParts = path__default.relative(path__default.resolve(config.rootDir, config.srcDir), appModule).split(".");
|
|
273
297
|
appImportParts.pop();
|
|
@@ -289,9 +313,14 @@ for (const route of routes) {
|
|
|
289
313
|
|
|
290
314
|
void listen(toNodeListener(app.h3App), {
|
|
291
315
|
port: process.env.PORT ?? ${config.port},
|
|
316
|
+
public: true,
|
|
292
317
|
});`;
|
|
293
318
|
await fs__default.writeFile(
|
|
294
|
-
path__default.resolve(
|
|
319
|
+
path__default.resolve(
|
|
320
|
+
config.rootDir,
|
|
321
|
+
config.buildDir,
|
|
322
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
323
|
+
),
|
|
295
324
|
virtualEntry
|
|
296
325
|
);
|
|
297
326
|
}
|
|
@@ -327,7 +356,7 @@ async function createBuildCodegenModule(config) {
|
|
|
327
356
|
{ tabWidth: 4, parser: "typescript" }
|
|
328
357
|
);
|
|
329
358
|
await fs__default.writeFile(
|
|
330
|
-
path__default.resolve(config.rootDir, config.buildDir,
|
|
359
|
+
path__default.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
|
|
331
360
|
virtualModule
|
|
332
361
|
);
|
|
333
362
|
}
|
|
@@ -429,19 +458,26 @@ const dev = citty.defineCommand({
|
|
|
429
458
|
await startDevServer(config$1);
|
|
430
459
|
}
|
|
431
460
|
});
|
|
432
|
-
const startListener = (config, showQr = false) => listhen.listenAndWatch(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
+
);
|
|
438
470
|
async function bundleFilesContext(config) {
|
|
439
471
|
return await esbuild__namespace.context({
|
|
440
472
|
...config.esbuild,
|
|
441
473
|
entryPoints: [
|
|
442
|
-
path__default.resolve(
|
|
474
|
+
path__default.resolve(
|
|
475
|
+
config.rootDir,
|
|
476
|
+
config.buildDir,
|
|
477
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
478
|
+
)
|
|
443
479
|
],
|
|
444
|
-
outfile: path__default.resolve(config.rootDir, ".output",
|
|
480
|
+
outfile: path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
|
|
445
481
|
format: "esm",
|
|
446
482
|
bundle: true,
|
|
447
483
|
sourcemap: true,
|
|
@@ -562,7 +598,11 @@ for (const route of routes) {
|
|
|
562
598
|
|
|
563
599
|
export default app.h3App;`;
|
|
564
600
|
await fs__default.writeFile(
|
|
565
|
-
path__default.resolve(
|
|
601
|
+
path__default.resolve(
|
|
602
|
+
config.rootDir,
|
|
603
|
+
config.buildDir,
|
|
604
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
605
|
+
),
|
|
566
606
|
virtualEntry
|
|
567
607
|
);
|
|
568
608
|
}
|
package/dist/cli.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import * as esbuild from 'esbuild';
|
|
|
10
10
|
import { build as build$1 } from 'esbuild';
|
|
11
11
|
import path from 'pathe';
|
|
12
12
|
import prettier from 'prettier';
|
|
13
|
-
import { n as defaultConfig, m as isResolvedArriConfig, a as DEV_DEFINITION_ENDPOINT } from './shared/arri.
|
|
13
|
+
import { n as defaultConfig, m as isResolvedArriConfig, a as DEV_DEFINITION_ENDPOINT } from './shared/arri.4d91d9b0.mjs';
|
|
14
14
|
import { globby } from 'globby';
|
|
15
15
|
import { camelCase, kebabCase } from 'scule';
|
|
16
16
|
import { dartClientGenerator } from 'arri-codegen-dart';
|
|
@@ -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");
|
|
@@ -136,7 +140,7 @@ async function transpileFiles(config) {
|
|
|
136
140
|
outdir: outDir,
|
|
137
141
|
bundle: false,
|
|
138
142
|
format: "esm",
|
|
139
|
-
target: "
|
|
143
|
+
target: "node20",
|
|
140
144
|
platform: "node"
|
|
141
145
|
});
|
|
142
146
|
}
|
|
@@ -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(
|
|
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,7 +208,7 @@ 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
|
|
211
|
+
`Build finished! You can start your server by running "node .output/${SERVER_ENTRY_OUTPUT}"`
|
|
204
212
|
);
|
|
205
213
|
}
|
|
206
214
|
async function bundleFiles(config, allowCodegen = true) {
|
|
@@ -208,26 +216,39 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
208
216
|
await build$1({
|
|
209
217
|
...config.esbuild,
|
|
210
218
|
entryPoints: [
|
|
211
|
-
path.resolve(
|
|
219
|
+
path.resolve(
|
|
220
|
+
config.rootDir,
|
|
221
|
+
config.buildDir,
|
|
222
|
+
DEFAULT_CODEGEN_FILE
|
|
223
|
+
)
|
|
212
224
|
],
|
|
213
225
|
platform: config.esbuild.platform ?? "node",
|
|
214
|
-
target: config.esbuild.target ?? "
|
|
226
|
+
target: config.esbuild.target ?? "node20",
|
|
215
227
|
bundle: true,
|
|
216
228
|
format: "esm",
|
|
217
229
|
sourcemap: false,
|
|
218
|
-
minifyWhitespace:
|
|
230
|
+
minifyWhitespace: false,
|
|
219
231
|
banner: {
|
|
220
232
|
js: `import { createRequire as topLevelCreateRequire } from 'module';
|
|
221
233
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
222
234
|
},
|
|
223
|
-
|
|
235
|
+
outfile: path.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
|
|
224
236
|
});
|
|
225
237
|
}
|
|
238
|
+
let buildEntry = path.resolve(
|
|
239
|
+
config.rootDir,
|
|
240
|
+
config.buildDir,
|
|
241
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
242
|
+
);
|
|
243
|
+
if (config.buildEntry) {
|
|
244
|
+
const parts = config.buildEntry.split(".");
|
|
245
|
+
parts.pop();
|
|
246
|
+
const mergedParts = `${parts.join(".")}.js`;
|
|
247
|
+
buildEntry = path.resolve(config.rootDir, config.buildDir, mergedParts);
|
|
248
|
+
}
|
|
226
249
|
await build$1({
|
|
227
250
|
...config.esbuild,
|
|
228
|
-
entryPoints: [
|
|
229
|
-
path.resolve(config.rootDir, config.buildDir, "server.js")
|
|
230
|
-
],
|
|
251
|
+
entryPoints: [buildEntry],
|
|
231
252
|
platform: config.esbuild.platform ?? "node",
|
|
232
253
|
target: config.esbuild.target ?? "node20",
|
|
233
254
|
bundle: true,
|
|
@@ -240,10 +261,13 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
240
261
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
241
262
|
},
|
|
242
263
|
allowOverwrite: true,
|
|
243
|
-
|
|
264
|
+
outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
|
|
244
265
|
});
|
|
245
266
|
}
|
|
246
267
|
async function createBuildEntryModule(config) {
|
|
268
|
+
if (config.buildEntry) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
247
271
|
const appModule = path.resolve(config.rootDir, config.srcDir, config.entry);
|
|
248
272
|
const appImportParts = path.relative(path.resolve(config.rootDir, config.srcDir), appModule).split(".");
|
|
249
273
|
appImportParts.pop();
|
|
@@ -265,9 +289,14 @@ for (const route of routes) {
|
|
|
265
289
|
|
|
266
290
|
void listen(toNodeListener(app.h3App), {
|
|
267
291
|
port: process.env.PORT ?? ${config.port},
|
|
292
|
+
public: true,
|
|
268
293
|
});`;
|
|
269
294
|
await fs.writeFile(
|
|
270
|
-
path.resolve(
|
|
295
|
+
path.resolve(
|
|
296
|
+
config.rootDir,
|
|
297
|
+
config.buildDir,
|
|
298
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
299
|
+
),
|
|
271
300
|
virtualEntry
|
|
272
301
|
);
|
|
273
302
|
}
|
|
@@ -303,7 +332,7 @@ async function createBuildCodegenModule(config) {
|
|
|
303
332
|
{ tabWidth: 4, parser: "typescript" }
|
|
304
333
|
);
|
|
305
334
|
await fs.writeFile(
|
|
306
|
-
path.resolve(config.rootDir, config.buildDir,
|
|
335
|
+
path.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
|
|
307
336
|
virtualModule
|
|
308
337
|
);
|
|
309
338
|
}
|
|
@@ -405,19 +434,26 @@ const dev = defineCommand({
|
|
|
405
434
|
await startDevServer(config);
|
|
406
435
|
}
|
|
407
436
|
});
|
|
408
|
-
const startListener = (config, showQr = false) => listenAndWatch(
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
+
);
|
|
414
446
|
async function bundleFilesContext(config) {
|
|
415
447
|
return await esbuild.context({
|
|
416
448
|
...config.esbuild,
|
|
417
449
|
entryPoints: [
|
|
418
|
-
path.resolve(
|
|
450
|
+
path.resolve(
|
|
451
|
+
config.rootDir,
|
|
452
|
+
config.buildDir,
|
|
453
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
454
|
+
)
|
|
419
455
|
],
|
|
420
|
-
outfile: path.resolve(config.rootDir, ".output",
|
|
456
|
+
outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
|
|
421
457
|
format: "esm",
|
|
422
458
|
bundle: true,
|
|
423
459
|
sourcemap: true,
|
|
@@ -538,7 +574,11 @@ for (const route of routes) {
|
|
|
538
574
|
|
|
539
575
|
export default app.h3App;`;
|
|
540
576
|
await fs.writeFile(
|
|
541
|
-
path.resolve(
|
|
577
|
+
path.resolve(
|
|
578
|
+
config.rootDir,
|
|
579
|
+
config.buildDir,
|
|
580
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
581
|
+
),
|
|
542
582
|
virtualEntry
|
|
543
583
|
);
|
|
544
584
|
}
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ArriApp, p as ArriRouter, a as DEV_DEFINITION_ENDPOINT, D as DEV_ENDPOINT_ROOT, E as ErrorResponse, c as createRpcDefinition, n as defaultConfig, o as defineConfig, h as defineError, q as defineRoute, d as defineRpc, j as errorResponseFromValidationErrors, e as getRpcParamName, g as getRpcPath, f as getRpcResponseName, k as handleH3Error, t as handleRoute, l as isArriConfig, m as isResolvedArriConfig, b as isRpc, i as isRpcParamSchema, s as registerRoute, r as registerRpc } from './shared/arri.
|
|
1
|
+
export { A as ArriApp, p as ArriRouter, a as DEV_DEFINITION_ENDPOINT, D as DEV_ENDPOINT_ROOT, E as ErrorResponse, c as createRpcDefinition, n as defaultConfig, o as defineConfig, h as defineError, q as defineRoute, d as defineRpc, j as errorResponseFromValidationErrors, e as getRpcParamName, g as getRpcPath, f as getRpcResponseName, k as handleH3Error, t as handleRoute, l as isArriConfig, m as isResolvedArriConfig, b as isRpc, i as isRpcParamSchema, s as registerRoute, r as registerRpc } from './shared/arri.4d91d9b0.mjs';
|
|
2
2
|
export * from 'h3';
|
|
3
3
|
import 'arri-validate';
|
|
4
4
|
import 'arri-codegen-utils';
|
|
@@ -713,6 +713,7 @@ const defaultConfig = {
|
|
|
713
713
|
procedureGlobPatterns: ["**/*.rpc.ts"],
|
|
714
714
|
clientGenerators: [],
|
|
715
715
|
buildDir: ".arri",
|
|
716
|
+
buildEntry: "",
|
|
716
717
|
esbuild: {}
|
|
717
718
|
};
|
|
718
719
|
function defineConfig(config) {
|
|
@@ -725,7 +726,8 @@ function defineConfig(config) {
|
|
|
725
726
|
procedureGlobPatterns: config.procedureGlobPatterns ?? defaultConfig.procedureGlobPatterns,
|
|
726
727
|
clientGenerators: config.clientGenerators ?? defaultConfig.clientGenerators,
|
|
727
728
|
buildDir: config.buildDir ?? defaultConfig.buildDir,
|
|
728
|
-
esbuild: config.esbuild ?? defaultConfig.esbuild
|
|
729
|
+
esbuild: config.esbuild ?? defaultConfig.esbuild,
|
|
730
|
+
buildEntry: config.buildEntry ?? ""
|
|
729
731
|
};
|
|
730
732
|
}
|
|
731
733
|
|
|
@@ -715,6 +715,7 @@ const defaultConfig = {
|
|
|
715
715
|
procedureGlobPatterns: ["**/*.rpc.ts"],
|
|
716
716
|
clientGenerators: [],
|
|
717
717
|
buildDir: ".arri",
|
|
718
|
+
buildEntry: "",
|
|
718
719
|
esbuild: {}
|
|
719
720
|
};
|
|
720
721
|
function defineConfig(config) {
|
|
@@ -727,7 +728,8 @@ function defineConfig(config) {
|
|
|
727
728
|
procedureGlobPatterns: config.procedureGlobPatterns ?? defaultConfig.procedureGlobPatterns,
|
|
728
729
|
clientGenerators: config.clientGenerators ?? defaultConfig.clientGenerators,
|
|
729
730
|
buildDir: config.buildDir ?? defaultConfig.buildDir,
|
|
730
|
-
esbuild: config.esbuild ?? defaultConfig.esbuild
|
|
731
|
+
esbuild: config.esbuild ?? defaultConfig.esbuild,
|
|
732
|
+
buildEntry: config.buildEntry ?? ""
|
|
731
733
|
};
|
|
732
734
|
}
|
|
733
735
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arri",
|
|
3
|
-
"version": "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.
|
|
34
|
-
"arri-codegen-utils": "0.
|
|
35
|
-
"arri-codegen-ts": "0.
|
|
36
|
-
"arri-validate": "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"
|