everything-dev 1.20.0 → 1.22.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.
Files changed (64) hide show
  1. package/dist/cli/init.cjs +163 -80
  2. package/dist/cli/init.cjs.map +1 -1
  3. package/dist/cli/init.d.cts +12 -6
  4. package/dist/cli/init.d.cts.map +1 -1
  5. package/dist/cli/init.d.mts +12 -6
  6. package/dist/cli/init.d.mts.map +1 -1
  7. package/dist/cli/init.mjs +163 -81
  8. package/dist/cli/init.mjs.map +1 -1
  9. package/dist/cli/parse.cjs +9 -0
  10. package/dist/cli/parse.cjs.map +1 -1
  11. package/dist/cli/parse.mjs +9 -0
  12. package/dist/cli/parse.mjs.map +1 -1
  13. package/dist/cli/prompts.cjs +44 -13
  14. package/dist/cli/prompts.cjs.map +1 -1
  15. package/dist/cli/prompts.mjs +44 -13
  16. package/dist/cli/prompts.mjs.map +1 -1
  17. package/dist/cli/sync.cjs +6 -0
  18. package/dist/cli/sync.cjs.map +1 -1
  19. package/dist/cli/sync.mjs +6 -0
  20. package/dist/cli/sync.mjs.map +1 -1
  21. package/dist/cli.cjs +3 -1
  22. package/dist/cli.cjs.map +1 -1
  23. package/dist/cli.mjs +3 -1
  24. package/dist/cli.mjs.map +1 -1
  25. package/dist/contract.cjs +9 -1
  26. package/dist/contract.cjs.map +1 -1
  27. package/dist/contract.d.cts +33 -4
  28. package/dist/contract.d.cts.map +1 -1
  29. package/dist/contract.d.mts +33 -4
  30. package/dist/contract.d.mts.map +1 -1
  31. package/dist/contract.meta.cjs +2 -2
  32. package/dist/contract.meta.cjs.map +1 -1
  33. package/dist/contract.meta.d.cts +3 -3
  34. package/dist/contract.meta.d.mts +3 -3
  35. package/dist/contract.meta.mjs +2 -2
  36. package/dist/contract.meta.mjs.map +1 -1
  37. package/dist/contract.mjs +9 -2
  38. package/dist/contract.mjs.map +1 -1
  39. package/dist/fastkv.cjs +4 -1
  40. package/dist/fastkv.cjs.map +1 -1
  41. package/dist/fastkv.mjs +4 -1
  42. package/dist/fastkv.mjs.map +1 -1
  43. package/dist/index.cjs +1 -0
  44. package/dist/index.d.cts +2 -2
  45. package/dist/index.d.mts +2 -2
  46. package/dist/index.mjs +2 -2
  47. package/dist/plugin.cjs +43 -20
  48. package/dist/plugin.cjs.map +1 -1
  49. package/dist/plugin.d.cts +13 -2
  50. package/dist/plugin.d.cts.map +1 -1
  51. package/dist/plugin.d.mts +13 -2
  52. package/dist/plugin.d.mts.map +1 -1
  53. package/dist/plugin.mjs +44 -21
  54. package/dist/plugin.mjs.map +1 -1
  55. package/package.json +1 -1
  56. package/src/cli/init.ts +252 -95
  57. package/src/cli/parse.ts +17 -0
  58. package/src/cli/prompts.ts +45 -28
  59. package/src/cli/sync.ts +1 -0
  60. package/src/cli.ts +8 -1
  61. package/src/contract.meta.ts +6 -2
  62. package/src/contract.ts +5 -1
  63. package/src/fastkv.ts +6 -1
  64. package/src/plugin.ts +58 -18
package/dist/cli/init.cjs CHANGED
@@ -16,6 +16,13 @@ let glob = require("glob");
16
16
 
17
17
  //#region src/cli/init.ts
