@holo-js/cli 0.1.9 → 0.2.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 (46) hide show
  1. package/dist/bin/holo.mjs +165 -81
  2. package/dist/broadcast-WI6PJS5P.mjs +203 -0
  3. package/dist/broadcast-YWS4N5QU.mjs +203 -0
  4. package/dist/{cache-ETOIQ5IG.mjs → cache-KWNQECAA.mjs} +6 -6
  5. package/dist/cache-QARFSW4F.mjs +66 -0
  6. package/dist/{cache-migrations-2GGI4TJK.mjs → cache-migrations-3OXR4FN5.mjs} +50 -30
  7. package/dist/cache-migrations-MDFMDVTK.mjs +173 -0
  8. package/dist/{chunk-IMOGEKB4.mjs → chunk-2DKQKZML.mjs} +188 -106
  9. package/dist/{chunk-7JR73TOH.mjs → chunk-2RGJTPYF.mjs} +36 -25
  10. package/dist/{chunk-ASTSSSL2.mjs → chunk-EWYXSN2C.mjs} +75 -122
  11. package/dist/{chunk-F4MT6GBK.mjs → chunk-FGQ2I2YH.mjs} +1 -1
  12. package/dist/chunk-I7QBCEV7.mjs +33 -0
  13. package/dist/{chunk-R6BWRY3E.mjs → chunk-ILU426CF.mjs} +3 -1
  14. package/dist/{chunk-HB4Q7VYK.mjs → chunk-IUDD5FYL.mjs} +28 -273
  15. package/dist/{chunk-WRZFATUT.mjs → chunk-KWRIBHC3.mjs} +229 -142
  16. package/dist/{chunk-57SJ566R.mjs → chunk-LBJAJLKU.mjs} +1 -1
  17. package/dist/{chunk-BAFQ2GOA.mjs → chunk-LXGQCG56.mjs} +1 -1
  18. package/dist/{chunk-SRPGIWCF.mjs → chunk-ONKESAQA.mjs} +2 -2
  19. package/dist/chunk-QA7TP5EO.mjs +448 -0
  20. package/dist/chunk-UPZH6KCF.mjs +3306 -0
  21. package/dist/{chunk-5EU32E7X.mjs → chunk-VRGB6DIS.mjs} +116 -12
  22. package/dist/{config-ARLE6PKR.mjs → config-TWEO2R4N.mjs} +3 -3
  23. package/dist/{dev-6RG5SSZ7.mjs → dev-2OULECTU.mjs} +7 -7
  24. package/dist/dev-PJMEGTAC.mjs +42 -0
  25. package/dist/{discovery-FCVGQQVD.mjs → discovery-7FXND7Y6.mjs} +3 -3
  26. package/dist/{generators-UI2LJK3O.mjs → generators-4BP7B47W.mjs} +11 -34
  27. package/dist/generators-Z4XLSMC7.mjs +520 -0
  28. package/dist/index.mjs +167 -83
  29. package/dist/{media-migrations-JQSDCC7S.mjs → media-migrations-BFEL7NFG.mjs} +9 -20
  30. package/dist/media-migrations-VR7DLLR6.mjs +106 -0
  31. package/dist/{queue-BY3PLH4I.mjs → queue-SVOJPTRO.mjs} +10 -10
  32. package/dist/queue-YCBQTCYI.mjs +625 -0
  33. package/dist/{queue-migrations-YZUKEZK7.mjs → queue-migrations-HPXOO3NA.mjs} +13 -12
  34. package/dist/queue-migrations-X4P7FZKJ.mjs +167 -0
  35. package/dist/{runtime-BI343WHS.mjs → runtime-CPKR663Y.mjs} +9 -9
  36. package/dist/runtime-GIE56H47.mjs +57 -0
  37. package/dist/{runtime-ZKD6URAV.mjs → runtime-GSXF4NB3.mjs} +1 -1
  38. package/dist/runtime-worker.d.ts +2 -0
  39. package/dist/runtime-worker.mjs +242 -0
  40. package/dist/{scaffold-UBOS2NZR.mjs → scaffold-3QPGYQEQ.mjs} +9 -5
  41. package/dist/scaffold-RGAAHC6I.mjs +139 -0
  42. package/dist/{security-TYPVOYGF.mjs → security-7H5TNHZY.mjs} +6 -6
  43. package/dist/security-BZGD6ONY.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
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadProjectConfig,
3
3
  resolveGeneratedSchemaPath
