arri 0.12.0 → 0.12.4
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 +44 -22
- package/dist/cli.mjs +44 -22
- 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
|
@@ -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(
|
|
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
|
|
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,27 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
237
243
|
path__default.resolve(
|
|
238
244
|
config.rootDir,
|
|
239
245
|
config.buildDir,
|
|
240
|
-
|
|
246
|
+
DEFAULT_CODEGEN_FILE
|
|
241
247
|
)
|
|
242
248
|
],
|
|
243
249
|
platform: config.esbuild.platform ?? "node",
|
|
244
|
-
target: config.esbuild.target ?? "
|
|
250
|
+
target: config.esbuild.target ?? "node20",
|
|
251
|
+
packages: "external",
|
|
245
252
|
bundle: true,
|
|
246
253
|
format: "esm",
|
|
247
254
|
sourcemap: false,
|
|
248
|
-
minifyWhitespace:
|
|
255
|
+
minifyWhitespace: false,
|
|
249
256
|
banner: {
|
|
250
257
|
js: `import { createRequire as topLevelCreateRequire } from 'module';
|
|
251
258
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
252
259
|
},
|
|
253
|
-
outfile: path__default.resolve(config.rootDir, ".output",
|
|
260
|
+
outfile: path__default.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
|
|
254
261
|
});
|
|
255
262
|
}
|
|
256
263
|
let buildEntry = path__default.resolve(
|
|
257
264
|
config.rootDir,
|
|
258
265
|
config.buildDir,
|
|
259
|
-
|
|
266
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
260
267
|
);
|
|
261
268
|
if (config.buildEntry) {
|
|
262
269
|
const parts = config.buildEntry.split(".");
|
|
@@ -279,7 +286,7 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
279
286
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
280
287
|
},
|
|
281
288
|
allowOverwrite: true,
|
|
282
|
-
outfile: path__default.resolve(config.rootDir, ".output",
|
|
289
|
+
outfile: path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
|
|
283
290
|
});
|
|
284
291
|
}
|
|
285
292
|
async function createBuildEntryModule(config) {
|
|
@@ -310,7 +317,11 @@ void listen(toNodeListener(app.h3App), {
|
|
|
310
317
|
public: true,
|
|
311
318
|
});`;
|
|
312
319
|
await fs__default.writeFile(
|
|
313
|
-
path__default.resolve(
|
|
320
|
+
path__default.resolve(
|
|
321
|
+
config.rootDir,
|
|
322
|
+
config.buildDir,
|
|
323
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
324
|
+
),
|
|
314
325
|
virtualEntry
|
|
315
326
|
);
|
|
316
327
|
}
|
|
@@ -346,7 +357,7 @@ async function createBuildCodegenModule(config) {
|
|
|
346
357
|
{ tabWidth: 4, parser: "typescript" }
|
|
347
358
|
);
|
|
348
359
|
await fs__default.writeFile(
|
|
349
|
-
path__default.resolve(config.rootDir, config.buildDir,
|
|
360
|
+
path__default.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
|
|
350
361
|
virtualModule
|
|
351
362
|
);
|
|
352
363
|
}
|
|
@@ -448,19 +459,26 @@ const dev = citty.defineCommand({
|
|
|
448
459
|
await startDevServer(config$1);
|
|
449
460
|
}
|
|
450
461
|
});
|
|
451
|
-
const startListener = (config, showQr = false) => listhen.listenAndWatch(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
462
|
+
const startListener = (config, showQr = false) => listhen.listenAndWatch(
|
|
463
|
+
path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
|
|
464
|
+
{
|
|
465
|
+
public: true,
|
|
466
|
+
port: config.port,
|
|
467
|
+
logger: logger$1,
|
|
468
|
+
qr: showQr
|
|
469
|
+
}
|
|
470
|
+
);
|
|
457
471
|
async function bundleFilesContext(config) {
|
|
458
472
|
return await esbuild__namespace.context({
|
|
459
473
|
...config.esbuild,
|
|
460
474
|
entryPoints: [
|
|
461
|
-
path__default.resolve(
|
|
475
|
+
path__default.resolve(
|
|
476
|
+
config.rootDir,
|
|
477
|
+
config.buildDir,
|
|
478
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
479
|
+
)
|
|
462
480
|
],
|
|
463
|
-
outfile: path__default.resolve(config.rootDir, ".output",
|
|
481
|
+
outfile: path__default.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
|
|
464
482
|
format: "esm",
|
|
465
483
|
bundle: true,
|
|
466
484
|
sourcemap: true,
|
|
@@ -581,7 +599,11 @@ for (const route of routes) {
|
|
|
581
599
|
|
|
582
600
|
export default app.h3App;`;
|
|
583
601
|
await fs__default.writeFile(
|
|
584
|
-
path__default.resolve(
|
|
602
|
+
path__default.resolve(
|
|
603
|
+
config.rootDir,
|
|
604
|
+
config.buildDir,
|
|
605
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
606
|
+
),
|
|
585
607
|
virtualEntry
|
|
586
608
|
);
|
|
587
609
|
}
|
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(
|
|
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
|
|
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,27 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
213
219
|
path.resolve(
|
|
214
220
|
config.rootDir,
|
|
215
221
|
config.buildDir,
|
|
216
|
-
|
|
222
|
+
DEFAULT_CODEGEN_FILE
|
|
217
223
|
)
|
|
218
224
|
],
|
|
219
225
|
platform: config.esbuild.platform ?? "node",
|
|
220
|
-
target: config.esbuild.target ?? "
|
|
226
|
+
target: config.esbuild.target ?? "node20",
|
|
227
|
+
packages: "external",
|
|
221
228
|
bundle: true,
|
|
222
229
|
format: "esm",
|
|
223
230
|
sourcemap: false,
|
|
224
|
-
minifyWhitespace:
|
|
231
|
+
minifyWhitespace: false,
|
|
225
232
|
banner: {
|
|
226
233
|
js: `import { createRequire as topLevelCreateRequire } from 'module';
|
|
227
234
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
228
235
|
},
|
|
229
|
-
outfile: path.resolve(config.rootDir, ".output",
|
|
236
|
+
outfile: path.resolve(config.rootDir, ".output", CODEGEN_OUTPUT)
|
|
230
237
|
});
|
|
231
238
|
}
|
|
232
239
|
let buildEntry = path.resolve(
|
|
233
240
|
config.rootDir,
|
|
234
241
|
config.buildDir,
|
|
235
|
-
|
|
242
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
236
243
|
);
|
|
237
244
|
if (config.buildEntry) {
|
|
238
245
|
const parts = config.buildEntry.split(".");
|
|
@@ -255,7 +262,7 @@ async function bundleFiles(config, allowCodegen = true) {
|
|
|
255
262
|
const require = topLevelCreateRequire(import.meta.url);`
|
|
256
263
|
},
|
|
257
264
|
allowOverwrite: true,
|
|
258
|
-
outfile: path.resolve(config.rootDir, ".output",
|
|
265
|
+
outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT)
|
|
259
266
|
});
|
|
260
267
|
}
|
|
261
268
|
async function createBuildEntryModule(config) {
|
|
@@ -286,7 +293,11 @@ void listen(toNodeListener(app.h3App), {
|
|
|
286
293
|
public: true,
|
|
287
294
|
});`;
|
|
288
295
|
await fs.writeFile(
|
|
289
|
-
path.resolve(
|
|
296
|
+
path.resolve(
|
|
297
|
+
config.rootDir,
|
|
298
|
+
config.buildDir,
|
|
299
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
300
|
+
),
|
|
290
301
|
virtualEntry
|
|
291
302
|
);
|
|
292
303
|
}
|
|
@@ -322,7 +333,7 @@ async function createBuildCodegenModule(config) {
|
|
|
322
333
|
{ tabWidth: 4, parser: "typescript" }
|
|
323
334
|
);
|
|
324
335
|
await fs.writeFile(
|
|
325
|
-
path.resolve(config.rootDir, config.buildDir,
|
|
336
|
+
path.resolve(config.rootDir, config.buildDir, DEFAULT_CODEGEN_FILE),
|
|
326
337
|
virtualModule
|
|
327
338
|
);
|
|
328
339
|
}
|
|
@@ -424,19 +435,26 @@ const dev = defineCommand({
|
|
|
424
435
|
await startDevServer(config);
|
|
425
436
|
}
|
|
426
437
|
});
|
|
427
|
-
const startListener = (config, showQr = false) => listenAndWatch(
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
438
|
+
const startListener = (config, showQr = false) => listenAndWatch(
|
|
439
|
+
path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
|
|
440
|
+
{
|
|
441
|
+
public: true,
|
|
442
|
+
port: config.port,
|
|
443
|
+
logger: logger$1,
|
|
444
|
+
qr: showQr
|
|
445
|
+
}
|
|
446
|
+
);
|
|
433
447
|
async function bundleFilesContext(config) {
|
|
434
448
|
return await esbuild.context({
|
|
435
449
|
...config.esbuild,
|
|
436
450
|
entryPoints: [
|
|
437
|
-
path.resolve(
|
|
451
|
+
path.resolve(
|
|
452
|
+
config.rootDir,
|
|
453
|
+
config.buildDir,
|
|
454
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
455
|
+
)
|
|
438
456
|
],
|
|
439
|
-
outfile: path.resolve(config.rootDir, ".output",
|
|
457
|
+
outfile: path.resolve(config.rootDir, ".output", SERVER_ENTRY_OUTPUT),
|
|
440
458
|
format: "esm",
|
|
441
459
|
bundle: true,
|
|
442
460
|
sourcemap: true,
|
|
@@ -557,7 +575,11 @@ for (const route of routes) {
|
|
|
557
575
|
|
|
558
576
|
export default app.h3App;`;
|
|
559
577
|
await fs.writeFile(
|
|
560
|
-
path.resolve(
|
|
578
|
+
path.resolve(
|
|
579
|
+
config.rootDir,
|
|
580
|
+
config.buildDir,
|
|
581
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
582
|
+
),
|
|
561
583
|
virtualEntry
|
|
562
584
|
);
|
|
563
585
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arri",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.4",
|
|
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.
|
|
34
|
-
"arri-codegen-
|
|
35
|
-
"arri-codegen-
|
|
36
|
-
"arri-validate": "0.12.
|
|
33
|
+
"arri-codegen-dart": "0.12.4",
|
|
34
|
+
"arri-codegen-utils": "0.12.4",
|
|
35
|
+
"arri-codegen-ts": "0.12.4",
|
|
36
|
+
"arri-validate": "0.12.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"listhen": "1.x"
|