@holo-js/cli 0.1.3 → 0.1.5

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 (56) hide show
  1. package/dist/bin/holo.mjs +192 -35
  2. package/dist/{broadcast-YZS4OFCM.mjs → broadcast-RT5KVZWP.mjs} +5 -5
  3. package/dist/{cache-V43YMG4K.mjs → cache-NHCCHT44.mjs} +5 -5
  4. package/dist/{cache-migrations-ZUOI2A7N.mjs → cache-migrations-R2RL2RVD.mjs} +15 -16
  5. package/dist/{chunk-EUIVXVJL.mjs → chunk-57SJ566R.mjs} +1 -1
  6. package/dist/chunk-5BLEC66P.mjs +284 -0
  7. package/dist/{chunk-JX2ZH6XY.mjs → chunk-5EU32E7X.mjs} +3 -3
  8. package/dist/{chunk-Q5F6C2D4.mjs → chunk-BAFQ2GOA.mjs} +1 -1
  9. package/dist/{chunk-CUL4RJTG.mjs → chunk-F4MT6GBK.mjs} +1 -1
  10. package/dist/{chunk-3OTCSFDG.mjs → chunk-MXKNQACM.mjs} +544 -82
  11. package/dist/{chunk-QYLSMF7V.mjs → chunk-OZUDZEAW.mjs} +142 -28
  12. package/dist/{chunk-66FHW725.mjs → chunk-R6BWRY3E.mjs} +28 -2
  13. package/dist/{chunk-RB65DLR4.mjs → chunk-SCCPDJGO.mjs} +156 -16
  14. package/dist/{chunk-VT5IDQG6.mjs → chunk-UZTDQKIY.mjs} +61 -44
  15. package/dist/{chunk-HE6FYNVN.mjs → chunk-VCEO6N5T.mjs} +3563 -2505
  16. package/dist/{config-LS5USBRB.mjs → config-5JSC6KJG.mjs} +3 -3
  17. package/dist/{dev-KGRIGLJY.mjs → dev-OSLYSBTL.mjs} +7 -7
  18. package/dist/{discovery-GBLAUTXS.mjs → discovery-JLT2EOGH.mjs} +3 -3
  19. package/dist/{generators-WSF23UKM.mjs → generators-ZIWACCBE.mjs} +134 -16
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.mjs +189 -32
  22. package/dist/media-migrations-UBAL2YVV.mjs +117 -0
  23. package/dist/{queue-6N7HQMRL.mjs → queue-I66EISVS.mjs} +14 -14
  24. package/dist/{queue-migrations-O6QSSDPQ.mjs → queue-migrations-UIAMAB6E.mjs} +24 -20
  25. package/dist/{runtime-RI4OWTIT.mjs → runtime-MMQGO4PP.mjs} +9 -7
  26. package/dist/{runtime-OOSJ5JBY.mjs → runtime-ZKD6URAV.mjs} +1 -1
  27. package/dist/{scaffold-IYWZKT3W.mjs → scaffold-ISDVICNQ.mjs} +18 -4
  28. package/dist/{security-AE6LGNC4.mjs → security-OZXTMYXF.mjs} +10 -7
  29. package/package.json +13 -12
  30. package/dist/broadcast-ZYFKUFM5.mjs +0 -85
  31. package/dist/cache-ODBZT6IP.mjs +0 -67
  32. package/dist/cache-migrations-KPOEH6GP.mjs +0 -155
  33. package/dist/chunk-BWW5TDFI.mjs +0 -4
  34. package/dist/chunk-D4GG556Y.mjs +0 -23
  35. package/dist/chunk-ET7UXHHQ.mjs +0 -166
  36. package/dist/chunk-G5ADO27Q.mjs +0 -463
  37. package/dist/chunk-GSQ3HTRO.mjs +0 -165
  38. package/dist/chunk-H7TJ4FB3.mjs +0 -848
  39. package/dist/chunk-ICJR7TS4.mjs +0 -66
  40. package/dist/chunk-ICKN56JY.mjs +0 -342
  41. package/dist/chunk-M7J3YTHR.mjs +0 -26
  42. package/dist/chunk-S7P7EBM3.mjs +0 -787
  43. package/dist/chunk-SRWJU3A5.mjs +0 -11
  44. package/dist/chunk-T4OVZZEE.mjs +0 -3204
  45. package/dist/chunk-URK7C3VQ.mjs +0 -538
  46. package/dist/chunk-XUYKPU5Q.mjs +0 -272
  47. package/dist/config-DMWBMMGD.mjs +0 -26
  48. package/dist/dev-LVHDCPVS.mjs +0 -43
  49. package/dist/discovery-R733D2PO.mjs +0 -29
  50. package/dist/generators-32R45P6Z.mjs +0 -426
  51. package/dist/queue-QG5EXOG4.mjs +0 -626
  52. package/dist/queue-migrations-JWKU45Y3.mjs +0 -163
  53. package/dist/runtime-ANBO7VQM.mjs +0 -33
  54. package/dist/runtime-ZRPK5DIT.mjs +0 -56
  55. package/dist/scaffold-ULATB4CA.mjs +0 -121
  56. package/dist/security-OCOPEH2V.mjs +0 -69
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env node
2
1
  import {
3
2
  CONFIG_EXTENSION_PRIORITY,
4
3
  GENERATED_AUTHORIZATION_REGISTRY_PATH,
5
4
  GENERATED_AUTHORIZATION_TYPES_PATH,
5
+ GENERATED_AUTH_TYPES_PATH,
6
6
  GENERATED_BROADCAST_MANIFEST_PATH,
7
7
  GENERATED_BROADCAST_PATH,
8
8
  GENERATED_BROADCAST_TYPES_PATH,
@@ -18,20 +18,24 @@ import {
18
18
  GENERATED_METADATA_PATH,
19
19
  GENERATED_MIGRATIONS_PATH,
20
20
  GENERATED_MODELS_PATH,
21
+ GENERATED_MODEL_TYPES_PATH,
21
22
  GENERATED_QUEUE_TYPES_PATH,
22
23
  GENERATED_REGISTRY_JSON_PATH,
23
24
  GENERATED_ROOT,
25
+ GENERATED_SCHEMA_RUNTIME_PATH,
24
26
  GENERATED_SEEDERS_PATH,
27
+ GENERATED_SVELTE_HOOKS_PATH,
28
+ GENERATED_SVELTE_SERVER_HOOKS_PATH,
25
29
  GENERATED_TSCONFIG_PATH,
26
30
  SUPPORTED_CONFIG_EXTENSIONS,
27
31
  importProjectModule,
28
32
  isRecord,
29
- makeProjectRelativePath,
30
- pathExists
31
- } from "./chunk-66FHW725.mjs";
33
+ makeProjectRelativePath
34
+ } from "./chunk-R6BWRY3E.mjs";
32
35
 
