everything-dev 1.19.0 → 1.21.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 (66) hide show
  1. package/dist/cli/init.cjs +138 -74
  2. package/dist/cli/init.cjs.map +1 -1
  3. package/dist/cli/init.d.cts +9 -5
  4. package/dist/cli/init.d.cts.map +1 -1
  5. package/dist/cli/init.d.mts +9 -5
  6. package/dist/cli/init.d.mts.map +1 -1
  7. package/dist/cli/init.mjs +138 -75
  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/timing.cjs +21 -1
  22. package/dist/cli/timing.cjs.map +1 -1
  23. package/dist/cli/timing.mjs +21 -1
  24. package/dist/cli/timing.mjs.map +1 -1
  25. package/dist/cli.cjs +3 -1
  26. package/dist/cli.cjs.map +1 -1
  27. package/dist/cli.mjs +3 -1
  28. package/dist/cli.mjs.map +1 -1
  29. package/dist/contract.cjs +9 -1
  30. package/dist/contract.cjs.map +1 -1
  31. package/dist/contract.d.cts +43 -14
  32. package/dist/contract.d.cts.map +1 -1
  33. package/dist/contract.d.mts +43 -14
  34. package/dist/contract.d.mts.map +1 -1
  35. package/dist/contract.meta.cjs +2 -2
  36. package/dist/contract.meta.cjs.map +1 -1
  37. package/dist/contract.meta.d.cts +3 -3
  38. package/dist/contract.meta.d.mts +3 -3
  39. package/dist/contract.meta.mjs +2 -2
  40. package/dist/contract.meta.mjs.map +1 -1
  41. package/dist/contract.mjs +9 -2
  42. package/dist/contract.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 +56 -38
  48. package/dist/plugin.cjs.map +1 -1
  49. package/dist/plugin.d.cts +20 -9
  50. package/dist/plugin.d.cts.map +1 -1
  51. package/dist/plugin.d.mts +20 -9
  52. package/dist/plugin.d.mts.map +1 -1
  53. package/dist/plugin.mjs +57 -39
  54. package/dist/plugin.mjs.map +1 -1
  55. package/dist/types.d.cts +4 -4
  56. package/dist/types.d.mts +4 -4
  57. package/package.json +5 -5
  58. package/src/cli/init.ts +215 -89
  59. package/src/cli/parse.ts +17 -0
  60. package/src/cli/prompts.ts +45 -28
  61. package/src/cli/sync.ts +1 -0
  62. package/src/cli/timing.ts +27 -0
  63. package/src/cli.ts +8 -1
  64. package/src/contract.meta.ts +6 -2
  65. package/src/contract.ts +5 -1
  66. package/src/plugin.ts +145 -73
package/src/cli/timing.ts CHANGED
@@ -1,13 +1,40 @@
1
+ import type { spinner as clackSpinner } from "@clack/prompts";
2
+
3
+ type Spinner = ReturnType<typeof clackSpinner>;
4
+
1
5
  export interface PhaseTiming {
2
6
  name: string;
3
7
  durationMs: number;
4
8
  }
5
9
 