18
18
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
19
+ const FRAMEWORK_PACKAGES = ["every-plugin", "everything-dev"];
20
+ const OVERRIDE_WORKSPACE_MAP = {
21
+ ui: ["ui"],
22
+ api: ["api"],
23
+ host: ["host"],
24
+ plugins: []
25
+ };
19
26
  async function resolveSourceDir(opts) {
20
27
  if (opts.source) {
21
28
  const sourceDir = (0, node_path.resolve)(opts.source);
@@ -81,6 +88,30 @@ async function resolveRepositoryViaExtendsChain(extendsAccount, extendsGateway,
81
88
  return null;
82
89
  }
83
90
  }
91
+ async function detectGitRemoteUrl(directory) {
92
+ try {
93
+ const { stdout } = await (0, execa.execa)("git", [
94
+ "remote",
95
+ "get-url",
96
+ "origin"
97
+ ], {
98
+ cwd: directory,
99
+ stdio: "pipe"
100
+ });
101
+ const url = stdout.trim();
102
+ if (!url) return void 0;
103
+ return normalizeGitUrl(url);
104
+ } catch {
105
+ return;
106
+ }
107
+ }
108
+ function normalizeGitUrl(url) {
109
+ const sshMatch = url.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/);
110
+ if (sshMatch) return `https://github.com/${sshMatch[1]}/${sshMatch[2]}`;
111
+ const httpsMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/.*)?$/);
112
+ if (httpsMatch) return `https://github.com/${httpsMatch[1]}/${httpsMatch[2]}`;
113
+ return url.endsWith(".git") ? url.slice(0, -4) : url;
114
+ }
84
115
  async function downloadTarball(repoUrl) {
85
116
  const parsed = parseGitHubUrl(repoUrl);
86
117
  if (!parsed) throw new Error(`Cannot parse repository URL: ${repoUrl}`);
@@ -154,9 +185,20 @@ function parseGitHubUrl(url) {
154
185
  };
155
186
  return null;
156
187
  }