33
36
  // src/templates.ts
34
37
  import { dirname, relative, resolve } from "path";
38
+ import inflection from "inflection";
35
39
  function toPosixPath(value) {
36
40
  return value.replace(/\\/g, "/");
37
41
  }
@@ -63,13 +67,7 @@ function toKebabCase(value) {
63
67
  return toSnakeCase(value).replaceAll("_", "-");
64
68
  }
65
69
  function pluralize(word) {
66
- if (word.endsWith("y") && !/[aeiou]y$/i.test(word)) {
67
- return `${word.slice(0, -1)}ies`;
68
- }
69
- if (/(?:[sxz]|ch|sh)$/i.test(word)) {
70
- return `${word}es`;
71
- }
72
- return `${word}s`;
70
+ return inflection.pluralize(word);
73
71
  }
74
72
  function ensureSuffix(name, suffix) {
75
73
  return name.endsWith(suffix) ? name : `${name}${suffix}`;
@@ -80,28 +78,17 @@ function relativeImportPath(fromFile, toFile) {
80
78
  return target.startsWith(".") ? target : `./${target}`;
81
79
  }
82
80
  function renderModelTemplate(options) {
83
- const imports = [
84
- `import { tables as holoGeneratedTables } from '${options.generatedSchemaImportPath}'`,
85
- "import { defineModel, type TableDefinition } from '@holo-js/db'"
86
- ];
81
+ const imports = ["import { defineModel } from '@holo-js/db'"];
87
82
  if (options.observerImportPath && options.observerClassName) {
88
83
  imports.push(`import { ${options.observerClassName} } from '${options.observerImportPath}'`);
89
84
  }
90
85
  return [
91
86
  ...imports,
92
87
  "",
93
- `const holoModelTable = (holoGeneratedTables as Partial<Record<string, TableDefinition>>)[${JSON.stringify(options.tableName)}]`,
94
- "export const holoModelPendingSchema = typeof holoModelTable === 'undefined'",
95
- "",
96
- "export default holoModelPendingSchema",
97
- " ? undefined",
98
- " : defineModel(",
99
- " holoModelTable,",
100
- " {",
101
- " fillable: [],",
102
- ...options.observerClassName ? [` observers: [${options.observerClassName}],`] : [],
103
- " },",
104
- " )",
88
+ `export default defineModel(${JSON.stringify(options.tableName)}, {`,
89
+ " fillable: [],",
90
+ ...options.observerClassName ? [` observers: [${options.observerClassName}],`] : [],
91
+ "})",
105
92
  ""
106
93
  ].join("\n");
107
94
  }
@@ -267,10 +254,336 @@ function resolveArtifactPath(root, subdir, directory, fileName) {
267
254
  }
268
255
 
269
256
  // src/project/registry.ts
270
- import { mkdir, readFile, readdir, writeFile } from "fs/promises";
271
- import { dirname as dirname2, extname, join, resolve as resolve2 } from "path";
257
+ import { constants as fsConstants } from "fs";
258
+ import { access, mkdir as mkdir2, readFile as readFile2, readdir, writeFile as writeFile2 } from "fs/promises";
259
+ import { dirname as dirname3, extname, join, resolve as resolve3 } from "path";
272
260
  import { loadConfigDirectory } from "@holo-js/config";
273
- import { DEFAULT_HOLO_PROJECT_PATHS } from "@holo-js/db";
261
+ import { DEFAULT_HOLO_PROJECT_PATHS, renderGeneratedSchemaRuntimeModule } from "@holo-js/db";
262
+
263
+ // src/project/registry-svelte.ts
264
+ import { mkdir, readFile, unlink, writeFile } from "fs/promises";
265
+ import { dirname as dirname2, resolve as resolve2 } from "path";
266
+ function renderManagedSvelteHooksModule() {
267
+ return [
268
+ "// Generated by holo prepare. Do not edit.",
269
+ "",
270
+ "import type { Reroute } from '@sveltejs/kit'",
271
+ "import { holoSvelteKitTransport } from '@holo-js/adapter-sveltekit/transport'",
272
+ "import * as userHooks from '../../src/hooks'",
273
+ "",
274
+ "const universalHooks = userHooks as {",
275
+ " reroute?: Reroute",
276
+ " transport?: Partial<typeof holoSvelteKitTransport>",
277
+ "}",
278
+ "",
279
+ "function normalizeStorageRoutePrefix(value: string | undefined): string {",
280
+ " const raw = value?.trim() ?? '/storage'",
281
+ " if (!raw || raw === '/') {",
282
+ " return '/storage'",
283
+ " }",
284
+ "",
285
+ " return `/${raw.replace(/^\\/+|\\/+$/g, '')}`",
286
+ "}",
287
+ "",
288
+ "function resolveStorageRoutePrefix(): string {",
289
+ " return normalizeStorageRoutePrefix(typeof process === 'undefined' ? undefined : process.env.STORAGE_ROUTE_PREFIX)",
290
+ "}",
291
+ "",
292
+ "export const reroute: Reroute = async (event) => {",
293
+ " const userPath = await universalHooks.reroute?.(event)",
294
+ " const pathname = typeof userPath === 'string' ? userPath : event.url.pathname",
295
+ " const storageRoutePrefix = resolveStorageRoutePrefix()",
296
+ "",
297
+ " if (storageRoutePrefix !== '/storage' && (pathname === storageRoutePrefix || pathname.startsWith(`${storageRoutePrefix}/`))) {",
298
+ " const suffix = pathname.slice(storageRoutePrefix.length)",
299
+ " return suffix ? `/storage${suffix}` : '/storage'",
300
+ " }",
301
+ "",
302
+ " return userPath",
303
+ "}",
304
+ "export const transport = {",
305
+ " ...(universalHooks.transport ?? {}),",
306
+ " ...holoSvelteKitTransport,",
307
+ "}",
308
+ ""
309
+ ].join("\n");
310
+ }
311
+ function renderManagedSvelteServerHooksModule() {
312
+ return [
313
+ "// Generated by holo prepare. Do not edit.",
314
+ "",
315
+ "import { error as svelteKitError, type Handle, type HandleFetch, type HandleServerError } from '@sveltejs/kit'",
316
+ "import { adapterSvelteKitInternals, runWithSvelteKitRequestEvent } from '@holo-js/adapter-sveltekit'",
317
+ "import { sequence } from '@sveltejs/kit/hooks'",
318
+ "import { holo } from '$lib/server/holo'",
319
+ "import * as userHooks from '../../src/hooks.server'",
320
+ "",
321
+ "const serverHooks = userHooks as {",
322
+ " handle?: Handle",
323
+ " handleError?: HandleServerError",
324
+ " handleFetch?: HandleFetch",
325
+ "}",
326
+ "",
327
+ "function isHoloAuthorizationHttpError(cause: unknown): cause is Error & { readonly decision: { readonly status: 403 | 404 } } {",
328
+ " if (!(cause instanceof Error) || cause.name !== 'AuthorizationError') {",
329
+ " return false",
330
+ " }",
331
+ "",
332
+ " const decision = (cause as { readonly decision?: { readonly status?: unknown } }).decision",
333
+ " return decision?.status === 403 || decision?.status === 404",
334
+ "}",
335
+ "",
336
+ "function serializeHoloValidationException(cause: unknown) {",
337
+ " return adapterSvelteKitInternals.serializeValidationException(cause) ?? null",
338
+ "}",
339
+ "",
340
+ "const holoHandle: Handle = ({ event, resolve }) => runWithSvelteKitRequestEvent(event, async () => {",
341
+ " await holo.getApp()",
342
+ "",
343
+ " try {",
344
+ " const response = await resolve(event)",
345
+ " return await adapterSvelteKitInternals.mapValidationActionResponse(event, response)",
346
+ " } catch (cause) {",
347
+ " if (isHoloAuthorizationHttpError(cause)) {",
348
+ " svelteKitError(cause.decision.status, cause.message)",
349
+ " }",
350
+ "",
351
+ " const validationPayload = serializeHoloValidationException(cause)",
352
+ " if (validationPayload) {",
353
+ " if (adapterSvelteKitInternals.isApiEvent(event)) {",
354
+ " return Response.json(validationPayload, { status: validationPayload.status })",
355
+ " }",
356
+ "",
357
+ " throw cause",
358
+ " }",
359
+ "",
360
+ " throw cause",
361
+ " }",
362
+ "})",
363
+ "",
364
+ "const holoHandleError: HandleServerError = async (input) => {",
365
+ " const validationPayload = serializeHoloValidationException(input.error)",
366
+ " if (validationPayload) {",
367
+ " adapterSvelteKitInternals.rememberValidationActionFailure(input.event, validationPayload)",
368
+ " return validationPayload",
369
+ " }",
370
+ "",
371
+ " if (serverHooks.handleError) {",
372
+ " return await serverHooks.handleError(input)",
373
+ " }",
374
+ "",
375
+ " return {",
376
+ " message: input.error instanceof Error ? input.error.message : 'Internal server error',",
377
+ " }",
378
+ "}",
379
+ "",
380
+ "export const handle = typeof serverHooks.handle === 'function'",
381
+ " ? sequence(holoHandle, serverHooks.handle)",
382
+ " : holoHandle",
383
+ "export const handleError = holoHandleError",
384
+ "export const handleFetch = serverHooks.handleFetch",
385
+ ""
386
+ ].join("\n");
387
+ }
388
+ function renderSvelteDefaultHooksModule() {
389
+ return [
390
+ "export {}",
391
+ ""
392
+ ].join("\n");
393
+ }
394
+ function renderSvelteDefaultServerHooksModule() {
395
+ return [
396
+ "export {}",
397
+ ""
398
+ ].join("\n");
399
+ }
400
+ function isManagedPrepareArtifact(contents) {
401
+ return contents.startsWith("// Generated by holo prepare. Do not edit.");
402
+ }
403
+ function isLegacySvelteTransportHook(contents) {
404
+ return contents.trim() === [
405
+ "import { holoSvelteKitTransport } from '@holo-js/adapter-sveltekit/transport'",
406
+ "",
407
+ "export const transport = holoSvelteKitTransport"
408
+ ].join("\n").trim();
409
+ }
410
+ function isLegacySvelteServerHook(contents) {
411
+ return contents.trim() === [
412
+ "import '@holo-js/adapter-sveltekit'",
413
+ "",
414
+ "import type { Handle } from '@sveltejs/kit'",
415
+ "import { holo } from '$lib/server/holo'",
416
+ "",
417
+ "function normalizeStorageRoutePrefix(value: string | undefined): string {",
418
+ " const raw = value?.trim() ?? '/storage'",
419
+ " if (!raw || raw === '/') {",
420
+ " return '/storage'",
421
+ " }",
422
+ "",
423
+ " return `/${raw.replace(/^\\/+|\\/+$/g, '')}`",
424
+ "}",
425
+ "",
426
+ "export const handle: Handle = async ({ event, resolve }) => {",
427
+ " await holo.getApp()",
428
+ "",
429
+ " const storageRoutePrefix = normalizeStorageRoutePrefix(process.env.STORAGE_ROUTE_PREFIX)",
430
+ "",
431
+ " if (storageRoutePrefix !== '/storage') {",
432
+ " const pathname = event.url.pathname",
433
+ " if (pathname === storageRoutePrefix || pathname.startsWith(`${storageRoutePrefix}/`)) {",
434
+ " const suffix = pathname.slice(storageRoutePrefix.length)",
435
+ " event.url.pathname = suffix ? `/storage${suffix}` : '/storage'",
436
+ " }",
437
+ " }",
438
+ "",
439
+ " return resolve(event)",
440
+ "}"
441
+ ].join("\n").trim();
442
+ }
443
+ async function readFileIfPresent(path) {
444
+ try {
445
+ return await readFile(path, "utf8");
446
+ } catch {
447
+ return void 0;
448
+ }
449
+ }
450
+ async function unlinkIfPresent(path) {
451
+ try {
452
+ await unlink(path);
453
+ } catch {
454
+ }
455
+ }
456
+ var SVELTE_HOOKS_OVERRIDE_BLOCK = [
457
+ " files: {",
458
+ " hooks: {",
459
+ " server: '.holo-js/generated/hooks.server',",
460
+ " universal: '.holo-js/generated/hooks',",
461
+ " },",
462
+ " },"
463
+ ].join("\n");
464
+ var SVELTE_CONFIG_WRAPPER_IMPORT = "import { withHoloSvelteKit } from '@holo-js/adapter-sveltekit/config'";
465
+ var LEGACY_SVELTE_PREPROCESS_IMPORT = "import { holoSveltePreprocess } from '@holo-js/adapter-sveltekit'";
466
+ var LEGACY_SVELTE_PREPROCESS_CALL = "holoSveltePreprocess()";
467
+ var SVELTE_CONFIG_WRAPPER_CALL = "withHoloSvelteKit(";
468
+ function getSvelteConfigHooksOverrideState(contents) {
469
+ if (contents.includes(".holo-js/generated/hooks")) {
470
+ return "managed";
471
+ }
472
+ if (/kit\s*:\s*\{[\s\S]*?files\s*:\s*\{[\s\S]*?hooks\s*:/.test(contents)) {
473
+ return "custom";
474
+ }
475
+ return "none";
476
+ }
477
+ function assertSvelteConfigHasNoCustomHookOverride(contents) {
478
+ const hooksOverrideState = getSvelteConfigHooksOverrideState(contents);
479
+ if (hooksOverrideState === "custom") {
480
+ throw new Error("Custom SvelteKit hook entrypoints are not supported. Remove kit.files.hooks from svelte.config.js and let holo prepare manage the generated hook bridge.");
481
+ }
482
+ }
483
+ function ensureSvelteConfigWrapperImport(contents) {
484
+ if (contents.includes(SVELTE_CONFIG_WRAPPER_IMPORT)) {
485
+ return contents;
486
+ }
487
+ const lastImport = [...contents.matchAll(/^import .+$/gm)].at(-1);
488
+ if (!lastImport || lastImport.index === void 0) {
489
+ return `${SVELTE_CONFIG_WRAPPER_IMPORT}
490
+ ${contents}`;
491
+ }
492
+ const insertAt = lastImport.index + lastImport[0].length;
493
+ return `${contents.slice(0, insertAt)}
494
+ ${SVELTE_CONFIG_WRAPPER_IMPORT}${contents.slice(insertAt)}`;
495
+ }
496
+ function removeLegacySvelteConfigWiring(contents) {
497
+ return contents.replace(`${LEGACY_SVELTE_PREPROCESS_IMPORT}
498
+ `, "").replace(new RegExp(String.raw`,\s*${LEGACY_SVELTE_PREPROCESS_CALL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "g"), "").replace(new RegExp(String.raw`${LEGACY_SVELTE_PREPROCESS_CALL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\s*,\s*`, "g"), "").replace(`${SVELTE_HOOKS_OVERRIDE_BLOCK}
499
+ `, "");
500
+ }
501
+ function patchSvelteConfigWithHoloWrapper(contents) {
502
+ assertSvelteConfigHasNoCustomHookOverride(contents);
503
+ const cleaned = ensureSvelteConfigWrapperImport(removeLegacySvelteConfigWiring(contents));
504
+ if (cleaned.includes(SVELTE_CONFIG_WRAPPER_CALL)) {
505
+ return cleaned === contents ? void 0 : cleaned;
506
+ }
507
+ const constConfigPattern = /(const\s+config\s*=\s*)\{/;
508
+ if (!constConfigPattern.test(cleaned)) {
509
+ throw new Error("Could not patch svelte.config.js with withHoloSvelteKit(). Export a const config object so holo prepare can manage the SvelteKit integration.");
510
+ }
511
+ const wrappedOpening = cleaned.replace(constConfigPattern, `$1${SVELTE_CONFIG_WRAPPER_CALL}{`);
512
+ const wrapped = wrappedOpening.replace(/\}\s*export\s+default\s+config\s*$/u, "})\n\nexport default config");
513
+ if (wrapped === wrappedOpening) {
514
+ throw new Error("Could not patch svelte.config.js with withHoloSvelteKit(). Export a const config object so holo prepare can manage the SvelteKit integration.");
515
+ }
516
+ return wrapped;
517
+ }
518
+ async function ensureSvelteConfigHooksOverride(projectRoot) {
519
+ const configPath = resolve2(projectRoot, "svelte.config.js");
520
+ const contents = await readFileIfPresent(configPath);
521
+ if (!contents) {
522
+ return;
523
+ }
524
+ const patched = patchSvelteConfigWithHoloWrapper(contents) ?? contents;
525
+ if (patched !== contents) {
526
+ await writeFile(configPath, patched, "utf8");
527
+ }
528
+ }
529
+ async function writeFileIfChanged(path, contents) {
530
+ if (await readFileIfPresent(path) === contents) {
531
+ return;
532
+ }
533
+ await mkdir(dirname2(path), { recursive: true });
534
+ await writeFile(path, contents, "utf8");
535
+ }
536
+ async function ensureSvelteManagedHooks(projectRoot) {
537
+ const hooksPath = resolve2(projectRoot, "src/hooks.ts");
538
+ const hooksServerPath = resolve2(projectRoot, "src/hooks.server.ts");
539
+ const generatedHooksPath = resolve2(projectRoot, GENERATED_SVELTE_HOOKS_PATH);
540
+ const generatedServerHooksPath = resolve2(projectRoot, GENERATED_SVELTE_SERVER_HOOKS_PATH);
541
+ const legacyHooksUserPath = resolve2(projectRoot, "src/hooks.user.ts");
542
+ const legacyHooksServerUserPath = resolve2(projectRoot, "src/hooks.server.user.ts");
543
+ const [hooksContents, hooksServerContents, legacyUserContents, legacyServerUserContents] = await Promise.all([
544
+ readFileIfPresent(hooksPath),
545
+ readFileIfPresent(hooksServerPath),
546
+ readFileIfPresent(legacyHooksUserPath),
547
+ readFileIfPresent(legacyHooksServerUserPath)
548
+ ]);
549
+ if (legacyUserContents && (!hooksContents || isManagedPrepareArtifact(hooksContents))) {
550
+ await writeFileIfChanged(hooksPath, legacyUserContents);
551
+ await unlinkIfPresent(legacyHooksUserPath);
552
+ } else if (legacyUserContents && hooksContents === legacyUserContents) {
553
+ await unlinkIfPresent(legacyHooksUserPath);
554
+ }
555
+ if (legacyServerUserContents && (!hooksServerContents || isManagedPrepareArtifact(hooksServerContents))) {
556
+ await writeFileIfChanged(hooksServerPath, legacyServerUserContents);
557
+ await unlinkIfPresent(legacyHooksServerUserPath);
558
+ } else if (legacyServerUserContents && hooksServerContents === legacyServerUserContents) {
559
+ await unlinkIfPresent(legacyHooksServerUserPath);
560
+ }
561
+ const currentHooks = await readFileIfPresent(hooksPath);
562
+ if (!currentHooks || isManagedPrepareArtifact(currentHooks) || isLegacySvelteTransportHook(currentHooks)) {
563
+ await writeFileIfChanged(hooksPath, renderSvelteDefaultHooksModule());
564
+ }
565
+ const currentServerHooks = await readFileIfPresent(hooksServerPath);
566
+ if (!currentServerHooks || isManagedPrepareArtifact(currentServerHooks) || isLegacySvelteServerHook(currentServerHooks)) {
567
+ await writeFileIfChanged(hooksServerPath, renderSvelteDefaultServerHooksModule());
568
+ }
569
+ await writeFileIfChanged(generatedHooksPath, renderManagedSvelteHooksModule());
570
+ await writeFileIfChanged(generatedServerHooksPath, renderManagedSvelteServerHooksModule());
571
+ await ensureSvelteConfigHooksOverride(projectRoot);
572
+ }
573
+ async function syncManagedFrameworkArtifacts(projectRoot) {
574
+ let manifest;
575
+ try {
576
+ const content = await readFile(resolve2(projectRoot, ".holo-js/framework/project.json"), "utf8");
577
+ manifest = JSON.parse(content);
578
+ } catch {
579
+ return;
580
+ }
581
+ if (manifest.framework === "sveltekit") {
582
+ await ensureSvelteManagedHooks(projectRoot);
583
+ }
584
+ }
585
+
586
+ // src/project/registry.ts
274
587
  function renderGeneratedModule(exportName, value) {
275
588
  return [
276
589
  "// Generated by holo prepare. Do not edit.",
@@ -281,6 +594,39 @@ function renderGeneratedModule(exportName, value) {
281
594
  ""
282
595
  ].join("\n");
283
596
  }
597
+ function isGeneratedSchemaTable(value) {
598
+ return isRecord(value) && value.kind === "table" && typeof value.tableName === "string" && isRecord(value.columns);
599
+ }
600
+ function extractGeneratedSchemaTables(moduleValue) {
601
+ if (isRecord(moduleValue) && isRecord(moduleValue.tables)) {
602
+ return Object.values(moduleValue.tables).filter(isGeneratedSchemaTable);
603
+ }
604
+ if (isRecord(moduleValue) && isGeneratedSchemaTable(moduleValue.default)) {
605
+ return [moduleValue.default];
606
+ }
607
+ if (isRecord(moduleValue)) {
608
+ return Object.values(moduleValue).filter(isGeneratedSchemaTable);
609
+ }
610
+ return [];
611
+ }
612
+ function getFilesystemErrorCode(error) {
613
+ return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : void 0;
614
+ }
615
+ async function renderGeneratedSchemaRuntimeArtifact(projectRoot, schemaEntry) {
616
+ const schemaPath = resolve3(projectRoot, schemaEntry);
617
+ try {
618
+ await access(schemaPath, fsConstants.R_OK);
619
+ } catch (error) {
620
+ const code = getFilesystemErrorCode(error);
621
+ if (code === "ENOENT" || code === "ENOTDIR") {
622
+ return renderGeneratedSchemaRuntimeModule([]);
623
+ }
624
+ throw error;
625
+ }
626
+ const moduleValue = await importProjectModule(projectRoot, schemaPath);
627
+ const tables = extractGeneratedSchemaTables(moduleValue);
628
+ return renderGeneratedSchemaRuntimeModule(tables);
629
+ }
284
630
  function renderGeneratedIndexModule() {
285
631
  return [
286
632
  "// Generated by holo prepare. Do not edit.",
@@ -288,9 +634,11 @@ function renderGeneratedIndexModule() {
288
634
  "/* eslint-disable @typescript-eslint/triple-slash-reference */",
289
635
  "",
290
636
  '/// <reference path="./broadcast.d.ts" />',
637
+ '/// <reference path="./auth.d.ts" />',
291
638
  '/// <reference path="./authorization/types.d.ts" />',
292
639
  '/// <reference path="./config.d.ts" />',
293
640
  '/// <reference path="./events.d.ts" />',
641
+ '/// <reference path="./model-registry.d.ts" />',
294
642
  '/// <reference path="./queue.d.ts" />',
295
643
  "",
296
644
  "import metadata from './metadata'",
@@ -328,6 +676,40 @@ function renderGeneratedIndexModule() {
328
676
  ""
329
677
  ].join("\n");
330
678
  }
679
+ function renderGeneratedModelTypes(models) {
680
+ const aliases = models.map((entry, index) => {
681
+ return `type HoloModel${index} = ModelReference<GeneratedSchemaTable<${JSON.stringify(entry.tableName)}>, EmptyScopeMap>`;
682
+ });
683
+ const modelTypeImports = aliases.length > 0 ? [
684
+ "import type { EmptyScopeMap, GeneratedSchemaTable, ModelReference } from '@holo-js/db'",
685
+ ""
686
+ ] : [];
687
+ const registryEntries = models.map((entry, index) => {
688
+ return ` readonly ${JSON.stringify(entry.name)}: HoloModel${index}`;
689
+ });
690
+ const registeredModelsDeclaration = registryEntries.length > 0 ? [
691
+ " interface RegisteredModels {",
692
+ ...registryEntries,
693
+ " }"
694
+ ] : [
695
+ " // eslint-disable-next-line @typescript-eslint/no-empty-object-type",
696
+ " interface RegisteredModels {}"
697
+ ];
698
+ return [
699
+ "// Generated by holo prepare. Do not edit.",
700
+ "",
701
+ "import './schema.generated'",
702
+ ...modelTypeImports,
703
+ ...aliases,
704
+ "",
705
+ "declare module '@holo-js/db' {",
706
+ ...registeredModelsDeclaration,
707
+ "}",
708
+ "",
709
+ "export {}",
710
+ ""
711
+ ].join("\n");
712
+ }
331
713
  function renderAugmentationInterface(name, members) {
332
714
  if (members.length === 0) {
333
715
  return [
@@ -398,7 +780,9 @@ function renderGeneratedBroadcastTypes(broadcast, channels) {
398
780
  }
399
781
  function renderGeneratedBroadcastManifest(registry) {
400
782
  const hasPresenceChannels = registry.channels.some((entry) => entry.type === "presence");
401
- const manifestImports = hasPresenceChannels ? ["import type { ChannelPresenceMemberFor, GeneratedBroadcastManifest } from '@holo-js/broadcast'"] : ["import type { GeneratedBroadcastManifest } from '@holo-js/broadcast'"];
783
+ const manifestImports = hasPresenceChannels ? [
784
+ "import type { ChannelPresenceMemberFor } from '@holo-js/broadcast'"
785
+ ] : [];
402
786
  const eventLines = registry.broadcast.flatMap((entry, index) => {
403
787
  const lines = [
404
788
  " {",
@@ -436,6 +820,30 @@ function renderGeneratedBroadcastManifest(registry) {
436
820
  "// Generated by holo prepare. Do not edit.",
437
821
  "",
438
822
  ...manifestImports,
823
+ ...manifestImports.length > 0 ? [""] : [],
824
+ "type GeneratedBroadcastManifestEvent = {",
825
+ " readonly name: string",
826
+ " readonly channels: readonly {",
827
+ " readonly type: 'public' | 'private' | 'presence'",
828
+ " readonly pattern: string",
829
+ " }[]",
830
+ "}",
831
+ "",
832
+ "type GeneratedBroadcastManifestChannel = {",
833
+ " readonly name: string",
834
+ " readonly pattern: string",
835
+ " readonly type: 'private' | 'presence'",
836
+ " readonly params: readonly string[]",
837
+ " readonly whispers: readonly string[]",
838
+ " readonly member?: Readonly<Record<string, unknown>>",
839
+ "}",
840
+ "",
841
+ "type GeneratedBroadcastManifest = {",
842
+ " readonly version: 1",
843
+ " readonly generatedAt: string",
844
+ " readonly events: readonly GeneratedBroadcastManifestEvent[]",
845
+ " readonly channels: readonly GeneratedBroadcastManifestChannel[]",
846
+ "}",
439
847
  "",
440
848
  "export const broadcastManifest = {",
441
849
  " version: 1,",
@@ -543,6 +951,37 @@ function renderGeneratedQueueTypes(jobs) {
543
951
  ""
544
952
  ].join("\n");
545
953
  }
954
+ function renderGeneratedAuthTypes(guards) {
955
+ const members = Object.entries(guards).sort(([left], [right]) => left.localeCompare(right)).filter((entry) => {
956
+ return entry[1].driver === "session" || entry[1].driver === "token";
957
+ }).map(([name, guard]) => {
958
+ return ` readonly ${JSON.stringify(name)}: ${JSON.stringify(guard.driver)}`;
959
+ });
960
+ const guardsMember = members.length > 0 ? [
961
+ " guards: {",
962
+ ...members,
963
+ " }"
964
+ ] : [
965
+ " guards: Readonly<Record<string, 'session'>>"
966
+ ];
967
+ return [
968
+ "// Generated by holo prepare. Do not edit.",
969
+ "",
970
+ "import '@holo-js/auth'",
971
+ "",
972
+ "declare global {",
973
+ " // eslint-disable-next-line @typescript-eslint/no-namespace",
974
+ " namespace HoloAuth {",
975
+ " interface TypeRegistry {",
976
+ ...guardsMember,
977
+ " }",
978
+ " }",
979
+ "}",
980
+ "",
981
+ "export {}",
982
+ ""
983
+ ].join("\n");
984
+ }
546
985
  function renderGeneratedAuthorizationRegistry(registry) {
547
986
  return [
548
987
  "// Generated by holo prepare. Do not edit.",
@@ -585,7 +1024,11 @@ function renderGeneratedAuthorizationTypes(authorizationPolicies, authorizationA
585
1024
  const typedAbilityEntries = authorizationAbilities.filter((entry) => [".ts", ".mts", ".cts"].includes(extname(entry.sourcePath)));
586
1025
  const policyImportNameByName = new Map(typedPolicyEntries.map((entry, index) => [entry.name, `holoAuthorizationPolicyModule${index}`]));
587
1026
  const abilityImportNameByName = new Map(typedAbilityEntries.map((entry, index) => [entry.name, `holoAuthorizationAbilityModule${index}`]));
1027
+ const usesHoloAuthUser = authorizationPolicies.length > 0 || authorizationAbilities.length > 0 || guardNames.length > 0;
588
1028
  const imports = [
1029
+ ...typedPolicyEntries.length > 0 ? ["import type { AuthorizationPolicyDefinition as HoloAuthorizationPolicyDefinition } from '@holo-js/authorization/contracts'"] : [],
1030
+ ...typedAbilityEntries.length > 0 ? ["import type { AuthorizationAbilityDefinition as HoloAuthorizationAbilityDefinition } from '@holo-js/authorization/contracts'"] : [],
1031
+ ...usesHoloAuthUser ? ["import type { AuthUser as HoloAuthUser } from '@holo-js/auth'"] : [],
589
1032
  ...typedPolicyEntries.map((entry, index) => {
590
1033
  return `import type * as holoAuthorizationPolicyModule${index} from '${relativeImportPath(GENERATED_AUTHORIZATION_TYPES_PATH, entry.sourcePath)}'`;
591
1034
  }),
@@ -600,7 +1043,7 @@ function renderGeneratedAuthorizationTypes(authorizationPolicies, authorizationA
600
1043
  if (!importName || !entry.exportName) {
601
1044
  return [
602
1045
  ` ${JSON.stringify(entry.name)}: {`,
603
- " actor: object",
1046
+ " actor: HoloAuthUser",
604
1047
  ` target: object`,
605
1048
  " classActions: {",
606
1049
  ...classActionEntries,
@@ -613,16 +1056,12 @@ function renderGeneratedAuthorizationTypes(authorizationPolicies, authorizationA
613
1056
  }
614
1057
  return [
615
1058
  ` ${JSON.stringify(entry.name)}: {`,
616
- " actor: object",
617
- ` target: typeof ${importName}[${JSON.stringify(entry.exportName)}] extends import('@holo-js/authorization/contracts').AuthorizationPolicyDefinition<infer _TName, infer TTarget, infer _TClassActions, infer _TRecordActions, infer _TActor> ? TTarget : object`,
618
- ` classActions: typeof ${importName}[${JSON.stringify(entry.exportName)}] extends import('@holo-js/authorization/contracts').AuthorizationPolicyDefinition<infer _TName, infer _TTarget, infer TClassActions, infer _TRecordActions, infer _TActor> ? {`,
619
- ...classActionEntries,
620
- " } : {",
1059
+ " actor: HoloAuthUser",
1060
+ ` target: typeof ${importName}[${JSON.stringify(entry.exportName)}] extends HoloAuthorizationPolicyDefinition<infer _TName, infer TTarget, infer _TClassActions, infer _TRecordActions, infer _TActor> ? TTarget : object`,
1061
+ " classActions: {",
621
1062
  ...classActionEntries,
622
1063
  " }",
623
- ` recordActions: typeof ${importName}[${JSON.stringify(entry.exportName)}] extends import('@holo-js/authorization/contracts').AuthorizationPolicyDefinition<infer _TName, infer _TTarget, infer _TClassActions, infer TRecordActions, infer _TActor> ? {`,
624
- ...recordActionEntries,
625
- " } : {",
1064
+ " recordActions: {",
626
1065
  ...recordActionEntries,
627
1066
  " }",
628
1067
  " }"
@@ -631,19 +1070,19 @@ function renderGeneratedAuthorizationTypes(authorizationPolicies, authorizationA
631
1070
  const abilityMembers = authorizationAbilities.map((entry) => {
632
1071
  const importName = abilityImportNameByName.get(entry.name);
633
1072
  if (!importName || !entry.exportName) {
634
- return ` ${JSON.stringify(entry.name)}: { actor: object, input: object }`;
1073
+ return ` ${JSON.stringify(entry.name)}: { actor: HoloAuthUser, input: object }`;
635
1074
  }
636
1075
  return [
637
1076
  ` ${JSON.stringify(entry.name)}: {`,
638
- " actor: object",
639
- ` input: typeof ${importName}[${JSON.stringify(entry.exportName)}] extends import('@holo-js/authorization/contracts').AuthorizationAbilityDefinition<infer _TName, infer TInput, infer _TActor> ? TInput : object`,
1077
+ " actor: HoloAuthUser",
1078
+ ` input: typeof ${importName}[${JSON.stringify(entry.exportName)}] extends HoloAuthorizationAbilityDefinition<infer _TName, infer TInput, infer _TActor> ? TInput : object`,
640
1079
  " }"
641
1080
  ].join("\n");
642
1081
  });
643
1082
  const guardMembers = guardNames.map((name) => {
644
1083
  return [
645
1084
  ` ${JSON.stringify(name)}: {`,
646
- ` user: import('@holo-js/auth').AuthUser`,
1085
+ " user: HoloAuthUser",
647
1086
  " }"
648
1087
  ].join("\n");
649
1088
  });
@@ -663,20 +1102,23 @@ function renderGeneratedAuthorizationTypes(authorizationPolicies, authorizationA
663
1102
  ""
664
1103
  ].join("\n");
665
1104
  }
666
- function renderGeneratedTsconfig() {
1105
+ function renderGeneratedTsconfigForBase(basePath) {
667
1106
  return `${JSON.stringify({
668
- extends: "../../tsconfig.json",
1107
+ extends: basePath,
669
1108
  include: ["./**/*.ts", "./**/*.d.ts"]
670
1109
  }, null, 2)}
671
1110
  `;
672
1111
  }
1112
+ async function resolveGeneratedTsconfigBase(_projectRoot) {
1113
+ return "../../tsconfig.json";
1114
+ }
673
1115
  function getConfigExtensionPriority(fileName) {
674
1116
  const extension = extname(fileName);
675
1117
  const index = CONFIG_EXTENSION_PRIORITY.indexOf(extension);
676
1118
  return index >= 0 ? index : Number.MAX_SAFE_INTEGER;
677
1119
  }
678
1120
  async function collectProjectConfigEntries(projectRoot) {
679
- const configDir = resolve2(projectRoot, "config");
1121
+ const configDir = resolve3(projectRoot, "config");
680
1122
  const entries = await readdir(configDir, { withFileTypes: true }).catch(() => []);
681
1123
  const selectedByName = /* @__PURE__ */ new Map();
682
1124
  for (const entry of entries) {
@@ -701,7 +1143,7 @@ async function collectProjectConfigEntries(projectRoot) {
701
1143
  }));
702
1144
  }
703
1145
  function renderGeneratedConfigTypes(projectRoot, entries) {
704
- const customEntries = entries.filter((entry) => !["app", "database", "redis", "cache", "storage", "queue", "broadcast", "notifications", "mail", "media", "session", "security", "auth"].includes(entry.configName));
1146
+ const customEntries = entries.filter((entry) => !["app", "database", "redis", "cache", "cors", "storage", "queue", "broadcast", "notifications", "mail", "media", "session", "security", "auth"].includes(entry.configName));
705
1147
  if (customEntries.length === 0) {
706
1148
  return [
707
1149
  "// Generated by holo prepare. Do not edit.",
@@ -733,27 +1175,31 @@ function renderGeneratedConfigTypes(projectRoot, entries) {
733
1175
  ""
734
1176
  ].join("\n");
735
1177
  }
736
- async function writeFileIfChanged(path, contents) {
1178
+ async function writeFileIfChanged2(path, contents) {
737
1179
  try {
738
- if (await readFile(path, "utf8") === contents) {
1180
+ if (await readFile2(path, "utf8") === contents) {
739
1181
  return;
740
1182
  }
741
1183
  } catch {
742
1184
  }
743
- await mkdir(dirname2(path), { recursive: true });
744
- await writeFile(path, contents, "utf8");
1185
+ await mkdir2(dirname3(path), { recursive: true });
1186
+ await writeFile2(path, contents, "utf8");
745
1187
  }
746
1188
  function stripGeneratedAt(registry) {
747
1189
  const { generatedAt: _generatedAt, ...stableRegistry } = registry;
748
1190
  return stableRegistry;
749
1191
  }
750
1192
  async function ensureGeneratedRegistryOwnership(projectRoot) {
751
- await mkdir(resolve2(projectRoot, GENERATED_ROOT), { recursive: true });
752
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_GITIGNORE_PATH), "*\n!.gitignore\n");
753
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_TSCONFIG_PATH), renderGeneratedTsconfig());
1193
+ await mkdir2(resolve3(projectRoot, GENERATED_ROOT), { recursive: true });
1194
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_GITIGNORE_PATH), "*\n!.gitignore\n");
754
1195
  }
755
1196
  async function writeGeneratedProjectRegistry(projectRoot, registry) {
756
1197
  await ensureGeneratedRegistryOwnership(projectRoot);
1198
+ const tsconfigPath = resolve3(projectRoot, GENERATED_TSCONFIG_PATH);
1199
+ await writeFileIfChanged2(
1200
+ tsconfigPath,
1201
+ renderGeneratedTsconfigForBase(await resolveGeneratedTsconfigBase(projectRoot))
1202
+ );
757
1203
  const loadedConfig = await loadConfigDirectory(projectRoot);
758
1204
  const configEntries = await collectProjectConfigEntries(projectRoot);
759
1205
  const existingRegistry = await loadGeneratedProjectRegistry(projectRoot);
@@ -761,34 +1207,41 @@ async function writeGeneratedProjectRegistry(projectRoot, registry) {
761
1207
  ...registry,
762
1208
  generatedAt: existingRegistry.generatedAt
763
1209
  } : registry;
764
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_METADATA_PATH), renderGeneratedModule("metadata", {
1210
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_METADATA_PATH), renderGeneratedModule("metadata", {
765
1211
  version: nextRegistry.version,
766
1212
  generatedAt: nextRegistry.generatedAt,
767
1213
  paths: nextRegistry.paths
768
1214
  }));
769
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_MODELS_PATH), renderGeneratedModule("models", nextRegistry.models));
770
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_MIGRATIONS_PATH), renderGeneratedModule("migrations", nextRegistry.migrations));
771
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_SEEDERS_PATH), renderGeneratedModule("seeders", nextRegistry.seeders));
772
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_COMMANDS_PATH), renderGeneratedModule("commands", nextRegistry.commands));
773
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_JOBS_PATH), renderGeneratedModule("jobs", nextRegistry.jobs));
774
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_EVENTS_PATH), renderGeneratedModule("events", nextRegistry.events));
775
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_LISTENERS_PATH), renderGeneratedModule("listeners", nextRegistry.listeners));
776
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_BROADCAST_PATH), renderGeneratedModule("broadcast", nextRegistry.broadcast));
777
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_CHANNELS_PATH), renderGeneratedModule("channels", nextRegistry.channels));
778
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_BROADCAST_MANIFEST_PATH), renderGeneratedBroadcastManifest(nextRegistry));
779
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_BROADCAST_TYPES_PATH), renderGeneratedBroadcastTypes(nextRegistry.broadcast, nextRegistry.channels));
780
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_CONFIG_TYPES_PATH), renderGeneratedConfigTypes(projectRoot, configEntries));
781
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_EVENT_TYPES_PATH), renderGeneratedEventTypes(nextRegistry.events, nextRegistry.listeners));
782
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_QUEUE_TYPES_PATH), renderGeneratedQueueTypes(nextRegistry.jobs));
783
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_AUTHORIZATION_REGISTRY_PATH), renderGeneratedAuthorizationRegistry(nextRegistry));
784
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_AUTHORIZATION_TYPES_PATH), renderGeneratedAuthorizationTypes(
1215
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_MODELS_PATH), renderGeneratedModule("models", nextRegistry.models));
1216
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_MODEL_TYPES_PATH), renderGeneratedModelTypes(nextRegistry.models));
1217
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_MIGRATIONS_PATH), renderGeneratedModule("migrations", nextRegistry.migrations));
1218
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_SEEDERS_PATH), renderGeneratedModule("seeders", nextRegistry.seeders));
1219
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_COMMANDS_PATH), renderGeneratedModule("commands", nextRegistry.commands));
1220
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_JOBS_PATH), renderGeneratedModule("jobs", nextRegistry.jobs));
1221
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_EVENTS_PATH), renderGeneratedModule("events", nextRegistry.events));
1222
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_LISTENERS_PATH), renderGeneratedModule("listeners", nextRegistry.listeners));
1223
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_BROADCAST_PATH), renderGeneratedModule("broadcast", nextRegistry.broadcast));
1224
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_CHANNELS_PATH), renderGeneratedModule("channels", nextRegistry.channels));
1225
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_BROADCAST_MANIFEST_PATH), renderGeneratedBroadcastManifest(nextRegistry));
1226
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_BROADCAST_TYPES_PATH), renderGeneratedBroadcastTypes(nextRegistry.broadcast, nextRegistry.channels));
1227
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_AUTH_TYPES_PATH), renderGeneratedAuthTypes(loadedConfig?.auth?.guards ?? {}));
1228
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_CONFIG_TYPES_PATH), renderGeneratedConfigTypes(projectRoot, configEntries));
1229
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_EVENT_TYPES_PATH), renderGeneratedEventTypes(nextRegistry.events, nextRegistry.listeners));
1230
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_QUEUE_TYPES_PATH), renderGeneratedQueueTypes(nextRegistry.jobs));
1231
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_AUTHORIZATION_REGISTRY_PATH), renderGeneratedAuthorizationRegistry(nextRegistry));
1232
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_AUTHORIZATION_TYPES_PATH), renderGeneratedAuthorizationTypes(
785
1233
  nextRegistry.authorizationPolicies,
786
1234
  nextRegistry.authorizationAbilities,
787
1235
  Object.keys(loadedConfig?.auth?.guards ?? {}).sort((left, right) => left.localeCompare(right))
788
1236
  ));
789
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_INDEX_PATH), renderGeneratedIndexModule());
790
- await writeFileIfChanged(resolve2(projectRoot, GENERATED_REGISTRY_JSON_PATH), `${JSON.stringify(nextRegistry, null, 2)}
1237
+ await syncManagedFrameworkArtifacts(projectRoot);
1238
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_INDEX_PATH), renderGeneratedIndexModule());
1239
+ await writeFileIfChanged2(resolve3(projectRoot, GENERATED_REGISTRY_JSON_PATH), `${JSON.stringify(nextRegistry, null, 2)}
791
1240
  `);
1241
+ await writeFileIfChanged2(
1242
+ resolve3(projectRoot, GENERATED_SCHEMA_RUNTIME_PATH),
1243
+ await renderGeneratedSchemaRuntimeArtifact(projectRoot, nextRegistry.paths.generatedSchema)
1244
+ );
792
1245
  }
793
1246
  function isGeneratedProjectRegistry(value) {
794
1247
  if (isRecord(value) && isRecord(value.paths)) {
@@ -810,16 +1263,24 @@ function isGeneratedProjectRegistry(value) {
810
1263
  return isRecord(value) && value.version === 1 && isRecord(value.paths) && Array.isArray(value.models) && Array.isArray(value.migrations) && Array.isArray(value.seeders) && Array.isArray(value.commands) && Array.isArray(value.jobs) && Array.isArray(value.events) && Array.isArray(value.listeners) && Array.isArray(value.broadcast) && Array.isArray(value.channels) && Array.isArray(value.authorizationPolicies) && Array.isArray(value.authorizationAbilities);
811
1264
  }
812
1265
  async function loadGeneratedProjectRegistry(projectRoot) {
813
- const filePath = resolve2(projectRoot, GENERATED_INDEX_PATH);
814
- if (!await pathExists(filePath)) {
815
- return void 0;
1266
+ const filePath = resolve3(projectRoot, GENERATED_REGISTRY_JSON_PATH);
1267
+ const contents = await readFile2(filePath, "utf8").catch(() => void 0);
1268
+ if (contents) {
1269
+ try {
1270
+ const parsed = JSON.parse(contents);
1271
+ if (isGeneratedProjectRegistry(parsed)) {
1272
+ return parsed;
1273
+ }
1274
+ } catch {
1275
+ }
816
1276
  }
817
- const moduleValue = await importProjectModule(projectRoot, filePath);
818
- if (isRecord(moduleValue) && isGeneratedProjectRegistry(moduleValue.default)) {
819
- return moduleValue.default;
1277
+ const generatedIndexPath = resolve3(projectRoot, GENERATED_INDEX_PATH);
1278
+ const generatedModule = await importProjectModule(projectRoot, generatedIndexPath).catch(() => void 0);
1279
+ if (isRecord(generatedModule) && isGeneratedProjectRegistry(generatedModule.registry)) {
1280
+ return generatedModule.registry;
820
1281
  }
821
- if (isRecord(moduleValue) && isGeneratedProjectRegistry(moduleValue.registry)) {
822
- return moduleValue.registry;
1282
+ if (isRecord(generatedModule) && isGeneratedProjectRegistry(generatedModule.default)) {
1283
+ return generatedModule.default;
823
1284
  }
824
1285
  return void 0;
825
1286
  }
@@ -844,6 +1305,7 @@ export {
844
1305
  renderMarkdownMailTemplate,
845
1306
  resolveNameInfo,
846
1307
  resolveArtifactPath,
1308
+ renderGeneratedModelTypes,
847
1309
  writeGeneratedProjectRegistry,
848
1310
  loadGeneratedProjectRegistry
849
1311
  };