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 +274 -20
- package/dist/cli.cjs +43 -22
- package/dist/cli.mjs +43 -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,26 @@ 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",
|
|
245
251
|
bundle: true,
|
|
246
252
|
format: "esm",
|
|
247
253
|
sourcemap: false,
|
|
248
|
-
minifyWhitespace:
|
|
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",
|
|
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
|
-
|
|
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",
|
|
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(
|
|
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,
|
|
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(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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(
|
|
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",
|
|
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(
|
|
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(
|
|
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,26 @@ 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",
|
|
221
227
|
bundle: true,
|
|
222
228
|
format: "esm",
|
|
223
229
|
sourcemap: false,
|
|
224
|
-
minifyWhitespace:
|
|
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",
|
|
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
|
-
|
|
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",
|
|
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(
|
|
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,
|
|
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(
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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(
|
|
450
|
+
path.resolve(
|
|
451
|
+
config.rootDir,
|
|
452
|
+
config.buildDir,
|
|
453
|
+
DEFAULT_SERVER_ENTRY_FILE
|
|
454
|
+
)
|
|
438
455
|
],
|
|
439
|
-
outfile: path.resolve(config.rootDir, ".output",
|
|
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(
|
|
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.
|
|
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.
|
|
34
|
-
"arri-codegen-
|
|
35
|
-
"arri-codegen-
|
|
36
|
-
"arri-validate": "0.12.
|
|
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"
|