arri 0.63.2 → 0.64.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.cjs CHANGED
@@ -9,10 +9,10 @@ const codegenUtils = require('@arrirpc/codegen-utils');
9
9
  const chokidar = require('chokidar');
10
10
  const ofetch = require('ofetch');
11
11
  const path = require('pathe');
12
+ const schema = require('@arrirpc/schema');
12
13
  const Degit = require('degit');
13
14
  const enquirer = require('enquirer');
14
15
  const prettier = require('prettier');
15
- const schema = require('@arrirpc/schema');
16
16
  const consola = require('consola');
17
17
  const promises = require('fs/promises');
18
18
  const node_url = require('node:url');
@@ -218,6 +218,13 @@ async function runGenerators(def, generators) {
218
218
  );
219
219
  }
220
220
 
221
+ const Language = schema.a.enumerator(["typescript", "go"]);
222
+ const CliArgs = schema.a.object({
223
+ dir: schema.a.string(),
224
+ force: schema.a.optional(schema.a.boolean()),
225
+ type: schema.a.optional(schema.a.enumerator(["app", "plugin"])),
226
+ language: schema.a.optional(Language)
227
+ });
221
228
  const init = citty.defineCommand({
222
229
  meta: {
223
230
  name: "Init",
@@ -238,19 +245,17 @@ const init = citty.defineCommand({
238
245
  type: {
239
246
  type: "string",
240
247
  description: `"app" | "plugin"`
248
+ },
249
+ language: {
250
+ type: "string",
251
+ alias: ["lang", "l"],
252
+ description: `"typescript" | "go"`
241
253
  }
242
254
  },
243
255
  async run(context) {
244
- let type;
245
- switch (context.args.type?.toLowerCase()) {
246
- case "app":
247
- type = "app";
248
- break;
249
- case "plugin":
250
- type = "plugin";
251
- break;
252
- }
253
- if (!type) {
256
+ console.log(context.args);
257
+ const args = schema.a.parse(CliArgs, context.args);
258
+ if (!args.type) {
254
259
  const { projectType } = await enquirer__default.prompt([
255
260
  {
256
261
  type: "select",
@@ -261,10 +266,10 @@ const init = citty.defineCommand({
261
266
  ]);
262
267
  switch (projectType) {
263
268
  case "application":
264
- type = "app";
269
+ args.type = "app";
265
270
  break;
266
271
  case "generator plugin":
267
- type = "plugin";
272
+ args.type = "plugin";
268
273
  break;
269
274
  default:
270
275
  throw new Error(
@@ -272,6 +277,17 @@ const init = citty.defineCommand({
272
277
  );
273
278
  }
274
279
  }
280
+ if (!args.language) {
281
+ const { language } = await enquirer__default.prompt([
282
+ {
283
+ type: "select",
284
+ name: "language",
285
+ message: "What language do you want to use?",
286
+ choices: ["typescript", "go"]
287
+ }
288
+ ]);
289
+ args.language = language;
290
+ }
275
291
  const dir = path__default.resolve(context.args.dir);
276
292
  if (!fs__default.existsSync(dir)) {
277
293
  fs__default.mkdirSync(dir);
@@ -283,21 +299,31 @@ const init = citty.defineCommand({
283
299
  );
284
300
  process.exit(1);
285
301
  }
286
- switch (type) {
302
+ switch (args.type) {
287
303
  case "app":
288
- await initApp(context.args.dir, context.args.force);
304
+ await initApp(args.dir, args.language, args.force ?? false);
289
305
  break;
290
306
  case "plugin":
291
- await initPlugin(context.args.dir, context.args.force);
307
+ await initPlugin(args.dir, args.force ?? false);
292
308
  break;
293
309
  default:
294
- common.logger.error(`Unknown app type: '${type}'"`);
310
+ common.logger.error(`Unknown app type: '${args.type}'"`);
295
311
  break;
296
312
  }
297
313
  process.exit(0);
298
314
  }
299
315
  });
300
- async function initApp(dir, force) {
316
+ async function initApp(dir, language, force) {
317
+ switch (language) {
318
+ case "typescript":
319
+ return initTypescriptApp(dir, force);
320
+ case "go":
321
+ return initGoApp(dir, force);
322
+ default:
323
+ throw new Error(`Unknown language ${language}`);
324
+ }
325
+ }
326
+ async function initTypescriptApp(dir, force) {
301
327
  const { eslint } = await enquirer__default.prompt([
302
328
  {
303
329
  name: "eslint",
@@ -316,6 +342,28 @@ async function initApp(dir, force) {
316
342
  force
317
343
  });
318
344
  await degit.clone(dir);
345
+ await cleanPackageJsonAndPnpmLockFiles(dir);
346
+ common.logger.success(`Project initialized in ${dir}!`);
347
+ common.logger.info(`To get started:
348
+ - cd ${dir}
349
+ - pnpm install
350
+ - pnpm run dev`);
351
+ }
352
+ async function initGoApp(dir, force) {
353
+ const degit = Degit__default("modiimedia/arri-starters/app-starter-go", { force });
354
+ await degit.clone(dir);
355
+ await cleanPackageJsonAndPnpmLockFiles(dir);
356
+ common.logger.success(`Project created in ${dir}!`);
357
+ common.logger.info(
358
+ `To get started:
359
+ - cd ${dir}
360
+ - go get
361
+ - go mod tidy
362
+ - pnpm install / npm install
363
+ - pnpm run dev / npm install`
364
+ );
365
+ }
366
+ async function cleanPackageJsonAndPnpmLockFiles(dir) {
319
367
  fs.rmSync(path__default.resolve(dir, "pnpm-lock.yaml"));
320
368
  const packageJson = JSON.parse(
321
369
  fs.readFileSync(path__default.resolve(dir, "package.json"), {
@@ -323,6 +371,9 @@ async function initApp(dir, force) {
323
371
  })
324
372
  );
325
373
  packageJson.name = codegenUtils.kebabCase(dir);
374
+ if (packageJson.name.startsWith("-")) {
375
+ packageJson.name = packageJson.name.replace("-", "");
376
+ }
326
377
  packageJson.description = "An RPC server created with Arri RPC";
327
378
  packageJson.private = true;
328
379
  delete packageJson.license;
@@ -340,11 +391,6 @@ async function initApp(dir, force) {
340
391
  trailingComma: "all"
341
392
  })
342
393
  );
343
- common.logger.success(`Project initialized in ${dir}!`);
344
- common.logger.info(`To get started:
345
- - cd ${dir}
346
- - pnpm install
347
- - pnpm run dev`);
348
394
  }
349
395
  async function initPlugin(dir, force) {
350
396
  const name = codegenUtils.kebabCase(dir);
package/dist/cli.mjs CHANGED
@@ -7,10 +7,10 @@ import { isAppDefinition, kebabCase } from '@arrirpc/codegen-utils';
7
7
  import { watch } from 'chokidar';
8
8
  import { ofetch } from 'ofetch';
9
9
  import path from 'pathe';
10
+ import { a } from '@arrirpc/schema';
10
11
  import Degit from 'degit';
11
12
  import enquirer from 'enquirer';
12
13
  import prettier from 'prettier';
13
- import { a } from '@arrirpc/schema';
14
14
  import consola from 'consola';
15
15
  import { readFile, writeFile } from 'fs/promises';
16
16
  import { fileURLToPath } from 'node:url';
@@ -206,6 +206,13 @@ async function runGenerators(def, generators) {
206
206
  );
207
207
  }
208
208
 
209
+ const Language = a.enumerator(["typescript", "go"]);
210
+ const CliArgs = a.object({
211
+ dir: a.string(),
212
+ force: a.optional(a.boolean()),
213
+ type: a.optional(a.enumerator(["app", "plugin"])),
214
+ language: a.optional(Language)
215
+ });
209
216
  const init = defineCommand({
210
217
  meta: {
211
218
  name: "Init",
@@ -226,19 +233,17 @@ const init = defineCommand({
226
233
  type: {
227
234
  type: "string",
228
235
  description: `"app" | "plugin"`
236
+ },
237
+ language: {
238
+ type: "string",
239
+ alias: ["lang", "l"],
240
+ description: `"typescript" | "go"`
229
241
  }
230
242
  },
231
243
  async run(context) {
232
- let type;
233
- switch (context.args.type?.toLowerCase()) {
234
- case "app":
235
- type = "app";
236
- break;
237
- case "plugin":
238
- type = "plugin";
239
- break;
240
- }
241
- if (!type) {
244
+ console.log(context.args);
245
+ const args = a.parse(CliArgs, context.args);
246
+ if (!args.type) {
242
247
  const { projectType } = await enquirer.prompt([
243
248
  {
244
249
  type: "select",
@@ -249,10 +254,10 @@ const init = defineCommand({
249
254
  ]);
250
255
  switch (projectType) {
251
256
  case "application":
252
- type = "app";
257
+ args.type = "app";
253
258
  break;
254
259
  case "generator plugin":
255
- type = "plugin";
260
+ args.type = "plugin";
256
261
  break;
257
262
  default:
258
263
  throw new Error(
@@ -260,6 +265,17 @@ const init = defineCommand({
260
265
  );
261
266
  }
262
267
  }
268
+ if (!args.language) {
269
+ const { language } = await enquirer.prompt([
270
+ {
271
+ type: "select",
272
+ name: "language",
273
+ message: "What language do you want to use?",
274
+ choices: ["typescript", "go"]
275
+ }
276
+ ]);
277
+ args.language = language;
278
+ }
263
279
  const dir = path.resolve(context.args.dir);
264
280
  if (!fs.existsSync(dir)) {
265
281
  fs.mkdirSync(dir);
@@ -271,21 +287,31 @@ const init = defineCommand({
271
287
  );
272
288
  process.exit(1);
273
289
  }
274
- switch (type) {
290
+ switch (args.type) {
275
291
  case "app":
276
- await initApp(context.args.dir, context.args.force);
292
+ await initApp(args.dir, args.language, args.force ?? false);
277
293
  break;
278
294
  case "plugin":
279
- await initPlugin(context.args.dir, context.args.force);
295
+ await initPlugin(args.dir, args.force ?? false);
280
296
  break;
281
297
  default:
282
- logger.error(`Unknown app type: '${type}'"`);
298
+ logger.error(`Unknown app type: '${args.type}'"`);
283
299
  break;
284
300
  }
285
301
  process.exit(0);
286
302
  }
287
303
  });
288
- async function initApp(dir, force) {
304
+ async function initApp(dir, language, force) {
305
+ switch (language) {
306
+ case "typescript":
307
+ return initTypescriptApp(dir, force);
308
+ case "go":
309
+ return initGoApp(dir, force);
310
+ default:
311
+ throw new Error(`Unknown language ${language}`);
312
+ }
313
+ }
314
+ async function initTypescriptApp(dir, force) {
289
315
  const { eslint } = await enquirer.prompt([
290
316
  {
291
317
  name: "eslint",
@@ -304,6 +330,28 @@ async function initApp(dir, force) {
304
330
  force
305
331
  });
306
332
  await degit.clone(dir);
333
+ await cleanPackageJsonAndPnpmLockFiles(dir);
334
+ logger.success(`Project initialized in ${dir}!`);
335
+ logger.info(`To get started:
336
+ - cd ${dir}
337
+ - pnpm install
338
+ - pnpm run dev`);
339
+ }
340
+ async function initGoApp(dir, force) {
341
+ const degit = Degit("modiimedia/arri-starters/app-starter-go", { force });
342
+ await degit.clone(dir);
343
+ await cleanPackageJsonAndPnpmLockFiles(dir);
344
+ logger.success(`Project created in ${dir}!`);
345
+ logger.info(
346
+ `To get started:
347
+ - cd ${dir}
348
+ - go get
349
+ - go mod tidy
350
+ - pnpm install / npm install
351
+ - pnpm run dev / npm install`
352
+ );
353
+ }
354
+ async function cleanPackageJsonAndPnpmLockFiles(dir) {
307
355
  rmSync(path.resolve(dir, "pnpm-lock.yaml"));
308
356
  const packageJson = JSON.parse(
309
357
  readFileSync(path.resolve(dir, "package.json"), {
@@ -311,6 +359,9 @@ async function initApp(dir, force) {
311
359
  })
312
360
  );
313
361
  packageJson.name = kebabCase(dir);
362
+ if (packageJson.name.startsWith("-")) {
363
+ packageJson.name = packageJson.name.replace("-", "");
364
+ }
314
365
  packageJson.description = "An RPC server created with Arri RPC";
315
366
  packageJson.private = true;
316
367
  delete packageJson.license;
@@ -328,11 +379,6 @@ async function initApp(dir, force) {
328
379
  trailingComma: "all"
329
380
  })
330
381
  );
331
- logger.success(`Project initialized in ${dir}!`);
332
- logger.info(`To get started:
333
- - cd ${dir}
334
- - pnpm install
335
- - pnpm run dev`);
336
382
  }
337
383
  async function initPlugin(dir, force) {
338
384
  const name = kebabCase(dir);
package/dist/index.cjs CHANGED
@@ -8,8 +8,9 @@ const codegenTs = require('@arrirpc/codegen-ts');
8
8
  const common = require('./shared/arri.27334236.cjs');
9
9
  const node_child_process = require('node:child_process');
10
10
  const fs = require('node:fs');
11
- const fs$1 = require('node:fs/promises');
12
11
  const path = require('node:path');
12
+ const chokidar = require('chokidar');
13
+ const fs$1 = require('node:fs/promises');
13
14
  const codegenUtils = require('@arrirpc/codegen-utils');
14
15
  const listhen = require('@joshmossas/listhen');
15
16
  const esbuild = require('esbuild');
@@ -37,11 +38,175 @@ function _interopNamespaceCompat(e) {
37
38
  return n;
38
39
  }
39
40
 
40
- const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs$1);
41
+ const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
41
42
  const path__default = /*#__PURE__*/_interopDefaultCompat(path);
43
+ const chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
44
+ const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs$1);
42
45
  const esbuild__default = /*#__PURE__*/_interopDefaultCompat(esbuild);
43
46
  const prettier__default = /*#__PURE__*/_interopDefaultCompat(prettier);
44
47
 
48
+ function goServer(options = {}) {
49
+ const outDir = options.outputDir ?? ".output";
50
+ const resolvedOutDir = options.cwd ? path__default.resolve(options.cwd, outDir) : outDir;
51
+ return common.defineServerConfig({
52
+ devFn: async (_, generators) => {
53
+ if (!fs__default.existsSync(resolvedOutDir)) {
54
+ fs__default.mkdirSync(resolvedOutDir);
55
+ }
56
+ const ignoredDirs = ["node_modules", ".arri", ".output"];
57
+ const watcher = chokidar__default.watch(".", {
58
+ ignoreInitial: true,
59
+ ignored: (path2, stats) => {
60
+ if (stats?.isFile() == true && !path2.endsWith(".go")) {
61
+ return true;
62
+ }
63
+ if (stats?.isDirectory()) {
64
+ for (const dir of ignoredDirs) {
65
+ if (path2.includes(dir)) {
66
+ return true;
67
+ }
68
+ }
69
+ }
70
+ return false;
71
+ },
72
+ cwd: options.cwd
73
+ });
74
+ let childProcess;
75
+ async function spawnProcess() {
76
+ try {
77
+ node_child_process.execSync(`go build -o ${outDir}/server`, {
78
+ stdio: "inherit",
79
+ cwd: options.cwd
80
+ });
81
+ childProcess = node_child_process.spawn(
82
+ `${outDir}/server`,
83
+ [`--def-out=${outDir}/__definition.json`],
84
+ {
85
+ stdio: "inherit",
86
+ cwd: options.cwd
87
+ }
88
+ );
89
+ childProcess.on("error", (_2) => {
90
+ childProcess?.kill("SIGTERM");
91
+ childProcess?.removeAllListeners();
92
+ childProcess = void 0;
93
+ });
94
+ childProcess.on("close", (_2) => {
95
+ childProcess?.removeAllListeners();
96
+ childProcess = void 0;
97
+ });
98
+ } catch (err) {
99
+ common.logger.error(err);
100
+ }
101
+ }
102
+ async function closeChildProcess() {
103
+ if (!childProcess)
104
+ return true;
105
+ return new Promise((res, rej) => {
106
+ childProcess?.on("close", () => res(true));
107
+ childProcess?.on("exit", () => res(true));
108
+ childProcess?.on("error", (err) => {
109
+ rej(err);
110
+ });
111
+ childProcess?.kill("SIGTERM");
112
+ });
113
+ }
114
+ spawnProcess();
115
+ watcher.on("all", async (evt) => {
116
+ common.logger.info(`Changed detected. Restarting server...`);
117
+ switch (evt) {
118
+ case "addDir":
119
+ return;
120
+ default: {
121
+ await closeChildProcess();
122
+ childProcess?.removeAllListeners();
123
+ childProcess = void 0;
124
+ spawnProcess();
125
+ }
126
+ }
127
+ });
128
+ if (generators.length == 0) {
129
+ common.logger.warn(
130
+ "No generators specified in arri config. Skipping codegen."
131
+ );
132
+ return;
133
+ }
134
+ let defFileCache = "";
135
+ let hasRunGenerators = false;
136
+ async function handleAppDef() {
137
+ let defFile = "";
138
+ try {
139
+ defFile = fs__default.readFileSync(
140
+ `${resolvedOutDir}/__definition.json`,
141
+ "utf8"
142
+ );
143
+ } catch (_2) {
144
+ return;
145
+ }
146
+ if (!defFile || defFile == defFileCache) {
147
+ return;
148
+ }
149
+ const startTime = /* @__PURE__ */ new Date();
150
+ if (hasRunGenerators) {
151
+ common.logger.info(
152
+ "App definition updated. Rerunning generators..."
153
+ );
154
+ } else {
155
+ common.logger.info("Running generators...");
156
+ }
157
+ defFileCache = defFile;
158
+ const appDef = JSON.parse(defFile);
159
+ await Promise.allSettled(
160
+ generators.map((gen) => gen.generator(appDef, true))
161
+ );
162
+ common.logger.success(
163
+ `Ran ${generators.length} generator(s) in ${( new Date()).getTime() - startTime.getTime()}ms`
164
+ );
165
+ hasRunGenerators = true;
166
+ }
167
+ const appDefWatcher = chokidar__default.watch(
168
+ [`${outDir}/__definition.json`],
169
+ {
170
+ cwd: options.cwd
171
+ }
172
+ );
173
+ appDefWatcher.on("add", () => handleAppDef());
174
+ appDefWatcher.on("change", () => handleAppDef());
175
+ },
176
+ buildFn: async (_, generators) => {
177
+ if (!fs__default.existsSync(outDir)) {
178
+ fs__default.mkdirSync(outDir);
179
+ }
180
+ node_child_process.execSync(`go build -o ${outDir}/server`, {
181
+ stdio: "inherit"
182
+ });
183
+ node_child_process.execSync(
184
+ `${outDir}/server def -output ${outDir}/__definition.json`,
185
+ {
186
+ stdio: "inherit"
187
+ }
188
+ );
189
+ if (generators.length === 0) {
190
+ common.logger.warn(
191
+ "No generators specified in arri config. Skipping codegen."
192
+ );
193
+ return;
194
+ }
195
+ const startTime = /* @__PURE__ */ new Date();
196
+ common.logger.info(`Running generators...`);
197
+ const appDef = JSON.parse(
198
+ fs__default.readFileSync(`${resolvedOutDir}/__definition.json`, "utf8")
199
+ );
200
+ await Promise.all(
201
+ generators.map((gen) => gen.generator(appDef, false))
202
+ );
203
+ common.logger.success(
204
+ `Ran ${generators.length} generator(s) in ${( new Date()).getTime() - startTime.getTime()}ms`
205
+ );
206
+ }
207
+ });
208
+ }
209
+
45
210
  function tsServer(serverConfig) {
46
211
  return common.defineServerConfig({
47
212
  devArgs: void 0,
@@ -571,7 +736,8 @@ const getRpcMetaFromPath = (config, filePath) => {
571
736
  };
572
737
 
573
738
  const servers = {
574
- tsServer
739
+ tsServer,
740
+ goServer
575
741
  };
576
742
 
577
743
  const generators = {
package/dist/index.d.cts CHANGED
@@ -29,6 +29,12 @@ interface ArriConfig<TDevArgs extends ArgsDef | undefined = any, TBuildArgs exte
29
29
  declare function isArriConfig(input: unknown): input is ArriConfig;
30
30
  declare function defineConfig(config: ArriConfig): ArriConfig;
31
31
 
32
+ interface GoServerOptions {
33
+ outputDir?: string;
34
+ cwd?: string;
35
+ }
36
+ declare function goServer(options?: GoServerOptions): ServerConfig<any, any>;
37
+
32
38
  declare function tsServer(serverConfig?: TsServerConfig): ServerConfig<undefined, undefined>;
33
39
  interface TsServerConfig {
34
40
  port?: number;
@@ -64,6 +70,7 @@ interface TsServerConfig {
64
70
 
65
71
  declare const servers: {
66
72
  readonly tsServer: typeof tsServer;
73
+ readonly goServer: typeof goServer;
67
74
  };
68
75
 
69
76
  declare const generators: {
package/dist/index.d.mts CHANGED
@@ -29,6 +29,12 @@ interface ArriConfig<TDevArgs extends ArgsDef | undefined = any, TBuildArgs exte
29
29
  declare function isArriConfig(input: unknown): input is ArriConfig;
30
30
  declare function defineConfig(config: ArriConfig): ArriConfig;
31
31
 
32
+ interface GoServerOptions {
33
+ outputDir?: string;
34
+ cwd?: string;
35
+ }
36
+ declare function goServer(options?: GoServerOptions): ServerConfig<any, any>;
37
+
32
38
  declare function tsServer(serverConfig?: TsServerConfig): ServerConfig<undefined, undefined>;
33
39
  interface TsServerConfig {
34
40
  port?: number;
@@ -64,6 +70,7 @@ interface TsServerConfig {
64
70
 
65
71
  declare const servers: {
66
72
  readonly tsServer: typeof tsServer;
73
+ readonly goServer: typeof goServer;
67
74
  };
68
75
 
69
76
  declare const generators: {
package/dist/index.d.ts CHANGED
@@ -29,6 +29,12 @@ interface ArriConfig<TDevArgs extends ArgsDef | undefined = any, TBuildArgs exte
29
29
  declare function isArriConfig(input: unknown): input is ArriConfig;
30
30
  declare function defineConfig(config: ArriConfig): ArriConfig;
31
31
 
32
+ interface GoServerOptions {
33
+ outputDir?: string;
34
+ cwd?: string;
35
+ }
36
+ declare function goServer(options?: GoServerOptions): ServerConfig<any, any>;
37
+
32
38
  declare function tsServer(serverConfig?: TsServerConfig): ServerConfig<undefined, undefined>;
33
39
  interface TsServerConfig {
34
40
  port?: number;
@@ -64,6 +70,7 @@ interface TsServerConfig {
64
70
 
65
71
  declare const servers: {
66
72
  readonly tsServer: typeof tsServer;
73
+ readonly goServer: typeof goServer;
67
74
  };
68
75
 
69
76
  declare const generators: {
package/dist/index.mjs CHANGED
@@ -5,10 +5,11 @@ import { swiftClientGenerator } from '@arrirpc/codegen-swift';
5
5
  import { typescriptClientGenerator } from '@arrirpc/codegen-ts';
6
6
  import { d as defineServerConfig, l as logger, i as isInsideDir } from './shared/arri.cc4e1de8.mjs';
7
7
  export { D as DEV_DEFINITION_ENDPOINT, b as defineConfig, a as isArriConfig, c as isServerConfig } from './shared/arri.cc4e1de8.mjs';
8
- import { execSync } from 'node:child_process';
9
- import { existsSync, readFileSync } from 'node:fs';
10
- import * as fs from 'node:fs/promises';
8
+ import { execSync, spawn } from 'node:child_process';
9
+ import fs$1, { existsSync, readFileSync } from 'node:fs';
11
10
  import path from 'node:path';
11
+ import chokidar from 'chokidar';
12
+ import * as fs from 'node:fs/promises';
12
13
  import { isAppDefinition, camelCase, removeDisallowedChars, kebabCase } from '@arrirpc/codegen-utils';
13
14
  export { createAppDefinition } from '@arrirpc/codegen-utils';
14
15
  import { listen } from '@joshmossas/listhen';
@@ -23,6 +24,168 @@ import '@arrirpc/schema';
23
24
  import 'consola';
24
25
  import 'ofetch';
25
26
 
27
+ function goServer(options = {}) {
28
+ const outDir = options.outputDir ?? ".output";
29
+ const resolvedOutDir = options.cwd ? path.resolve(options.cwd, outDir) : outDir;
30
+ return defineServerConfig({
31
+ devFn: async (_, generators) => {
32
+ if (!fs$1.existsSync(resolvedOutDir)) {
33
+ fs$1.mkdirSync(resolvedOutDir);
34
+ }
35
+ const ignoredDirs = ["node_modules", ".arri", ".output"];
36
+ const watcher = chokidar.watch(".", {
37
+ ignoreInitial: true,
38
+ ignored: (path2, stats) => {
39
+ if (stats?.isFile() == true && !path2.endsWith(".go")) {
40
+ return true;
41
+ }
42
+ if (stats?.isDirectory()) {
43
+ for (const dir of ignoredDirs) {
44
+ if (path2.includes(dir)) {
45
+ return true;
46
+ }
47
+ }
48
+ }
49
+ return false;
50
+ },
51
+ cwd: options.cwd
52
+ });
53
+ let childProcess;
54
+ async function spawnProcess() {
55
+ try {
56
+ execSync(`go build -o ${outDir}/server`, {
57
+ stdio: "inherit",
58
+ cwd: options.cwd
59
+ });
60
+ childProcess = spawn(
61
+ `${outDir}/server`,
62
+ [`--def-out=${outDir}/__definition.json`],
63
+ {
64
+ stdio: "inherit",
65
+ cwd: options.cwd
66
+ }
67
+ );
68
+ childProcess.on("error", (_2) => {
69
+ childProcess?.kill("SIGTERM");
70
+ childProcess?.removeAllListeners();
71
+ childProcess = void 0;
72
+ });
73
+ childProcess.on("close", (_2) => {
74
+ childProcess?.removeAllListeners();
75
+ childProcess = void 0;
76
+ });
77
+ } catch (err) {
78
+ logger.error(err);
79
+ }
80
+ }
81
+ async function closeChildProcess() {
82
+ if (!childProcess)
83
+ return true;
84
+ return new Promise((res, rej) => {
85
+ childProcess?.on("close", () => res(true));
86
+ childProcess?.on("exit", () => res(true));
87
+ childProcess?.on("error", (err) => {
88
+ rej(err);
89
+ });
90
+ childProcess?.kill("SIGTERM");
91
+ });
92
+ }
93
+ spawnProcess();
94
+ watcher.on("all", async (evt) => {
95
+ logger.info(`Changed detected. Restarting server...`);
96
+ switch (evt) {
97
+ case "addDir":
98
+ return;
99
+ default: {
100
+ await closeChildProcess();
101
+ childProcess?.removeAllListeners();
102
+ childProcess = void 0;
103
+ spawnProcess();
104
+ }
105
+ }
106
+ });
107
+ if (generators.length == 0) {
108
+ logger.warn(
109
+ "No generators specified in arri config. Skipping codegen."
110
+ );
111
+ return;
112
+ }
113
+ let defFileCache = "";
114
+ let hasRunGenerators = false;
115
+ async function handleAppDef() {
116
+ let defFile = "";
117
+ try {
118
+ defFile = fs$1.readFileSync(
119
+ `${resolvedOutDir}/__definition.json`,
120
+ "utf8"
121
+ );
122
+ } catch (_2) {
123
+ return;
124
+ }
125
+ if (!defFile || defFile == defFileCache) {
126
+ return;
127
+ }
128
+ const startTime = /* @__PURE__ */ new Date();
129
+ if (hasRunGenerators) {
130
+ logger.info(
131
+ "App definition updated. Rerunning generators..."
132
+ );
133
+ } else {
134
+ logger.info("Running generators...");
135
+ }
136
+ defFileCache = defFile;
137
+ const appDef = JSON.parse(defFile);
138
+ await Promise.allSettled(
139
+ generators.map((gen) => gen.generator(appDef, true))
140
+ );
141
+ logger.success(
142
+ `Ran ${generators.length} generator(s) in ${( new Date()).getTime() - startTime.getTime()}ms`
143
+ );
144
+ hasRunGenerators = true;
145
+ }
146
+ const appDefWatcher = chokidar.watch(
147
+ [`${outDir}/__definition.json`],
148
+ {
149
+ cwd: options.cwd
150
+ }
151
+ );
152
+ appDefWatcher.on("add", () => handleAppDef());
153
+ appDefWatcher.on("change", () => handleAppDef());
154
+ },
155
+ buildFn: async (_, generators) => {
156
+ if (!fs$1.existsSync(outDir)) {
157
+ fs$1.mkdirSync(outDir);
158
+ }
159
+ execSync(`go build -o ${outDir}/server`, {
160
+ stdio: "inherit"
161
+ });
162
+ execSync(
163
+ `${outDir}/server def -output ${outDir}/__definition.json`,
164
+ {
165
+ stdio: "inherit"
166
+ }
167
+ );
168
+ if (generators.length === 0) {
169
+ logger.warn(
170
+ "No generators specified in arri config. Skipping codegen."
171
+ );
172
+ return;
173
+ }
174
+ const startTime = /* @__PURE__ */ new Date();
175
+ logger.info(`Running generators...`);
176
+ const appDef = JSON.parse(
177
+ fs$1.readFileSync(`${resolvedOutDir}/__definition.json`, "utf8")
178
+ );
179
+ await Promise.all(
180
+ generators.map((gen) => gen.generator(appDef, false))
181
+ );
182
+ logger.success(
183
+ `Ran ${generators.length} generator(s) in ${( new Date()).getTime() - startTime.getTime()}ms`
184
+ );
185
+ }
186
+ });
187
+ }
188
+
26
189
  function tsServer(serverConfig) {
27
190
  return defineServerConfig({
28
191
  devArgs: void 0,
@@ -552,7 +715,8 @@ const getRpcMetaFromPath = (config, filePath) => {
552
715
  };
553
716
 
554
717
  const servers = {
555
- tsServer
718
+ tsServer,
719
+ goServer
556
720
  };
557
721
 
558
722
  const generators = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arri",
3
- "version": "0.63.2",
3
+ "version": "0.64.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -39,13 +39,13 @@
39
39
  "h3": "^1.13.0",
40
40
  "pathe": "^1.1.2",
41
41
  "prettier": "^3.3.3",
42
- "@arrirpc/codegen-dart": "0.63.2",
43
- "@arrirpc/codegen-rust": "0.63.2",
44
- "@arrirpc/codegen-swift": "0.63.2",
45
- "@arrirpc/codegen-kotlin": "0.63.2",
46
- "@arrirpc/codegen-ts": "0.63.2",
47
- "@arrirpc/schema": "0.63.2",
48
- "@arrirpc/codegen-utils": "0.63.2"
42
+ "@arrirpc/codegen-dart": "0.64.0",
43
+ "@arrirpc/codegen-kotlin": "0.64.0",
44
+ "@arrirpc/codegen-rust": "0.64.0",
45
+ "@arrirpc/codegen-ts": "0.64.0",
46
+ "@arrirpc/codegen-swift": "0.64.0",
47
+ "@arrirpc/codegen-utils": "0.64.0",
48
+ "@arrirpc/schema": "0.64.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/degit": "^2.8.6"