@holo-js/cli 0.1.9 → 0.2.1

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 (46) hide show
  1. package/dist/bin/holo.mjs +179 -81
  2. package/dist/broadcast-III5MB3R.mjs +203 -0
  3. package/dist/broadcast-ZIFYFOUQ.mjs +203 -0
  4. package/dist/{cache-ETOIQ5IG.mjs → cache-634WUR3T.mjs} +6 -6
  5. package/dist/cache-7J7DIOP6.mjs +66 -0
  6. package/dist/{cache-migrations-2GGI4TJK.mjs → cache-migrations-2NBEUF2T.mjs} +50 -30
  7. package/dist/cache-migrations-S2LJMDOQ.mjs +173 -0
  8. package/dist/{chunk-WRZFATUT.mjs → chunk-4OHJC3GL.mjs} +232 -143
  9. package/dist/{chunk-ASTSSSL2.mjs → chunk-5TEH2QPK.mjs} +99 -122
  10. package/dist/{chunk-F4MT6GBK.mjs → chunk-FGQ2I2YH.mjs} +1 -1
  11. package/dist/chunk-I7QBCEV7.mjs +33 -0
  12. package/dist/{chunk-R6BWRY3E.mjs → chunk-ILU426CF.mjs} +3 -1
  13. package/dist/{chunk-IMOGEKB4.mjs → chunk-J76GH2DR.mjs} +229 -119
  14. package/dist/{chunk-HB4Q7VYK.mjs → chunk-KS5TWO75.mjs} +30 -273
  15. package/dist/{chunk-57SJ566R.mjs → chunk-LBJAJLKU.mjs} +1 -1
  16. package/dist/{chunk-BAFQ2GOA.mjs → chunk-LXGQCG56.mjs} +1 -1
  17. package/dist/chunk-MCVRN7KX.mjs +3308 -0
  18. package/dist/chunk-SFRAGRHY.mjs +472 -0
  19. package/dist/{chunk-7JR73TOH.mjs → chunk-VP2E62DF.mjs} +36 -25
  20. package/dist/{chunk-5EU32E7X.mjs → chunk-VRGB6DIS.mjs} +116 -12
  21. package/dist/{chunk-SRPGIWCF.mjs → chunk-YEFJBN56.mjs} +2 -2
  22. package/dist/{config-ARLE6PKR.mjs → config-MD27U4FM.mjs} +3 -3
  23. package/dist/{dev-6RG5SSZ7.mjs → dev-M2GGURAX.mjs} +9 -7
  24. package/dist/dev-PBNFQK6Y.mjs +44 -0
  25. package/dist/{discovery-FCVGQQVD.mjs → discovery-GWTBF5RZ.mjs} +3 -3
  26. package/dist/{generators-UI2LJK3O.mjs → generators-BZJ53PUU.mjs} +13 -36
  27. package/dist/generators-DEPLONDJ.mjs +520 -0
  28. package/dist/index.mjs +181 -83
  29. package/dist/{media-migrations-JQSDCC7S.mjs → media-migrations-5EISZBSD.mjs} +9 -20
  30. package/dist/media-migrations-NMUWBEKE.mjs +106 -0
  31. package/dist/{queue-BY3PLH4I.mjs → queue-FRAVPNFJ.mjs} +12 -12
  32. package/dist/queue-GY7BWGTX.mjs +625 -0
  33. package/dist/{queue-migrations-YZUKEZK7.mjs → queue-migrations-J7YPIKRB.mjs} +13 -12
  34. package/dist/queue-migrations-O24ERNFF.mjs +167 -0
  35. package/dist/{runtime-BI343WHS.mjs → runtime-2AA7ZLJ6.mjs} +9 -9
  36. package/dist/{runtime-ZKD6URAV.mjs → runtime-GSXF4NB3.mjs} +1 -1
  37. package/dist/runtime-HGK2MWSC.mjs +57 -0
  38. package/dist/runtime-worker.d.ts +2 -0
  39. package/dist/runtime-worker.mjs +276 -0
  40. package/dist/{scaffold-UBOS2NZR.mjs → scaffold-DEOTRALR.mjs} +9 -5
  41. package/dist/scaffold-Y232IGYS.mjs +139 -0
  42. package/dist/{security-TYPVOYGF.mjs → security-MZW2CJKS.mjs} +6 -6
  43. package/dist/security-XVG673UR.mjs +71 -0
  44. package/package.json +9 -7
  45. package/dist/broadcast-VR46UZEL.mjs +0 -84
  46. package/dist/chunk-ZXDU7RHU.mjs +0 -9