4
- } from "./chunk-SRPGIWCF.mjs";
4
+ } from "./chunk-ONKESAQA.mjs";
5
5
  import {
6
6
  loadGeneratedProjectRegistry,
7
7
  relativeImportPath,
@@ -11,11 +11,16 @@ import {
11
11
  renderFrameworkRunner,
12
12
  renderGeneratedModelTypes,
13
13
  renderNextBroadcastAuthRoute,
14
+ renderNextBroadcastConfigRoute,
14
15
  renderNextGeneratedBroadcastAuthRoute,
16
+ renderNextGeneratedBroadcastConfigRoute,
17
+ renderNextGeneratedRealtimeDefinitions,
15
18
  renderNextHoloHelper,
16
19
  renderNextManagedHostedAuthRouteFiles,
17
- renderSvelteHoloHelper
18
- } from "./chunk-IMOGEKB4.mjs";
20
+ renderNextRuntimeBootstrap,
21
+ renderSvelteHoloHelper,
22
+ renderSvelteViteConfig
23
+ } from "./chunk-2DKQKZML.mjs";
19
24
  import {
20
25
  AUTH_CONFIG_FILE_NAMES,
21
26
  AUTH_SOCIAL_PROVIDER_PACKAGE_NAMES,
@@ -40,11 +45,11 @@ import {
40
45
  resolveFirstExistingPath,
41
46
  sanitizePackageName,
42
47
  writeTextFile
43
- } from "./chunk-R6BWRY3E.mjs";
48
+ } from "./chunk-ILU426CF.mjs";
44
49
 
45
50
  // src/project/scaffold.ts
46
51
  import { mkdir as mkdir3, readdir as readdir2 } from "fs/promises";
47
- import { dirname as dirname2, extname as extname2, resolve as resolve4 } from "path";
52
+ import { dirname as dirname2, extname as extname2, relative, resolve as resolve4, sep } from "path";
48
53
  import { loadConfigDirectory as loadConfigDirectory2 } from "@holo-js/config";
49
54
 
50
55
  // src/project/scaffold/config-renderers.ts
@@ -59,7 +64,7 @@ import { loadConfigDirectory } from "@holo-js/config";
59
64
  // package.json
