@businessdash/sdk 0.9.60 → 0.9.80

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 (239) hide show
  1. package/README.md +991 -295
  2. package/assets/biab-sw.js +92 -0
  3. package/dist/account-core/index.d.ts +126 -0
  4. package/dist/account-core/index.d.ts.map +1 -0
  5. package/dist/account-core/index.js +191 -0
  6. package/dist/account-core/index.js.map +1 -0
  7. package/dist/account.d.ts +11 -0
  8. package/dist/account.d.ts.map +1 -0
  9. package/dist/account.js +11 -0
  10. package/dist/account.js.map +1 -0
  11. package/dist/auth-handler.d.ts +1 -1
  12. package/dist/auth-links.d.ts +33 -0
  13. package/dist/auth-links.d.ts.map +1 -0
  14. package/dist/auth-links.js +64 -0
  15. package/dist/auth-links.js.map +1 -0
  16. package/dist/blog-core/index.d.ts +112 -0
  17. package/dist/blog-core/index.d.ts.map +1 -0
  18. package/dist/blog-core/index.js +330 -0
  19. package/dist/blog-core/index.js.map +1 -0
  20. package/dist/blog.d.ts +11 -0
  21. package/dist/blog.d.ts.map +1 -0
  22. package/dist/blog.js +11 -0
  23. package/dist/blog.js.map +1 -0
  24. package/dist/chat-core/index.d.ts +97 -0
  25. package/dist/chat-core/index.d.ts.map +1 -0
  26. package/dist/chat-core/index.js +237 -0
  27. package/dist/chat-core/index.js.map +1 -0
  28. package/dist/chat.d.ts +11 -0
  29. package/dist/chat.d.ts.map +1 -0
  30. package/dist/chat.js +11 -0
  31. package/dist/chat.js.map +1 -0
  32. package/dist/checkout-core/index.d.ts +65 -0
  33. package/dist/checkout-core/index.d.ts.map +1 -0
  34. package/dist/checkout-core/index.js +159 -0
  35. package/dist/checkout-core/index.js.map +1 -0
  36. package/dist/checkout.d.ts +10 -0
  37. package/dist/checkout.d.ts.map +1 -0
  38. package/dist/checkout.js +10 -0
  39. package/dist/checkout.js.map +1 -0
  40. package/dist/cli.js +133 -25
  41. package/dist/cli.js.map +1 -1
  42. package/dist/client.d.ts +622 -1
  43. package/dist/client.d.ts.map +1 -1
  44. package/dist/client.js +888 -1
  45. package/dist/client.js.map +1 -1
  46. package/dist/consent-core/index.cjs +107 -0
  47. package/dist/consent-core/index.d.ts +103 -0
  48. package/dist/consent-core/index.d.ts.map +1 -0
  49. package/dist/consent-core/index.js +157 -0
  50. package/dist/consent-core/index.js.map +1 -0
  51. package/dist/contracts.d.ts +3526 -767
  52. package/dist/contracts.d.ts.map +1 -1
  53. package/dist/contracts.js +571 -4
  54. package/dist/contracts.js.map +1 -1
  55. package/dist/data-model-schema.d.ts +1 -1
  56. package/dist/data-model-schema.d.ts.map +1 -1
  57. package/dist/element.d.ts +30 -0
  58. package/dist/element.d.ts.map +1 -1
  59. package/dist/element.js +56 -0
  60. package/dist/element.js.map +1 -1
  61. package/dist/embed-protocol.d.ts +86 -0
  62. package/dist/embed-protocol.d.ts.map +1 -0
  63. package/dist/embed-protocol.js +60 -0
  64. package/dist/embed-protocol.js.map +1 -0
  65. package/dist/framework-support.d.ts +122 -0
  66. package/dist/framework-support.d.ts.map +1 -0
  67. package/dist/framework-support.js +323 -0
  68. package/dist/framework-support.js.map +1 -0
  69. package/dist/index.cjs +1355 -24
  70. package/dist/legal-core/index.cjs +115 -0
  71. package/dist/legal-core/index.d.ts +160 -0
  72. package/dist/legal-core/index.d.ts.map +1 -0
  73. package/dist/legal-core/index.js +220 -0
  74. package/dist/legal-core/index.js.map +1 -0
  75. package/dist/marketing-core/index.d.ts +66 -0
  76. package/dist/marketing-core/index.d.ts.map +1 -0
  77. package/dist/marketing-core/index.js +154 -0
  78. package/dist/marketing-core/index.js.map +1 -0
  79. package/dist/marketing.d.ts +7 -0
  80. package/dist/marketing.d.ts.map +1 -0
  81. package/dist/marketing.js +7 -0
  82. package/dist/marketing.js.map +1 -0
  83. package/dist/mcp-adapters/index.d.ts +135 -0
  84. package/dist/mcp-adapters/index.d.ts.map +1 -0
  85. package/dist/mcp-adapters/index.js +187 -0
  86. package/dist/mcp-adapters/index.js.map +1 -0
  87. package/dist/mcp-adapters.d.ts +7 -0
  88. package/dist/mcp-adapters.d.ts.map +1 -0
  89. package/dist/mcp-adapters.js +7 -0
  90. package/dist/mcp-adapters.js.map +1 -0
  91. package/dist/model3d-core/index.cjs +95 -0
  92. package/dist/model3d-core/index.d.ts +167 -0
  93. package/dist/model3d-core/index.d.ts.map +1 -0
  94. package/dist/model3d-core/index.js +158 -0
  95. package/dist/model3d-core/index.js.map +1 -0
  96. package/dist/notifications-core/index.cjs +315 -0
  97. package/dist/notifications-core/index.d.ts +229 -0
  98. package/dist/notifications-core/index.d.ts.map +1 -0
  99. package/dist/notifications-core/index.js +445 -0
  100. package/dist/notifications-core/index.js.map +1 -0
  101. package/dist/portal-core/index.d.ts +451 -0
  102. package/dist/portal-core/index.d.ts.map +1 -0
  103. package/dist/portal-core/index.js +819 -0
  104. package/dist/portal-core/index.js.map +1 -0
  105. package/dist/portal.d.ts +7 -0
  106. package/dist/portal.d.ts.map +1 -0
  107. package/dist/portal.js +7 -0
  108. package/dist/portal.js.map +1 -0
  109. package/dist/push-core/index.cjs +171 -0
  110. package/dist/push-core/index.d.ts +149 -0
  111. package/dist/push-core/index.d.ts.map +1 -0
  112. package/dist/push-core/index.js +231 -0
  113. package/dist/push-core/index.js.map +1 -0
  114. package/dist/react-marketing.d.ts +1 -17
  115. package/dist/react-marketing.d.ts.map +1 -1
  116. package/dist/react-marketing.js +4 -0
  117. package/dist/react-marketing.js.map +1 -1
  118. package/dist/react.d.ts +294 -101
  119. package/dist/react.d.ts.map +1 -1
  120. package/dist/react.js +302 -246
  121. package/dist/react.js.map +1 -1
  122. package/dist/seed-core/index.d.ts +354 -0
  123. package/dist/seed-core/index.d.ts.map +1 -0
  124. package/dist/seed-core/index.js +420 -0
  125. package/dist/seed-core/index.js.map +1 -0
  126. package/dist/seed.d.ts +7 -0
  127. package/dist/seed.d.ts.map +1 -0
  128. package/dist/seed.js +7 -0
  129. package/dist/seed.js.map +1 -0
  130. package/dist/seo-core/blog.d.ts +94 -0
  131. package/dist/seo-core/blog.d.ts.map +1 -0
  132. package/dist/seo-core/blog.js +149 -0
  133. package/dist/seo-core/blog.js.map +1 -0
  134. package/dist/seo-core/commerce.d.ts +64 -0
  135. package/dist/seo-core/commerce.d.ts.map +1 -0
  136. package/dist/seo-core/commerce.js +87 -0
  137. package/dist/seo-core/commerce.js.map +1 -0
  138. package/dist/seo-core/index.cjs +751 -0
  139. package/dist/seo-core/index.d.ts +226 -0
  140. package/dist/seo-core/index.d.ts.map +1 -0
  141. package/dist/seo-core/index.js +455 -0
  142. package/dist/seo-core/index.js.map +1 -0
  143. package/dist/seo-core/local.d.ts +181 -0
  144. package/dist/seo-core/local.d.ts.map +1 -0
  145. package/dist/seo-core/local.js +193 -0
  146. package/dist/seo-core/local.js.map +1 -0
  147. package/dist/sitemap-core/index.cjs +167 -0
  148. package/dist/sitemap-core/index.d.ts +155 -0
  149. package/dist/sitemap-core/index.d.ts.map +1 -0
  150. package/dist/sitemap-core/index.js +195 -0
  151. package/dist/sitemap-core/index.js.map +1 -0
  152. package/dist/social-core/index.d.ts +74 -0
  153. package/dist/social-core/index.d.ts.map +1 -0
  154. package/dist/social-core/index.js +72 -0
  155. package/dist/social-core/index.js.map +1 -0
  156. package/dist/social.d.ts +7 -0
  157. package/dist/social.d.ts.map +1 -0
  158. package/dist/social.js +7 -0
  159. package/dist/social.js.map +1 -0
  160. package/dist/solid-compat.d.ts +204 -0
  161. package/dist/solid-compat.d.ts.map +1 -0
  162. package/dist/solid-compat.js +221 -0
  163. package/dist/solid-compat.js.map +1 -0
  164. package/dist/store-core/index.d.ts +141 -0
  165. package/dist/store-core/index.d.ts.map +1 -0
  166. package/dist/store-core/index.js +277 -0
  167. package/dist/store-core/index.js.map +1 -0
  168. package/dist/store.d.ts +12 -0
  169. package/dist/store.d.ts.map +1 -0
  170. package/dist/store.js +12 -0
  171. package/dist/store.js.map +1 -0
  172. package/dist/vanilla.d.ts +111 -0
  173. package/dist/vanilla.d.ts.map +1 -1
  174. package/dist/vanilla.js +206 -0
  175. package/dist/vanilla.js.map +1 -1
  176. package/dist/verify-core/index.d.ts +98 -0
  177. package/dist/verify-core/index.d.ts.map +1 -0
  178. package/dist/verify-core/index.js +186 -0
  179. package/dist/verify-core/index.js.map +1 -0
  180. package/dist/verify.d.ts +8 -0
  181. package/dist/verify.d.ts.map +1 -0
  182. package/dist/verify.js +8 -0
  183. package/dist/verify.js.map +1 -0
  184. package/openapi.json +4516 -1311
  185. package/package.json +128 -11
  186. package/src/account-core/index.ts +309 -0
  187. package/src/account.ts +11 -0
  188. package/src/angular/headless.ts +519 -0
  189. package/src/angular/index.ts +3 -0
  190. package/src/auth-links.ts +76 -0
  191. package/src/blog-core/index.ts +423 -0
  192. package/src/blog.ts +11 -0
  193. package/src/chat-core/index.ts +335 -0
  194. package/src/chat.ts +11 -0
  195. package/src/checkout-core/index.ts +225 -0
  196. package/src/checkout.ts +10 -0
  197. package/src/cli.ts +184 -28
  198. package/src/client.ts +1097 -0
  199. package/src/consent-core/index.ts +213 -0
  200. package/src/contracts.ts +768 -11
  201. package/src/data-model-schema.ts +1 -1
  202. package/src/element.ts +102 -0
  203. package/src/embed-protocol.ts +100 -0
  204. package/src/framework-support.ts +440 -0
  205. package/src/legal-core/index.ts +276 -0
  206. package/src/marketing-core/index.ts +209 -0
  207. package/src/marketing.ts +7 -0
  208. package/src/mcp-adapters/index.ts +264 -0
  209. package/src/mcp-adapters.ts +7 -0
  210. package/src/model3d-core/index.ts +248 -0
  211. package/src/notifications-core/index.ts +650 -0
  212. package/src/portal-core/index.ts +1564 -0
  213. package/src/portal.ts +7 -0
  214. package/src/push-core/index.ts +335 -0
  215. package/src/qwik.tsx +602 -2
  216. package/src/react-marketing.tsx +5 -0
  217. package/src/react.tsx +434 -319
  218. package/src/seed-core/index.ts +735 -0
  219. package/src/seed.ts +7 -0
  220. package/src/seo-core/blog.ts +216 -0
  221. package/src/seo-core/commerce.ts +138 -0
  222. package/src/seo-core/index.ts +605 -0
  223. package/src/seo-core/local.ts +333 -0
  224. package/src/sitemap-core/index.ts +296 -0
  225. package/src/social-core/index.ts +103 -0
  226. package/src/social.ts +7 -0
  227. package/src/solid-compat.tsx +347 -0
  228. package/src/solid-surfaces.tsx +1311 -0
  229. package/src/solid.tsx +82 -60
  230. package/src/store-core/index.ts +426 -0
  231. package/src/store.ts +12 -0
  232. package/src/svelte/SocialLinks.svelte +84 -0
  233. package/src/svelte/headless.ts +435 -0
  234. package/src/svelte/index.ts +9 -0
  235. package/src/vanilla.ts +367 -0
  236. package/src/verify-core/index.ts +288 -0
  237. package/src/verify.ts +8 -0
  238. package/src/vue/headless.ts +527 -0
  239. package/src/vue/index.ts +3 -0