package/dist/index.mjs CHANGED
@@ -3,35 +3,38 @@ import {
3
3
  SUPPORTED_INSTALL_TARGETS,
4
4
  SUPPORTED_QUEUE_INSTALL_DRIVERS,
5
5
  collectMultiStringFlag,
6
- confirm,
7
6
  ensureRequiredArg,
8
7
  isInteractive,
9
8
  normalizeChoice,
10
9
  normalizeOptionalPackages,
11
10
  parseNumberFlag,
12
11
  parseTokens,
12
+ promptChoice,
13
+ promptMultiChoice,
13
14
  resolveBooleanFlag,
14
15
  resolveNewProjectInput,
15
16
  resolveStringFlag,
16
17
  splitCsv
17
- } from "./chunk-5EU32E7X.mjs";
18
+ } from "./chunk-VRGB6DIS.mjs";
18
19
  import {
19
20
  hasProjectDependency
20
- } from "./chunk-F4MT6GBK.mjs";
21
- import {
22
- writeLine
23
- } from "./chunk-ZXDU7RHU.mjs";
21
+ } from "./chunk-FGQ2I2YH.mjs";
24
22
  import {
25
23
  fileExists
26
- } from "./chunk-57SJ566R.mjs";
24
+ } from "./chunk-LBJAJLKU.mjs";
25
+ import {
26
+ runWithSpinner,
27
+ supportsSpinner,
28
+ writeLine
29
+ } from "./chunk-I7QBCEV7.mjs";
27
30
  import "./chunk-D7O4SU6N.mjs";
28
- import "./chunk-7JR73TOH.mjs";
29
- import "./chunk-WRZFATUT.mjs";
30
- import "./chunk-SRPGIWCF.mjs";
31
- import "./chunk-IMOGEKB4.mjs";
31
+ import "./chunk-VP2E62DF.mjs";
32
+ import "./chunk-MCVRN7KX.mjs";
33
+ import "./chunk-YEFJBN56.mjs";
34
+ import "./chunk-J76GH2DR.mjs";
32
35
  import {
33
36
  SUPPORTED_AUTH_SOCIAL_PROVIDERS
34
- } from "./chunk-R6BWRY3E.mjs";
37
+ } from "./chunk-ILU426CF.mjs";
35
38
 
36
39
  // src/types.ts