60
65
  var package_default = {
61
66
  name: "@holo-js/cli",
62
- version: "0.1.9",
67
+ version: "0.2.0",
63
68
  description: "Holo-JS Framework - project creation, discovery, and operational CLI",
64
69
  type: "module",
65
70
  license: "MIT",
@@ -86,6 +91,8 @@ var package_default = {
86
91
  "test:integration": "HOLO_CLI_INCLUDE_INTEGRATION=1 vitest --run tests/cli.test.ts"
87
92
  },
88
93
  dependencies: {
94
+ "@clack/prompts": "catalog:",
95
+ "@holo-js/cache-db": "catalog:",
89
96
  "@holo-js/config": "catalog:",
90
97
  "@holo-js/core": "catalog:",
91
98
  "@holo-js/db": "catalog:",
@@ -109,49 +116,51 @@ var package_default = {
109
116
  // src/generated/workspaceCatalog.ts
110
117
  var WORKSPACE_CATALOG = Object.freeze({
111
118
  "@clerk/backend": "^3.4.7",
119
+ "@clack/prompts": "^1.5.1",
112
120
  "@eslint/js": "^9.17.0",
113
- "@holo-js/adapter-next": "^0.1.9",
114
- "@holo-js/adapter-nuxt": "^0.1.9",
115
- "@holo-js/adapter-sveltekit": "^0.1.9",
116
- "@holo-js/auth": "^0.1.9",
117
- "@holo-js/auth-clerk": "^0.1.9",
118
- "@holo-js/auth-social": "^0.1.9",
119
- "@holo-js/auth-social-apple": "^0.1.9",
120
- "@holo-js/auth-social-discord": "^0.1.9",
121
- "@holo-js/auth-social-facebook": "^0.1.9",
122
- "@holo-js/auth-social-github": "^0.1.9",
123
- "@holo-js/auth-social-google": "^0.1.9",
124
- "@holo-js/auth-social-linkedin": "^0.1.9",
125
- "@holo-js/auth-workos": "^0.1.9",
126
- "@holo-js/authorization": "^0.1.9",
127
- "@holo-js/broadcast": "^0.1.9",
128
- "@holo-js/cache": "^0.1.9",
129
- "@holo-js/cache-db": "^0.1.9",
130
- "@holo-js/cache-redis": "^0.1.9",
131
- "@holo-js/cli": "^0.1.9",
132
- "@holo-js/config": "^0.1.9",
133
- "@holo-js/core": "^0.1.9",
134
- "@holo-js/db": "^0.1.9",
135
- "@holo-js/db-mysql": "^0.1.9",
136
- "@holo-js/db-postgres": "^0.1.9",
137
- "@holo-js/db-sqlite": "^0.1.9",
138
- "@holo-js/events": "^0.1.9",
139
- "@holo-js/flux": "^0.1.9",
140
- "@holo-js/flux-react": "^0.1.9",
141
- "@holo-js/flux-svelte": "^0.1.9",
142
- "@holo-js/flux-vue": "^0.1.9",
143
- "@holo-js/forms": "^0.1.9",
144
- "@holo-js/mail": "^0.1.9",
145
- "@holo-js/media": "^0.1.9",
146
- "@holo-js/notifications": "^0.1.9",
147
- "@holo-js/queue": "^0.1.9",
148
- "@holo-js/queue-db": "^0.1.9",
149
- "@holo-js/queue-redis": "^0.1.9",
150
- "@holo-js/security": "^0.1.9",
151
- "@holo-js/session": "^0.1.9",
152
- "@holo-js/storage": "^0.1.9",
153
- "@holo-js/storage-s3": "^0.1.9",
154
- "@holo-js/validation": "^0.1.9",
121
+ "@holo-js/adapter-next": "^0.2.0",
122
+ "@holo-js/adapter-nuxt": "^0.2.0",
123
+ "@holo-js/adapter-sveltekit": "^0.2.0",
124
+ "@holo-js/auth": "^0.2.0",
125
+ "@holo-js/auth-clerk": "^0.2.0",
126
+ "@holo-js/auth-social": "^0.2.0",
127
+ "@holo-js/auth-social-apple": "^0.2.0",
128
+ "@holo-js/auth-social-discord": "^0.2.0",
129
+ "@holo-js/auth-social-facebook": "^0.2.0",
130
+ "@holo-js/auth-social-github": "^0.2.0",
131
+ "@holo-js/auth-social-google": "^0.2.0",
132
+ "@holo-js/auth-social-linkedin": "^0.2.0",
133
+ "@holo-js/auth-workos": "^0.2.0",
134
+ "@holo-js/authorization": "^0.2.0",
135
+ "@holo-js/broadcast": "^0.2.0",
136
+ "@holo-js/cache": "^0.2.0",
137
+ "@holo-js/cache-db": "^0.2.0",
138
+ "@holo-js/cache-redis": "^0.2.0",
139
+ "@holo-js/cli": "^0.2.0",
140
+ "@holo-js/config": "^0.2.0",
141
+ "@holo-js/core": "^0.2.0",
142
+ "@holo-js/db": "^0.2.0",
143
+ "@holo-js/db-mysql": "^0.2.0",
144
+ "@holo-js/db-postgres": "^0.2.0",
145
+ "@holo-js/db-sqlite": "^0.2.0",
146
+ "@holo-js/events": "^0.2.0",
147
+ "@holo-js/flux": "^0.2.0",
148
+ "@holo-js/flux-react": "^0.2.0",
149
+ "@holo-js/flux-svelte": "^0.2.0",
150
+ "@holo-js/flux-vue": "^0.2.0",
151
+ "@holo-js/forms": "^0.2.0",
152
+ "@holo-js/mail": "^0.2.0",
153
+ "@holo-js/media": "^0.2.0",
154
+ "@holo-js/notifications": "^0.2.0",
155
+ "@holo-js/queue": "^0.2.0",
156
+ "@holo-js/queue-db": "^0.2.0",
157
+ "@holo-js/queue-redis": "^0.2.0",
158
+ "@holo-js/realtime": "^0.2.0",
159
+ "@holo-js/security": "^0.2.0",
160
+ "@holo-js/session": "^0.2.0",
161
+ "@holo-js/storage": "^0.2.0",
162
+ "@holo-js/storage-s3": "^0.2.0",
163
+ "@holo-js/validation": "^0.2.0",
155
164
  "@nuxt/kit": "^4.4.4",
156
165
  "@nuxt/module-builder": "^1.0.2",
157
166
  "@sveltejs/adapter-node": "^5.5.4",
@@ -168,7 +177,7 @@ var WORKSPACE_CATALOG = Object.freeze({
168
177
  "@vitest/coverage-v8": "^4.1.5",
169
178
  "better-sqlite3": "^11.7.0",
170
179
  "bullmq": "^5.71.0",
171
- "create-holo-js": "^0.1.9",
180
+ "create-holo-js": "^0.2.0",
172
181
  "esbuild": "^0.27.4",
173
182
  "eslint": "^9.17.0",
174
183
  "fast-check": "^4.5.3",
@@ -181,6 +190,7 @@ var WORKSPACE_CATALOG = Object.freeze({
181
190
  "nodemailer": "^6.10.1",
182
191
  "nuxt": "^4.4.4",
183
192
  "pg": "^8.13.0",
193
+ "playwright": "^1.57.0",
184
194
  "react": "^19.2.6",
185
195
  "react-dom": "^19.2.6",
186
196
  "react-test-renderer": "^19.2.6",
@@ -386,6 +396,9 @@ async function projectHasEventsScaffold(projectRoot) {
386
396
  const listenersRoot = resolve(projectRoot, project.config.paths.listeners);
387
397
  return await pathExists(eventsRoot) || await pathExists(listenersRoot);
388
398
  }
399
+ async function projectHasRealtimeScaffold(projectRoot) {
400
+ return await pathExists(resolve(projectRoot, "server/realtime"));
401
+ }
389
402
  async function syncManagedDriverDependencies(projectRoot, registry) {
390
403
  const loaded = await loadConfigDirectory(projectRoot, {
391
404
  preferCache: false,
@@ -405,6 +418,7 @@ async function syncManagedDriverDependencies(projectRoot, registry) {
405
418
  const requiredPackages = /* @__PURE__ */ new Set();
406
419
  const hasAuthorizationScaffold = await projectHasAuthorizationScaffold(projectRoot);
407
420
  const hasEventsScaffold = await projectHasEventsScaffold(projectRoot);
421
+ const hasRealtimeScaffold = await projectHasRealtimeScaffold(projectRoot);
408
422
  const {
409
423
  packageJsonPath,
410
424
  parsed,
@@ -468,8 +482,23 @@ async function syncManagedDriverDependencies(projectRoot, registry) {
468
482
  if (notificationsConfigured) {
469
483
  requiredPackages.add("@holo-js/notifications");
470
484
  }
471
- if (broadcastConfigured || registryHasBroadcastDefinitions(discoveredRegistry)) {
485
+ if (broadcastConfigured || registryHasBroadcastDefinitions(discoveredRegistry) || hasRealtimeScaffold) {
472
486
  requiredPackages.add("@holo-js/broadcast");
487
+ requiredPackages.add("@holo-js/flux");
488
+ const framework = detectProjectFrameworkFromPackageJson(dependencies, devDependencies);
489
+ if (framework === "next") {
490
+ requiredPackages.add("@holo-js/flux-react");
491
+ requiredPackages.add("@holo-js/adapter-next");
492
+ } else if (framework === "nuxt") {
493
+ requiredPackages.add("@holo-js/flux-vue");
494
+ requiredPackages.add("@holo-js/adapter-nuxt");
495
+ } else if (framework === "sveltekit") {
496
+ requiredPackages.add("@holo-js/flux-svelte");
497
+ requiredPackages.add("@holo-js/adapter-sveltekit");
498
+ }
499
+ }
500
+ if (hasRealtimeScaffold) {
501
+ requiredPackages.add("@holo-js/realtime");
473
502
  }
474
503
  if (registryHasAuthorizationDefinitions(discoveredRegistry) || hasAuthorizationScaffold) {
475
504
  requiredPackages.add("@holo-js/authorization");
@@ -512,12 +541,17 @@ async function syncManagedDriverDependencies(projectRoot, registry) {
512
541
  "@holo-js/cache-db",
513
542
  "@holo-js/cache-redis",
514
543
  "@holo-js/events",
544
+ "@holo-js/flux",
545
+ "@holo-js/flux-react",
546
+ "@holo-js/flux-svelte",
547
+ "@holo-js/flux-vue",
515
548
  "@holo-js/mail",
516
549
  "@holo-js/media",
517
550
  "@holo-js/notifications",
518
551
  "@holo-js/queue",
519
552
  "@holo-js/queue-db",
520
553
  "@holo-js/queue-redis",
554
+ "@holo-js/realtime",
521
555
  "@holo-js/security",
522
556
  "@holo-js/session",
523
557
  "@holo-js/storage",
@@ -615,57 +649,30 @@ async function upsertEventsPackageDependency(projectRoot) {
615
649
  await writePackageJsonDependencyState(packageJsonPath, parsed, dependencies, devDependencies);
616
650
  return true;
617
651
  }
618
- async function upsertNotificationsPackageDependency(projectRoot) {
652
+ async function upsertManagedPackageDependency(projectRoot, packageName) {
619
653
  const { packageJsonPath, parsed, dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
620
- const nextVersion = resolveManagedHoloPackageVersion("@holo-js/notifications", dependencies, devDependencies);
621
- const currentVersion = dependencies["@holo-js/notifications"];
622
- const currentDevVersion = devDependencies["@holo-js/notifications"];
654
+ const nextVersion = resolveManagedHoloPackageVersion(packageName, dependencies, devDependencies);
655
+ const currentVersion = dependencies[packageName];
656
+ const currentDevVersion = devDependencies[packageName];
623
657
  if (currentVersion === nextVersion && typeof currentDevVersion === "undefined") {
624
658
  return false;
625
659
  }
626
- dependencies["@holo-js/notifications"] = nextVersion;
627
- delete devDependencies["@holo-js/notifications"];
660
+ dependencies[packageName] = nextVersion;
661
+ delete devDependencies[packageName];
628
662
  await writePackageJsonDependencyState(packageJsonPath, parsed, dependencies, devDependencies);
629
663
  return true;
630
664
  }
665
+ async function upsertNotificationsPackageDependency(projectRoot) {
666
+ return await upsertManagedPackageDependency(projectRoot, "@holo-js/notifications");
667
+ }
631
668
  async function upsertMailPackageDependency(projectRoot) {
632
- const { packageJsonPath, parsed, dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
633
- const nextVersion = resolveManagedHoloPackageVersion("@holo-js/mail", dependencies, devDependencies);
634
- const currentVersion = dependencies["@holo-js/mail"];
635
- const currentDevVersion = devDependencies["@holo-js/mail"];
636
- if (currentVersion === nextVersion && typeof currentDevVersion === "undefined") {
637
- return false;
638
- }
639
- dependencies["@holo-js/mail"] = nextVersion;
640
- delete devDependencies["@holo-js/mail"];
641
- await writePackageJsonDependencyState(packageJsonPath, parsed, dependencies, devDependencies);
642
- return true;
669
+ return await upsertManagedPackageDependency(projectRoot, "@holo-js/mail");
643
670
  }
644
671
  async function upsertMediaPackageDependency(projectRoot) {
645
- const { packageJsonPath, parsed, dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
646
- const nextVersion = resolveManagedHoloPackageVersion("@holo-js/media", dependencies, devDependencies);
647
- const currentVersion = dependencies["@holo-js/media"];
648
- const currentDevVersion = devDependencies["@holo-js/media"];
649
- if (currentVersion === nextVersion && typeof currentDevVersion === "undefined") {
650
- return false;
651
- }
652
- dependencies["@holo-js/media"] = nextVersion;
653
- delete devDependencies["@holo-js/media"];
654
- await writePackageJsonDependencyState(packageJsonPath, parsed, dependencies, devDependencies);
655
- return true;
672
+ return await upsertManagedPackageDependency(projectRoot, "@holo-js/media");
656
673
  }
657
674
  async function upsertSecurityPackageDependency(projectRoot) {
658
- const { packageJsonPath, parsed, dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
659
- const nextVersion = resolveManagedHoloPackageVersion("@holo-js/security", dependencies, devDependencies);
660
- const currentVersion = dependencies["@holo-js/security"];
661
- const currentDevVersion = devDependencies["@holo-js/security"];
662
- if (currentVersion === nextVersion && typeof currentDevVersion === "undefined") {
663
- return false;
664
- }
665
- dependencies["@holo-js/security"] = nextVersion;
666
- delete devDependencies["@holo-js/security"];
667
- await writePackageJsonDependencyState(packageJsonPath, parsed, dependencies, devDependencies);
668
- return true;
675
+ return await upsertManagedPackageDependency(projectRoot, "@holo-js/security");
669
676
  }
670
677
  async function upsertCachePackageDependencies(projectRoot, driver = "file") {
671
678
  const { packageJsonPath, parsed, dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
@@ -838,15 +845,19 @@ async function upsertAuthPackageDependencies(projectRoot, features = {}) {
838
845
  return true;
839
846
  }
840
847
  async function upsertAuthorizationPackageDependency(projectRoot) {
848
+ return await upsertManagedPackageDependency(projectRoot, "@holo-js/authorization");
849
+ }
850
+ async function upsertRealtimePackageDependency(projectRoot) {
851
+ const broadcastResult = await upsertBroadcastPackageDependencies(projectRoot);
841
852
  const { packageJsonPath, parsed, dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
842
- const nextVersion = resolveManagedHoloPackageVersion("@holo-js/authorization", dependencies, devDependencies);
843
- const currentVersion = dependencies["@holo-js/authorization"];
844
- const currentDevVersion = devDependencies["@holo-js/authorization"];
853
+ const nextVersion = resolveManagedHoloPackageVersion("@holo-js/realtime", dependencies, devDependencies);
854
+ const currentVersion = dependencies["@holo-js/realtime"];
855
+ const currentDevVersion = devDependencies["@holo-js/realtime"];
845
856
  if (currentVersion === nextVersion && typeof currentDevVersion === "undefined") {
846
- return false;
857
+ return broadcastResult.updated;
847
858
  }
848
- dependencies["@holo-js/authorization"] = nextVersion;
849
- delete devDependencies["@holo-js/authorization"];
859
+ dependencies["@holo-js/realtime"] = nextVersion;
860
+ delete devDependencies["@holo-js/realtime"];
850
861
  await writePackageJsonDependencyState(packageJsonPath, parsed, dependencies, devDependencies);
851
862
  return true;
852
863
  }
@@ -1296,40 +1307,6 @@ function renderBroadcastEnvFiles() {
1296
1307
  example
1297
1308
  };
1298
1309
  }
1299
- function renderNuxtBroadcastAuthRoute() {
1300
- return [
1301
- "import { defineEventHandler, getHeaders, getRequestURL, readRawBody } from 'h3'",
1302
- "import { renderBroadcastAuthResponse } from '@holo-js/broadcast/auth'",
1303
- "import { holo } from '#imports'",
1304
- "",
1305
- "export default defineEventHandler(async (event) => {",
1306
- " const app = await holo.getApp()",
1307
- " const auth = await holo.getAuth()",
1308
- " const headers = new Headers()",
1309
- " for (const [key, value] of Object.entries(getHeaders(event))) {",
1310
- " if (typeof value === 'string') {",
1311
- " headers.set(key, value)",
1312
- " }",
1313
- " }",
1314
- " const request = new Request(getRequestURL(event), {",
1315
- " method: event.method,",
1316
- " headers,",
1317
- " body: await readRawBody(event),",
1318
- " })",
1319
- "",
1320
- " return await renderBroadcastAuthResponse(request, {",
1321
- " resolveUser: async () => await auth?.user(),",
1322
- " channelAuth: {",
1323
- " registry: {",
1324
- " projectRoot: app.projectRoot,",
1325
- " channels: app.registry?.channels ?? [],",
1326
- " },",
1327
- " },",
1328
- " })",
1329
- "})",
1330
- ""
1331
- ].join("\n");
1332
- }
1333
1310
  async function syncBroadcastAuthSupportAfterAuthInstall(projectRoot) {
1334
1311
  const { dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
1335
1312
  const framework = detectProjectFrameworkFromPackageJson(dependencies, devDependencies);
@@ -1376,17 +1353,6 @@ async function syncBroadcastAuthSupportAfterAuthInstall(projectRoot) {
1376
1353
  createdBroadcastAuthRoute
1377
1354
  };
1378
1355
  }
1379
- if (framework === "nuxt") {
1380
- const authRoutePath = resolve2(projectRoot, "server/routes/broadcasting/auth.post.ts");
1381
- if (!await pathExists(authRoutePath)) {
1382
- await writeTextFile(authRoutePath, renderNuxtBroadcastAuthRoute());
1383
- createdBroadcastAuthRoute = true;
1384
- }
1385
- return {
1386
- updatedBroadcastConfig,
1387
- createdBroadcastAuthRoute
1388
- };
1389
- }
1390
1356
  if (framework === "sveltekit") {
1391
1357
  const holoHelperPath = resolve2(projectRoot, ".holo-js/generated/sveltekit/holo.ts");
1392
1358
  await writeTextFile(holoHelperPath, renderSvelteHoloHelper());
@@ -2422,7 +2388,7 @@ function renderScaffoldPackageJson(options) {
2422
2388
  if (optionalPackages.includes("mail")) {
2423
2389
  dependencies["@holo-js/mail"] = `^${HOLO_PACKAGE_VERSION}`;
2424
2390
  }
2425
- if (optionalPackages.includes("broadcast")) {
2391
+ if (optionalPackages.includes("broadcast") || optionalPackages.includes("realtime")) {
2426
2392
  dependencies["@holo-js/broadcast"] = `^${HOLO_PACKAGE_VERSION}`;
2427
2393
  dependencies["@holo-js/flux"] = `^${HOLO_PACKAGE_VERSION}`;
2428
2394
  if (options.framework === "next") {
@@ -2433,6 +2399,9 @@ function renderScaffoldPackageJson(options) {
2433
2399
  dependencies["@holo-js/flux-svelte"] = `^${HOLO_PACKAGE_VERSION}`;
2434
2400
  }
2435
2401
  }
2402
+ if (optionalPackages.includes("realtime")) {
2403
+ dependencies["@holo-js/realtime"] = `^${HOLO_PACKAGE_VERSION}`;
2404
+ }
2436
2405
  if (optionalPackages.includes("security")) {
2437
2406
  dependencies["@holo-js/security"] = `^${HOLO_PACKAGE_VERSION}`;
2438
2407
  }
@@ -2493,6 +2462,7 @@ async function scaffoldProject(projectRoot, options) {
2493
2462
  const notificationsEnabled = optionalPackages.includes("notifications");
2494
2463
  const mailEnabled = optionalPackages.includes("mail");
2495
2464
  const broadcastEnabled = optionalPackages.includes("broadcast");
2465
+ const realtimeEnabled = optionalPackages.includes("realtime");
2496
2466
  const securityEnabled = optionalPackages.includes("security");
2497
2467
  const cacheEnabled = optionalPackages.includes("cache");
2498
2468
  const broadcastEnvFiles = broadcastEnabled ? renderBroadcastEnvFiles() : void 0;
@@ -2521,6 +2491,9 @@ async function scaffoldProject(projectRoot, options) {
2521
2491
  await mkdir2(resolve3(projectRoot, "server/broadcast"), { recursive: true });
2522
2492
  await mkdir2(resolve3(projectRoot, "server/channels"), { recursive: true });
2523
2493
  }
2494
+ if (realtimeEnabled) {
2495
+ await mkdir2(resolve3(projectRoot, "server/realtime"), { recursive: true });
2496
+ }
2524
2497
  await mkdir2(resolve3(projectRoot, "server/db/factories"), { recursive: true });
2525
2498
  await mkdir2(resolve3(projectRoot, "server/db/migrations"), { recursive: true });
2526
2499
  await mkdir2(resolve3(projectRoot, "server/db/seeders"), { recursive: true });
@@ -2638,6 +2611,69 @@ async function resolveExistingModelPath(modelsRoot, modelName) {
2638
2611
  }
2639
2612
  return void 0;
2640
2613
  }
2614
+ function injectSvelteRealtimeVitePlugin(viteConfigContents) {
2615
+ if (/\bholoSvelteKitRealtime\b/.test(viteConfigContents)) {
2616
+ return void 0;
2617
+ }
2618
+ const adapterImportPattern = /import\s*\{([^}]*)\}\s*from\s*(['"])@holo-js\/adapter-sveltekit\/vite\2/;
2619
+ const svelteKitImportPattern = /(import\s*\{[^}]*\bsveltekit\b[^}]*\}\s*from\s*(['"])@sveltejs\/kit\/vite\2)/;
2620
+ const existingAdapterImport = adapterImportPattern.exec(viteConfigContents);
2621
+ let withImport = viteConfigContents;
2622
+ if (existingAdapterImport) {
2623
+ const imports = existingAdapterImport[1]?.split(",").map((value) => value.trim()).filter(Boolean) ?? [];
2624
+ withImport = viteConfigContents.replace(adapterImportPattern, `import { ${["holoSvelteKitRealtime", ...imports].join(", ")} } from ${existingAdapterImport[2]}@holo-js/adapter-sveltekit/vite${existingAdapterImport[2]}`);
2625
+ } else {
2626
+ withImport = viteConfigContents.replace(
2627
+ svelteKitImportPattern,
2628
+ [
2629
+ "$1",
2630
+ "import { holoSvelteKitRealtime } from '@holo-js/adapter-sveltekit/vite'"
2631
+ ].join("\n")
2632
+ );
2633
+ }
2634
+ if (withImport === viteConfigContents && !existingAdapterImport) {
2635
+ return {
2636
+ error: "Unable to add holoSvelteKitRealtime() to vite.config.ts because the SvelteKit Vite import could not be found."
2637
+ };
2638
+ }
2639
+ const withPlugin = withImport.replace(/plugins\s*:\s*\[([\s\S]*?)\]/, (_match, plugins) => {
2640
+ const separator = plugins.trim() ? " " : "";
2641
+ return `plugins: [holoSvelteKitRealtime(),${separator}${plugins}]`;
2642
+ });
2643
+ if (withPlugin === withImport) {
2644
+ if (/\bplugins\s*:\s*(?!\[)|\bplugins\s*(?:,|})/.test(withImport)) {
2645
+ return {
2646
+ error: "Unable to add holoSvelteKitRealtime() to vite.config.ts because the plugins option is not an inline array."
2647
+ };
2648
+ }
2649
+ return {
2650
+ error: "Unable to add holoSvelteKitRealtime() to vite.config.ts because no plugins array was found."
2651
+ };
2652
+ }
2653
+ return withPlugin;
2654
+ }
2655
+ var realtimeDefinitionExtensions = /* @__PURE__ */ new Set([".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"]);
2656
+ async function collectRealtimeDefinitionFiles(root) {
2657
+ const entries = await readdir2(root, { withFileTypes: true }).catch(() => []);
2658
+ const files = await Promise.all(entries.map(async (entry) => {
2659
+ const entryPath = resolve4(root, entry.name);
2660
+ if (entry.isDirectory()) {
2661
+ return await collectRealtimeDefinitionFiles(entryPath);
2662
+ }
2663
+ return realtimeDefinitionExtensions.has(extname2(entry.name)) ? [entryPath] : [];
2664
+ }));
2665
+ return files.flat().sort((left, right) => left.localeCompare(right));
2666
+ }
2667
+ async function renderNextRealtimeDefinitions(projectRoot) {
2668
+ const generatedRoot = resolve4(projectRoot, ".holo-js/generated/next");
2669
+ const files = await collectRealtimeDefinitionFiles(resolve4(projectRoot, "server/realtime"));
2670
+ const importPaths = files.map((filePath) => {
2671
+ const withoutExtension = filePath.slice(0, -extname2(filePath).length);
2672
+ const importPath = relative(generatedRoot, withoutExtension).split(sep).join("/");
2673
+ return importPath.startsWith(".") ? importPath : `./${importPath}`;
2674
+ });
2675
+ return renderNextGeneratedRealtimeDefinitions(importPaths);
2676
+ }
2641
2677
  async function resolveExistingAuthMigrationFiles(migrationsRoot) {
2642
2678
  const entries = await readdir2(migrationsRoot).catch(() => []);
2643
2679
  const resolved = /* @__PURE__ */ new Map();
@@ -2934,6 +2970,49 @@ async function installEventsIntoProject(projectRoot) {
2934
2970
  createdListenersDirectory: !listenersDirectoryExists
2935
2971
  };
2936
2972
  }
2973
+ async function installRealtimeIntoProject(projectRoot) {
2974
+ await loadProjectConfig(projectRoot, { required: true });
2975
+ const realtimeRoot = resolve4(projectRoot, "server/realtime");
2976
+ const realtimeDirectoryExists = await pathExists(realtimeRoot);
2977
+ const { dependencies, devDependencies } = await readPackageJsonDependencyState(projectRoot);
2978
+ const framework = detectProjectFrameworkFromPackageJson(dependencies, devDependencies);
2979
+ let createdFrameworkSetup = false;
2980
+ await mkdir3(realtimeRoot, { recursive: true });
2981
+ if (framework === "next") {
2982
+ const routes = [
2983
+ { path: ".holo-js/generated/next/holo.ts", contents: renderNextHoloHelper() },
2984
+ { path: ".holo-js/generated/next/bootstrap.mjs", contents: renderNextRuntimeBootstrap() },
2985
+ { path: ".holo-js/generated/next/realtime-definitions.ts", contents: await renderNextRealtimeDefinitions(projectRoot) }
2986
+ ];
2987
+ for (const route of routes) {
2988
+ const routePath = resolve4(projectRoot, route.path);
2989
+ if (!await pathExists(routePath)) {
2990
+ createdFrameworkSetup = true;
2991
+ }
2992
+ await writeTextFile(routePath, route.contents);
2993
+ }
2994
+ } else if (framework === "sveltekit") {
2995
+ const viteConfigPath = resolve4(projectRoot, "vite.config.ts");
2996
+ if (await pathExists(viteConfigPath)) {
2997
+ const existingViteConfig = await readTextFile(viteConfigPath);
2998
+ const viteConfigContents = existingViteConfig ? injectSvelteRealtimeVitePlugin(existingViteConfig) : void 0;
2999
+ if (typeof viteConfigContents === "string") {
3000
+ createdFrameworkSetup = true;
3001
+ await writeTextFile(viteConfigPath, viteConfigContents);
3002
+ } else if (viteConfigContents) {
3003
+ throw new Error(viteConfigContents.error);
3004
+ }
3005
+ } else {
3006
+ createdFrameworkSetup = true;
3007
+ await writeTextFile(viteConfigPath, renderSvelteViteConfig(false, true));
3008
+ }
3009
+ }
3010
+ return {
3011
+ updatedPackageJson: await upsertRealtimePackageDependency(projectRoot),
3012
+ createdRealtimeDirectory: !realtimeDirectoryExists,
3013
+ createdFrameworkSetup
3014
+ };
3015
+ }
2937
3016
  async function installNotificationsIntoProject(projectRoot) {
2938
3017
  const project = await loadProjectConfig(projectRoot);
2939
3018
  const migrationsRoot = resolve4(projectRoot, project.config.paths.migrations);
@@ -3013,7 +3092,7 @@ async function installMediaIntoProject(projectRoot) {
3013
3092
  if (!mediaConfigPath) {
3014
3093
  await writeTextFile(resolve4(projectRoot, "config/media.ts"), renderMediaConfig());
3015
3094
  }
3016
- const { createMediaTableMigration } = await import("./media-migrations-JQSDCC7S.mjs");
3095
+ const { createMediaTableMigration } = await import("./media-migrations-BFEL7NFG.mjs");
3017
3096
  const migrationFilePath = await createMediaTableMigration(projectRoot, {
3018
3097
  skipIfExists: true
3019
3098
  });
@@ -3129,10 +3208,17 @@ async function installBroadcastIntoProject(projectRoot) {
3129
3208
  let createdFrameworkSetup = false;
3130
3209
  if (framework === "next") {
3131
3210
  const holoHelperPath = resolve4(projectRoot, ".holo-js/generated/next/holo.ts");
3211
+ const broadcastConfigRoutePath = resolve4(projectRoot, "app/broadcasting/config/route.ts");
3212
+ const generatedBroadcastConfigRoutePath = resolve4(projectRoot, ".holo-js/generated/next/broadcast-config-route.ts");
3132
3213
  if (!await pathExists(holoHelperPath)) {
3133
3214
  await writeTextFile(holoHelperPath, renderNextHoloHelper());
3134
3215
  createdFrameworkSetup = true;
3135
3216
  }
3217
+ if (!await pathExists(broadcastConfigRoutePath)) {
3218
+ await writeTextFile(broadcastConfigRoutePath, renderNextBroadcastConfigRoute());
3219
+ createdFrameworkSetup = true;
3220
+ }
3221
+ await writeTextFile(generatedBroadcastConfigRoutePath, renderNextGeneratedBroadcastConfigRoute());
3136
3222
  } else if (framework === "sveltekit") {
3137
3223
  const holoHelperPath = resolve4(projectRoot, ".holo-js/generated/sveltekit/holo.ts");
3138
3224
  if (!await pathExists(holoHelperPath)) {
@@ -3209,6 +3295,7 @@ export {
3209
3295
  installAuthorizationIntoProject,
3210
3296
  installQueueIntoProject,
3211
3297
  installEventsIntoProject,
3298
+ installRealtimeIntoProject,
3212
3299
  installNotificationsIntoProject,
3213
3300
  publishAuthNotificationsIntoProject,
3214
3301
  installMailIntoProject,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readTextFile
3
- } from "./chunk-R6BWRY3E.mjs";
3
+ } from "./chunk-ILU426CF.mjs";
4
4
 
5
5
  // src/fs-utils.ts
6
6
  import { stat } from "fs/promises";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fileExists
3
- } from "./chunk-57SJ566R.mjs";
3
+ } from "./chunk-LBJAJLKU.mjs";
4
4
 
5
5
  // src/migrations.ts
6
6
  import { join } from "path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadGeneratedProjectRegistry
3
- } from "./chunk-IMOGEKB4.mjs";
3
+ } from "./chunk-2DKQKZML.mjs";
4
4
  import {
5
5
  APP_CONFIG_FILE_NAMES,
6
6
  DATABASE_CONFIG_FILE_NAMES,
@@ -8,7 +8,7 @@ import {
8
8
  isModulePackage,
9
9
  pathExists,
10
10
  resolveFirstExistingPath
11
- } from "./chunk-R6BWRY3E.mjs";
11
+ } from "./chunk-ILU426CF.mjs";
12
12
 
13
13
  // src/project/config.ts
14
14
  import { createHash } from "crypto";