10
+ const PHASE_LABELS: Record<string, string> = {
11
+ "parent config": "Fetching parent config...",
12
+ "template source": "Resolving template source...",
13
+ "scaffold project": "Creating project scaffold...",
14
+ "copy files": "Copying template files...",
15
+ "personalize config": "Personalizing config...",
16
+ "write snapshot": "Writing snapshot...",
17
+ "resolve config": "Resolving config...",
18
+ "generate env/docker": "Generating environment config...",
19
+ "create env file": "Creating .env file...",
20
+ "install dependencies": "Installing dependencies...",
21
+ "generate types": "Generating types...",
22
+ "generate migrations": "Generating database migrations...",
23
+ "generate code artifacts": "Generating code artifacts...",
24
+ "docker compose up": "Starting Docker services...",
25
+ };
26
+
27
+ function phaseLabel(name: string): string {
28
+ return PHASE_LABELS[name] ?? name;
29
+ }
30
+
6
31
  export async function timePhase<T>(
7
32
  timings: PhaseTiming[],
8
33
  name: string,
9
34
  fn: () => Promise<T>,
35
+ spinner?: Spinner,
10
36
  ): Promise<T> {
37
+ spinner?.message(phaseLabel(name));
11
38
  const startedAt = Date.now();
12
39
  try {
13
40
  return await fn();
package/src/cli.ts CHANGED
@@ -70,9 +70,14 @@ async function warnIfOutdated(client: any, command: string): Promise<void> {
70
70
  const status = await client.status();
71
71
  if (status.status === "error" || !status.packages) return;
72
72
 
73
+ const frameworkPackages = ["everything-dev", "every-plugin"];
74
+
73
75
  const outdated = status.packages.filter(
74
76
  (p: { name: string; installed?: string; latest?: string }) =>
75
- p.installed && p.latest && normalizeVersion(p.installed) !== normalizeVersion(p.latest),
77
+ p.installed &&
78
+ p.latest &&
79
+ normalizeVersion(p.installed) !== normalizeVersion(p.latest) &&
80
+ frameworkPackages.includes(p.name),
76
81
  );
77
82
 
78
83
  if (outdated.length === 0) return;
@@ -162,6 +167,8 @@ async function main() {
162
167
  console.log(` ${colors.dim("Directory:")} ${result.directory}`);
163
168
  if (result.account) console.log(` ${colors.dim("Account:")} ${result.account}`);
164
169
  if (result.domain) console.log(` ${colors.dim("Domain:")} ${result.domain}`);
170
+ if (result.overrides && result.overrides.length > 0)
171
+ console.log(` ${colors.dim("Overrides:")} ${result.overrides.join(", ")}`);
165
172
  if (result.plugins && result.plugins.length > 0)
166
173
  console.log(` ${colors.dim("Plugins:")} ${result.plugins.join(", ")}`);
167
174
  console.log(` ${colors.dim("Files copied:")} ${result.filesCopied}`);
@@ -92,8 +92,12 @@ export const cliCommandMeta = {
92
92
  account: { description: "New project NEAR account (auto-derived from extends)" },
93
93
  directory: { description: "Target directory (auto-derived from domain)" },
94
94
  source: { description: "Local source dir (skips GitHub download)" },
95
- plugins: { description: "Comma-separated plugin keys to include" },
96
- withHost: { description: "Include host/ in template output" },
95
+ plugins: {
96
+ description: "Comma-separated plugin keys to include (requires --overrides=plugins)",
97
+ },
98
+ overrides: {
99
+ description: "Comma-separated sections to override locally: ui,api,host,plugins",
100
+ },
97
101
  noInteractive: { description: "Skip prompts, use flags only" },
98
102
  noInstall: { description: "Skip bun install" },
99
103
  },
package/src/contract.ts CHANGED
@@ -142,6 +142,8 @@ export const KeyPublishResultSchema = z.object({
142
142
  error: z.string().optional(),
143
143
  });
144
144
 
145
+ export const OverrideSectionSchema = z.enum(["ui", "api", "host", "plugins"]);
146
+
145
147
  export const InitOptionsSchema = z.object({
146
148
  extends: z.string().optional(),
147
149
  directory: z.string().optional(),
@@ -149,7 +151,7 @@ export const InitOptionsSchema = z.object({
149
151
  domain: z.string().optional(),
150
152
  source: z.string().optional(),
151
153
  plugins: z.array(z.string()).optional(),
152
- withHost: z.boolean().default(false),
154
+ overrides: z.array(OverrideSectionSchema).optional(),
153
155
  noInteractive: z.boolean().default(false),
154
156
  noInstall: z.boolean().default(false),
155
157
  });
@@ -167,6 +169,7 @@ export const InitResultSchema = z.object({
167
169
  domain: z.string().optional(),
168
170
  extends: z.string(),
169
171
  plugins: z.array(z.string()).optional(),
172
+ overrides: z.array(OverrideSectionSchema).optional(),
170
173
  filesCopied: z.number(),
171
174
  timings: z.array(PhaseTimingSchema).optional(),
172
175
  error: z.string().optional(),
@@ -311,6 +314,7 @@ export type KeyPublishOptions = z.infer<typeof KeyPublishOptionsSchema>;
311
314
  export type KeyPublishResult = z.infer<typeof KeyPublishResultSchema>;
312
315
  export type InitOptions = z.infer<typeof InitOptionsSchema>;
313
316
  export type InitResult = z.infer<typeof InitResultSchema>;
317
+ export type OverrideSection = z.infer<typeof OverrideSectionSchema>;
314
318
  export type PhaseTiming = z.infer<typeof PhaseTimingSchema>;
315
319
  export type SyncOptions = z.infer<typeof SyncOptionsSchema>;
316
320
  export type SyncResult = z.infer<typeof SyncResultSchema>;
package/src/plugin.ts CHANGED
@@ -7,6 +7,7 @@ import { buildRuntimeConfig, detectLocalPackages, prepareDevelopmentRuntimeConfi
7
7
  import { ensureEnvFile, writeGeneratedInfra } from "./cli/infra";
8
8
  import {
9
9
  copyFilteredFiles,
10
+ detectGitRemoteUrl,
10
11
  fetchParentConfig,
11
12
  generateDatabaseMigrations,
12
13
  personalizeConfig,
@@ -35,6 +36,7 @@ import {
35
36
  import {
36
37
  type BosConfigResult,
37
38
  bosContract,
39
+ type OverrideSection,
38
40
  type PhaseTiming,
39
41
  type PluginListResult,
40
42
  } from "./contract";
@@ -1196,7 +1198,7 @@ export default createPlugin({
1196
1198
  let directory = input.directory;
1197
1199
  let account = input.account;
1198
1200
  let domain = input.domain;
1199
- let withHost = input.withHost;
1201
+ let overrides = input.overrides as OverrideSection[] | undefined;
1200
1202
  let plugins = input.plugins;
1201
1203
 
1202
1204
  if (input.extends) {
@@ -1213,11 +1215,17 @@ export default createPlugin({
1213
1215
  extendsAccount = extendsAccount || "dev.everything.near";
1214
1216
  extendsGateway = extendsGateway || "everything.dev";
1215
1217
 
1218
+ const s = p.spinner();
1219
+ s.start("Initializing project");
1220
+
1216
1221
  let parentPluginKeys: string[] = [];
1217
1222
  let parentConfig: BosConfig | null = null;
1218
1223
  try {
1219
- parentConfig = await timePhase(timings, "parent config", () =>
1220
- fetchParentConfig(extendsAccount, extendsGateway),
1224
+ parentConfig = await timePhase(
1225
+ timings,
1226
+ "parent config",
1227
+ () => fetchParentConfig(extendsAccount, extendsGateway),
1228
+ s,
1221
1229
  );
1222
1230
  if (parentConfig?.plugins && typeof parentConfig.plugins === "object") {
1223
1231
  parentPluginKeys = Object.keys(parentConfig.plugins);
@@ -1225,13 +1233,14 @@ export default createPlugin({
1225
1233
  } catch {}
1226
1234
 
1227
1235
  if (!input.noInteractive) {
1236
+ s.stop("Config fetched");
1228
1237
  const prompted = await promptInitOptions({
1229
1238
  extends: `bos://${extendsAccount}/${extendsGateway}`,
1230
1239
  directory,
1231
1240
  account,
1232
1241
  domain,
1233
1242
  plugins,
1234
- withHost,
1243
+ overrides,
1235
1244
  parentPluginKeys,
1236
1245
  });
1237
1246
  extendsAccount = prompted.extendsAccount;
@@ -1239,21 +1248,39 @@ export default createPlugin({
1239
1248
  directory = prompted.directory;
1240
1249
  account = prompted.account;
1241
1250
  domain = prompted.domain;
1242
- withHost = prompted.withHost;
1243
1251
  plugins = prompted.plugins;
1252
+ overrides = prompted.overrides;
1253
+ s.start("Setting up project");
1244
1254
  }
1245
1255
 
1256
+ overrides = overrides?.length ? overrides : (["ui", "api"] as OverrideSection[]);
1257
+ if (overrides.includes("plugins") && !plugins?.length) {
1258
+ plugins = parentPluginKeys;
1259
+ }
1260
+ plugins = plugins ?? [];
1261
+
1246
1262
  directory = directory || domain || extendsGateway;
1247
1263
  const targetDir = resolve(directory);
1248
- plugins = plugins ?? [];
1249
1264
  const extendsRef = `bos://${extendsAccount}/${extendsGateway}`;
1250
1265
 
1266
+ if (overrides.includes("plugins") && !plugins.length) {
1267
+ // explicitly selected plugins override with none selected — back out of all inherited plugins
1268
+ }
1269
+
1270
+ const repository =
1271
+ (await detectGitRemoteUrl(process.cwd()).catch(() => undefined)) ??
1272
+ parentConfig?.repository;
1273
+
1251
1274
  if (!parentConfig) {
1252
1275
  try {
1253
- parentConfig = await timePhase(timings, "parent config", () =>
1254
- fetchParentConfig(extendsAccount, extendsGateway),
1276
+ parentConfig = await timePhase(
1277
+ timings,
1278
+ "parent config",
1279
+ () => fetchParentConfig(extendsAccount, extendsGateway),
1280
+ s,
1255
1281
  );
1256
1282
  } catch {
1283
+ s.stop("Failed");
1257
1284
  return {
1258
1285
  status: "error" as const,
1259
1286
  directory,
@@ -1261,7 +1288,8 @@ export default createPlugin({
1261
1288
  account,
1262
1289
  domain,
1263
1290
  extends: extendsRef,
1264
- plugins: plugins ?? [],
1291
+ plugins,
1292
+ overrides,
1265
1293
  filesCopied: 0,
1266
1294
  timings,
1267
1295
  error: `No config found at ${extendsRef} — are you sure this is the right parent?`,
@@ -1273,12 +1301,16 @@ export default createPlugin({
1273
1301
  sourceDir,
1274
1302
  parentConfig: resolvedParentConfig,
1275
1303
  cleanup,
1276
- } = await timePhase(timings, "template source", () =>
1277
- resolveSourceDir({
1278
- extendsAccount,
1279
- extendsGateway,
1280
- source: input.source,
1281
- }),
1304
+ } = await timePhase(
1305
+ timings,
1306
+ "template source",
1307
+ () =>
1308
+ resolveSourceDir({
1309
+ extendsAccount,
1310
+ extendsGateway,
1311
+ source: input.source,
1312
+ }),
1313
+ s,
1282
1314
  );
1283
1315
 
1284
1316
  parentConfig = resolvedParentConfig;
@@ -1286,25 +1318,28 @@ export default createPlugin({
1286
1318
  const isMinimalScaffold = sourceDir === "";
1287
1319
 
1288
1320
  try {
1289
- const s = p.spinner();
1290
- s.start("Setting up project");
1291
-
1292
1321
  let filesCopied: number;
1293
1322
 
1294
1323
  if (isMinimalScaffold) {
1295
- filesCopied = await timePhase(timings, "scaffold project", () =>
1296
- scaffoldMinimalProject(targetDir, parentConfig as unknown as BosConfigInput, {
1297
- extendsAccount,
1298
- extendsGateway,
1299
- account: account || extendsAccount,
1300
- domain,
1301
- plugins,
1302
- withHost,
1303
- }),
1324
+ filesCopied = await timePhase(
1325
+ timings,
1326
+ "scaffold project",
1327
+ () =>
1328
+ scaffoldMinimalProject(targetDir, parentConfig as unknown as BosConfigInput, {
1329
+ extendsAccount,
1330
+ extendsGateway,
1331
+ account: account || extendsAccount,
1332
+ domain,
1333
+ plugins,
1334
+ overrides,
1335
+ repository,
1336
+ }),
1337
+ s,
1304
1338
  );
1305
1339
  } else {
1306
1340
  const patterns = await readTemplatekeep(sourceDir);
1307
1341
  if (patterns.length === 0) {
1342
+ s.stop("Failed");
1308
1343
  return {
1309
1344
  status: "error" as const,
1310
1345
  directory,
@@ -1312,77 +1347,112 @@ export default createPlugin({
1312
1347
  account,
1313
1348
  domain,
1314
1349
  extends: extendsRef,
1315
- plugins: plugins ?? [],
1350
+ plugins,
1351
+ overrides,
1316
1352
  filesCopied: 0,
1317
1353
  error: "No .templatekeep found in template source",
1318
1354
  };
1319
1355
  }
1320
1356
 
1321
1357
  const pluginRoutes: Record<string, string[]> = {};
1322
- const parentRuntimePlugins = await buildRuntimePluginsForConfig(
1323
- parentConfig as BosConfig,
1324
- sourceDir,
1325
- "production",
1326
- );
1327
- for (const [key, plugin] of Object.entries(parentRuntimePlugins ?? {})) {
1328
- if (plugin.routes && plugin.routes.length > 0) {
1329
- pluginRoutes[key] = plugin.routes;
1358
+ if (overrides.includes("plugins")) {
1359
+ const parentRuntimePlugins = await buildRuntimePluginsForConfig(
1360
+ parentConfig as BosConfig,
1361
+ sourceDir,
1362
+ "production",
1363
+ );
1364
+ for (const [key, plugin] of Object.entries(parentRuntimePlugins ?? {})) {
1365
+ if (plugin.routes && plugin.routes.length > 0) {
1366
+ pluginRoutes[key] = plugin.routes;
1367
+ }
1330
1368
  }
1331
1369
  }
1332
1370
 
1333
- filesCopied = await timePhase(timings, "copy files", () =>
1334
- copyFilteredFiles(sourceDir, targetDir, patterns, {
1335
- withHost,
1336
- plugins,
1337
- pluginRoutes,
1338
- }),
1371
+ filesCopied = await timePhase(
1372
+ timings,
1373
+ "copy files",
1374
+ () =>
1375
+ copyFilteredFiles(sourceDir, targetDir, patterns, {
1376
+ overrides,
1377
+ plugins,
1378
+ pluginRoutes,
1379
+ }),
1380
+ s,
1339
1381
  );
1340
1382
 
1341
- await timePhase(timings, "personalize config", () =>
1342
- personalizeConfig(targetDir, {
1343
- extendsAccount,
1344
- extendsGateway,
1345
- account: account || extendsAccount,
1346
- domain: domain || extendsGateway,
1347
- plugins,
1348
- pluginRoutes,
1349
- workspaceOpts: { sourceDir },
1350
- withHost,
1351
- }),
1383
+ await timePhase(
1384
+ timings,
1385
+ "personalize config",
1386
+ () =>
1387
+ personalizeConfig(targetDir, {
1388
+ extendsAccount,
1389
+ extendsGateway,
1390
+ account: account || extendsAccount,
1391
+ domain: domain || extendsGateway,
1392
+ plugins,
1393
+ overrides,
1394
+ pluginRoutes,
1395
+ workspaceOpts: { sourceDir },
1396
+ repository,
1397
+ }),
1398
+ s,
1352
1399
  );
1353
1400
 
1354
- await timePhase(timings, "write snapshot", () =>
1355
- writeInitSnapshot(targetDir, extendsAccount, extendsGateway, sourceDir, patterns, {
1356
- withHost,
1357
- plugins,
1358
- pluginRoutes,
1359
- }),
1401
+ await timePhase(
1402
+ timings,
1403
+ "write snapshot",
1404
+ () =>
1405
+ writeInitSnapshot(targetDir, extendsAccount, extendsGateway, sourceDir, patterns, {
1406
+ overrides,
1407
+ plugins,
1408
+ pluginRoutes,
1409
+ }),
1410
+ s,
1360
1411
  );
1361
1412
  }
1362
1413
 
1363
- const initConfig = await timePhase(timings, "resolve config", () =>
1364
- loadConfig({ cwd: targetDir }),
1414
+ const initConfig = await timePhase(
1415
+ timings,
1416
+ "resolve config",
1417
+ () => loadConfig({ cwd: targetDir }),
1418
+ s,
1365
1419
  );
1366
1420
  if (initConfig?.runtime) {
1367
- await timePhase(timings, "generate env/docker", async () => {
1368
- writeGeneratedInfra(targetDir, initConfig.runtime);
1369
- });
1421
+ await timePhase(
1422
+ timings,
1423
+ "generate env/docker",
1424
+ async () => {
1425
+ writeGeneratedInfra(targetDir, initConfig.runtime);
1426
+ },
1427
+ s,
1428
+ );
1370
1429
  }
1371
- await timePhase(timings, "create env file", async () => {
1372
- ensureEnvFile(targetDir);
1373
- });
1430
+ await timePhase(
1431
+ timings,
1432
+ "create env file",
1433
+ async () => {
1434
+ ensureEnvFile(targetDir);
1435
+ },
1436
+ s,
1437
+ );
1374
1438
 
1375
1439
  if (!input.noInstall) {
1376
- await timePhase(timings, "install dependencies", () => runBunInstall(targetDir));
1377
- await timePhase(timings, "generate types", () => runTypesGen(targetDir));
1378
- await timePhase(timings, "generate migrations", () =>
1379
- generateDatabaseMigrations(targetDir),
1440
+ await timePhase(timings, "install dependencies", () => runBunInstall(targetDir), s);
1441
+ await timePhase(timings, "generate types", () => runTypesGen(targetDir), s);
1442
+ await timePhase(
1443
+ timings,
1444
+ "generate migrations",
1445
+ () => generateDatabaseMigrations(targetDir),
1446
+ s,
1380
1447
  );
1381
1448
  }
1382
1449
 
1383
1450
  if (input.noInstall && initConfig?.config) {
1384
- await timePhase(timings, "generate code artifacts", () =>
1385
- generateCodeArtifacts(targetDir, initConfig.config),
1451
+ await timePhase(
1452
+ timings,
1453
+ "generate code artifacts",
1454
+ () => generateCodeArtifacts(targetDir, initConfig.config),
1455
+ s,
1386
1456
  );
1387
1457
  }
1388
1458
 
@@ -1417,6 +1487,7 @@ export default createPlugin({
1417
1487
  domain,
1418
1488
  extends: extendsRef,
1419
1489
  plugins,
1490
+ overrides,
1420
1491
  filesCopied,
1421
1492
  timings,
1422
1493
  };
@@ -1437,6 +1508,7 @@ export default createPlugin({
1437
1508
  domain: input.domain,
1438
1509
  extends: extendsRef,
1439
1510
  plugins: input.plugins ?? [],
1511
+ overrides: input.overrides,
1440
1512
  filesCopied: 0,
1441
1513
  timings: [],
1442
1514
  error: error instanceof Error ? error.message : "Unknown error",