37
40
  function defineCommand(command) {
@@ -109,6 +112,10 @@ async function generateProjectAppKey(projectRoot) {
109
112
  }
110
113
 
111
114
  // src/cli.ts
115
+ var AUTH_INSTALL_FEATURES = ["social", "workos", "clerk"];
116
+ var AUTH_SOCIAL_PROVIDER_MODES = ["default", "specific"];
117
+ var EVENTS_QUEUE_ACTIONS = ["skip", "enable"];
118
+ var MODEL_GENERATOR_OPTIONS = ["migration", "observer", "seeder", "factory"];
112
119
  var runtimeModulePromise;
113
120
  var queueModulePromise;
114
121
  var cacheModulePromise;
@@ -124,59 +131,59 @@ var projectDiscoveryModulePromise;
124
131
  var projectRuntimeModulePromise;
125
132
  var projectScaffoldModulePromise;
126
133
  function loadRuntimeModule() {
127
- runtimeModulePromise ??= import("./runtime-BI343WHS.mjs");
134
+ runtimeModulePromise ??= import("./runtime-2AA7ZLJ6.mjs");
128
135
  return runtimeModulePromise;
129
136
  }
130
137
  function loadQueueModule() {
131
- queueModulePromise ??= import("./queue-BY3PLH4I.mjs");
138
+ queueModulePromise ??= import("./queue-FRAVPNFJ.mjs");
132
139
  return queueModulePromise;
133
140
  }
134
141
  function loadCacheModule() {
135
- cacheModulePromise ??= import("./cache-ETOIQ5IG.mjs");
142
+ cacheModulePromise ??= import("./cache-7J7DIOP6.mjs");
136
143
  return cacheModulePromise;
137
144
  }
138
145
  function loadQueueMigrationsModule() {
139
- queueMigrationsModulePromise ??= import("./queue-migrations-YZUKEZK7.mjs");
146
+ queueMigrationsModulePromise ??= import("./queue-migrations-O24ERNFF.mjs");
140
147
  return queueMigrationsModulePromise;
141
148
  }
142
149
  function loadCacheMigrationsModule() {
143
- cacheMigrationsModulePromise ??= import("./cache-migrations-2GGI4TJK.mjs");
150
+ cacheMigrationsModulePromise ??= import("./cache-migrations-S2LJMDOQ.mjs");
144
151
  return cacheMigrationsModulePromise;
145
152
  }
146
153
  function loadMediaMigrationsModule() {
147
- mediaMigrationsModulePromise ??= import("./media-migrations-JQSDCC7S.mjs");
154
+ mediaMigrationsModulePromise ??= import("./media-migrations-NMUWBEKE.mjs");
148
155
  return mediaMigrationsModulePromise;
149
156
  }
150
157
  function loadGeneratorsModule() {
151
- generatorsModulePromise ??= import("./generators-UI2LJK3O.mjs");
158
+ generatorsModulePromise ??= import("./generators-BZJ53PUU.mjs");
152
159
  return generatorsModulePromise;
153
160
  }
154
161
  function loadBroadcastModule() {
155
- broadcastModulePromise ??= import("./broadcast-VR46UZEL.mjs");
162
+ broadcastModulePromise ??= import("./broadcast-III5MB3R.mjs");
156
163
  return broadcastModulePromise;
157
164
  }
158
165
  function loadSecurityModule() {
159
- securityModulePromise ??= import("./security-TYPVOYGF.mjs");
166
+ securityModulePromise ??= import("./security-MZW2CJKS.mjs");
160
167
  return securityModulePromise;
161
168
  }
162
169
  function loadDevModule() {
163
- devModulePromise ??= import("./dev-6RG5SSZ7.mjs");
170
+ devModulePromise ??= import("./dev-PBNFQK6Y.mjs");
164
171
  return devModulePromise;
165
172
  }
166
173
  function loadProjectConfigModule() {
167
- projectConfigModulePromise ??= import("./config-ARLE6PKR.mjs");
174
+ projectConfigModulePromise ??= import("./config-MD27U4FM.mjs");
168
175
  return projectConfigModulePromise;
169
176
  }
170
177
  function loadProjectDiscoveryModule() {
171
- projectDiscoveryModulePromise ??= import("./discovery-FCVGQQVD.mjs");
178
+ projectDiscoveryModulePromise ??= import("./discovery-GWTBF5RZ.mjs");
172
179
  return projectDiscoveryModulePromise;
173
180
  }
174
181
  function loadProjectRuntimeModule() {
175
- projectRuntimeModulePromise ??= import("./runtime-ZKD6URAV.mjs");
182
+ projectRuntimeModulePromise ??= import("./runtime-GSXF4NB3.mjs");
176
183
  return projectRuntimeModulePromise;
177
184
  }
178
185
  function loadProjectScaffoldModule() {
179
- projectScaffoldModulePromise ??= import("./scaffold-UBOS2NZR.mjs");
186
+ projectScaffoldModulePromise ??= import("./scaffold-DEOTRALR.mjs");
180
187
  return projectScaffoldModulePromise;
181
188
  }
182
189
  async function resolveRuntimeExecutor(runtimeExecutor) {
@@ -186,14 +193,18 @@ var projectExecutorLoaders = {
186
193
  runProjectPrepare: async () => (await loadDevModule()).runProjectPrepare,
187
194
  runProjectDevServer: async () => (await loadDevModule()).runProjectDevServer,
188
195
  runProjectLifecycleScript: async () => (await loadDevModule()).runProjectLifecycleScript,
196
+ runProjectStartServer: async () => (await loadDevModule()).runProjectStartServer,
189
197
  runProjectDependencyInstall: async () => (await loadDevModule()).runProjectDependencyInstall
190
198
  };
191
- async function resolveProjectExecutor(projectExecutors, key) {
192
- const existing = projectExecutors[key];
199
+ async function resolveExecutor(executors, loaders, key) {
200
+ const existing = executors[key];
193
201
  if (existing) {
194
202
  return existing;
195
203
  }
196
- return projectExecutorLoaders[key]();
204
+ return await loaders[key]();
205
+ }
206
+ async function resolveProjectExecutor(projectExecutors, key) {
207
+ return await resolveExecutor(projectExecutors, projectExecutorLoaders, key);
197
208
  }
198
209
  var queueExecutorLoaders = {
199
210
  runQueueFailedTableCommand: async () => (await loadQueueMigrationsModule()).runQueueFailedTableCommand,
@@ -219,32 +230,16 @@ var broadcastExecutorLoaders = {
219
230
  runBroadcastWorkCommand: async () => (await loadBroadcastModule()).runBroadcastWorkCommand
220
231
  };
221
232
  async function resolveQueueExecutor(queueExecutors, key) {
222
- const existing = queueExecutors[key];
223
- if (existing) {
224
- return existing;
225
- }
226
- return queueExecutorLoaders[key]();
233
+ return await resolveExecutor(queueExecutors, queueExecutorLoaders, key);
227
234
  }
228
235
  async function resolveCacheExecutor(cacheExecutors, key) {
229
- const existing = cacheExecutors[key];
230
- if (existing) {
231
- return existing;
232
- }
233
- return cacheExecutorLoaders[key]();
236
+ return await resolveExecutor(cacheExecutors, cacheExecutorLoaders, key);
234
237
  }
235
238
  async function resolveMediaExecutor(mediaExecutors, key) {
236
- const existing = mediaExecutors[key];
237
- if (existing) {
238
- return existing;
239
- }
240
- return mediaExecutorLoaders[key]();
239
+ return await resolveExecutor(mediaExecutors, mediaExecutorLoaders, key);
241
240
  }
242
241
  async function resolveBroadcastExecutor(broadcastExecutors, key) {
243
- const existing = broadcastExecutors[key];
244
- if (existing) {
245
- return existing;
246
- }
247
- return broadcastExecutorLoaders[key]();
242
+ return await resolveExecutor(broadcastExecutors, broadcastExecutorLoaders, key);
248
243
  }
249
244
  async function resolveGeneratorCommand(key) {
250
245
  return (await loadGeneratorsModule())[key];
@@ -299,10 +294,12 @@ async function runProjectDependencyInstallAfterPackageJsonUpdate(context, projec
299
294
  const runProjectPrepare = await resolveProjectExecutor(projectExecutors, "runProjectPrepare");
300
295
  await runProjectPrepare(context.projectRoot, context);
301
296
  }
302
- async function runProjectDependencyInstallForProject(context, projectExecutors, projectRoot) {
297
+ async function runProjectDependencyInstallForProject(context, projectExecutors, projectRoot, options = {}) {
303
298
  const runProjectDependencyInstall = await resolveProjectExecutor(projectExecutors, "runProjectDependencyInstall");
304
299
  await runProjectDependencyInstall(context, projectRoot);
305
- writeLine(context.stdout, " - installed dependencies");
300
+ if (options.writeStatus ?? true) {
301
+ writeLine(context.stdout, " - installed dependencies");
302
+ }
306
303
  }
307
304
  function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, projectExecutors = {}, broadcastExecutors = {}, securityExecutors = {}, cacheExecutors = {}, mediaExecutors = {}) {
308
305
  return [
@@ -321,7 +318,7 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
321
318
  {
322
319
  name: "new",
323
320
  description: "Scaffold a new Holo project",
324
- usage: "holo new <name> [--framework <nuxt|next|sveltekit>] [--database <sqlite|mysql|postgres>] [--package-manager <bun|npm|pnpm|yarn>] [--package <storage|events|queue|validation|forms|auth|authorization|notifications|mail|broadcast|security|cache>] [--storage-default-disk <local|public>]",
321
+ usage: "holo new <name> [--framework <nuxt|next|sveltekit>] [--database <sqlite|mysql|postgres>] [--package-manager <bun|npm|pnpm|yarn>] [--package <storage|events|queue|validation|forms|auth|authorization|notifications|mail|broadcast|realtime|security|cache>] [--storage-default-disk <local|public>]",
325
322
  source: "internal",
326
323
  async prepare(input) {
327
324
  const resolved = await resolveNewProjectInput(context, input);
@@ -347,16 +344,28 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
347
344
  );
348
345
  const targetDir = resolve2(commandContext.cwd, projectName);
349
346
  const { scaffoldProject } = await loadProjectScaffoldModule();
350
- await scaffoldProject(targetDir, {
351
- projectName,
352
- framework,
353
- databaseDriver,
354
- packageManager,
355
- storageDefaultDisk,
356
- optionalPackages
357
- });
347
+ await runWithSpinner(
348
+ context,
349
+ "Creating project files...",
350
+ () => scaffoldProject(targetDir, {
351
+ projectName,
352
+ framework,
353
+ databaseDriver,
354
+ packageManager,
355
+ storageDefaultDisk,
356
+ optionalPackages
357
+ }),
358
+ "Project files created."
359
+ );
358
360
  writeLine(context.stdout, `Created Holo project: ${targetDir}`);
359
- await runProjectDependencyInstallForProject(context, projectExecutors, targetDir);
361
+ await runWithSpinner(
362
+ context,
363
+ "Installing dependencies...",
364
+ () => runProjectDependencyInstallForProject(context, projectExecutors, targetDir, {
365
+ writeStatus: !supportsSpinner(context)
366
+ }),
367
+ "Dependencies installed."
368
+ );
360
369
  writeLine(context.stdout);
361
370
  writeLine(context.stdout, "Next steps");
362
371
  writeLine(context.stdout, ` cd ${projectName}`);
@@ -382,11 +391,13 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
382
391
  {
383
392
  name: "install",
384
393
  description: "Install first-party Holo support into an existing project.",
385
- usage: "holo install <queue|events|auth|authorization|notifications|mail|broadcast|security|cache|media> [--driver <queue: sync|file|redis|database; cache: file|redis|database>] [--social] [--provider <google|github|discord|facebook|apple|linkedin>] [--workos] [--clerk]",
394
+ usage: "holo install <queue|events|auth|authorization|notifications|mail|broadcast|realtime|security|cache|media> [--driver <queue: sync|file|redis|database; cache: file|redis|database>] [--social] [--provider <google|github|discord|facebook|apple|linkedin>] [--workos] [--clerk]",
386
395
  source: "internal",
387
396
  async prepare(input) {
397
+ const interactive = isInteractive(context, input.flags);
398
+ const requestedTarget = input.args[0]?.trim();
388
399
  const target = normalizeChoice(
389
- await ensureRequiredArg(context, input, 0, "Install target"),
400
+ requestedTarget || (interactive ? await promptChoice(context, "Install target", SUPPORTED_INSTALL_TARGETS, "queue") : await ensureRequiredArg(context, input, 0, "Install target")),
390
401
  SUPPORTED_INSTALL_TARGETS,
391
402
  "install target"
392
403
  );
@@ -409,17 +420,65 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
409
420
  if (target === "broadcast" && requestedDriver) {
410
421
  throw new Error("The broadcast installer does not support --driver.");
411
422
  }
423
+ if (target === "realtime" && requestedDriver) {
424
+ throw new Error("The realtime installer does not support --driver.");
425
+ }
412
426
  if (target === "security" && requestedDriver) {
413
427
  throw new Error("The security installer does not support --driver.");
414
428
  }
415
429
  if (target === "media" && requestedDriver) {
416
430
  throw new Error("The media installer does not support --driver.");
417
431
  }
418
- const driver = target === "queue" ? requestedDriver ? normalizeChoice(requestedDriver, SUPPORTED_QUEUE_INSTALL_DRIVERS, "queue driver") : "sync" : target === "cache" ? requestedDriver ? normalizeChoice(requestedDriver, SUPPORTED_CACHE_INSTALL_DRIVERS, "cache driver") : "file" : void 0;
419
- const socialProviders = target === "auth" ? (collectMultiStringFlag(input.flags, "provider") ?? []).flatMap((entry) => splitCsv(entry) ?? []).map((provider) => normalizeChoice(provider, SUPPORTED_AUTH_SOCIAL_PROVIDERS, "auth social provider")) : [];
420
- const social = target === "auth" ? resolveBooleanFlag(input.flags, "social") === true || socialProviders.length > 0 : false;
421
- const workos = target === "auth" ? resolveBooleanFlag(input.flags, "workos") === true : false;
422
- const clerk = target === "auth" ? resolveBooleanFlag(input.flags, "clerk") === true : false;
432
+ const driver = target === "queue" ? requestedDriver ? normalizeChoice(requestedDriver, SUPPORTED_QUEUE_INSTALL_DRIVERS, "queue driver") : interactive ? await promptChoice(context, "Queue driver", SUPPORTED_QUEUE_INSTALL_DRIVERS, "sync") : "sync" : target === "cache" ? requestedDriver ? normalizeChoice(requestedDriver, SUPPORTED_CACHE_INSTALL_DRIVERS, "cache driver") : interactive ? await promptChoice(context, "Cache driver", SUPPORTED_CACHE_INSTALL_DRIVERS, "file") : "file" : void 0;
433
+ let socialProviders = target === "auth" ? (collectMultiStringFlag(input.flags, "provider") ?? []).flatMap((entry) => splitCsv(entry) ?? []).map((provider) => normalizeChoice(provider, SUPPORTED_AUTH_SOCIAL_PROVIDERS, "auth social provider")) : [];
434
+ let social = target === "auth" ? resolveBooleanFlag(input.flags, "social") === true || socialProviders.length > 0 : false;
435
+ let workos = target === "auth" ? resolveBooleanFlag(input.flags, "workos") === true : false;
436
+ let clerk = target === "auth" ? resolveBooleanFlag(input.flags, "clerk") === true : false;
437
+ const authFlagsProvided = "social" in input.flags || "provider" in input.flags || "workos" in input.flags || "clerk" in input.flags;
438
+ if (target === "auth" && interactive && !authFlagsProvided) {
439
+ const features = await promptMultiChoice(
440
+ context,
441
+ "Auth providers",
442
+ AUTH_INSTALL_FEATURES,
443
+ {
444
+ labels: {
445
+ social: "Social OAuth",
446
+ workos: "WorkOS",
447
+ clerk: "Clerk"
448
+ },
449
+ hints: {
450
+ social: "Google, GitHub, Discord, Facebook, Apple, or LinkedIn"
451
+ }
452
+ }
453
+ );
454
+ social = features.includes("social");
455
+ workos = features.includes("workos");
456
+ clerk = features.includes("clerk");
457
+ if (social) {
458
+ const providerMode = await promptChoice(
459
+ context,
460
+ "Social provider setup",
461
+ AUTH_SOCIAL_PROVIDER_MODES,
462
+ "default",
463
+ {
464
+ labels: {
465
+ default: "Default social setup",
466
+ specific: "Choose specific providers"
467
+ }
468
+ }
469
+ );
470
+ if (providerMode === "specific") {
471
+ socialProviders = [
472
+ ...await promptMultiChoice(
473
+ context,
474
+ "Social providers",
475
+ SUPPORTED_AUTH_SOCIAL_PROVIDERS,
476
+ { required: true }
477
+ )
478
+ ];
479
+ }
480
+ }
481
+ }
423
482
  return {
424
483
  args: [target],
425
484
  flags: {
@@ -443,12 +502,19 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
443
502
  const eventsResult = await installEventsIntoProject(context.projectRoot);
444
503
  let queueResult;
445
504
  if (!queueConfigured && isInteractive(context, commandContext.flags)) {
446
- const enableQueuedListeners = await confirm(
505
+ const queueAction = await promptChoice(
447
506
  context,
448
- "Enable queued listeners too?",
449
- false
507
+ "Queued listeners",
508
+ EVENTS_QUEUE_ACTIONS,
509
+ "skip",
510
+ {
511
+ labels: {
512
+ skip: "Skip queued listeners",
513
+ enable: "Enable queued listeners"
514
+ }
515
+ }
450
516
  );
451
- if (enableQueuedListeners) {
517
+ if (queueAction === "enable") {
452
518
  queueResult = await installQueueIntoProject2(context.projectRoot, { driver: "sync" });
453
519
  }
454
520
  }
@@ -549,6 +615,17 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
549
615
  await runProjectDependencyInstallAfterPackageJsonUpdate(context, projectExecutors, result2.updatedPackageJson);
550
616
  return;
551
617
  }
618
+ if (target === "realtime") {
619
+ const { installRealtimeIntoProject } = await loadProjectScaffoldModule();
620
+ const result2 = await installRealtimeIntoProject(context.projectRoot);
621
+ const changed2 = result2.updatedPackageJson || result2.createdRealtimeDirectory || result2.createdFrameworkSetup;
622
+ writeLine(context.stdout, changed2 ? "Installed realtime support." : "Realtime support is already installed.");
623
+ if (result2.updatedPackageJson) writeLine(context.stdout, " - updated package.json");
624
+ if (result2.createdRealtimeDirectory) writeLine(context.stdout, " - created server/realtime");
625
+ if (result2.createdFrameworkSetup) writeLine(context.stdout, " - created realtime framework setup");
626
+ await runProjectDependencyInstallAfterPackageJsonUpdate(context, projectExecutors, result2.updatedPackageJson);
627
+ return;
628
+ }
552
629
  if (target === "security") {
553
630
  const { installSecurityIntoProject } = await loadProjectScaffoldModule();
554
631
  const result2 = await installSecurityIntoProject(context.projectRoot);
@@ -673,6 +750,19 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
673
750
  await runProjectLifecycleScript(context, context.projectRoot, "holo:build");
674
751
  }
675
752
  },
753
+ {
754
+ name: "start",
755
+ description: "Run the production framework server with Holo runtime preloads.",
756
+ usage: "holo start",
757
+ source: "internal",
758
+ async prepare() {
759
+ return { args: [], flags: {} };
760
+ },
761
+ async run() {
762
+ const runProjectStartServer = await resolveProjectExecutor(projectExecutors, "runProjectStartServer");
763
+ await runProjectStartServer(context, context.projectRoot);
764
+ }
765
+ },
676
766
  {
677
767
  name: "broadcast:work",
678
768
  description: "Run the self-hosted broadcast worker.",
@@ -1045,17 +1135,25 @@ function createInternalCommands(context, runtimeExecutor, queueExecutors = {}, p
1045
1135
  };
1046
1136
  if (isInteractive(context, input.flags)) {
1047
1137
  const noneSelected = [flags.migration, flags.observer, flags.seeder, flags.factory].every((value) => value !== true);
1048
- if (noneSelected && await confirm(context, "Generate a migration?", true)) {
1049
- flags.migration = true;
1050
- }
1051
- if (!flags.observer && await confirm(context, "Generate an observer?")) {
1052
- flags.observer = true;
1053
- }
1054
- if (!flags.seeder && await confirm(context, "Generate a seeder?")) {
1055
- flags.seeder = true;
1056
- }
1057
- if (!flags.factory && await confirm(context, "Generate a factory?")) {
1058
- flags.factory = true;
1138
+ if (noneSelected) {
1139
+ const selectedArtifacts = await promptMultiChoice(
1140
+ context,
1141
+ "Model artifacts",
1142
+ MODEL_GENERATOR_OPTIONS,
1143
+ {
1144
+ initialValues: ["migration"],
1145
+ labels: {
1146
+ migration: "Migration",
1147
+ observer: "Observer",
1148
+ seeder: "Seeder",
1149
+ factory: "Factory"
1150
+ }
1151
+ }
1152
+ );
1153
+ flags.migration = selectedArtifacts.includes("migration");
1154
+ flags.observer = selectedArtifacts.includes("observer");
1155
+ flags.seeder = selectedArtifacts.includes("seeder");
1156
+ flags.factory = selectedArtifacts.includes("factory");
1059
1157
  }
1060
1158
  }
1061
1159
  return {
@@ -1,29 +1,28 @@
1
1
  import {
2
- getRegistryMigrationSlug,
3
2
  hasRegisteredCreateTableMigration,
4
3
  hasRegisteredMigrationSlug,
5
4
  nextMigrationTemplate
6
- } from "./chunk-BAFQ2GOA.mjs";
5
+ } from "./chunk-LXGQCG56.mjs";
7
6
  import {
8
7
  writeLine
9
- } from "./chunk-ZXDU7RHU.mjs";
10
- import "./chunk-57SJ566R.mjs";
8
+ } from "./chunk-I7QBCEV7.mjs";
9
+ import "./chunk-LBJAJLKU.mjs";
11
10
  import "./chunk-D7O4SU6N.mjs";
12
11
  import {
13
12
  prepareProjectDiscovery
14
- } from "./chunk-7JR73TOH.mjs";
15
- import "./chunk-WRZFATUT.mjs";
13
+ } from "./chunk-VP2E62DF.mjs";
14
+ import "./chunk-4OHJC3GL.mjs";
16
15
  import {
17
16
  ensureProjectConfig
18
- } from "./chunk-SRPGIWCF.mjs";
17
+ } from "./chunk-YEFJBN56.mjs";
19
18
  import {
20
19
  loadGeneratedProjectRegistry
21
- } from "./chunk-IMOGEKB4.mjs";
20
+ } from "./chunk-J76GH2DR.mjs";
22
21
  import {
23
22
  makeProjectRelativePath,
24
23
  resolveDefaultArtifactPath,
25
24
  writeTextFile
26
- } from "./chunk-R6BWRY3E.mjs";
25
+ } from "./chunk-ILU426CF.mjs";
27
26
 
28
27
  // src/media-migrations.ts
29
28
  import { readdir } from "fs/promises";
@@ -94,23 +93,13 @@ async function createMediaTableMigration(projectRoot, options = {}) {
94
93
  }
95
94
  async function runMediaTableCommand(io, projectRoot) {
96
95
  const migrationFilePath = await createMediaTableMigration(projectRoot);
97
- const { runProjectPrepare } = await import("./dev-6RG5SSZ7.mjs");
98
- if (!migrationFilePath) {
99
- throw new Error(`A migration for table "${DEFAULT_MEDIA_TABLE}" already exists.`);
100
- }
96
+ const { runProjectPrepare } = await import("./dev-M2GGURAX.mjs");
101
97
  await runProjectPrepare(projectRoot);
102
98
  writeLine(io.stdout, `Created migration: ${makeProjectRelativePath(projectRoot, migrationFilePath)}`);
103
99
  }
104
- var mediaMigrationInternals = {
105
- getRegistryMigrationSlug,
106
- hasRegisteredMigrationSlug,
107
- hasRegisteredCreateTableMigration,
108
- nextMigrationTemplate
109
- };
110
100
  export {
111
101
  DEFAULT_MEDIA_TABLE,
112
102
  createMediaTableMigration,
113
- mediaMigrationInternals,
114
103
  normalizeMediaMigrationName,
115
104
  renderMediaTableMigration,
116
105
  runMediaTableCommand
@@ -0,0 +1,106 @@
1
+ import {
2
+ hasRegisteredCreateTableMigration,
3
+ hasRegisteredMigrationSlug,
4
+ nextMigrationTemplate
5
+ } from "./chunk-LXGQCG56.mjs";
6
+ import "./chunk-LBJAJLKU.mjs";
7
+ import {
8
+ writeLine
9
+ } from "./chunk-I7QBCEV7.mjs";
10
+ import "./chunk-D7O4SU6N.mjs";
11
+ import {
12
+ prepareProjectDiscovery
13
+ } from "./chunk-VP2E62DF.mjs";
14
+ import "./chunk-MCVRN7KX.mjs";
15
+ import {
16
+ ensureProjectConfig
17
+ } from "./chunk-YEFJBN56.mjs";
18
+ import {
19
+ loadGeneratedProjectRegistry
20
+ } from "./chunk-J76GH2DR.mjs";
21
+ import {
22
+ makeProjectRelativePath,
23
+ resolveDefaultArtifactPath,
24
+ writeTextFile
25
+ } from "./chunk-ILU426CF.mjs";
26
+
27
+ // src/media-migrations.ts
28
+ import { readdir } from "fs/promises";
29
+ import { resolve } from "path";
30
+ import { normalizeMigrationSlug } from "@holo-js/db";
31
+ var DEFAULT_MEDIA_TABLE = "media";
32
+ function normalizeMediaMigrationName(tableName = DEFAULT_MEDIA_TABLE) {
33
+ return normalizeMigrationSlug(`create_${tableName.replaceAll(".", "_")}_table`);
34
+ }
35
+ function renderMediaTableMigration(tableName = DEFAULT_MEDIA_TABLE) {
36
+ const tableNameLiteral = JSON.stringify(tableName);
37
+ return [
38
+ "import { defineMigration, type MigrationContext } from '@holo-js/db'",
39
+ "",
40
+ "export default defineMigration({",
41
+ " async up({ schema }: MigrationContext) {",
42
+ ` await schema.createTable(${tableNameLiteral}, (table) => {`,
43
+ " table.id()",
44
+ " table.uuid('uuid').unique()",
45
+ " table.string('model_type')",
46
+ " table.string('model_id')",
47
+ " table.string('collection_name').default('default')",
48
+ " table.string('name')",
49
+ " table.string('file_name')",
50
+ " table.string('disk')",
51
+ " table.string('conversions_disk').nullable()",
52
+ " table.string('mime_type').nullable()",
53
+ " table.string('extension').nullable()",
54
+ " table.bigInteger('size')",
55
+ " table.string('path')",
56
+ " table.json('generated_conversions')",
57
+ " table.integer('order_column').default(1)",
58
+ " table.timestamps()",
59
+ " table.index(['model_type', 'model_id'])",
60
+ " table.index(['model_type', 'model_id', 'collection_name'])",
61
+ " })",
62
+ " },",
63
+ " async down({ schema }: MigrationContext) {",
64
+ ` await schema.dropTable(${tableNameLiteral})`,
65
+ " },",
66
+ "})",
67
+ ""
68
+ ].join("\n");
69
+ }
70
+ async function hasMigrationFile(migrationsDir, migrationName) {
71
+ const entries = await readdir(migrationsDir).catch(() => []);
72
+ return entries.some((entry) => entry.endsWith(`_${migrationName}.ts`) || entry.endsWith(`_${migrationName}.mts`) || entry.endsWith(`_${migrationName}.js`) || entry.endsWith(`_${migrationName}.mjs`) || entry.endsWith(`_${migrationName}.cts`) || entry.endsWith(`_${migrationName}.cjs`));
73
+ }
74
+ async function createMediaTableMigration(projectRoot, options = {}) {
75
+ const project = await ensureProjectConfig(projectRoot);
76
+ const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
77
+ const tableName = DEFAULT_MEDIA_TABLE;
78
+ const migrationName = normalizeMediaMigrationName(tableName);
79
+ const migrationsDir = resolve(projectRoot, project.config.paths.migrations);
80
+ if (hasRegisteredMigrationSlug(registry, migrationName) || hasRegisteredCreateTableMigration(registry, tableName) || await hasMigrationFile(migrationsDir, migrationName)) {
81
+ if (options.skipIfExists === true) {
82
+ return void 0;
83
+ }
84
+ throw new Error(`A migration for table "${tableName}" already exists.`);
85
+ }
86
+ const migrationTemplate = await nextMigrationTemplate(
87
+ migrationName,
88
+ migrationsDir
89
+ );
90
+ const migrationFilePath = resolveDefaultArtifactPath(projectRoot, project.config.paths.migrations, migrationTemplate.fileName);
91
+ await writeTextFile(migrationFilePath, renderMediaTableMigration(tableName));
92
+ return migrationFilePath;
93
+ }
94
+ async function runMediaTableCommand(io, projectRoot) {
95
+ const migrationFilePath = await createMediaTableMigration(projectRoot);
96
+ const { runProjectPrepare } = await import("./dev-PBNFQK6Y.mjs");
97
+ await runProjectPrepare(projectRoot);
98
+ writeLine(io.stdout, `Created migration: ${makeProjectRelativePath(projectRoot, migrationFilePath)}`);
99
+ }
100
+ export {
101
+ DEFAULT_MEDIA_TABLE,
102
+ createMediaTableMigration,
103
+ normalizeMediaMigrationName,
104
+ renderMediaTableMigration,
105
+ runMediaTableCommand
106
+ };
@@ -1,35 +1,35 @@
1
+ import {
2
+ initializeProjectRuntime
3
+ } from "./chunk-KS5TWO75.mjs";
1
4
  import {
2
5
  isIgnorableWatchError,
3
6
  isRecursiveWatchUnsupported,
4
7
  normalizeWatchedFilePath,
5
8
  runProjectPrepare,
6
9
  toPosixSlashes
7
- } from "./chunk-ASTSSSL2.mjs";
8
- import "./chunk-F4MT6GBK.mjs";
10
+ } from "./chunk-SFRAGRHY.mjs";
11
+ import "./chunk-FGQ2I2YH.mjs";
12
+ import "./chunk-LBJAJLKU.mjs";
9
13
  import {
10
14
  writeLine
11
- } from "./chunk-ZXDU7RHU.mjs";
12
- import {
13
- initializeProjectRuntime
14
- } from "./chunk-HB4Q7VYK.mjs";
15
- import "./chunk-57SJ566R.mjs";
15
+ } from "./chunk-I7QBCEV7.mjs";
16
16
  import "./chunk-D7O4SU6N.mjs";
17
17
  import {
18
18
  prepareProjectDiscovery
19
- } from "./chunk-7JR73TOH.mjs";
20
- import "./chunk-WRZFATUT.mjs";
19
+ } from "./chunk-VP2E62DF.mjs";
20
+ import "./chunk-MCVRN7KX.mjs";
21
21
  import {
22
22
  ensureProjectConfig,
23
23
  loadProjectConfig
24
- } from "./chunk-SRPGIWCF.mjs";
24
+ } from "./chunk-YEFJBN56.mjs";
25
25
  import {
26
26
  loadGeneratedProjectRegistry
27
- } from "./chunk-IMOGEKB4.mjs";
27
+ } from "./chunk-J76GH2DR.mjs";
28
28
  import {
29
29
  HOLO_RUNTIME_ROOT,
30
30
  bundleProjectModule,
31
31
  resolveProjectPackageImportSpecifier
32
- } from "./chunk-R6BWRY3E.mjs";
32
+ } from "./chunk-ILU426CF.mjs";
33
33
 
34
34
  // src/queue.ts
35
35
  import { spawn } from "child_process";