package/src/cli.ts CHANGED
@@ -67,6 +67,11 @@ import {
67
67
  isReservedPagePath,
68
68
  reservedPagePathErrorMessage,
69
69
  } from "./reserved-paths.js";
70
+ import {
71
+ callPackageApi,
72
+ runSeed,
73
+ type SeedDefinition,
74
+ } from "./seed-core/index.js";
70
75
 
71
76
  const COMMANDS = [
72
77
  "sync-schema",
@@ -80,10 +85,23 @@ const COMMANDS = [
80
85
  "export-graphql-schema",
81
86
  "sync-data-model",
82
87
  "sync-records",
88
+ // Whole-seed: schema, records, collections, products, posts and coupons in
89
+ // one dependency-ordered run. Same functions the programmatic API exposes.
90
+ "seed",
83
91
  "wipe-collections",
84
92
  "wipe-database",
85
93
  "help",
86
94
  ] as const;
95
+
96
+ /** Candidates for a whole-seed file, newest naming first. */
97
+ const SEED_CONFIG_CANDIDATES = [
98
+ "businessdash.seed.ts",
99
+ "businessdash.seed.mjs",
100
+ "businessdash.seed.js",
101
+ "biab.seed.ts",
102
+ "biab.seed.mjs",
103
+ "biab.seed.js",
104
+ ];
87
105
  type Command = (typeof COMMANDS)[number];
88
106
 
89
107
  /** Config candidates per flow. The marketing and data-model configs are
@@ -453,6 +471,14 @@ function resolveApiTarget(env: Record<string, string>): ApiTarget {
453
471
  return { baseUrl: normalizeBaseUrl(rawBase), apiKey, siteId };
454
472
  }
455
473
 
474
+ /**
475
+ * One data-model request.
476
+ *
477
+ * The transport, the auth header and the error shaping live in
478
+ * `seed-core/callPackageApi`, which the programmatic seeding API also uses.
479
+ * Two copies would drift, and the one that drifted would be whichever of the
480
+ * CLI or a consumer's build step nobody happened to be testing that week.
481
+ */
456
482
  async function callDataModelApi(input: {
457
483
  target: ApiTarget;
458
484
  path: string;
@@ -460,35 +486,14 @@ async function callDataModelApi(input: {
460
486
  body?: unknown;
461
487
  }): Promise<Record<string, unknown>> {
462
488
  const { target, path, method, body } = input;
463
- const url = `${target.baseUrl}/sites/${encodeURIComponent(target.siteId)}/data-model/${path}`;
464
- const res = await fetch(url, {
465
- method,
466
- headers: {
467
- "content-type": "application/json",
468
- authorization: `Bearer ${target.apiKey}`,
489
+ return callPackageApi(
490
+ { apiKey: target.apiKey, siteId: target.siteId, baseUrl: target.baseUrl },
491
+ {
492
+ path: `sites/${encodeURIComponent(target.siteId)}/data-model/${path}`,
493
+ method,
494
+ ...(body !== undefined ? { body } : {}),
469
495
  },
470
- ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
471
- });
472
- const text = await res.text();
473
- let parsed: Record<string, unknown> | null = null;
474
- try {
475
- parsed = JSON.parse(text) as Record<string, unknown>;
476
- } catch {
477
- parsed = null;
478
- }
479
- if (!res.ok) {
480
- const message =
481
- typeof parsed?.["message"] === "string"
482
- ? parsed["message"]
483
- : `HTTP ${res.status} ${res.statusText} — ${text.slice(0, 240)}`;
484
- throw new Error(message);
485
- }
486
- if (!parsed) {
487
- throw new Error(
488
- `Server replied ${res.status} but the body wasn't JSON — first 240 chars: ${text.slice(0, 240)}`,
489
- );
490
- }
491
- return parsed;
496
+ );
492
497
  }
493
498
 
494
499
  type PlanChange = {
@@ -1241,6 +1246,134 @@ type WipeCollectionsResult = {
1241
1246
  * no `--all` and no `--yes`: a human must name the targets, review live counts,
1242
1247
  * answer once, and then type a state-bound phrase exactly.
1243
1248
  */
1249
+ /**
1250
+ * Run a whole seed file: schema, records, static collections, products, blog
1251
+ * posts and coupons, in that order.
1252
+ *
1253
+ * This is the same `runSeed` the programmatic API exposes, not a second
1254
+ * implementation — a consumer running `businessdash seed` in CI and a consumer
1255
+ * calling `runSeed` from a Nuxt module get identical behaviour, including the
1256
+ * refusal on a destructive plan.
1257
+ */
1258
+ async function cmdSeed(opts: {
1259
+ env: Record<string, string>;
1260
+ cwd: string;
1261
+ configPath?: string | undefined;
1262
+ dryRun: boolean;
1263
+ force: boolean;
1264
+ }) {
1265
+ const seedPath = findConfigPath(
1266
+ opts.cwd,
1267
+ opts.configPath,
1268
+ SEED_CONFIG_CANDIDATES,
1269
+ "Create one with `defineSeed({...})` exported as default.",
1270
+ );
1271
+
1272
+ const url = pathToFileURL(seedPath).href;
1273
+ let mod: { default?: unknown; seed?: unknown };
1274
+ try {
1275
+ mod = (await import(url)) as typeof mod;
1276
+ } catch (err) {
1277
+ if (seedPath.endsWith(".ts")) {
1278
+ throw new Error(
1279
+ `Could not load TypeScript seed at ${seedPath}. Run the CLI under tsx, e.g.: ` +
1280
+ `\`npx tsx node_modules/@businessdash/sdk/dist/cli.js seed\`.\nUnderlying: ${
1281
+ err instanceof Error ? err.message : String(err)
1282
+ }`,
1283
+ );
1284
+ }
1285
+ throw err;
1286
+ }
1287
+
1288
+ const seed = (mod.default ?? mod.seed) as SeedDefinition | undefined;
1289
+ if (!seed || typeof seed !== "object") {
1290
+ throw new Error(
1291
+ `${seedPath} did not export a seed. Default-export \`defineSeed({...})\`.`,
1292
+ );
1293
+ }
1294
+
1295
+ const counts = [
1296
+ seed.dataModel && "schema",
1297
+ seed.records && `${Object.keys(seed.records).length} record set(s)`,
1298
+ seed.collections?.length && `${seed.collections.length} collection(s)`,
1299
+ seed.products?.length && `${seed.products.length} product(s)`,
1300
+ seed.posts?.length && `${seed.posts.length} post(s)`,
1301
+ seed.coupons?.length && `${seed.coupons.length} coupon(s)`,
1302
+ ].filter(Boolean) as string[];
1303
+
1304
+ logStep(
1305
+ counts.length > 0
1306
+ ? `Seeding ${counts.join(", ")} from ${fg.bold(seedPath)}.`
1307
+ : `${seedPath} is empty — nothing to seed.`,
1308
+ );
1309
+ if (counts.length === 0) return;
1310
+
1311
+ if (opts.dryRun) {
1312
+ // The schema step still runs, because its own dry run is plan-only and
1313
+ // the plan is the single most useful thing to see before a real seed.
1314
+ // Everything else is skipped rather than faked.
1315
+ logStep("--dry-run: planning the schema, uploading nothing else.");
1316
+ if (seed.dataModel) {
1317
+ await runSeed(
1318
+ resolveSeedTarget(opts.env),
1319
+ { dataModel: seed.dataModel, dataModelOptions: { dryRun: true } },
1320
+ { onProgress: (m) => console.log(` ${fg.dim("→")} ${m}`) },
1321
+ );
1322
+ }
1323
+ for (const line of counts.filter((c) => c !== "schema")) {
1324
+ console.log(` ${fg.dim("→")} would seed ${line}`);
1325
+ }
1326
+ return;
1327
+ }
1328
+
1329
+ const result = await runSeed(resolveSeedTarget(opts.env), seed, {
1330
+ onProgress: (message) => console.log(` ${fg.dim("→")} ${message}`),
1331
+ // --force is the deliberate decision the refusal asks for.
1332
+ failOnDangerousPlan: !opts.force,
1333
+ });
1334
+
1335
+ // Conflicts are REPORTED rather than thrown, so a duplicate slug halfway
1336
+ // through does not hide the seven that worked. Surface them here or they
1337
+ // are invisible.
1338
+ const skipped = [
1339
+ ...(result.posts ?? [])
1340
+ .filter((p) => !p.created)
1341
+ .map((p) => `post "${p.slug}" already existed`),
1342
+ ...(result.coupons ?? [])
1343
+ .filter((c) => !c.created)
1344
+ .map((c) => `coupon "${c.code}" already existed`),
1345
+ ];
1346
+ for (const line of skipped) {
1347
+ console.log(` ${fg.amber("⚠")} ${fg.dim(line)}`);
1348
+ }
1349
+
1350
+ console.log("");
1351
+ logStep(fg.green("✓ Seed complete."));
1352
+ if (
1353
+ result.dataModel &&
1354
+ !result.dataModel.noop &&
1355
+ !result.dataModel.planOnly
1356
+ ) {
1357
+ console.log(
1358
+ ` ${fg.dim("The schema landed as a DRAFT. Promote it in Site Builder → Site Data → Database to apply it.")}`,
1359
+ );
1360
+ }
1361
+ if (result.products?.length) {
1362
+ console.log(
1363
+ ` ${fg.dim("Products were created unpublished and are NOT in Stripe yet — publish them, then sync the catalogue.")}`,
1364
+ );
1365
+ }
1366
+ }
1367
+
1368
+ /** The seed target, from the same env the rest of the CLI reads. */
1369
+ function resolveSeedTarget(env: Record<string, string>): {
1370
+ baseUrl: string;
1371
+ apiKey: string;
1372
+ siteId: string;
1373
+ } {
1374
+ return resolveApiTarget(env);
1375
+ }
1376
+
1244
1377
  async function cmdWipeCollections(opts: {
1245
1378
  env: Record<string, string>;
1246
1379
  collections: string[];
@@ -2162,10 +2295,17 @@ CUSTOM DATABASE (biab.data-model.config.ts)
2162
2295
  npx biab-dev export-graphql-schema [--out path] [--include-standard]
2163
2296
  npx biab-dev sync-data-model [--config path] [--dry-run] [--prune] [--forms [slugs]] [--no-forms] [--note "..."]
2164
2297
  npx biab-dev sync-records [--records-dir path] [--dry-run]
2298
+ npx biab-dev seed [--config path] [--dry-run] [--yes]
2165
2299
  npx biab-dev wipe-collections --collections name-a,name-b [--dry-run]
2166
2300
  npx biab-dev wipe-database --collections name-a,name-b [--config path] [--dry-run] [--yes]
2167
2301
  npx biab-dev wipe-database --all [--config path] [--dry-run] [--yes]
2168
2302
 
2303
+ seed run businessdash.seed.ts — schema, records, static collections,
2304
+ products, blog posts and coupons, in dependency order. Products and
2305
+ posts are created UNPUBLISHED, and the schema lands as a DRAFT you
2306
+ promote in the dashboard. A destructive schema plan refuses unless
2307
+ you pass --yes. Same code path as runSeed() from @businessdash/sdk/seed.
2308
+
2169
2309
  view what's LIVE in BIAB right now (the dashboard can change it too, so
2170
2310
  this is not just "what I last pushed")
2171
2311
  print what your local config resolves to — no network
@@ -2489,6 +2629,22 @@ async function main(): Promise<void> {
2489
2629
  return;
2490
2630
  }
2491
2631
 
2632
+ // Above the marketing-config resolution below: a seed file is its own
2633
+ // config, and a project that seeds a store without a marketing site should
2634
+ // not be told its businessdash.config.ts is missing.
2635
+ if (command === "seed") {
2636
+ await cmdSeed({
2637
+ env,
2638
+ cwd,
2639
+ configPath: configOverride,
2640
+ dryRun,
2641
+ // A destructive plan refuses by default; --yes is the deliberate
2642
+ // decision, matching how the wipe commands read.
2643
+ force: yes,
2644
+ });
2645
+ return;
2646
+ }
2647
+
2492
2648
  const configPath = findConfigPath(cwd, configOverride);
2493
2649
  if (command === "print-schema") {
2494
2650
  await cmdPrintSchema({ configPath });