arri 0.58.0 → 0.59.0
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 +5 -3
- package/dist/cli.cjs +58 -211
- package/dist/cli.mjs +32 -184
- package/dist/index.cjs +568 -13
- package/dist/index.d.cts +28 -10
- package/dist/index.d.mts +28 -10
- package/dist/index.d.ts +28 -10
- package/dist/index.mjs +546 -9
- package/dist/shared/arri.7f2f73b2.cjs +177 -0
- package/dist/shared/arri.f4637ba5.mjs +163 -0
- package/package.json +8 -8
- package/dist/shared/arri.09919c6d.cjs +0 -527
- package/dist/shared/arri.339f2f92.mjs +0 -493
package/dist/index.cjs
CHANGED
|
@@ -4,20 +4,574 @@ const codegenDart = require('@arrirpc/codegen-dart');
|
|
|
4
4
|
const codegenKotlin = require('@arrirpc/codegen-kotlin');
|
|
5
5
|
const codegenRust = require('@arrirpc/codegen-rust');
|
|
6
6
|
const codegenTs = require('@arrirpc/codegen-ts');
|
|
7
|
-
const
|
|
7
|
+
const common = require('./shared/arri.7f2f73b2.cjs');
|
|
8
|
+
const node_child_process = require('node:child_process');
|
|
9
|
+
const fs = require('node:fs');
|
|
10
|
+
const fs$1 = require('node:fs/promises');
|
|
11
|
+
const path = require('node:path');
|
|
8
12
|
const codegenUtils = require('@arrirpc/codegen-utils');
|
|
9
|
-
require('
|
|
10
|
-
require('
|
|
13
|
+
const listhen = require('@joshmossas/listhen');
|
|
14
|
+
const esbuild = require('esbuild');
|
|
15
|
+
const esbuildPluginReplace = require('esbuild-plugin-replace');
|
|
16
|
+
const h3 = require('h3');
|
|
17
|
+
const prettier = require('prettier');
|
|
11
18
|
require('c12');
|
|
12
19
|
require('citty');
|
|
13
|
-
require('esbuild');
|
|
14
|
-
require('h3');
|
|
15
20
|
require('pathe');
|
|
16
|
-
require('node:fs/promises');
|
|
17
21
|
require('@arrirpc/schema');
|
|
22
|
+
require('@joshmossas/ofetch');
|
|
18
23
|
require('consola');
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
|
|
25
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
26
|
+
|
|
27
|
+
function _interopNamespaceCompat(e) {
|
|
28
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
29
|
+
const n = Object.create(null);
|
|
30
|
+
if (e) {
|
|
31
|
+
for (const k in e) {
|
|
32
|
+
n[k] = e[k];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
n.default = e;
|
|
36
|
+
return n;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs$1);
|
|
40
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
41
|
+
const esbuild__default = /*#__PURE__*/_interopDefaultCompat(esbuild);
|
|
42
|
+
const prettier__default = /*#__PURE__*/_interopDefaultCompat(prettier);
|
|
43
|
+
|
|
44
|
+
function tsServer(serverConfig) {
|
|
45
|
+
return common.defineServerConfig({
|
|
46
|
+
devArgs: void 0,
|
|
47
|
+
async devFn(_, generators) {
|
|
48
|
+
const resolvedConfig = {
|
|
49
|
+
port: serverConfig?.port ?? defaultTsServerConfig.port,
|
|
50
|
+
entry: serverConfig?.entry ?? defaultTsServerConfig.entry,
|
|
51
|
+
serverEntry: serverConfig?.serverEntry ?? defaultTsServerConfig.serverEntry,
|
|
52
|
+
rootDir: serverConfig?.rootDir ?? defaultTsServerConfig.rootDir,
|
|
53
|
+
srcDir: serverConfig?.srcDir ?? defaultTsServerConfig.srcDir,
|
|
54
|
+
procedureDir: serverConfig?.procedureDir ?? defaultTsServerConfig.procedureDir,
|
|
55
|
+
procedureGlobPatterns: serverConfig?.procedureGlobPatterns ?? defaultTsServerConfig.procedureGlobPatterns,
|
|
56
|
+
buildDir: serverConfig?.buildDir ?? defaultTsServerConfig.buildDir,
|
|
57
|
+
esbuild: serverConfig?.esbuild ?? defaultTsServerConfig.esbuild,
|
|
58
|
+
https: serverConfig?.https ?? defaultTsServerConfig.https,
|
|
59
|
+
http2: serverConfig?.http2 ?? defaultTsServerConfig.http2,
|
|
60
|
+
devServer: serverConfig?.devServer ?? defaultTsServerConfig.devServer
|
|
61
|
+
};
|
|
62
|
+
await startDevServer(resolvedConfig, generators);
|
|
63
|
+
},
|
|
64
|
+
buildArgs: void 0,
|
|
65
|
+
async buildFn(args, generators) {
|
|
66
|
+
const resolvedConfig = {
|
|
67
|
+
port: serverConfig?.port ?? 3e3,
|
|
68
|
+
entry: serverConfig?.entry ?? "app.ts",
|
|
69
|
+
serverEntry: serverConfig?.serverEntry ?? defaultTsServerConfig.serverEntry,
|
|
70
|
+
rootDir: serverConfig?.rootDir ?? defaultTsServerConfig.rootDir,
|
|
71
|
+
srcDir: serverConfig?.srcDir ?? defaultTsServerConfig.srcDir,
|
|
72
|
+
procedureDir: serverConfig?.procedureDir ?? defaultTsServerConfig.procedureDir,
|
|
73
|
+
procedureGlobPatterns: serverConfig?.procedureGlobPatterns ?? defaultTsServerConfig.procedureGlobPatterns,
|
|
74
|
+
buildDir: serverConfig?.buildDir ?? defaultTsServerConfig.buildDir,
|
|
75
|
+
esbuild: serverConfig?.esbuild ?? defaultTsServerConfig.esbuild,
|
|
76
|
+
https: serverConfig?.https ?? defaultTsServerConfig.https,
|
|
77
|
+
http2: serverConfig?.http2 ?? defaultTsServerConfig.http2,
|
|
78
|
+
devServer: serverConfig?.devServer ?? defaultTsServerConfig.devServer
|
|
79
|
+
};
|
|
80
|
+
const appEntry = path__default.resolve(
|
|
81
|
+
resolvedConfig.rootDir,
|
|
82
|
+
resolvedConfig.srcDir,
|
|
83
|
+
resolvedConfig.entry
|
|
84
|
+
);
|
|
85
|
+
if (!fs.existsSync(appEntry)) {
|
|
86
|
+
throw new Error(`Unable to find entry at ${appEntry}`);
|
|
87
|
+
}
|
|
88
|
+
await startBuild(generators, resolvedConfig, args.skipCodegen);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const defaultTsServerConfig = {
|
|
93
|
+
port: 3e3,
|
|
94
|
+
entry: "app.ts",
|
|
95
|
+
serverEntry: "",
|
|
96
|
+
rootDir: ".",
|
|
97
|
+
srcDir: "src",
|
|
98
|
+
procedureDir: "procedures",
|
|
99
|
+
procedureGlobPatterns: ["**/*.rpc.ts"],
|
|
100
|
+
buildDir: ".arri",
|
|
101
|
+
esbuild: {},
|
|
102
|
+
https: false,
|
|
103
|
+
http2: false,
|
|
104
|
+
devServer: {
|
|
105
|
+
additionalWatchDirs: void 0,
|
|
106
|
+
httpWithHttps: void 0,
|
|
107
|
+
httpWithHttpsPort: void 0
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
async function startBuild(generators, serverConfig, skipCodeGen = false) {
|
|
111
|
+
common.logger.log("Bundling server....");
|
|
112
|
+
const appEntry = path__default.resolve(
|
|
113
|
+
serverConfig.rootDir,
|
|
114
|
+
serverConfig.srcDir,
|
|
115
|
+
serverConfig.entry
|
|
116
|
+
);
|
|
117
|
+
if (!fs.existsSync(
|
|
118
|
+
path__default.resolve(
|
|
119
|
+
serverConfig.rootDir,
|
|
120
|
+
serverConfig.srcDir,
|
|
121
|
+
serverConfig.entry
|
|
122
|
+
)
|
|
123
|
+
)) {
|
|
124
|
+
common.logger.error(`Unable to find entry at ${appEntry}`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
await setupWorkingDir(serverConfig);
|
|
128
|
+
await Promise.all([
|
|
129
|
+
createAppWithRoutesModule(serverConfig),
|
|
130
|
+
createServerEntryFile(serverConfig),
|
|
131
|
+
createCodegenEntryFile(serverConfig)
|
|
132
|
+
]);
|
|
133
|
+
await bundleAppEntry(serverConfig);
|
|
134
|
+
common.logger.log("Finished bundling");
|
|
135
|
+
const clientCount = generators.length ?? 0;
|
|
136
|
+
const codegenModule = path__default.resolve(
|
|
137
|
+
serverConfig.rootDir,
|
|
138
|
+
".output",
|
|
139
|
+
OUT_CODEGEN
|
|
140
|
+
);
|
|
141
|
+
if (!skipCodeGen) {
|
|
142
|
+
common.logger.log("Generating Arri app definition (__definition.json)");
|
|
143
|
+
node_child_process.execSync(`node ${codegenModule}`, { env: process.env });
|
|
144
|
+
const defJson = path__default.resolve(
|
|
145
|
+
serverConfig.rootDir,
|
|
146
|
+
".output",
|
|
147
|
+
"__definition.json"
|
|
148
|
+
);
|
|
149
|
+
const def = JSON.parse(fs.readFileSync(defJson, { encoding: "utf-8" }));
|
|
150
|
+
if (codegenUtils.isAppDefinition(def) && clientCount > 0) {
|
|
151
|
+
const startTime = (/* @__PURE__ */ new Date()).getTime();
|
|
152
|
+
common.logger.log(`Generating ${clientCount} client(s)...`);
|
|
153
|
+
await Promise.all(
|
|
154
|
+
generators.map((plugin) => plugin.generator(def)) ?? []
|
|
155
|
+
);
|
|
156
|
+
common.logger.log(
|
|
157
|
+
`${clientCount} client(s) generated in ${( new Date()).getTime() - startTime}ms`
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
common.logger.warn(
|
|
161
|
+
"No client generators specified. Skipping client codegen."
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
common.logger.log("Skipping codegen");
|
|
166
|
+
}
|
|
167
|
+
common.logger.log("Cleaning up files");
|
|
168
|
+
await fs__namespace.rm(codegenModule);
|
|
169
|
+
common.logger.success(
|
|
170
|
+
`Build finished! You can start your server by running "node .output/${OUT_SERVER_ENTRY}"`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
async function bundleAppEntry(config, _allowCodegen = true) {
|
|
174
|
+
const appEntry = path__default.resolve(
|
|
175
|
+
config.rootDir,
|
|
176
|
+
config.buildDir,
|
|
177
|
+
GEN_APP_FILE
|
|
178
|
+
);
|
|
179
|
+
await esbuild__default.build({
|
|
180
|
+
...config.esbuild,
|
|
181
|
+
entryPoints: [appEntry],
|
|
182
|
+
platform: config.esbuild.platform ?? "node",
|
|
183
|
+
target: config.esbuild.target ?? "node20",
|
|
184
|
+
bundle: true,
|
|
185
|
+
packages: "external",
|
|
186
|
+
format: "esm",
|
|
187
|
+
sourcemap: config.esbuild.sourcemap ?? true,
|
|
188
|
+
minify: config.esbuild.minify ?? true,
|
|
189
|
+
banner: {
|
|
190
|
+
js: `import { createRequire as topLevelCreateRequire } from 'module';
|
|
191
|
+
const require = topLevelCreateRequire(import.meta.url);`
|
|
192
|
+
},
|
|
193
|
+
allowOverwrite: true,
|
|
194
|
+
outfile: path__default.resolve(config.rootDir, ".output", OUT_APP_FILE)
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
async function createServerEntryFile(config) {
|
|
198
|
+
if (config.serverEntry) {
|
|
199
|
+
const buildEntry = path__default.resolve(
|
|
200
|
+
config.rootDir,
|
|
201
|
+
config.srcDir,
|
|
202
|
+
config.serverEntry
|
|
203
|
+
);
|
|
204
|
+
await esbuild__default.build({
|
|
205
|
+
...config.esbuild,
|
|
206
|
+
entryPoints: [buildEntry],
|
|
207
|
+
platform: config.esbuild.platform ?? "node",
|
|
208
|
+
target: config.esbuild.target ?? "node20",
|
|
209
|
+
bundle: false,
|
|
210
|
+
packages: "external",
|
|
211
|
+
format: "esm",
|
|
212
|
+
sourcemap: true,
|
|
213
|
+
minifyWhitespace: true,
|
|
214
|
+
banner: {
|
|
215
|
+
js: `import { createRequire as topLevelCreateRequire } from 'module';
|
|
216
|
+
const require = topLevelCreateRequire(import.meta.url);`
|
|
217
|
+
},
|
|
218
|
+
plugins: [esbuildPluginReplace.replace({ "virtual:arri/app": "./app.mjs" })],
|
|
219
|
+
allowOverwrite: true,
|
|
220
|
+
outfile: path__default.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY)
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const appModule = path__default.resolve(config.rootDir, config.srcDir, config.entry);
|
|
225
|
+
const appImportParts = path__default.relative(path__default.resolve(config.rootDir, config.srcDir), appModule).split(".");
|
|
226
|
+
appImportParts.pop();
|
|
227
|
+
let httpsString = ``;
|
|
228
|
+
if (config.https === true) {
|
|
229
|
+
httpsString = `https: true,`;
|
|
230
|
+
} else if (typeof config.https === "object") {
|
|
231
|
+
httpsString = `https: { cert: '${config.https.cert}', key: '${config.https.key}', passphrase: ${config.https.passphrase ? `'${config.https.passphrase}'` : "undefined"}},`;
|
|
232
|
+
}
|
|
233
|
+
const virtualEntry = `import { toNodeListener } from '@arrirpc/server';
|
|
234
|
+
import { listen } from '@joshmossas/listhen';
|
|
235
|
+
import app from './${OUT_APP_FILE}';
|
|
236
|
+
|
|
237
|
+
void listen(toNodeListener(app.h3App), {
|
|
238
|
+
port: process.env.PORT ?? ${config.port},
|
|
239
|
+
public: true,
|
|
240
|
+
ws: {
|
|
241
|
+
resolve(info) {
|
|
242
|
+
if (app.h3App.websocket?.resolve) {
|
|
243
|
+
return app.h3App.websocket.resolve(info);
|
|
244
|
+
}
|
|
245
|
+
return app.h3App.websocket?.hooks ?? app.h3App.handler?.__websocket__ ?? {};
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
http2: ${config.http2 ?? false},
|
|
249
|
+
${httpsString}
|
|
250
|
+
});`;
|
|
251
|
+
await fs__namespace.writeFile(
|
|
252
|
+
path__default.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY),
|
|
253
|
+
virtualEntry
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
async function createCodegenEntryFile(config) {
|
|
257
|
+
const appModule = path__default.resolve(config.rootDir, config.srcDir, config.entry);
|
|
258
|
+
const appImportParts = path__default.relative(path__default.resolve(config.rootDir, config.srcDir), appModule).split(".");
|
|
259
|
+
appImportParts.pop();
|
|
260
|
+
const virtualModule = await prettier__default.format(
|
|
261
|
+
`
|
|
262
|
+
import { writeFileSync } from 'node:fs';
|
|
263
|
+
import path from 'pathe';
|
|
264
|
+
import app from './${OUT_APP_FILE}';
|
|
265
|
+
|
|
266
|
+
const __dirname = new URL(".", import.meta.url).pathname;
|
|
267
|
+
const def = app.getAppDefinition();
|
|
268
|
+
writeFileSync(
|
|
269
|
+
path.resolve(__dirname, "../.output", "__definition.json"),
|
|
270
|
+
JSON.stringify(def),
|
|
271
|
+
);
|
|
272
|
+
process.exit(0);`,
|
|
273
|
+
{ tabWidth: 4, parser: "typescript" }
|
|
274
|
+
);
|
|
275
|
+
await fs__namespace.writeFile(
|
|
276
|
+
path__default.resolve(config.rootDir, ".output", OUT_CODEGEN),
|
|
277
|
+
virtualModule
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
async function bundleFilesContext(config) {
|
|
281
|
+
return await esbuild__default.context({
|
|
282
|
+
...config.esbuild,
|
|
283
|
+
entryPoints: [
|
|
284
|
+
path__default.resolve(config.rootDir, config.buildDir, GEN_APP_FILE)
|
|
285
|
+
],
|
|
286
|
+
outfile: path__default.resolve(config.rootDir, ".output", OUT_APP_FILE),
|
|
287
|
+
format: "esm",
|
|
288
|
+
bundle: true,
|
|
289
|
+
packages: "external",
|
|
290
|
+
sourcemap: config.esbuild.sourcemap ?? true,
|
|
291
|
+
target: config.esbuild.target ?? "node20",
|
|
292
|
+
platform: config.esbuild.platform ?? "node"
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
async function createDevServer(config) {
|
|
296
|
+
const h3$1 = await import('h3');
|
|
297
|
+
const app = h3$1.createApp();
|
|
298
|
+
const dynamicHandler = h3.dynamicEventHandler(
|
|
299
|
+
() => "<div>initializing server...</div>"
|
|
300
|
+
);
|
|
301
|
+
app.use(dynamicHandler);
|
|
302
|
+
let ws;
|
|
303
|
+
const listener = await listhen.listen(h3.toNodeListener(app), {
|
|
304
|
+
port: config.port,
|
|
305
|
+
https: config.https,
|
|
306
|
+
http2: config.http2,
|
|
307
|
+
public: true,
|
|
308
|
+
ws: {
|
|
309
|
+
resolve(info) {
|
|
310
|
+
if (ws?.resolve) {
|
|
311
|
+
return ws.resolve(info);
|
|
312
|
+
}
|
|
313
|
+
return {};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
let secondaryListener;
|
|
318
|
+
if (config.devServer.httpWithHttps) {
|
|
319
|
+
secondaryListener = await listhen.listen(h3.toNodeListener(app), {
|
|
320
|
+
port: config.devServer.httpWithHttpsPort ?? config.port + 1,
|
|
321
|
+
https: false,
|
|
322
|
+
http2: config.http2,
|
|
323
|
+
public: true,
|
|
324
|
+
ws: {
|
|
325
|
+
resolve(info) {
|
|
326
|
+
if (ws?.resolve) {
|
|
327
|
+
return ws.resolve(info);
|
|
328
|
+
}
|
|
329
|
+
return {};
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
qr: false,
|
|
333
|
+
showURL: false
|
|
334
|
+
});
|
|
335
|
+
common.logger.info(
|
|
336
|
+
`Serving unencrypted traffic from port ${secondaryListener.address.port}`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
async function reload() {
|
|
340
|
+
const appEntry = (await import(path__default.resolve(
|
|
341
|
+
config.rootDir,
|
|
342
|
+
".output",
|
|
343
|
+
`${OUT_APP_FILE}?version=${Date.now()}`
|
|
344
|
+
))).default;
|
|
345
|
+
dynamicHandler.set(h3.fromNodeMiddleware(appEntry.h3App.handler));
|
|
346
|
+
ws = appEntry.h3App.websocket;
|
|
347
|
+
return appEntry.getAppDefinition();
|
|
348
|
+
}
|
|
349
|
+
await reload();
|
|
350
|
+
return {
|
|
351
|
+
h3App: app,
|
|
352
|
+
listener,
|
|
353
|
+
secondaryListener,
|
|
354
|
+
reload,
|
|
355
|
+
ws
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
async function startDevServer(config, generators) {
|
|
359
|
+
await setupWorkingDir(config);
|
|
360
|
+
const watcher = await import('chokidar');
|
|
361
|
+
let fileWatcher;
|
|
362
|
+
await createAppWithRoutesModule(config);
|
|
363
|
+
const context = await bundleFilesContext(config);
|
|
364
|
+
await context.rebuild();
|
|
365
|
+
const devServer = await createDevServer(config);
|
|
366
|
+
let appDef = await devServer.reload();
|
|
367
|
+
let appDefStr = JSON.stringify(appDef);
|
|
368
|
+
if (generators.length) {
|
|
369
|
+
common.logger.info(`Running generators...`);
|
|
370
|
+
await generateClientsFromDefinition(appDef, generators);
|
|
371
|
+
} else {
|
|
372
|
+
common.logger.warn(`No generators specified in config. Skipping codegen.`);
|
|
373
|
+
}
|
|
374
|
+
const cleanExit = async () => {
|
|
375
|
+
process.exit();
|
|
376
|
+
};
|
|
377
|
+
process.on("exit", async () => {
|
|
378
|
+
await Promise.allSettled([fileWatcher?.close(), context.dispose()]);
|
|
379
|
+
});
|
|
380
|
+
process.on("SIGINT", cleanExit);
|
|
381
|
+
process.on("SIGTERM", cleanExit);
|
|
382
|
+
async function load(_isRestart, _reason) {
|
|
383
|
+
if (fileWatcher) {
|
|
384
|
+
await fileWatcher.close();
|
|
385
|
+
}
|
|
386
|
+
const srcDir = path__default.resolve(config.rootDir ?? "", config.srcDir);
|
|
387
|
+
const dirsToWatch = [srcDir];
|
|
388
|
+
if (config.esbuild.alias) {
|
|
389
|
+
for (const key of Object.keys(config.esbuild.alias)) {
|
|
390
|
+
const alias = config.esbuild.alias[key];
|
|
391
|
+
if (alias) {
|
|
392
|
+
if (!common.isInsideDir(alias, srcDir)) {
|
|
393
|
+
dirsToWatch.push(alias);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (config.devServer.additionalWatchDirs?.length) {
|
|
399
|
+
for (const dir of config.devServer.additionalWatchDirs) {
|
|
400
|
+
dirsToWatch.push(dir);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const buildDir = path__default.resolve(config.rootDir, config.buildDir);
|
|
404
|
+
const outDir = path__default.resolve(config.rootDir, ".output");
|
|
405
|
+
fileWatcher = watcher.watch(dirsToWatch, {
|
|
406
|
+
ignoreInitial: true,
|
|
407
|
+
ignored: [
|
|
408
|
+
buildDir,
|
|
409
|
+
outDir,
|
|
410
|
+
"**/.output",
|
|
411
|
+
"**/dist/**",
|
|
412
|
+
"**/node_modules/**",
|
|
413
|
+
"**/.git/**"
|
|
414
|
+
]
|
|
415
|
+
});
|
|
416
|
+
fileWatcher.on("all", async (eventName, _path) => {
|
|
417
|
+
if (eventName === "addDir" || eventName === "add") {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
await createAppWithRoutesModule(config);
|
|
421
|
+
try {
|
|
422
|
+
const reloadStart = (/* @__PURE__ */ new Date()).getTime();
|
|
423
|
+
common.logger.log(
|
|
424
|
+
"Change detected. Bundling files and restarting server...."
|
|
425
|
+
);
|
|
426
|
+
await context.rebuild();
|
|
427
|
+
const newAppDef = await devServer.reload();
|
|
428
|
+
const newAppDefStr = JSON.stringify(newAppDef);
|
|
429
|
+
common.logger.log(
|
|
430
|
+
`Server restarted in ${( new Date()).getTime() - reloadStart}ms`
|
|
431
|
+
);
|
|
432
|
+
if (generators.length && newAppDefStr !== appDefStr) {
|
|
433
|
+
common.logger.info(
|
|
434
|
+
`App Definition updated. Regenerating clients...`
|
|
435
|
+
);
|
|
436
|
+
await generateClientsFromDefinition(newAppDef, generators);
|
|
437
|
+
appDef = newAppDef;
|
|
438
|
+
appDefStr = newAppDefStr;
|
|
439
|
+
}
|
|
440
|
+
} catch (err) {
|
|
441
|
+
common.logger.error("ERROR", err);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
await load();
|
|
446
|
+
}
|
|
447
|
+
async function generateClientsFromDefinition(appDef, generators) {
|
|
448
|
+
const startTime = (/* @__PURE__ */ new Date()).getTime();
|
|
449
|
+
try {
|
|
450
|
+
const clientCount = generators.length;
|
|
451
|
+
await Promise.allSettled(
|
|
452
|
+
generators.map((generator) => generator.generator(appDef, true))
|
|
453
|
+
);
|
|
454
|
+
common.logger.success(
|
|
455
|
+
`Generated ${clientCount} client${clientCount === 1 ? "" : "s"} in ${( new Date()).getTime() - startTime}ms`
|
|
456
|
+
);
|
|
457
|
+
} catch (err) {
|
|
458
|
+
common.logger.error(err);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
const GEN_APP_FILE = "__arri_app.ts";
|
|
462
|
+
const OUT_APP_FILE = "app.mjs";
|
|
463
|
+
const OUT_SERVER_ENTRY = "server.mjs";
|
|
464
|
+
const OUT_CODEGEN = "codegen.mjs";
|
|
465
|
+
async function setupWorkingDir(config) {
|
|
466
|
+
const arriDir = path__default.resolve(config.rootDir, config.buildDir);
|
|
467
|
+
const outDir = path__default.resolve(config.rootDir, ".output");
|
|
468
|
+
if (fs.existsSync(arriDir)) {
|
|
469
|
+
await fs__namespace.rm(arriDir, { recursive: true, force: true });
|
|
470
|
+
}
|
|
471
|
+
if (fs.existsSync(outDir)) {
|
|
472
|
+
await fs__namespace.rm(outDir, { recursive: true, force: true });
|
|
473
|
+
}
|
|
474
|
+
await fs__namespace.mkdir(arriDir);
|
|
475
|
+
await fs__namespace.mkdir(outDir);
|
|
476
|
+
}
|
|
477
|
+
async function createAppWithRoutesModule(config) {
|
|
478
|
+
const glob = await import('globby');
|
|
479
|
+
const appModule = path__default.resolve(config.rootDir, config.srcDir, config.entry);
|
|
480
|
+
const appImportParts = path__default.relative(path__default.resolve(config.rootDir, config.buildDir), appModule).split(".");
|
|
481
|
+
appImportParts.pop();
|
|
482
|
+
const routes = [];
|
|
483
|
+
const existingRoutes = [];
|
|
484
|
+
await Promise.all(
|
|
485
|
+
config.procedureGlobPatterns.map(async (pattern) => {
|
|
486
|
+
const results = await getFsRouteBatch(glob.globby, pattern, config);
|
|
487
|
+
for (const result of results) {
|
|
488
|
+
if (!existingRoutes.includes(result.name)) {
|
|
489
|
+
routes.push(result);
|
|
490
|
+
existingRoutes.push(result.name);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
})
|
|
494
|
+
);
|
|
495
|
+
routes.sort((a, b) => a.name < b.name ? -1 : 1);
|
|
496
|
+
const module = await prettier__default.format(
|
|
497
|
+
`import sourceMapSupport from 'source-map-support';
|
|
498
|
+
sourceMapSupport.install();
|
|
499
|
+
import app from '${appImportParts.join(".")}';
|
|
500
|
+
${routes.map(
|
|
501
|
+
(route) => `import ${route.importName} from '${route.importPath}';`
|
|
502
|
+
).join("\n")}
|
|
503
|
+
|
|
504
|
+
${routes.map((route) => `app.rpc('${route.name}', ${route.importName});`).join("\n")}
|
|
505
|
+
|
|
506
|
+
export default app;`,
|
|
507
|
+
{ parser: "typescript", tabWidth: 4 }
|
|
508
|
+
);
|
|
509
|
+
await fs__namespace.writeFile(
|
|
510
|
+
path__default.resolve(config.rootDir, config.buildDir, GEN_APP_FILE),
|
|
511
|
+
module
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
async function getFsRouteBatch(glob, globPattern, config) {
|
|
515
|
+
if (!config.procedureDir) {
|
|
516
|
+
return [];
|
|
517
|
+
}
|
|
518
|
+
const target = `${config.rootDir}/${config.srcDir}/${config.procedureDir}/${globPattern}`.split("//").join("/").split("//").join("/");
|
|
519
|
+
const files = await glob(target, {
|
|
520
|
+
onlyFiles: true
|
|
521
|
+
});
|
|
522
|
+
const routes = [];
|
|
523
|
+
for (const file of files) {
|
|
524
|
+
const meta = getRpcMetaFromPath(config, file);
|
|
525
|
+
if (meta) {
|
|
526
|
+
const importParts = path__default.relative(path__default.resolve(config.rootDir, config.buildDir), file).split(".");
|
|
527
|
+
importParts.pop();
|
|
528
|
+
routes.push({
|
|
529
|
+
name: meta.id,
|
|
530
|
+
importName: codegenUtils.camelCase(meta.id.split(".").join("_")),
|
|
531
|
+
importPath: `./${importParts.join(".")}`
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return routes;
|
|
536
|
+
}
|
|
537
|
+
const disallowedNameChars = "~`!@#$%^&*()-+=[]{}\\|:;\"'<>,./";
|
|
538
|
+
const getRpcMetaFromPath = (config, filePath) => {
|
|
539
|
+
if (!config.procedureDir) {
|
|
540
|
+
return void 0;
|
|
541
|
+
}
|
|
542
|
+
const resolvedFilePath = filePath.split("./").join("/");
|
|
543
|
+
const parts = resolvedFilePath.split("/");
|
|
544
|
+
const reversedParts = [...parts].reverse();
|
|
545
|
+
const nameParts = [];
|
|
546
|
+
for (const part of reversedParts) {
|
|
547
|
+
if (part === config.procedureDir) {
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
nameParts.push(part);
|
|
551
|
+
}
|
|
552
|
+
const fileName = nameParts.reverse().pop() ?? "";
|
|
553
|
+
const serviceParts = nameParts.filter((part) => part.trim().length > 0).map((part) => codegenUtils.removeDisallowedChars(part, disallowedNameChars));
|
|
554
|
+
const fileNameParts = fileName.split(".");
|
|
555
|
+
if (!fileNameParts.length) {
|
|
556
|
+
return void 0;
|
|
557
|
+
}
|
|
558
|
+
const rpcName = codegenUtils.removeDisallowedChars(
|
|
559
|
+
fileNameParts[0],
|
|
560
|
+
disallowedNameChars
|
|
561
|
+
);
|
|
562
|
+
const httpParts = [
|
|
563
|
+
...serviceParts.map((part) => codegenUtils.kebabCase(part)),
|
|
564
|
+
codegenUtils.kebabCase(rpcName)
|
|
565
|
+
];
|
|
566
|
+
return {
|
|
567
|
+
id: [...serviceParts, rpcName].join("."),
|
|
568
|
+
httpPath: `/${httpParts.join("/")}`
|
|
569
|
+
};
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const servers = {
|
|
573
|
+
tsServer
|
|
574
|
+
};
|
|
21
575
|
|
|
22
576
|
const generators = {
|
|
23
577
|
dartClient: codegenDart.dartClientGenerator,
|
|
@@ -26,10 +580,11 @@ const generators = {
|
|
|
26
580
|
typescriptClient: codegenTs.typescriptClientGenerator
|
|
27
581
|
};
|
|
28
582
|
|
|
29
|
-
exports.DEV_DEFINITION_ENDPOINT =
|
|
30
|
-
exports.
|
|
31
|
-
exports.
|
|
32
|
-
exports.isArriConfig =
|
|
33
|
-
exports.
|
|
583
|
+
exports.DEV_DEFINITION_ENDPOINT = common.DEV_DEFINITION_ENDPOINT;
|
|
584
|
+
exports.defineConfig = common.defineConfig;
|
|
585
|
+
exports.defineServerConfig = common.defineServerConfig;
|
|
586
|
+
exports.isArriConfig = common.isArriConfig;
|
|
587
|
+
exports.isServerConfig = common.isServerConfig;
|
|
34
588
|
exports.createAppDefinition = codegenUtils.createAppDefinition;
|
|
35
589
|
exports.generators = generators;
|
|
590
|
+
exports.servers = servers;
|
package/dist/index.d.cts
CHANGED
|
@@ -5,11 +5,31 @@ import * as _arrirpc_codegen_utils from '@arrirpc/codegen-utils';
|
|
|
5
5
|
import { Generator } from '@arrirpc/codegen-utils';
|
|
6
6
|
export { AppDefinition, createAppDefinition } from '@arrirpc/codegen-utils';
|
|
7
7
|
import * as _arrirpc_codegen_dart from '@arrirpc/codegen-dart';
|
|
8
|
-
import {
|
|
8
|
+
import { ArgsDef, ParsedArgs } from 'citty';
|
|
9
|
+
import esbuild from 'esbuild';
|
|
9
10
|
|
|
10
11
|
declare const DEV_DEFINITION_ENDPOINT = "/__arri_dev__/__definition";
|
|
11
12
|
|
|
12
|
-
interface
|
|
13
|
+
interface ServerConfig<TDevArgs extends ArgsDef | undefined = any, TBuildArgs extends ArgsDef | undefined = any> {
|
|
14
|
+
devArgs?: TDevArgs;
|
|
15
|
+
buildArgs?: TBuildArgs;
|
|
16
|
+
devFn: (args: TDevArgs extends ArgsDef ? ParsedArgs<TDevArgs> : {}, generators: Generator<any>[]) => any;
|
|
17
|
+
buildFn: (args: (TBuildArgs extends ArgsDef ? ParsedArgs<TBuildArgs> : {}) & {
|
|
18
|
+
skipCodegen?: boolean;
|
|
19
|
+
}, generators: Generator<any>[]) => any;
|
|
20
|
+
}
|
|
21
|
+
declare function isServerConfig(input: unknown): input is ServerConfig<any, any>;
|
|
22
|
+
declare function defineServerConfig<DevArgs extends ArgsDef | undefined = any, BuildArgs extends ArgsDef | undefined = any>(config: ServerConfig<DevArgs, BuildArgs>): ServerConfig<DevArgs, BuildArgs>;
|
|
23
|
+
|
|
24
|
+
interface ArriConfig<TDevArgs extends ArgsDef | undefined = any, TBuildArgs extends ArgsDef | undefined = any> {
|
|
25
|
+
server?: ServerConfig<TDevArgs, TBuildArgs>;
|
|
26
|
+
generators: Generator<any>[];
|
|
27
|
+
}
|
|
28
|
+
declare function isArriConfig(input: unknown): input is ArriConfig;
|
|
29
|
+
declare function defineConfig(config: ArriConfig): ArriConfig;
|
|
30
|
+
|
|
31
|
+
declare function tsServer(serverConfig?: TsServerConfig): ServerConfig<undefined, undefined>;
|
|
32
|
+
interface TsServerConfig {
|
|
13
33
|
port?: number;
|
|
14
34
|
entry?: string;
|
|
15
35
|
serverEntry?: string;
|
|
@@ -20,9 +40,8 @@ interface ArriConfig {
|
|
|
20
40
|
* this defaults to ["***\/*\*.rpc.ts"]
|
|
21
41
|
*/
|
|
22
42
|
procedureGlobPatterns?: string[];
|
|
23
|
-
generators?: Array<Generator<any>>;
|
|
24
43
|
buildDir?: string;
|
|
25
|
-
esbuild?: Omit<BuildOptions, "bundle" | "format" | "outfile" | "outdir" | "entryNames" | "entryPoints" | "packages">;
|
|
44
|
+
esbuild?: Omit<esbuild.BuildOptions, "bundle" | "format" | "outfile" | "outdir" | "entryNames" | "entryPoints" | "packages">;
|
|
26
45
|
https?: {
|
|
27
46
|
cert: string;
|
|
28
47
|
key: string;
|
|
@@ -41,11 +60,10 @@ interface ArriConfig {
|
|
|
41
60
|
httpWithHttpsPort?: number;
|
|
42
61
|
};
|
|
43
62
|
}
|
|
44
|
-
|
|
45
|
-
declare
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
declare function defineConfig(config: ArriConfig): ResolvedArriConfig;
|
|
63
|
+
|
|
64
|
+
declare const servers: {
|
|
65
|
+
readonly tsServer: typeof tsServer;
|
|
66
|
+
};
|
|
49
67
|
|
|
50
68
|
declare const generators: {
|
|
51
69
|
readonly dartClient: _arrirpc_codegen_utils.GeneratorPlugin<_arrirpc_codegen_dart.DartClientGeneratorOptions>;
|
|
@@ -54,4 +72,4 @@ declare const generators: {
|
|
|
54
72
|
readonly typescriptClient: _arrirpc_codegen_utils.GeneratorPlugin<_arrirpc_codegen_ts.TypescriptGeneratorOptions>;
|
|
55
73
|
};
|
|
56
74
|
|
|
57
|
-
export { type ArriConfig, DEV_DEFINITION_ENDPOINT, type
|
|
75
|
+
export { type ArriConfig, DEV_DEFINITION_ENDPOINT, type ServerConfig, type TsServerConfig, defineConfig, defineServerConfig, generators, isArriConfig, isServerConfig, servers };
|