188
+ function filterPatternsByOverrides(patterns, overrides, _plugins) {
189
+ const has = (section) => overrides.includes(section);
190
+ let filtered = [...patterns];
191
+ if (!has("host")) filtered = filtered.filter((p) => !p.startsWith("host/") && p !== "host/**");
192
+ if (!has("ui")) filtered = filtered.filter((p) => !p.startsWith("ui/") && p !== "ui/**");
193
+ if (!has("api")) filtered = filtered.filter((p) => !p.startsWith("api/") && p !== "api/**");
194
+ if (!has("plugins")) filtered = filtered.filter((p) => !p.startsWith("plugins/") && p !== "plugins/**");
195
+ return filtered;
196
+ }
157
197
  async function copyFilteredFiles(sourceDir, destination, patterns, options) {
158
198
  if (patterns.length === 0) return 0;
159
- const effectivePatterns = options.withHost ? [...patterns, "host/**"] : patterns.filter((p) => !p.startsWith("host/") && p !== "host/**");
199
+ const has = (section) => options.overrides.includes(section);
200
+ const effectivePatterns = filterPatternsByOverrides(patterns, options.overrides, options.plugins);
201
+ if (has("host") && !effectivePatterns.some((p) => p.startsWith("host/") || p === "host/**")) effectivePatterns.push("host/**");
160
202
  const excludedRoutePatterns = [];
161
203
  if (options.pluginRoutes) {
162
204
  for (const [pluginKey, routePatterns] of Object.entries(options.pluginRoutes)) if (!(options.plugins?.includes(pluginKey) ?? true)) excludedRoutePatterns.push(...routePatterns);
@@ -205,45 +247,52 @@ async function copyFilteredFiles(sourceDir, destination, patterns, options) {
205
247
  }
206
248
  return count;
207
249
  }
250
+ function stripProductionFields(entry) {
251
+ delete entry.production;
252
+ delete entry.integrity;
253
+ delete entry.ssr;
254
+ delete entry.ssrIntegrity;
255
+ }
208
256
  async function personalizeConfig(destination, opts) {
209
257
  const isInit = opts.mode !== "sync";
258
+ const has = (section) => opts.overrides.includes(section);
210
259
  const configPath = (0, node_path.join)(destination, "bos.config.json");
211
260
  if ((0, node_fs.existsSync)(configPath)) {
212
261
  const config = JSON.parse((0, node_fs.readFileSync)(configPath, "utf-8"));
213
262
  config.extends = `bos://${opts.extendsAccount}/${opts.extendsGateway}`;
214
263
  if (opts.account) config.account = opts.account;
215
264
  if (opts.domain) config.domain = opts.domain;
265
+ if (opts.repository) config.repository = opts.repository;
216
266
  if (isInit && config.app && typeof config.app === "object") {
217
267
  const app = config.app;
218
268
  for (const entryKey of Object.keys(app)) {
219
- const entry = app[entryKey];
220
- if (entry && typeof entry === "object") {
221
- const e = entry;
222
- delete e.production;
223
- delete e.integrity;
224
- delete e.ssr;
225
- delete e.ssrIntegrity;
269
+ if (!has(entryKey) && (entryKey === "host" || entryKey === "ui" || entryKey === "api" || entryKey === "auth")) {
270
+ delete app[entryKey];
271
+ continue;
226
272
  }
273
+ const entry = app[entryKey];
274
+ if (entry && typeof entry === "object") stripProductionFields(entry);
227
275
  }
228
276
  }
229
- if (config.plugins && typeof config.plugins === "object") {
230
- const plugins = config.plugins;
231
- if (opts.plugins !== void 0) {
232
- for (const pluginKey of Object.keys(plugins)) if (!opts.plugins.includes(pluginKey)) delete plugins[pluginKey];
233
- }
234
- for (const pluginKey of Object.keys(plugins)) {
235
- const plugin = plugins[pluginKey];
236
- let pluginObj;
237
- if (typeof plugin === "string") {
238
- pluginObj = { extends: plugin };
239
- plugins[pluginKey] = pluginObj;
240
- } else if (plugin && typeof plugin === "object") pluginObj = { ...plugin };
241
- else continue;
242
- delete pluginObj.production;
243
- delete pluginObj.integrity;
277
+ if (has("plugins")) {
278
+ if (config.plugins && typeof config.plugins === "object") {
279
+ const plugins = config.plugins;
280
+ if (opts.plugins !== void 0) {
281
+ for (const pluginKey of Object.keys(plugins)) if (!opts.plugins.includes(pluginKey)) delete plugins[pluginKey];
282
+ }
283
+ for (const pluginKey of Object.keys(plugins)) {
284
+ const plugin = plugins[pluginKey];
285
+ let pluginObj;
286
+ if (typeof plugin === "string") {
287
+ pluginObj = { extends: plugin };
288
+ plugins[pluginKey] = pluginObj;
289
+ } else if (plugin && typeof plugin === "object") pluginObj = { ...plugin };
290
+ else continue;
291
+ stripProductionFields(pluginObj);
292
+ }
293
+ if (Object.keys(plugins).length === 0) config.plugins = {};
244
294
  }
245
- if (Object.keys(plugins).length === 0) config.plugins = {};
246
- }
295
+ } else delete config.plugins;
247
296
  await require_save_config.saveBosConfig(destination, config);
248
297
  }
249
298
  const pkgPath = (0, node_path.join)(destination, "package.json");
@@ -253,10 +302,10 @@ async function personalizeConfig(destination, opts) {
253
302
  const ws = pkg.workspaces;
254
303
  if (Array.isArray(ws.packages)) ws.packages = ws.packages.filter((p) => {
255
304
  if (p.startsWith("packages/")) return false;
256
- if (p === "host") return opts.withHost ?? false;
257
- if (p === "plugins/*") return (opts.plugins?.length ?? 0) > 0;
305
+ if (p === "host") return has("host");
306
+ if (p === "plugins/*") return has("plugins") && (opts.plugins?.length ?? 0) > 0;
258
307
  const pluginMatch = p.match(/^plugins\/([^/]+)/);
259
- if (pluginMatch) return opts.plugins?.includes(pluginMatch[1]) ?? true;
308
+ if (pluginMatch) return has("plugins") && (opts.plugins?.includes(pluginMatch[1]) ?? true);
260
309
  return true;
261
310
  });
262
311
  }
@@ -277,7 +326,7 @@ async function personalizeConfig(destination, opts) {
277
326
  scripts["types:gen"] = "node_modules/.bin/bos types gen";
278
327
  if (scripts.typecheck) {
279
328
  scripts.typecheck = scripts.typecheck.replace("bun run types:gen && ", "").replace(/bun run --cwd packages\/everything-dev typecheck & ?/, "");
280
- if (!opts.withHost) scripts.typecheck = scripts.typecheck.replace(/bun run --cwd host tsc --noEmit & ?/, "");
329
+ if (!has("host")) scripts.typecheck = scripts.typecheck.replace(/bun run --cwd host tsc --noEmit & ?/, "");
281
330
  }
282
331
  }
283
332
  if (pkg.devDependencies && typeof pkg.devDependencies === "object") {
@@ -315,19 +364,25 @@ async function personalizeConfig(destination, opts) {
315
364
  }
316
365
  }
317
366
  await resolveWorkspaceRefs(destination, opts.workspaceOpts);
318
- const genContractPath = (0, node_path.join)(destination, "ui", "src", "lib", "api-types.gen.ts");
319
- if (!(0, node_fs.existsSync)(genContractPath)) {
320
- (0, node_fs.mkdirSync)((0, node_path.dirname)(genContractPath), { recursive: true });
321
- (0, node_fs.writeFileSync)(genContractPath, `export type ApiContract = Record<string, never>;\n`);
367
+ if (has("ui")) {
368
+ const genContractPath = (0, node_path.join)(destination, "ui", "src", "lib", "api-types.gen.ts");
369
+ if (!(0, node_fs.existsSync)(genContractPath)) {
370
+ (0, node_fs.mkdirSync)((0, node_path.dirname)(genContractPath), { recursive: true });
371
+ (0, node_fs.writeFileSync)(genContractPath, `export type ApiContract = Record<string, never>;\n`);
372
+ }
322
373
  }
323
- const pluginsClientGenPath = (0, node_path.join)(destination, "api", "src", "lib", "plugins-types.gen.ts");
324
- if (!(0, node_fs.existsSync)(pluginsClientGenPath)) {
325
- (0, node_fs.mkdirSync)((0, node_path.dirname)(pluginsClientGenPath), { recursive: true });
326
- (0, node_fs.writeFileSync)(pluginsClientGenPath, `import type { ContractRouterClient, AnyContractRouter } from "@orpc/contract";\ntype ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;\nexport type PluginsClient = Record<string, never>;\n`);
374
+ if (has("api")) {
375
+ const pluginsClientGenPath = (0, node_path.join)(destination, "api", "src", "lib", "plugins-types.gen.ts");
376
+ if (!(0, node_fs.existsSync)(pluginsClientGenPath)) {
377
+ (0, node_fs.mkdirSync)((0, node_path.dirname)(pluginsClientGenPath), { recursive: true });
378
+ (0, node_fs.writeFileSync)(pluginsClientGenPath, `import type { ContractRouterClient, AnyContractRouter } from "@orpc/contract";\ntype ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;\nexport type PluginsClient = Record<string, never>;\n`);
379
+ }
327
380
  }
328
381
  const authTypesContent = generateAuthTypesTemplate();
329
- const authTypesPaths = [(0, node_path.join)(destination, "ui", "src", "lib", "auth-types.gen.ts"), (0, node_path.join)(destination, "api", "src", "lib", "auth-types.gen.ts")];
330
- if ((0, node_fs.existsSync)((0, node_path.join)(destination, "host", "src"))) authTypesPaths.push((0, node_path.join)(destination, "host", "src", "lib", "auth-types.gen.ts"));
382
+ const authTypesPaths = [];
383
+ if (has("ui")) authTypesPaths.push((0, node_path.join)(destination, "ui", "src", "lib", "auth-types.gen.ts"));
384
+ if (has("api")) authTypesPaths.push((0, node_path.join)(destination, "api", "src", "lib", "auth-types.gen.ts"));
385
+ if (has("host") && (0, node_fs.existsSync)((0, node_path.join)(destination, "host", "src"))) authTypesPaths.push((0, node_path.join)(destination, "host", "src", "lib", "auth-types.gen.ts"));
331
386
  for (const authTypesGenPath of authTypesPaths) if (!(0, node_fs.existsSync)(authTypesGenPath)) {
332
387
  (0, node_fs.mkdirSync)((0, node_path.dirname)(authTypesGenPath), { recursive: true });
333
388
  (0, node_fs.writeFileSync)(authTypesGenPath, authTypesContent);
@@ -384,10 +439,10 @@ export interface AuthServices {
384
439
  `;
385
440
  }
386
441
  async function runBunInstall(destination) {
387
- await execCommand("bun", ["install", "--ignore-scripts"], destination);
442
+ await execCommand("bun", ["install", "--ignore-scripts"], destination, { stdio: "inherit" });
388
443
  }
389
444
  async function runTypesGen(destination) {
390
- await execCommand("node_modules/.bin/bos", ["types", "gen"], destination);
445
+ await execCommand("node_modules/.bin/bos", ["types", "gen"], destination, { stdio: "inherit" });
391
446
  }
392
447
  async function runDockerComposeUp(destination) {
393
448
  await execCommand("docker", [
@@ -395,65 +450,69 @@ async function runDockerComposeUp(destination) {
395
450
  "up",
396
451
  "-d",
397
452
  "--wait"
398
- ], destination);
453
+ ], destination, { stdio: "inherit" });
399
454
  }
400
455
  const WORKSPACE_LOCAL_PATHS = {
401
456
  "everything-dev": "packages/everything-dev",
402
457
  "every-plugin": "packages/every-plugin"
403
458
  };
459
+ function resolveFrameworkCatalog() {
460
+ const catalog = {};
461
+ for (const packageName of FRAMEWORK_PACKAGES) try {
462
+ const resolved = require$1.resolve(`${packageName}/package.json`);
463
+ const pkg = JSON.parse((0, node_fs.readFileSync)(resolved, "utf-8"));
464
+ if (pkg.version) catalog[packageName] = `^${pkg.version}`;
465
+ } catch {}
466
+ return catalog;
467
+ }
404
468
  async function scaffoldMinimalProject(destination, parentConfig, opts) {
405
469
  (0, node_fs.mkdirSync)(destination, { recursive: true });
470
+ const has = (section) => opts.overrides.includes(section);
406
471
  const config = {
407
472
  extends: `bos://${opts.extendsAccount}/${opts.extendsGateway}`,
408
473
  account: opts.account || opts.extendsAccount,
409
- ...opts.domain ? { domain: opts.domain } : {}
474
+ ...opts.domain ? { domain: opts.domain } : {},
475
+ ...opts.repository ? { repository: opts.repository } : {}
410
476
  };
411
477
  if (parentConfig.app && typeof parentConfig.app === "object") {
412
478
  const app = {};
413
479
  const parentApp = parentConfig.app;
414
- if (parentApp.host) {
480
+ if (has("host") && parentApp.host) {
415
481
  app.host = { ...parentApp.host };
416
- const host = app.host;
417
- delete host.production;
418
- delete host.integrity;
482
+ stripProductionFields(app.host);
419
483
  }
420
- if (parentApp.ui) {
484
+ if (has("ui") && parentApp.ui) {
421
485
  app.ui = { ...parentApp.ui };
422
- const ui = app.ui;
423
- delete ui.production;
424
- delete ui.integrity;
425
- delete ui.ssr;
426
- delete ui.ssrIntegrity;
486
+ stripProductionFields(app.ui);
427
487
  }
428
- if (parentApp.api) {
488
+ if (has("api") && parentApp.api) {
429
489
  app.api = { ...parentApp.api };
430
- const api = app.api;
431
- delete api.production;
432
- delete api.integrity;
490
+ stripProductionFields(app.api);
433
491
  }
434
- if (parentApp.auth) {
492
+ if (has("plugins") && parentApp.auth) {
435
493
  app.auth = { ...parentApp.auth };
436
- const auth = app.auth;
437
- delete auth.production;
438
- delete auth.integrity;
494
+ stripProductionFields(app.auth);
439
495
  }
440
- config.app = app;
496
+ if (Object.keys(app).length > 0) config.app = app;
441
497
  }
442
- if (opts.plugins && opts.plugins.length > 0 && parentConfig.plugins) {
498
+ if (has("plugins") && opts.plugins && opts.plugins.length > 0 && parentConfig.plugins) {
443
499
  const plugins = {};
444
500
  for (const key of opts.plugins) {
445
501
  const parentPlugin = parentConfig.plugins?.[key];
446
502
  if (parentPlugin) if (typeof parentPlugin === "string") plugins[key] = { extends: parentPlugin };
447
503
  else {
448
504
  const pluginCopy = { ...parentPlugin };
449
- delete pluginCopy.production;
450
- delete pluginCopy.integrity;
505
+ stripProductionFields(pluginCopy);
451
506
  plugins[key] = pluginCopy;
452
507
  }
453
508
  }
454
509
  config.plugins = plugins;
455
510
  }
456
511
  await require_save_config.saveBosConfig(destination, config);
512
+ const workspacePackages = [];
513
+ for (const section of opts.overrides) workspacePackages.push(...OVERRIDE_WORKSPACE_MAP[section]);
514
+ if (has("plugins") && opts.plugins) for (const plugin of opts.plugins) workspacePackages.push(`plugins/${plugin}`);
515
+ const catalog = resolveFrameworkCatalog();
457
516
  const pkg = {
458
517
  name: opts.domain || opts.extendsGateway,
459
518
  private: true,
@@ -476,12 +535,12 @@ async function scaffoldMinimalProject(destination, parentConfig, opts) {
476
535
  },
477
536
  devDependencies: {},
478
537
  workspaces: {
479
- packages: [],
480
- catalog: {}
538
+ packages: workspacePackages,
539
+ catalog
481
540
  }
482
541
  };
483
542
  (0, node_fs.writeFileSync)((0, node_path.join)(destination, "package.json"), `${JSON.stringify(pkg, null, 2)}\n`);
484
- const envExample = generateEnvExample(parentConfig);
543
+ const envExample = generateEnvExample(parentConfig, opts.overrides);
485
544
  if (envExample) (0, node_fs.writeFileSync)((0, node_path.join)(destination, ".env.example"), envExample);
486
545
  (0, node_fs.writeFileSync)((0, node_path.join)(destination, ".gitignore"), generateGitignore());
487
546
  return 4;
@@ -516,7 +575,9 @@ async function resolveWorkspaceRefs(destination, options) {
516
575
  }
517
576
  }
518
577
  async function writeInitSnapshot(destination, extendsAccount, extendsGateway, sourceDir, patterns, options) {
519
- const effectivePatterns = options.withHost ? [...patterns, "host/**"] : patterns.filter((p) => !p.startsWith("host/") && p !== "host/**");
578
+ const effectivePatterns = filterPatternsByOverrides(patterns, options.overrides, options.plugins);
579
+ const has = (section) => options.overrides.includes(section);
580
+ if (has("host") && !effectivePatterns.some((p) => p.startsWith("host/") || p === "host/**")) effectivePatterns.push("host/**");
520
581
  const excludedRoutePatterns = [];
521
582
  if (options.pluginRoutes) {
522
583
  for (const [pluginKey, routePatterns] of Object.entries(options.pluginRoutes)) if (!(options.plugins?.includes(pluginKey) ?? true)) excludedRoutePatterns.push(...routePatterns);
@@ -583,23 +644,44 @@ async function generateDatabaseMigrations(destination) {
583
644
  await execCommand("bun", ["run", "db:generate"], (0, node_path.join)(destination, workspaceDir));
584
645
  }
585
646
  }
586
- async function execCommand(command, args, cwd) {
647
+ const COMMAND_TIMEOUTS = {
648
+ bun: 5 * 6e4,
649
+ docker: 5 * 6e4,
650
+ node_modules: 2 * 6e4,
651
+ tar: 6e4
652
+ };
653
+ async function execCommand(command, args, cwd, options) {
654
+ const timeout = COMMAND_TIMEOUTS[command] ?? 2 * 6e4;
587
655
  await (0, execa.execa)(command, args, {
588
656
  cwd,
589
- stdio: "pipe"
657
+ stdio: options?.stdio ?? "pipe",
658
+ timeout
590
659
  });
591
660
  }
592
- function generateEnvExample(config) {
661
+ function generateEnvExample(config, overrides) {
662
+ const has = (section) => overrides.includes(section);
593
663
  const lines = ["# Environment variables"];
594
- const collectSecrets = (obj, prefix = "") => {
595
- for (const [key, value] of Object.entries(obj)) if (key === "secrets" && Array.isArray(value)) {
596
- for (const secret of value) if (typeof secret === "string") lines.push(`${secret}=`);
597
- } else if (key === "variables" && isPlainObject(value)) {
598
- for (const [varKey, varVal] of Object.entries(value)) if (typeof varVal === "string") lines.push(`${varKey}=${varVal}`);
599
- } else if (isPlainObject(value) && key !== "extends") collectSecrets(value, `${prefix}${key}.`);
664
+ const collectSecrets = (obj, includeSection, prefix = "") => {
665
+ for (const [key, value] of Object.entries(obj)) {
666
+ if (!includeSection) continue;
667
+ if (key === "secrets" && Array.isArray(value)) {
668
+ for (const secret of value) if (typeof secret === "string") lines.push(`${secret}=`);
669
+ } else if (key === "variables" && isPlainObject(value)) {
670
+ for (const [varKey, varVal] of Object.entries(value)) if (typeof varVal === "string") lines.push(`${varKey}=${varVal}`);
671
+ } else if (isPlainObject(value) && key !== "extends") collectSecrets(value, includeSection, `${prefix}${key}.`);
672
+ }
600
673
  };
601
- if (config.app && typeof config.app === "object") collectSecrets(config.app);
602
- if (config.plugins && typeof config.plugins === "object") collectSecrets(config.plugins);
674
+ if (config.app && typeof config.app === "object") {
675
+ const app = config.app;
676
+ collectSecrets(app, has("host"), "host.");
677
+ collectSecrets(app, has("ui"), "ui.");
678
+ collectSecrets(app, has("api"), "api.");
679
+ collectSecrets(app, has("plugins"), "auth.");
680
+ }
681
+ if (has("plugins") && config.plugins && typeof config.plugins === "object") {
682
+ for (const [pluginKey, pluginVal] of Object.entries(config.plugins)) if (isPlainObject(pluginVal)) collectSecrets(pluginVal, true);
683
+ else if (typeof pluginVal === "string") lines.push(`# Plugin '${pluginKey}' extends ${pluginVal}`);
684
+ }
603
685
  lines.push("BETTER_AUTH_SECRET=generate-a-secret-here");
604
686
  return `${lines.join("\n")}\n`;
605
687
  }
@@ -618,6 +700,7 @@ dist/
618
700
 
619
701
  //#endregion
620
702
  exports.copyFilteredFiles = copyFilteredFiles;
703
+ exports.detectGitRemoteUrl = detectGitRemoteUrl;
621
704
  exports.downloadTarball = downloadTarball;
622
705
  exports.execCommand = execCommand;
623
706
  exports.fetchParentConfig = fetchParentConfig;