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/dist/cli.mjs CHANGED
@@ -1,25 +1,19 @@
1
1
  #! /usr/bin/env node
2
- import { defineCommand, runMain } from 'citty';
3
- import { execSync } from 'node:child_process';
4
- import fs$1, { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
5
- import fs from 'node:fs/promises';
6
- import { isAppDefinition, kebabCase } from '@arrirpc/codegen-utils';
2
+ import { defineCommand, runCommand, runMain } from 'citty';
7
3
  import { loadConfig } from 'c12';
8
- import { build as build$1 } from 'esbuild';
9
- import { replace } from 'esbuild-plugin-replace';
10
- import path from 'pathe';
11
- import prettier from 'prettier';
12
- import { d as defaultConfig, l as logger, s as setupWorkingDir, c as createAppWithRoutesModule, O as OUT_CODEGEN, e as OUT_SERVER_ENTRY, G as GEN_APP_FILE, f as OUT_APP_FILE, i as isArriConfig, g as getArriPackageMetadata, h as dev } from './shared/arri.339f2f92.mjs';
4
+ import { a as isArriConfig, l as logger, g as getArriPackageMetadata, e as dev } from './shared/arri.f4637ba5.mjs';
5
+ import fs, { rmSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { isAppDefinition, kebabCase } from '@arrirpc/codegen-utils';
7
+ import { ofetch } from '@joshmossas/ofetch';
13
8
  import { watch } from 'chokidar';
14
- import { ofetch } from 'ofetch';
9
+ import path from 'pathe';
15
10
  import Degit from 'degit';
16
11
  import enquirer from 'enquirer';
12
+ import prettier from 'prettier';
17
13
  import { a } from '@arrirpc/schema';
18
14
  import consola from 'consola';
19
15
  import { readFile, writeFile } from 'fs/promises';
20
16
  import { fileURLToPath } from 'node:url';
21
- import '@joshmossas/listhen';
22
- import 'h3';
23
17
 
24
18
  const build = defineCommand({
25
19
  meta: {
@@ -37,181 +31,35 @@ const build = defineCommand({
37
31
  default: false
38
32
  }
39
33
  },
40
- async run({ args }) {
34
+ async run({ args, rawArgs }) {
41
35
  const { config } = await loadConfig({
42
- configFile: args.config,
43
- defaultConfig
36
+ configFile: args.config
44
37
  });
45
38
  if (!config) {
46
39
  throw new Error("Unable to find arri config");
47
40
  }
48
- const appEntry = path.resolve(
49
- config.rootDir,
50
- config.srcDir,
51
- config.entry
52
- );
53
- if (!existsSync(appEntry)) {
54
- throw new Error(`Unable to find entry at ${appEntry}`);
41
+ if (!isArriConfig(config)) {
42
+ throw new Error(`Invalid arri config at ${args.config}`);
55
43
  }
56
- await startBuild(config, args.skipCodegen);
57
- }
58
- });
59
- async function startBuild(config, skipCodeGen = false) {
60
- logger.log("Bundling server....");
61
- const appEntry = path.resolve(config.rootDir, config.srcDir, config.entry);
62
- if (!existsSync(path.resolve(config.rootDir, config.srcDir, config.entry))) {
63
- logger.error(`Unabled to find entry at ${appEntry}`);
64
- process.exit(1);
65
- }
66
- await setupWorkingDir(config);
67
- await Promise.all([
68
- createAppWithRoutesModule(config),
69
- createServerEntryFile(config),
70
- createCodegenEntryFile(config)
71
- ]);
72
- await bundleAppEntry(config);
73
- logger.log("Finished bundling");
74
- const clientCount = config.generators.length;
75
- const codegenModule = path.resolve(config.rootDir, ".output", OUT_CODEGEN);
76
- if (!skipCodeGen) {
77
- logger.log("Generating Arri app definition (__definition.json)");
78
- execSync(`node ${codegenModule}`, { env: process.env });
79
- const defJson = path.resolve(
80
- config.rootDir,
81
- ".output",
82
- "__definition.json"
83
- );
84
- const def = JSON.parse(readFileSync(defJson, { encoding: "utf-8" }));
85
- if (isAppDefinition(def) && clientCount > 0) {
86
- const startTime = (/* @__PURE__ */ new Date()).getTime();
87
- logger.log(`Generating ${clientCount} client(s)...`);
88
- await Promise.all(
89
- config.generators.map((plugin) => plugin.generator(def))
90
- );
91
- logger.log(
92
- `${clientCount} client(s) generated in ${( new Date()).getTime() - startTime}ms`
93
- );
94
- } else {
95
- logger.warn(
96
- "No client generators specified. Skipping client codegen."
44
+ if (!config.server) {
45
+ throw new Error(
46
+ "No server specified in config file. Cannot run build."
97
47
  );
98
48
  }
99
- } else {
100
- logger.log("Skipping codegen");
101
- }
102
- logger.log("Cleaning up files");
103
- await fs.rm(codegenModule);
104
- logger.success(
105
- `Build finished! You can start your server by running "node .output/${OUT_SERVER_ENTRY}"`
106
- );
107
- }
108
- async function bundleAppEntry(config, _allowCodegen = true) {
109
- const appEntry = path.resolve(
110
- config.rootDir,
111
- config.buildDir,
112
- GEN_APP_FILE
113
- );
114
- await build$1({
115
- ...config.esbuild,
116
- entryPoints: [appEntry],
117
- platform: config.esbuild.platform ?? "node",
118
- target: config.esbuild.target ?? "node20",
119
- bundle: true,
120
- packages: "external",
121
- format: "esm",
122
- sourcemap: config.esbuild.sourcemap ?? true,
123
- minify: config.esbuild.minify ?? true,
124
- banner: {
125
- js: `import { createRequire as topLevelCreateRequire } from 'module';
126
- const require = topLevelCreateRequire(import.meta.url);`
127
- },
128
- allowOverwrite: true,
129
- outfile: path.resolve(config.rootDir, ".output", OUT_APP_FILE)
130
- });
131
- }
132
- async function createServerEntryFile(config) {
133
- if (config.serverEntry) {
134
- const buildEntry = path.resolve(
135
- config.rootDir,
136
- config.srcDir,
137
- config.serverEntry
138
- );
139
- await build$1({
140
- ...config.esbuild,
141
- entryPoints: [buildEntry],
142
- platform: config.esbuild.platform ?? "node",
143
- target: config.esbuild.target ?? "node20",
144
- bundle: false,
145
- packages: "external",
146
- format: "esm",
147
- sourcemap: true,
148
- minifyWhitespace: true,
149
- banner: {
150
- js: `import { createRequire as topLevelCreateRequire } from 'module';
151
- const require = topLevelCreateRequire(import.meta.url);`
152
- },
153
- plugins: [replace({ "virtual:arri/app": "./app.mjs" })],
154
- allowOverwrite: true,
155
- outfile: path.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY)
49
+ const subArgs = config.server.buildArgs ?? {};
50
+ subArgs.skipCodegen = {
51
+ type: "boolean",
52
+ default: false
53
+ };
54
+ const subCommand = defineCommand({
55
+ args: subArgs,
56
+ async run({ args: args2 }) {
57
+ await config.server?.buildFn(args2, config.generators);
58
+ }
156
59
  });
157
- return;
60
+ await runCommand(subCommand, { rawArgs });
158
61
  }
159
- const appModule = path.resolve(config.rootDir, config.srcDir, config.entry);
160
- const appImportParts = path.relative(path.resolve(config.rootDir, config.srcDir), appModule).split(".");
161
- appImportParts.pop();
162
- let httpsString = ``;
163
- if (config.https === true) {
164
- httpsString = `https: true,`;
165
- } else if (typeof config.https === "object") {
166
- httpsString = `https: { cert: '${config.https.cert}', key: '${config.https.key}', passphrase: ${config.https.passphrase ? `'${config.https.passphrase}'` : "undefined"}},`;
167
- }
168
- const virtualEntry = `import { toNodeListener } from '@arrirpc/server';
169
- import { listen } from '@joshmossas/listhen';
170
- import app from './${OUT_APP_FILE}';
171
-
172
- void listen(toNodeListener(app.h3App), {
173
- port: process.env.PORT ?? ${config.port},
174
- public: true,
175
- ws: {
176
- resolve(info) {
177
- if (app.h3App.websocket?.resolve) {
178
- return app.h3App.websocket.resolve(info);
179
- }
180
- return app.h3App.websocket?.hooks ?? app.h3App.handler?.__websocket__ ?? {};
181
- }
182
- },
183
- http2: ${config.http2 ?? false},
184
- ${httpsString}
185
- });`;
186
- await fs.writeFile(
187
- path.resolve(config.rootDir, ".output", OUT_SERVER_ENTRY),
188
- virtualEntry
189
- );
190
- }
191
- async function createCodegenEntryFile(config) {
192
- const appModule = path.resolve(config.rootDir, config.srcDir, config.entry);
193
- const appImportParts = path.relative(path.resolve(config.rootDir, config.srcDir), appModule).split(".");
194
- appImportParts.pop();
195
- const virtualModule = await prettier.format(
196
- `
197
- import { writeFileSync } from 'node:fs';
198
- import path from 'pathe';
199
- import app from './${OUT_APP_FILE}';
200
-
201
- const __dirname = new URL(".", import.meta.url).pathname;
202
- const def = app.getAppDefinition();
203
- writeFileSync(
204
- path.resolve(__dirname, "../.output", "__definition.json"),
205
- JSON.stringify(def),
206
- );
207
- process.exit(0);`,
208
- { tabWidth: 4, parser: "typescript" }
209
- );
210
- await fs.writeFile(
211
- path.resolve(config.rootDir, ".output", OUT_CODEGEN),
212
- virtualModule
213
- );
214
- }
62
+ });
215
63
 
216
64
  const codegen = defineCommand({
217
65
  meta: {
@@ -236,7 +84,7 @@ const codegen = defineCommand({
236
84
  }
237
85
  },
238
86
  async run({ args }) {
239
- if (!fs$1.existsSync(path.resolve(args.config))) {
87
+ if (!fs.existsSync(path.resolve(args.config))) {
240
88
  logger.error(
241
89
  `Unable to load arri config at ${args.config}. Please specify a valid config path with --config`
242
90
  );
@@ -320,7 +168,7 @@ const codegen = defineCommand({
320
168
  }
321
169
  });
322
170
  async function getAppDefinitionFromFile(file) {
323
- if (!fs$1.existsSync(file)) {
171
+ if (!fs.existsSync(file)) {
324
172
  throw new Error(`Unable to find ${file}`);
325
173
  }
326
174
  const isTs = file.endsWith(".ts");
@@ -335,7 +183,7 @@ async function getAppDefinitionFromFile(file) {
335
183
  return schemaResult.config;
336
184
  } else {
337
185
  const parsingResult = JSON.parse(
338
- fs$1.readFileSync(file, { encoding: "utf-8" })
186
+ fs.readFileSync(file, { encoding: "utf-8" })
339
187
  );
340
188
  if (!isAppDefinition(parsingResult)) {
341
189
  throw new Error(`Invalid App Definition at ${file}`);
@@ -413,10 +261,10 @@ const init = defineCommand({
413
261
  }
414
262
  }
415
263
  const dir = path.resolve(context.args.dir);
416
- if (!fs$1.existsSync(dir)) {
417
- fs$1.mkdirSync(dir);
264
+ if (!fs.existsSync(dir)) {
265
+ fs.mkdirSync(dir);
418
266
  }
419
- const dirFiles = fs$1.readdirSync(dir);
267
+ const dirFiles = fs.readdirSync(dir);
420
268
  if (dirFiles.length && !context.args.force) {
421
269
  logger.error(
422
270
  `"${context.args.dir}" is a non-empty directory. To continue with this operation rerun "arri init" with the --force flag.`