@idevconn/create-icore 0.9.3 → 0.10.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 (42) hide show
  1. package/dist/cli.js +755 -190
  2. package/dist/index.cjs +778 -213
  3. package/dist/index.js +771 -206
  4. package/package.json +4 -4
  5. package/templates/.yarn/releases/{yarn-4.16.0.cjs → yarn-4.17.0.cjs} +326 -326
  6. package/templates/.yarnrc.yml +1 -1
  7. package/templates/apps/api/package.json +6 -6
  8. package/templates/apps/microservices/auth/package.json +4 -4
  9. package/templates/apps/microservices/jobs/package.json +5 -5
  10. package/templates/apps/microservices/notes/package.json +5 -5
  11. package/templates/apps/microservices/payment/package.json +4 -4
  12. package/templates/apps/microservices/upload/package.json +6 -6
  13. package/templates/apps/templates/client-antd/package.json +2 -2
  14. package/templates/apps/templates/client-mui/package.json +4 -4
  15. package/templates/apps/templates/client-shadcn/package.json +7 -7
  16. package/templates/apps/templates/client-shadcn/src/components/ui/button.tsx +1 -2
  17. package/templates/libs/auth-client/package.json +3 -3
  18. package/templates/libs/auth-strategies/firebase/package.json +5 -4
  19. package/templates/libs/auth-strategies/firebase/src/lib/firebase-auth.module.ts +2 -1
  20. package/templates/libs/auth-strategies/mongodb/package.json +4 -4
  21. package/templates/libs/auth-strategies/supabase/package.json +5 -5
  22. package/templates/libs/db-strategies/firestore/package.json +5 -4
  23. package/templates/libs/db-strategies/firestore/src/lib/firestore-db.module.ts +2 -1
  24. package/templates/libs/db-strategies/mongodb/package.json +3 -3
  25. package/templates/libs/db-strategies/supabase/package.json +5 -5
  26. package/templates/libs/firebase-admin/package.json +2 -2
  27. package/templates/libs/firebase-admin/src/lib/__tests__/firebase-admin.unit.test.ts +11 -11
  28. package/templates/libs/firebase-admin/src/lib/firebase-admin.ts +6 -6
  29. package/templates/libs/jobs-client/package.json +4 -4
  30. package/templates/libs/notes-client/package.json +3 -3
  31. package/templates/libs/payment-client/package.json +3 -3
  32. package/templates/libs/shared/package.json +2 -2
  33. package/templates/libs/storage-strategies/cloudinary/package.json +4 -4
  34. package/templates/libs/storage-strategies/firebase/package.json +5 -4
  35. package/templates/libs/storage-strategies/firebase/src/lib/firebase-storage.module.ts +4 -1
  36. package/templates/libs/storage-strategies/mongodb/package.json +3 -3
  37. package/templates/libs/storage-strategies/supabase/package.json +5 -5
  38. package/templates/libs/template-shared/package.json +8 -8
  39. package/templates/libs/upload-client/package.json +3 -3
  40. package/templates/libs/vite-plugins/package.json +3 -3
  41. package/templates/package.json +32 -32
  42. package/templates/tools/create-icore/_template-shell/package.json +32 -32
package/dist/index.cjs CHANGED
@@ -47,9 +47,9 @@ function pmRun(pm, script) {
47
47
  }
48
48
 
49
49
  // src/lib/scaffold.ts
50
- var import_promises8 = require("fs/promises");
50
+ var import_promises9 = require("fs/promises");
51
51
  var import_node_fs = require("fs");
52
- var import_node_path8 = require("path");
52
+ var import_node_path9 = require("path");
53
53
  var import_node_child_process = require("child_process");
54
54
 
55
55
  // src/lib/scaffold-env.ts
@@ -215,6 +215,9 @@ async function writeGatewayEnv(targetDir, opts) {
215
215
  for (const prefix of ["AUTH", "UPLOAD", "NOTES", "PAYMENT"]) {
216
216
  next = uncommentTransportEnv(next, prefix, opts.transport);
217
217
  }
218
+ if (opts.authProvider === "none") {
219
+ next = next.split("\n").filter((line) => !line.startsWith("AUTH_") && !line.startsWith("# AUTH_")).join("\n");
220
+ }
218
221
  await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/api/.env"), next);
219
222
  }
220
223
  async function writeRootEnv(targetDir, opts) {
@@ -300,6 +303,7 @@ async function removeStrategiesLib(targetDir) {
300
303
  await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/shared/src/strategies"), { recursive: true, force: true });
301
304
  await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/shared/src/testing.ts"), { force: true });
302
305
  await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/shared/src/transport.ts"), { force: true });
306
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/shared/src/__tests__/transport.unit.test.ts"), { force: true });
303
307
  const indexPath = (0, import_node_path2.join)(targetDir, "libs/shared/src/index.ts");
304
308
  try {
305
309
  const src = await (0, import_promises2.readFile)(indexPath, "utf8");
@@ -318,122 +322,6 @@ async function removeStrategiesLib(targetDir) {
318
322
  } catch {
319
323
  }
320
324
  }
321
- async function removeAuthStack(targetDir) {
322
- const rmPaths = [
323
- "apps/microservices/auth",
324
- "libs/auth-strategies",
325
- "libs/auth-client",
326
- "Dockerfile.ms-auth",
327
- "apps/api/src/app/auth",
328
- "apps/api/src/app/profile",
329
- "apps/api/src/app/abilities",
330
- "libs/shared/src/abilities",
331
- "apps/client/src/components/auth",
332
- "apps/client/src/routes/login.tsx",
333
- "apps/client/src/routes/auth.callback.tsx",
334
- "apps/client/src/routes/auth.oauth.callback.tsx",
335
- "apps/client/src/routes/_dashboard/profile.tsx"
336
- ];
337
- for (const p2 of rmPaths) {
338
- await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
339
- }
340
- const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
341
- try {
342
- const src = await (0, import_promises2.readFile)(appModulePath, "utf8");
343
- const next = src.replace(/^import \{ AuthModule \} from '\.\/auth\/auth\.module';\n/m, "").replace(/^import \{ ProfileModule \} from '\.\/profile\/profile\.module';\n/m, "").replace(/^import \{ AbilitiesModule \} from '\.\/abilities\/abilities\.module';\n/m, "").replace(/\bAuthModule,\s*/g, "").replace(/,\s*AuthModule\b/g, "").replace(/\bProfileModule,\s*/g, "").replace(/,\s*ProfileModule\b/g, "").replace(/\bAbilitiesModule,\s*/g, "").replace(/,\s*AbilitiesModule\b/g, "");
344
- await (0, import_promises2.writeFile)(appModulePath, next);
345
- } catch {
346
- }
347
- const dashboardPath = (0, import_node_path2.join)(targetDir, "apps/client/src/routes/_dashboard.tsx");
348
- try {
349
- const src = await (0, import_promises2.readFile)(dashboardPath, "utf8");
350
- const next = src.replace(/^import \{ useAuthStore \} from '@icore\/template-shared';\n/m, "").replace(/, redirect/g, "").replace(/\n {2}beforeLoad: \(\) => \{[\s\S]*?\n {2}\},/m, "");
351
- await (0, import_promises2.writeFile)(dashboardPath, next);
352
- } catch {
353
- }
354
- for (const alias of [
355
- "@icore/auth-client",
356
- "@icore/auth-supabase",
357
- "@icore/auth-firebase",
358
- "@icore/auth-mongodb"
359
- ]) {
360
- await stripTsconfigPath(targetDir, alias);
361
- }
362
- await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
363
- "@icore/auth-client",
364
- "cookie-parser"
365
- ]);
366
- const gatewayMainPath = (0, import_node_path2.join)(targetDir, "apps/api/src/main.ts");
367
- try {
368
- const src = await (0, import_promises2.readFile)(gatewayMainPath, "utf8");
369
- const next = src.replace(/^import cookieParser from 'cookie-parser';\n/m, "").replace(/^\s*app\.use\(cookieParser\(\)\);\n/m, "");
370
- await (0, import_promises2.writeFile)(gatewayMainPath, next);
371
- } catch {
372
- }
373
- const gatewayEnv = (0, import_node_path2.join)(targetDir, "apps/api/.env");
374
- try {
375
- const env = await (0, import_promises2.readFile)(gatewayEnv, "utf8");
376
- const next = env.split("\n").filter((line) => !line.startsWith("AUTH_") && !line.startsWith("# AUTH_")).join("\n");
377
- await (0, import_promises2.writeFile)(gatewayEnv, next);
378
- } catch {
379
- }
380
- const composePath = (0, import_node_path2.join)(targetDir, "docker-compose.yml");
381
- try {
382
- const compose = await (0, import_promises2.readFile)(composePath, "utf8");
383
- const next = compose.replace(/\n {2}auth:[\s\S]+?(?=\n {2}\w|\nnetworks:)/m, "\n").replace(/\n {6}auth:\n {8}condition: service_started/g, "").replace(/\n {6}AUTH_TRANSPORT:[^\n]*/g, "").replace(/\n {6}AUTH_REDIS_URL:[^\n]*/g, "");
384
- await (0, import_promises2.writeFile)(composePath, next);
385
- } catch {
386
- }
387
- for (const rel of ["libs/shared/src/index.ts", "libs/shared/src/client.ts"]) {
388
- const sharedIndexPath = (0, import_node_path2.join)(targetDir, rel);
389
- try {
390
- const src = await (0, import_promises2.readFile)(sharedIndexPath, "utf8");
391
- await (0, import_promises2.writeFile)(sharedIndexPath, src.replace(/^export \* from '\.\/abilities';\n?/m, ""));
392
- } catch {
393
- }
394
- }
395
- const routesIndexPath = (0, import_node_path2.join)(targetDir, "apps/client/src/routes/index.tsx");
396
- try {
397
- const src = await (0, import_promises2.readFile)(routesIndexPath, "utf8");
398
- await (0, import_promises2.writeFile)(
399
- routesIndexPath,
400
- src.replace(/ctaHref="\/login"/, 'ctaHref="/dashboard"').replace(/ctaLabel="Log in →"/, 'ctaLabel="Dashboard \u2192"')
401
- );
402
- } catch {
403
- }
404
- const mainTsxPath = (0, import_node_path2.join)(targetDir, "apps/client/src/main.tsx");
405
- try {
406
- const src = await (0, import_promises2.readFile)(mainTsxPath, "utf8");
407
- const next = src.replace(/\n {2}onUnauthorized: \(\) => router\.navigate\(\{ to: '\/login' \}\),/, "").replace(/^\s*AbilityProvider,\n/m, "").replace(/^\s*<AbilityProvider>\n/m, "").replace(/^\s*<\/AbilityProvider>\n/m, "");
408
- await (0, import_promises2.writeFile)(mainTsxPath, next);
409
- } catch {
410
- }
411
- await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/template-shared/src/lib/abilities"), {
412
- recursive: true,
413
- force: true
414
- });
415
- const templateSharedIndexPath = (0, import_node_path2.join)(targetDir, "libs/template-shared/src/index.ts");
416
- try {
417
- const src = await (0, import_promises2.readFile)(templateSharedIndexPath, "utf8");
418
- await (0, import_promises2.writeFile)(
419
- templateSharedIndexPath,
420
- src.replace(/^export \* from '\.\/lib\/abilities\/ability-provider\.js';\n/m, "")
421
- );
422
- } catch {
423
- }
424
- const headerPath = (0, import_node_path2.join)(targetDir, "apps/client/src/components/layout/LayoutHeader.tsx");
425
- try {
426
- const src = await (0, import_promises2.readFile)(headerPath, "utf8");
427
- await (0, import_promises2.writeFile)(
428
- headerPath,
429
- src.replace(/^import \{ useTranslation \} from 'react-i18next';\n/m, "").replace(/^import \{ useNavigate \} from '@tanstack\/react-router';\n/m, "").replace(/^import \{ LogOut \} from 'lucide-react';\n/m, "").replace(/^import \{ Button \} from '\.\.\/ui\/button';\n/m, "").replace(
430
- /import \{ useAuthStore, setStoredLocale, type IcoreLocale \} from '@icore\/template-shared';/,
431
- "import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';"
432
- ).replace(/^ {2}const \{ t \} = useTranslation\(\);\n/m, "").replace(/^ {2}const navigate = useNavigate\(\);\n/m, "").replace(/^ {2}const user = useAuthStore\(\(s\) => s\.user\);\n/m, "").replace(/^ {2}const logout = useAuthStore\(\(s\) => s\.logout\);\n/m, "").replace(/\n {2}function handleLogout\(\) \{[\s\S]*?\n {2}\}\n(?=\n {2}return)/m, "\n").replace(/\n {8}<div className="hidden sm:flex[\s\S]*?\n {8}<\/div>\n/m, "\n").replace(/\n {8}<Button[\s\S]*?sm:hidden[\s\S]*?\n {8}<\/Button>\n/m, "\n")
433
- );
434
- } catch {
435
- }
436
- }
437
325
  async function removeUploadStack(targetDir) {
438
326
  const paths = [
439
327
  "apps/microservices/upload",
@@ -475,9 +363,674 @@ async function removeUploadStack(targetDir) {
475
363
  }
476
364
  }
477
365
 
366
+ // src/lib/scaffold-auth-none.ts
367
+ var import_promises3 = require("fs/promises");
368
+ var import_node_path3 = require("path");
369
+ async function stripDeps2(pkgPath, names) {
370
+ try {
371
+ const raw = await (0, import_promises3.readFile)(pkgPath, "utf8");
372
+ const pkg = JSON.parse(raw);
373
+ for (const n of names) {
374
+ if (pkg.dependencies) delete pkg.dependencies[n];
375
+ if (pkg.devDependencies) delete pkg.devDependencies[n];
376
+ }
377
+ await (0, import_promises3.writeFile)(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
378
+ } catch {
379
+ }
380
+ }
381
+ var AUTH_ONLY_PATHS = [
382
+ "apps/microservices/auth",
383
+ "libs/auth-strategies",
384
+ "libs/auth-client",
385
+ "Dockerfile.ms-auth",
386
+ "apps/api/src/app/auth",
387
+ "apps/api/src/app/profile",
388
+ "apps/api/src/app/abilities",
389
+ "libs/shared/src/abilities",
390
+ "apps/client/src/components/auth",
391
+ "apps/client/src/routes/login.tsx",
392
+ "apps/client/src/routes/auth.callback.tsx",
393
+ "apps/client/src/routes/auth.oauth.callback.tsx",
394
+ "apps/client/src/routes/_dashboard/profile.tsx",
395
+ "libs/template-shared/src/lib/abilities"
396
+ ];
397
+ async function removeAuthOnlyPaths(targetDir) {
398
+ for (const p2 of AUTH_ONLY_PATHS) {
399
+ await (0, import_promises3.rm)((0, import_node_path3.join)(targetDir, p2), { recursive: true, force: true });
400
+ }
401
+ await stripDeps2((0, import_node_path3.join)(targetDir, "apps/api/package.json"), [
402
+ "@icore/auth-client",
403
+ "cookie-parser"
404
+ ]);
405
+ }
406
+ async function stripTsconfigPath2(targetDir, alias) {
407
+ const tsconfigPath = (0, import_node_path3.join)(targetDir, "tsconfig.base.json");
408
+ try {
409
+ const src = await (0, import_promises3.readFile)(tsconfigPath, "utf8");
410
+ const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
411
+ const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
412
+ if (pretty !== src) {
413
+ await (0, import_promises3.writeFile)(tsconfigPath, pretty);
414
+ return;
415
+ }
416
+ const parsed = JSON.parse(src);
417
+ if (parsed.compilerOptions?.paths) delete parsed.compilerOptions.paths[alias];
418
+ await (0, import_promises3.writeFile)(tsconfigPath, JSON.stringify(parsed));
419
+ } catch {
420
+ }
421
+ }
422
+ async function removeAuthTsconfigPaths(targetDir) {
423
+ for (const alias of [
424
+ "@icore/auth-client",
425
+ "@icore/auth-supabase",
426
+ "@icore/auth-firebase",
427
+ "@icore/auth-mongodb"
428
+ ]) {
429
+ await stripTsconfigPath2(targetDir, alias);
430
+ }
431
+ }
432
+ async function removeDockerComposeAuthService(targetDir) {
433
+ const composePath = (0, import_node_path3.join)(targetDir, "docker-compose.yml");
434
+ try {
435
+ const compose = await (0, import_promises3.readFile)(composePath, "utf8");
436
+ const next = compose.replace(/\n {2}auth:[\s\S]+?(?=\n {2}\w|\nnetworks:)/m, "\n").replace(/\n {6}auth:\n {8}condition: service_started/g, "").replace(/\n {6}AUTH_TRANSPORT:[^\n]*/g, "").replace(/\n {6}AUTH_REDIS_URL:[^\n]*/g, "");
437
+ await (0, import_promises3.writeFile)(composePath, next);
438
+ } catch {
439
+ }
440
+ }
441
+ var GATEWAY_MAIN_TS = `import { Logger } from '@nestjs/common';
442
+ import { NestFactory } from '@nestjs/core';
443
+ import { NestExpressApplication } from '@nestjs/platform-express';
444
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
445
+ import { formatGatewayBanner } from '@icore/shared';
446
+ import { AppModule } from './app/app.module';
447
+ import { GATEWAY_SERVICES } from './app/gateway-services';
448
+ import pkg from '@icore/package.json';
449
+
450
+ const DEFAULT_PORT = 3001;
451
+
452
+ async function bootstrap() {
453
+ const app = await NestFactory.create<NestExpressApplication>(AppModule);
454
+ app.setGlobalPrefix('api');
455
+
456
+ const swaggerConfig = new DocumentBuilder()
457
+ .setTitle('iCore API')
458
+ .setDescription('iCore Gateway HTTP surface')
459
+ .setVersion(pkg.version)
460
+ .addBearerAuth()
461
+ .build();
462
+ const document = SwaggerModule.createDocument(app, swaggerConfig);
463
+ SwaggerModule.setup('api/docs', app, document);
464
+
465
+ const port = Number(process.env.API_PORT ?? DEFAULT_PORT);
466
+ await app.listen(port);
467
+ }
468
+
469
+ bootstrap()
470
+ .then(() => {
471
+ const origin = process.env.API_ORIGIN ?? 'http://localhost';
472
+ const port = Number(process.env.API_PORT ?? DEFAULT_PORT);
473
+ new Logger('API-Bootstrap').log(
474
+ formatGatewayBanner({ port, origin, services: GATEWAY_SERVICES }),
475
+ );
476
+ })
477
+ .catch((err) => {
478
+ new Logger('API-Bootstrap').error(
479
+ 'Gateway bootstrap failed',
480
+ err instanceof Error ? err.stack : err,
481
+ );
482
+ process.exit(1);
483
+ });
484
+ `;
485
+ var GATEWAY_APP_MODULE_TS = `import { join } from 'node:path';
486
+ import { Module } from '@nestjs/common';
487
+ import { ConfigModule } from '@nestjs/config';
488
+ import { ThrottlerModule, seconds } from '@nestjs/throttler';
489
+ import { StorageModule } from './storage/storage.module';
490
+ import { FeaturesModule } from './features.module';
491
+
492
+ @Module({
493
+ imports: [
494
+ ConfigModule.forRoot({
495
+ isGlobal: true,
496
+ envFilePath: [join(process.cwd(), 'apps/api/.env'), join(process.cwd(), '.env')],
497
+ }),
498
+ ThrottlerModule.forRoot([{ name: 'auth-burst', ttl: seconds(60), limit: 10 }]),
499
+ StorageModule,
500
+ FeaturesModule,
501
+ ],
502
+ })
503
+ export class AppModule {}
504
+ `;
505
+ var SHARED_CLIENT_TS = `// Browser-safe subset of @icore/shared.
506
+ // Import from '@icore/shared/client' in client-side code to avoid pulling
507
+ // in NestJS / Node.js-only modules (transport, strategies, contracts).
508
+ export * from './types';
509
+ `;
510
+ var SHARED_INDEX_TS = `export * from './env';
511
+ export * from './bootstrap';
512
+ export * from './jobs';
513
+ export * from './strategies';
514
+ export * from './transport';
515
+ export * from './types';
516
+ `;
517
+ var TEMPLATE_SHARED_INDEX_TS = `export * from './lib/api/create-api.js';
518
+ export * from './lib/stores/auth.store.js';
519
+ export * from './lib/stores/loading.store.js';
520
+ export * from './lib/i18n/create-i18n.js';
521
+ export * from './lib/i18n/keys.js';
522
+ export * from './lib/notify/use-notify.js';
523
+ export * from './lib/draft/index.js';
524
+ export * from './lib/landing/LandingPage.js';
525
+ export * from './lib/stores/theme.store.js';
526
+ `;
527
+ var SHADCN_MAIN_TSX = `import './globals.css';
528
+ import { StrictMode } from 'react';
529
+ import { createRoot } from 'react-dom/client';
530
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
531
+ import { RouterProvider, createRouter } from '@tanstack/react-router';
532
+ import {
533
+ createIcoreApi,
534
+ createIcoreI18n,
535
+ ICORE_LOCALES,
536
+ useThemeStore,
537
+ } from '@icore/template-shared';
538
+ import { I18nextProvider } from 'react-i18next';
539
+ import { Toaster } from 'sonner';
540
+ import { routeTree } from './routeTree.gen';
541
+ import { wireShadcnNotifier } from './lib/notify';
542
+
543
+ const queryClient = new QueryClient({
544
+ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },
545
+ });
546
+
547
+ const router = createRouter({ routeTree, context: { queryClient } });
548
+
549
+ declare module '@tanstack/react-router' {
550
+ interface Register {
551
+ router: typeof router;
552
+ }
553
+ }
554
+
555
+ const i18n = createIcoreI18n({ resources: ICORE_LOCALES });
556
+
557
+ // Single shared API instance \u2014 used by every query in src/queries/
558
+ export const api = createIcoreApi({
559
+ baseUrl: import.meta.env.VITE_API_URL ?? '/api',
560
+ });
561
+
562
+ wireShadcnNotifier();
563
+
564
+ // Apply the theme class before React mounts so the first paint is correct
565
+ const applyTheme = (mode: 'light' | 'dark') => {
566
+ document.documentElement.classList.toggle('dark', mode === 'dark');
567
+ };
568
+ applyTheme(useThemeStore.getState().mode);
569
+ useThemeStore.subscribe((s) => applyTheme(s.mode));
570
+
571
+ createRoot(document.getElementById('root')!).render(
572
+ <StrictMode>
573
+ <I18nextProvider i18n={i18n}>
574
+ <QueryClientProvider client={queryClient}>
575
+ <RouterProvider router={router} />
576
+ <Toaster richColors />
577
+ </QueryClientProvider>
578
+ </I18nextProvider>
579
+ </StrictMode>,
580
+ );
581
+ `;
582
+ var SHADCN_DASHBOARD_TSX = `import { createFileRoute, Outlet } from '@tanstack/react-router';
583
+ import { MainLayout } from '../layouts/MainLayout';
584
+
585
+ export const Route = createFileRoute('/_dashboard')({
586
+ component: () => (
587
+ <MainLayout>
588
+ <Outlet />
589
+ </MainLayout>
590
+ ),
591
+ });
592
+ `;
593
+ var SHADCN_INDEX_TSX = `import { createFileRoute } from '@tanstack/react-router';
594
+ import { LandingPage } from '@icore/template-shared';
595
+
596
+ // All version strings are injected at build time by vite.config.mts
597
+ // (reads root package.json via fs.readFileSync so they stay accurate
598
+ // even when workspace packages are bumped independently).
599
+ const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
600
+
601
+ export const Route = createFileRoute('/')({
602
+ component: () => (
603
+ <LandingPage
604
+ coreVersion={APP_VERSION}
605
+ uiLibrary="shadcn"
606
+ deps={[
607
+ { name: 'react', version: (import.meta.env.VITE_DEP_REACT as string) ?? '?' },
608
+ { name: 'vite', version: (import.meta.env.VITE_DEP_VITE as string) ?? '?' },
609
+ { name: 'tailwindcss', version: (import.meta.env.VITE_DEP_TAILWINDCSS as string) ?? '?' },
610
+ {
611
+ name: '@tanstack/react-router',
612
+ version: (import.meta.env.VITE_DEP_TANSTACK_ROUTER as string) ?? '?',
613
+ },
614
+ {
615
+ name: '@tanstack/react-query',
616
+ version: (import.meta.env.VITE_DEP_TANSTACK_QUERY as string) ?? '?',
617
+ },
618
+ { name: 'zustand', version: (import.meta.env.VITE_DEP_ZUSTAND as string) ?? '?' },
619
+ { name: '@casl/ability', version: (import.meta.env.VITE_DEP_CASL as string) ?? '?' },
620
+ ]}
621
+ ctaHref="/dashboard"
622
+ ctaLabel="Dashboard \u2192"
623
+ />
624
+ ),
625
+ });
626
+ `;
627
+ var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
628
+ import { ThemeToggle } from '../ThemeToggle';
629
+
630
+ const LOCALES: { code: IcoreLocale; label: string }[] = [
631
+ { code: 'en', label: 'EN' },
632
+ { code: 'ru', label: 'RU' },
633
+ { code: 'he', label: 'HE' },
634
+ ];
635
+
636
+ export function LayoutHeader() {
637
+ function handleLocale(code: IcoreLocale) {
638
+ setStoredLocale(code);
639
+ window.location.reload();
640
+ }
641
+
642
+ return (
643
+ <header className="sticky top-0 z-30 flex h-14 items-center justify-between border-b border-[--color-border] bg-[--color-background]/80 px-4 backdrop-blur-sm">
644
+ <div className="flex items-center gap-2">
645
+ <div className="flex h-6 w-6 items-center justify-center rounded bg-[--color-primary]">
646
+ <span className="text-xs font-bold text-[--color-primary-foreground]">i</span>
647
+ </div>
648
+ <span className="text-sm font-semibold tracking-tight">iCore</span>
649
+ </div>
650
+
651
+ <div className="flex items-center gap-1">
652
+ <div className="flex items-center rounded-md border border-[--color-border] overflow-hidden mr-2">
653
+ {LOCALES.map(({ code, label }) => (
654
+ <button
655
+ key={code}
656
+ type="button"
657
+ onClick={() => handleLocale(code)}
658
+ className="px-2.5 py-1 text-xs text-[--color-muted-foreground] hover:bg-[--color-muted] hover:text-[--color-foreground] transition-colors cursor-pointer"
659
+ >
660
+ {label}
661
+ </button>
662
+ ))}
663
+ </div>
664
+
665
+ <ThemeToggle />
666
+ </div>
667
+ </header>
668
+ );
669
+ }
670
+ `;
671
+ var ANTD_MAIN_TSX = `import './globals.less';
672
+ import { StrictMode } from 'react';
673
+ import { createRoot } from 'react-dom/client';
674
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
675
+ import { RouterProvider, createRouter } from '@tanstack/react-router';
676
+ import { ConfigProvider, App as AntApp, theme } from 'antd';
677
+ import { I18nextProvider } from 'react-i18next';
678
+ import {
679
+ createIcoreApi,
680
+ createIcoreI18n,
681
+ ICORE_LOCALES,
682
+ useThemeStore,
683
+ } from '@icore/template-shared';
684
+ import { routeTree } from './routeTree.gen';
685
+
686
+ const queryClient = new QueryClient({
687
+ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },
688
+ });
689
+
690
+ const router = createRouter({ routeTree, context: { queryClient } });
691
+
692
+ declare module '@tanstack/react-router' {
693
+ interface Register {
694
+ router: typeof router;
695
+ }
696
+ }
697
+
698
+ const i18n = createIcoreI18n({ resources: ICORE_LOCALES });
699
+
700
+ // Single shared API instance \u2014 used by every query in src/queries/
701
+ export const api = createIcoreApi({
702
+ baseUrl: import.meta.env.VITE_API_URL ?? '/api',
703
+ });
704
+
705
+ function Root() {
706
+ const mode = useThemeStore((s) => s.mode);
707
+ const algorithm = mode === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm;
708
+ return (
709
+ <ConfigProvider theme={{ algorithm, token: { colorPrimary: '#22c55e', colorLink: '#22c55e' } }}>
710
+ <AntApp>
711
+ <QueryClientProvider client={queryClient}>
712
+ <RouterProvider router={router} />
713
+ </QueryClientProvider>
714
+ </AntApp>
715
+ </ConfigProvider>
716
+ );
717
+ }
718
+
719
+ createRoot(document.getElementById('root')!).render(
720
+ <StrictMode>
721
+ <I18nextProvider i18n={i18n}>
722
+ <Root />
723
+ </I18nextProvider>
724
+ </StrictMode>,
725
+ );
726
+ `;
727
+ var ANTD_DASHBOARD_TSX = `import { createFileRoute, Outlet } from '@tanstack/react-router';
728
+ import { MainLayout } from '../layouts/MainLayout';
729
+
730
+ export const Route = createFileRoute('/_dashboard')({
731
+ component: () => (
732
+ <MainLayout>
733
+ <Outlet />
734
+ </MainLayout>
735
+ ),
736
+ });
737
+ `;
738
+ var ANTD_INDEX_TSX = `import { createFileRoute, Link } from '@tanstack/react-router';
739
+ import { LandingPage } from '@icore/template-shared';
740
+
741
+ // All version strings are injected at build time by vite.config.mts
742
+ // (reads root package.json via fs.readFileSync so they stay accurate
743
+ // even when workspace packages are bumped independently).
744
+ const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
745
+
746
+ export const Route = createFileRoute('/')({
747
+ component: () => (
748
+ <LandingPage
749
+ coreVersion={APP_VERSION}
750
+ uiLibrary="antd"
751
+ deps={[
752
+ { name: 'react', version: (import.meta.env.VITE_DEP_REACT as string) ?? '?' },
753
+ { name: 'antd', version: (import.meta.env.VITE_DEP_ANTD as string) ?? '?' },
754
+ { name: 'vite', version: (import.meta.env.VITE_DEP_VITE as string) ?? '?' },
755
+ {
756
+ name: '@tanstack/react-router',
757
+ version: (import.meta.env.VITE_DEP_TANSTACK_ROUTER as string) ?? '?',
758
+ },
759
+ {
760
+ name: '@tanstack/react-query',
761
+ version: (import.meta.env.VITE_DEP_TANSTACK_QUERY as string) ?? '?',
762
+ },
763
+ { name: 'zustand', version: (import.meta.env.VITE_DEP_ZUSTAND as string) ?? '?' },
764
+ { name: '@casl/ability', version: (import.meta.env.VITE_DEP_CASL as string) ?? '?' },
765
+ ]}
766
+ ctaHref="/dashboard"
767
+ ctaLabel={<Link to="/dashboard">Dashboard \u2192</Link>}
768
+ />
769
+ ),
770
+ });
771
+ `;
772
+ var ANTD_LAYOUT_HEADER_TSX = `import { Button, Layout, Space } from 'antd';
773
+ import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
774
+ import { ThemeToggle } from '../ThemeToggle';
775
+
776
+ const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
777
+
778
+ const LOCALES: { code: IcoreLocale; label: string }[] = [
779
+ { code: 'en', label: 'EN' },
780
+ { code: 'ru', label: 'RU' },
781
+ { code: 'he', label: 'HE' },
782
+ ];
783
+
784
+ export function LayoutHeader() {
785
+ function handleLocale(code: IcoreLocale) {
786
+ setStoredLocale(code);
787
+ window.location.reload();
788
+ }
789
+
790
+ return (
791
+ <Layout.Header
792
+ style={{
793
+ display: 'flex',
794
+ alignItems: 'center',
795
+ justifyContent: 'space-between',
796
+ padding: '0 24px',
797
+ }}
798
+ >
799
+ <Space>
800
+ <span style={{ color: '#fff', fontWeight: 600, fontSize: 16 }}>iCore</span>
801
+ <span
802
+ style={{
803
+ color: 'rgba(255,255,255,0.45)',
804
+ fontSize: 11,
805
+ background: 'rgba(255,255,255,0.1)',
806
+ padding: '1px 6px',
807
+ borderRadius: 4,
808
+ }}
809
+ >
810
+ v{APP_VERSION}
811
+ </span>
812
+ </Space>
813
+
814
+ <Space size="middle">
815
+ <Space size={4}>
816
+ {LOCALES.map(({ code, label }) => (
817
+ <Button
818
+ key={code}
819
+ size="small"
820
+ type="text"
821
+ style={{ color: 'rgba(255,255,255,0.65)' }}
822
+ onClick={() => handleLocale(code)}
823
+ >
824
+ {label}
825
+ </Button>
826
+ ))}
827
+ </Space>
828
+
829
+ <ThemeToggle />
830
+ </Space>
831
+ </Layout.Header>
832
+ );
833
+ }
834
+ `;
835
+ var MUI_MAIN_TSX = `import './globals.css';
836
+ import { StrictMode, useMemo } from 'react';
837
+ import { createRoot } from 'react-dom/client';
838
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
839
+ import { RouterProvider, createRouter } from '@tanstack/react-router';
840
+ import { CssBaseline, ThemeProvider, createTheme } from '@mui/material';
841
+ import { I18nextProvider } from 'react-i18next';
842
+ import {
843
+ createIcoreApi,
844
+ createIcoreI18n,
845
+ ICORE_LOCALES,
846
+ useThemeStore,
847
+ } from '@icore/template-shared';
848
+ import { routeTree } from './routeTree.gen';
849
+ import { wireMuiNotifier } from './lib/notify';
850
+
851
+ const queryClient = new QueryClient({
852
+ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },
853
+ });
854
+
855
+ const router = createRouter({ routeTree, context: { queryClient } });
856
+
857
+ declare module '@tanstack/react-router' {
858
+ interface Register {
859
+ router: typeof router;
860
+ }
861
+ }
862
+
863
+ const i18n = createIcoreI18n({ resources: ICORE_LOCALES });
864
+
865
+ export const api = createIcoreApi({
866
+ baseUrl: import.meta.env.VITE_API_URL ?? '/api',
867
+ });
868
+
869
+ wireMuiNotifier();
870
+
871
+ function Root() {
872
+ const mode = useThemeStore((s) => s.mode);
873
+ const theme = useMemo(
874
+ () => createTheme({ palette: { mode, primary: { main: '#22c55e' } } }),
875
+ [mode],
876
+ );
877
+ return (
878
+ <ThemeProvider theme={theme}>
879
+ <CssBaseline />
880
+ <QueryClientProvider client={queryClient}>
881
+ <RouterProvider router={router} />
882
+ </QueryClientProvider>
883
+ </ThemeProvider>
884
+ );
885
+ }
886
+
887
+ createRoot(document.getElementById('root')!).render(
888
+ <StrictMode>
889
+ <I18nextProvider i18n={i18n}>
890
+ <Root />
891
+ </I18nextProvider>
892
+ </StrictMode>,
893
+ );
894
+ `;
895
+ var MUI_DASHBOARD_TSX = `import { createFileRoute, Outlet } from '@tanstack/react-router';
896
+ import { MainLayout } from '../layouts/MainLayout';
897
+
898
+ export const Route = createFileRoute('/_dashboard')({
899
+ component: () => (
900
+ <MainLayout>
901
+ <Outlet />
902
+ </MainLayout>
903
+ ),
904
+ });
905
+ `;
906
+ var MUI_INDEX_TSX = `import { createFileRoute, Link } from '@tanstack/react-router';
907
+ import { LandingPage } from '@icore/template-shared';
908
+
909
+ // All version strings are injected at build time by vite.config.mts
910
+ // (reads root package.json via fs.readFileSync so they stay accurate
911
+ // even when workspace packages are bumped independently).
912
+ const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
913
+
914
+ export const Route = createFileRoute('/')({
915
+ component: () => (
916
+ <LandingPage
917
+ coreVersion={APP_VERSION}
918
+ uiLibrary="mui"
919
+ deps={[
920
+ { name: 'react', version: (import.meta.env.VITE_DEP_REACT as string) ?? '?' },
921
+ { name: '@mui/material', version: (import.meta.env.VITE_DEP_MUI as string) ?? '?' },
922
+ { name: 'vite', version: (import.meta.env.VITE_DEP_VITE as string) ?? '?' },
923
+ {
924
+ name: '@tanstack/react-router',
925
+ version: (import.meta.env.VITE_DEP_TANSTACK_ROUTER as string) ?? '?',
926
+ },
927
+ {
928
+ name: '@tanstack/react-query',
929
+ version: (import.meta.env.VITE_DEP_TANSTACK_QUERY as string) ?? '?',
930
+ },
931
+ { name: 'zustand', version: (import.meta.env.VITE_DEP_ZUSTAND as string) ?? '?' },
932
+ { name: '@casl/ability', version: (import.meta.env.VITE_DEP_CASL as string) ?? '?' },
933
+ ]}
934
+ ctaHref="/dashboard"
935
+ ctaLabel={<Link to="/dashboard">Dashboard \u2192</Link>}
936
+ />
937
+ ),
938
+ });
939
+ `;
940
+ var MUI_LAYOUT_HEADER_TSX = `import { AppBar, Box, Button, Toolbar, Typography } from '@mui/material';
941
+ import { useTranslation } from 'react-i18next';
942
+ import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
943
+ import { ThemeToggle } from '../ThemeToggle';
944
+
945
+ const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
946
+
947
+ const LOCALES: { code: IcoreLocale; label: string }[] = [
948
+ { code: 'en', label: 'EN' },
949
+ { code: 'ru', label: 'RU' },
950
+ { code: 'he', label: 'HE' },
951
+ ];
952
+
953
+ export function LayoutHeader() {
954
+ const { i18n } = useTranslation();
955
+ const currentLocale = i18n.language as IcoreLocale;
956
+
957
+ function handleLocale(code: IcoreLocale) {
958
+ setStoredLocale(code);
959
+ window.location.reload();
960
+ }
961
+
962
+ return (
963
+ <AppBar position="sticky" color="default" elevation={1}>
964
+ <Toolbar sx={{ justifyContent: 'space-between' }}>
965
+ <Typography variant="h6" component="div" fontWeight={600}>
966
+ iCore{' '}
967
+ <span style={{ opacity: 0.6, fontSize: '0.75em', fontWeight: 400 }}>v{APP_VERSION}</span>
968
+ </Typography>
969
+
970
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
971
+ <Box sx={{ display: 'flex', gap: 0.5 }}>
972
+ {LOCALES.map(({ code, label }) => (
973
+ <Button
974
+ key={code}
975
+ size="small"
976
+ variant={currentLocale === code ? 'contained' : 'text'}
977
+ onClick={() => handleLocale(code)}
978
+ >
979
+ {label}
980
+ </Button>
981
+ ))}
982
+ </Box>
983
+
984
+ <ThemeToggle />
985
+ </Box>
986
+ </Toolbar>
987
+ </AppBar>
988
+ );
989
+ }
990
+ `;
991
+ var COMMON_VARIANTS = {
992
+ "apps/api/src/main.ts": GATEWAY_MAIN_TS,
993
+ "apps/api/src/app/app.module.ts": GATEWAY_APP_MODULE_TS,
994
+ "libs/shared/src/client.ts": SHARED_CLIENT_TS,
995
+ "libs/shared/src/index.ts": SHARED_INDEX_TS,
996
+ "libs/template-shared/src/index.ts": TEMPLATE_SHARED_INDEX_TS
997
+ };
998
+ var UI_VARIANTS = {
999
+ shadcn: {
1000
+ "apps/client/src/main.tsx": SHADCN_MAIN_TSX,
1001
+ "apps/client/src/routes/_dashboard.tsx": SHADCN_DASHBOARD_TSX,
1002
+ "apps/client/src/routes/index.tsx": SHADCN_INDEX_TSX,
1003
+ "apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX
1004
+ },
1005
+ antd: {
1006
+ "apps/client/src/main.tsx": ANTD_MAIN_TSX,
1007
+ "apps/client/src/routes/_dashboard.tsx": ANTD_DASHBOARD_TSX,
1008
+ "apps/client/src/routes/index.tsx": ANTD_INDEX_TSX,
1009
+ "apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX
1010
+ },
1011
+ mui: {
1012
+ "apps/client/src/main.tsx": MUI_MAIN_TSX,
1013
+ "apps/client/src/routes/_dashboard.tsx": MUI_DASHBOARD_TSX,
1014
+ "apps/client/src/routes/index.tsx": MUI_INDEX_TSX,
1015
+ "apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX
1016
+ }
1017
+ };
1018
+ async function applyAuthNoneVariants(targetDir, ui) {
1019
+ const uiFiles = UI_VARIANTS[ui] ?? UI_VARIANTS["shadcn"];
1020
+ const all = { ...COMMON_VARIANTS, ...uiFiles };
1021
+ for (const [rel, content] of Object.entries(all)) {
1022
+ const dest = (0, import_node_path3.join)(targetDir, rel);
1023
+ try {
1024
+ await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(dest), { recursive: true });
1025
+ await (0, import_promises3.writeFile)(dest, content);
1026
+ } catch {
1027
+ }
1028
+ }
1029
+ }
1030
+
478
1031
  // src/manifest/wire-features.ts
479
- var import_promises4 = require("fs/promises");
480
- var import_node_path4 = require("path");
1032
+ var import_promises5 = require("fs/promises");
1033
+ var import_node_path5 = require("path");
481
1034
 
482
1035
  // src/manifest/index.ts
483
1036
  var EMPTY = { libDirs: [], deps: {}, tsPaths: {} };
@@ -637,8 +1190,8 @@ var MANIFEST = {
637
1190
  };
638
1191
 
639
1192
  // src/manifest/wire-provider.ts
640
- var import_promises3 = require("fs/promises");
641
- var import_node_path3 = require("path");
1193
+ var import_promises4 = require("fs/promises");
1194
+ var import_node_path4 = require("path");
642
1195
  async function writeProvider(targetDir, axis, provider) {
643
1196
  const nestModule = axis.section[provider]?.nestModule;
644
1197
  if (!nestModule) throw new Error(`provider "${provider}" has no nestModule in the manifest`);
@@ -649,27 +1202,27 @@ const ENV_PATH = '${axis.envPath}';
649
1202
 
650
1203
  export const ${axis.exportConst} = ${symbol}.forRoot(ENV_PATH);
651
1204
  `;
652
- await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, axis.providerFile), content);
1205
+ await (0, import_promises4.writeFile)((0, import_node_path4.join)(targetDir, axis.providerFile), content);
653
1206
  }
654
1207
  async function stripJsonKeys(path, drop) {
655
1208
  try {
656
- const pkg = JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
1209
+ const pkg = JSON.parse(await (0, import_promises4.readFile)(path, "utf8"));
657
1210
  for (const field of ["dependencies", "devDependencies"]) {
658
1211
  const deps = pkg[field];
659
1212
  if (!deps) continue;
660
1213
  for (const k of Object.keys(deps)) if (drop(k)) delete deps[k];
661
1214
  }
662
- await (0, import_promises3.writeFile)(path, JSON.stringify(pkg, null, 2) + "\n");
1215
+ await (0, import_promises4.writeFile)(path, JSON.stringify(pkg, null, 2) + "\n");
663
1216
  } catch {
664
1217
  }
665
1218
  }
666
1219
  async function stripTsconfigKeys(targetDir, aliases) {
667
- const path = (0, import_node_path3.join)(targetDir, "tsconfig.base.json");
1220
+ const path = (0, import_node_path4.join)(targetDir, "tsconfig.base.json");
668
1221
  try {
669
- const parsed = JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
1222
+ const parsed = JSON.parse(await (0, import_promises4.readFile)(path, "utf8"));
670
1223
  const paths = parsed.compilerOptions?.paths;
671
1224
  if (paths) for (const a of aliases) delete paths[a];
672
- await (0, import_promises3.writeFile)(path, JSON.stringify(parsed, null, 2) + "\n");
1225
+ await (0, import_promises4.writeFile)(path, JSON.stringify(parsed, null, 2) + "\n");
673
1226
  } catch {
674
1227
  }
675
1228
  }
@@ -678,10 +1231,10 @@ async function cleanupUnusedAxis(targetDir, axis, chosen) {
678
1231
  if (provider === chosen) continue;
679
1232
  const unit = axis.section[provider];
680
1233
  for (const dir of unit.libDirs)
681
- await (0, import_promises3.rm)((0, import_node_path3.join)(targetDir, dir), { recursive: true, force: true });
682
- for (const t of unit.appTests ?? []) await (0, import_promises3.rm)((0, import_node_path3.join)(targetDir, t), { force: true });
1234
+ await (0, import_promises4.rm)((0, import_node_path4.join)(targetDir, dir), { recursive: true, force: true });
1235
+ for (const t of unit.appTests ?? []) await (0, import_promises4.rm)((0, import_node_path4.join)(targetDir, t), { force: true });
683
1236
  const dropKeys = /* @__PURE__ */ new Set([...Object.keys(unit.tsPaths), ...Object.keys(unit.deps)]);
684
- await stripJsonKeys((0, import_node_path3.join)(targetDir, axis.msPackageJson), (k) => dropKeys.has(k));
1237
+ await stripJsonKeys((0, import_node_path4.join)(targetDir, axis.msPackageJson), (k) => dropKeys.has(k));
685
1238
  await stripTsconfigKeys(targetDir, Object.keys(unit.tsPaths));
686
1239
  }
687
1240
  }
@@ -710,7 +1263,7 @@ async function writeFeaturesWiring(targetDir, opts) {
710
1263
  })
711
1264
  export class FeaturesModule {}
712
1265
  `;
713
- await (0, import_promises4.writeFile)((0, import_node_path4.join)(targetDir, FEATURES_MODULE), featuresModule);
1266
+ await (0, import_promises5.writeFile)((0, import_node_path5.join)(targetDir, FEATURES_MODULE), featuresModule);
714
1267
  const services = [];
715
1268
  if (opts.authProvider !== "none") services.push({ name: "auth", prefix: "AUTH" });
716
1269
  if (opts.upload !== "none") services.push({ name: "upload", prefix: "UPLOAD" });
@@ -724,14 +1277,14 @@ export const GATEWAY_SERVICES = [
724
1277
  ${entries}
725
1278
  ];
726
1279
  `;
727
- await (0, import_promises4.writeFile)((0, import_node_path4.join)(targetDir, GATEWAY_SERVICES), gatewayServices);
1280
+ await (0, import_promises5.writeFile)((0, import_node_path5.join)(targetDir, GATEWAY_SERVICES), gatewayServices);
728
1281
  }
729
1282
  async function stripJobsDockerCompose(targetDir) {
730
- const composePath = (0, import_node_path4.join)(targetDir, "docker-compose.yml");
1283
+ const composePath = (0, import_node_path5.join)(targetDir, "docker-compose.yml");
731
1284
  try {
732
- const compose = await (0, import_promises4.readFile)(composePath, "utf8");
1285
+ const compose = await (0, import_promises5.readFile)(composePath, "utf8");
733
1286
  const next = compose.replace(/\n {2}jobs:[\s\S]+?(?=\n {2}\w+:|\nnetworks:)/m, "\n").replace(/\n {6}jobs:\n {8}condition: service_started/g, "").replace(/\n {6}JOBS_REDIS_URL:[^\n]*/g, "");
734
- await (0, import_promises4.writeFile)(composePath, next);
1287
+ await (0, import_promises5.writeFile)(composePath, next);
735
1288
  } catch {
736
1289
  }
737
1290
  }
@@ -741,34 +1294,38 @@ async function cleanupUnusedFeatures(targetDir, opts) {
741
1294
  if (chosen.has(key)) continue;
742
1295
  const unit = FEATURES[key];
743
1296
  for (const dir of unit.libDirs)
744
- await (0, import_promises4.rm)((0, import_node_path4.join)(targetDir, dir), { recursive: true, force: true });
1297
+ await (0, import_promises5.rm)((0, import_node_path5.join)(targetDir, dir), { recursive: true, force: true });
745
1298
  const dropKeys = /* @__PURE__ */ new Set([...Object.keys(unit.tsPaths), ...Object.keys(unit.deps)]);
746
- await stripJsonKeys((0, import_node_path4.join)(targetDir, API_PKG), (k) => dropKeys.has(k));
1299
+ await stripJsonKeys((0, import_node_path5.join)(targetDir, API_PKG), (k) => dropKeys.has(k));
747
1300
  await stripTsconfigKeys(targetDir, Object.keys(unit.tsPaths));
748
1301
  if (unit.gatewayService) await stripGatewayTransport(targetDir, unit.gatewayService.prefix);
749
1302
  if (unit.dockerService === "jobs") await stripJobsDockerCompose(targetDir);
750
1303
  if (key === "jobs") {
751
1304
  try {
752
- await (0, import_promises4.unlink)((0, import_node_path4.join)(targetDir, "libs/shared/src/jobs.ts"));
1305
+ await (0, import_promises5.unlink)((0, import_node_path5.join)(targetDir, "libs/shared/src/jobs.ts"));
753
1306
  } catch {
754
1307
  }
755
- const sharedIdx = (0, import_node_path4.join)(targetDir, "libs/shared/src/index.ts");
756
1308
  try {
757
- const src = await (0, import_promises4.readFile)(sharedIdx, "utf8");
758
- await (0, import_promises4.writeFile)(sharedIdx, src.replace(/^export \* from '\.\/jobs';\n/m, ""));
1309
+ await (0, import_promises5.unlink)((0, import_node_path5.join)(targetDir, "libs/shared/src/__tests__/jobs.unit.test.ts"));
1310
+ } catch {
1311
+ }
1312
+ const sharedIdx = (0, import_node_path5.join)(targetDir, "libs/shared/src/index.ts");
1313
+ try {
1314
+ const src = await (0, import_promises5.readFile)(sharedIdx, "utf8");
1315
+ await (0, import_promises5.writeFile)(sharedIdx, src.replace(/^export \* from '\.\/jobs';\n/m, ""));
759
1316
  } catch {
760
1317
  }
761
1318
  }
762
1319
  }
763
1320
  try {
764
- await (0, import_promises4.rmdir)((0, import_node_path4.join)(targetDir, "apps/client/src/queries"));
1321
+ await (0, import_promises5.rmdir)((0, import_node_path5.join)(targetDir, "apps/client/src/queries"));
765
1322
  } catch {
766
1323
  }
767
1324
  }
768
1325
 
769
1326
  // src/manifest/wire-client.ts
770
- var import_promises5 = require("fs/promises");
771
- var import_node_path5 = require("path");
1327
+ var import_promises6 = require("fs/promises");
1328
+ var import_node_path6 = require("path");
772
1329
  var NAV_CONFIG_FILE = "apps/client/src/nav.config.ts";
773
1330
  var BASE_NAV = [
774
1331
  { to: "/dashboard", labelKey: "nav.dashboard", iconName: "dashboard", exact: true }
@@ -806,12 +1363,12 @@ export const NAV_CONFIG: NavItem[] = [
806
1363
  ` + entries.map(renderEntry).join("\n") + `
807
1364
  ];
808
1365
  `;
809
- await (0, import_promises5.writeFile)((0, import_node_path5.join)(targetDir, NAV_CONFIG_FILE), content);
1366
+ await (0, import_promises6.writeFile)((0, import_node_path6.join)(targetDir, NAV_CONFIG_FILE), content);
810
1367
  }
811
1368
 
812
1369
  // src/manifest/blueprint.ts
813
- var import_promises6 = require("fs/promises");
814
- var import_node_path6 = require("path");
1370
+ var import_promises7 = require("fs/promises");
1371
+ var import_node_path7 = require("path");
815
1372
  async function writeBlueprintJson(targetDir, opts) {
816
1373
  const blueprint = {
817
1374
  schemaVersion: 1,
@@ -826,10 +1383,10 @@ async function writeBlueprintJson(targetDir, opts) {
826
1383
  transport: opts.transport,
827
1384
  packageManager: opts.packageManager
828
1385
  };
829
- await (0, import_promises6.writeFile)((0, import_node_path6.join)(targetDir, "blueprint.json"), JSON.stringify(blueprint, null, 2) + "\n");
1386
+ await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "blueprint.json"), JSON.stringify(blueprint, null, 2) + "\n");
830
1387
  }
831
1388
  async function writeJson(targetDir, rel, data) {
832
- await (0, import_promises6.writeFile)((0, import_node_path6.join)(targetDir, rel, "blueprint.json"), JSON.stringify(data, null, 2) + "\n");
1389
+ await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, rel, "blueprint.json"), JSON.stringify(data, null, 2) + "\n");
833
1390
  }
834
1391
  async function writeServiceBlueprints(targetDir, opts) {
835
1392
  const t = opts.transport;
@@ -923,11 +1480,11 @@ var writeDbProvider = (targetDir, provider) => writeProvider(targetDir, DB, prov
923
1480
  var cleanupUnusedDb = (targetDir, chosen) => cleanupUnusedAxis(targetDir, DB, chosen);
924
1481
 
925
1482
  // src/lib/scaffold-pkg.ts
926
- var import_promises7 = require("fs/promises");
927
- var import_node_path7 = require("path");
1483
+ var import_promises8 = require("fs/promises");
1484
+ var import_node_path8 = require("path");
928
1485
  async function writePnpmWorkspace(targetDir) {
929
- const pkgPath = (0, import_node_path7.join)(targetDir, "package.json");
930
- const pkg = JSON.parse(await (0, import_promises7.readFile)(pkgPath, "utf8"));
1486
+ const pkgPath = (0, import_node_path8.join)(targetDir, "package.json");
1487
+ const pkg = JSON.parse(await (0, import_promises8.readFile)(pkgPath, "utf8"));
931
1488
  const workspaces = pkg.workspaces ?? [];
932
1489
  const packagesBlock = workspaces.map((p2) => ` - '${p2}'`).join("\n");
933
1490
  const allowBuilds = [
@@ -950,22 +1507,22 @@ ${packagesBlock}
950
1507
  allowBuilds:
951
1508
  ${allowBuilds}
952
1509
  `;
953
- await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "pnpm-workspace.yaml"), content);
1510
+ await (0, import_promises8.writeFile)((0, import_node_path8.join)(targetDir, "pnpm-workspace.yaml"), content);
954
1511
  }
955
1512
  async function rewritePnpmWorkspaceDeps(targetDir) {
956
1513
  async function walk2(dir) {
957
1514
  const found = [];
958
1515
  let entries;
959
1516
  try {
960
- entries = await (0, import_promises7.readdir)(dir, { withFileTypes: true });
1517
+ entries = await (0, import_promises8.readdir)(dir, { withFileTypes: true });
961
1518
  } catch {
962
1519
  return found;
963
1520
  }
964
1521
  for (const e of entries) {
965
1522
  if (e.isDirectory() && e.name !== "node_modules") {
966
- found.push(...await walk2((0, import_node_path7.join)(dir, e.name)));
1523
+ found.push(...await walk2((0, import_node_path8.join)(dir, e.name)));
967
1524
  } else if (e.isFile() && e.name === "package.json") {
968
- found.push((0, import_node_path7.join)(dir, e.name));
1525
+ found.push((0, import_node_path8.join)(dir, e.name));
969
1526
  }
970
1527
  }
971
1528
  return found;
@@ -973,17 +1530,17 @@ async function rewritePnpmWorkspaceDeps(targetDir) {
973
1530
  const pkgFiles = await walk2(targetDir);
974
1531
  for (const f of pkgFiles) {
975
1532
  try {
976
- const raw = await (0, import_promises7.readFile)(f, "utf8");
1533
+ const raw = await (0, import_promises8.readFile)(f, "utf8");
977
1534
  const next = raw.replace(/"(@icore\/[^"]+)":\s*"\*"/g, '"$1": "workspace:*"');
978
- if (next !== raw) await (0, import_promises7.writeFile)(f, next);
1535
+ if (next !== raw) await (0, import_promises8.writeFile)(f, next);
979
1536
  } catch {
980
1537
  }
981
1538
  }
982
1539
  }
983
1540
  async function patchGitignoreForPm(targetDir, pm) {
984
- const giPath = (0, import_node_path7.join)(targetDir, ".gitignore");
1541
+ const giPath = (0, import_node_path8.join)(targetDir, ".gitignore");
985
1542
  try {
986
- let src = await (0, import_promises7.readFile)(giPath, "utf8");
1543
+ let src = await (0, import_promises8.readFile)(giPath, "utf8");
987
1544
  src = src.replace(/^# Build artifacts.*\ntools\/create-icore\/templates\/\s*\n/m, "");
988
1545
  if (pm !== "yarn") {
989
1546
  src = src.replace(/^\.yarn\/\*\s*\n/m, "").replace(/^!\.yarn\/patches\s*\n/m, "").replace(/^!\.yarn\/plugins\s*\n/m, "").replace(/^!\.yarn\/releases\s*\n/m, "").replace(/^!\.yarn\/sdks\s*\n/m, "").replace(/^!\.yarn\/versions\s*\n/m, "").replace(/^\.pnp\.\*\s*\n/m, "");
@@ -998,7 +1555,7 @@ async function patchGitignoreForPm(targetDir, pm) {
998
1555
  src += "\n# npm\nnpm-debug.log*\n";
999
1556
  }
1000
1557
  }
1001
- await (0, import_promises7.writeFile)(giPath, src);
1558
+ await (0, import_promises8.writeFile)(giPath, src);
1002
1559
  } catch {
1003
1560
  }
1004
1561
  }
@@ -1014,7 +1571,7 @@ async function writeAiFiles(targetDir, opts) {
1014
1571
  if (opts.jobs !== "none") activeMSes.push(`jobs (standalone)`);
1015
1572
  const usesSupabase = opts.authProvider === "supabase" || opts.dbProvider === "supabase" || opts.upload === "supabase";
1016
1573
  const usesFirebase = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
1017
- await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
1574
+ await (0, import_promises8.writeFile)((0, import_node_path8.join)(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
1018
1575
  const uiLabel = { shadcn: "shadcn/ui + Tailwind", antd: "Ant Design 6", mui: "MUI 6" }[opts.ui];
1019
1576
  const readme = `# ${opts.projectName}
1020
1577
 
@@ -1062,7 +1619,7 @@ ${pm === "yarn" ? "yarn remove-notes" : pm === "pnpm" ? "pnpm remove-notes" : "n
1062
1619
 
1063
1620
  Apache-2.0
1064
1621
  `;
1065
- await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "README.md"), readme);
1622
+ await (0, import_promises8.writeFile)((0, import_node_path8.join)(targetDir, "README.md"), readme);
1066
1623
  const agents = `# ${opts.projectName} \u2014 Agent Instructions
1067
1624
 
1068
1625
  ## Stack snapshot
@@ -1143,8 +1700,8 @@ ${opts.authProvider !== "none" ? `| \`apps/microservices/auth/.env\` | \`AUTH_PR
1143
1700
  - Test behaviour, not implementation. Fake strategies from \`@icore/shared\` (FakeAuthStrategy etc.) serve as test doubles.
1144
1701
  - Run: \`${nx} test <project>\`
1145
1702
  `;
1146
- await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "AGENTS.md"), agents);
1147
- await (0, import_promises7.mkdir)((0, import_node_path7.join)(targetDir, ".claude"), { recursive: true });
1703
+ await (0, import_promises8.writeFile)((0, import_node_path8.join)(targetDir, "AGENTS.md"), agents);
1704
+ await (0, import_promises8.mkdir)((0, import_node_path8.join)(targetDir, ".claude"), { recursive: true });
1148
1705
  const mcpServers = {
1149
1706
  nx: {
1150
1707
  command: "npx",
@@ -1185,8 +1742,8 @@ ${opts.authProvider !== "none" ? `| \`apps/microservices/auth/.env\` | \`AUTH_PR
1185
1742
  ]
1186
1743
  }
1187
1744
  };
1188
- await (0, import_promises7.writeFile)(
1189
- (0, import_node_path7.join)(targetDir, ".claude", "settings.json"),
1745
+ await (0, import_promises8.writeFile)(
1746
+ (0, import_node_path8.join)(targetDir, ".claude", "settings.json"),
1190
1747
  JSON.stringify(settings, null, 2) + "\n"
1191
1748
  );
1192
1749
  }
@@ -1206,30 +1763,30 @@ var IGNORE_TOP = /* @__PURE__ */ new Set([
1206
1763
  ".vscode"
1207
1764
  ]);
1208
1765
  async function copyTree(src, dest) {
1209
- await (0, import_promises8.mkdir)(dest, { recursive: true });
1210
- const entries = await (0, import_promises8.readdir)(src, { withFileTypes: true });
1766
+ await (0, import_promises9.mkdir)(dest, { recursive: true });
1767
+ const entries = await (0, import_promises9.readdir)(src, { withFileTypes: true });
1211
1768
  for (const entry of entries) {
1212
1769
  if (IGNORE_TOP.has(entry.name)) continue;
1213
- const s = (0, import_node_path8.join)(src, entry.name);
1214
- const d = (0, import_node_path8.join)(dest, entry.name);
1770
+ const s = (0, import_node_path9.join)(src, entry.name);
1771
+ const d = (0, import_node_path9.join)(dest, entry.name);
1215
1772
  if (entry.isDirectory()) await copyTree(s, d);
1216
- else if (entry.isFile()) await (0, import_promises8.copyFile)(s, d);
1773
+ else if (entry.isFile()) await (0, import_promises9.copyFile)(s, d);
1217
1774
  }
1218
1775
  }
1219
1776
  async function selectClientTemplate(targetDir, opts) {
1220
- const templatesRoot = (0, import_node_path8.join)(targetDir, "apps/templates");
1221
- const chosen = (0, import_node_path8.join)(templatesRoot, `client-${opts.ui}`);
1222
- const destClient = (0, import_node_path8.join)(targetDir, "apps/client");
1777
+ const templatesRoot = (0, import_node_path9.join)(targetDir, "apps/templates");
1778
+ const chosen = (0, import_node_path9.join)(templatesRoot, `client-${opts.ui}`);
1779
+ const destClient = (0, import_node_path9.join)(targetDir, "apps/client");
1223
1780
  let chosenUi = opts.ui;
1224
1781
  try {
1225
- const s = await (0, import_promises8.stat)(chosen);
1782
+ const s = await (0, import_promises9.stat)(chosen);
1226
1783
  if (!s.isDirectory()) throw new Error("not a dir");
1227
1784
  await copyTree(chosen, destClient);
1228
1785
  } catch {
1229
1786
  chosenUi = "shadcn";
1230
- await copyTree((0, import_node_path8.join)(templatesRoot, "client-shadcn"), destClient);
1787
+ await copyTree((0, import_node_path9.join)(templatesRoot, "client-shadcn"), destClient);
1231
1788
  }
1232
- await (0, import_promises8.rm)(templatesRoot, { recursive: true, force: true });
1789
+ await (0, import_promises9.rm)(templatesRoot, { recursive: true, force: true });
1233
1790
  await rewriteClientPaths(destClient, chosenUi);
1234
1791
  }
1235
1792
  async function rewriteClientPaths(clientDir, ui) {
@@ -1242,11 +1799,11 @@ async function rewriteClientPaths(clientDir, ui) {
1242
1799
  "eslint.config.mjs"
1243
1800
  ];
1244
1801
  for (const rel of candidates) {
1245
- const path = (0, import_node_path8.join)(clientDir, rel);
1802
+ const path = (0, import_node_path9.join)(clientDir, rel);
1246
1803
  try {
1247
- const raw = await (0, import_promises8.readFile)(path, "utf8");
1804
+ const raw = await (0, import_promises9.readFile)(path, "utf8");
1248
1805
  const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
1249
- if (next !== raw) await (0, import_promises8.writeFile)(path, next);
1806
+ if (next !== raw) await (0, import_promises9.writeFile)(path, next);
1250
1807
  } catch {
1251
1808
  }
1252
1809
  }
@@ -1262,12 +1819,12 @@ function gitInit(cwd, projectName) {
1262
1819
  }
1263
1820
  function resolveYarnBin(cwd) {
1264
1821
  try {
1265
- const yarnrc = (0, import_node_fs.readFileSync)((0, import_node_path8.join)(cwd, ".yarnrc.yml"), "utf8");
1822
+ const yarnrc = (0, import_node_fs.readFileSync)((0, import_node_path9.join)(cwd, ".yarnrc.yml"), "utf8");
1266
1823
  const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
1267
- if (match?.[1]) return (0, import_node_path8.join)(cwd, match[1].trim());
1824
+ if (match?.[1]) return (0, import_node_path9.join)(cwd, match[1].trim());
1268
1825
  } catch {
1269
1826
  }
1270
- return (0, import_node_path8.join)(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
1827
+ return (0, import_node_path9.join)(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
1271
1828
  }
1272
1829
  function runInstall(cwd, pm) {
1273
1830
  if (pm === "yarn") {
@@ -1290,6 +1847,10 @@ async function scaffold(rawOpts, templatesDir) {
1290
1847
  await writeRootEnv(opts.targetDir, opts);
1291
1848
  await selectClientTemplate(opts.targetDir, opts);
1292
1849
  await writeClientEnv(opts.targetDir);
1850
+ if (opts.authProvider === "none") {
1851
+ await removeAuthOnlyPaths(opts.targetDir);
1852
+ await applyAuthNoneVariants(opts.targetDir, opts.ui);
1853
+ }
1293
1854
  if (opts.upload === "none") await removeUploadStack(opts.targetDir);
1294
1855
  await cleanupUnusedFeatures(opts.targetDir, opts);
1295
1856
  await writeFeaturesWiring(opts.targetDir, opts);
@@ -1298,7 +1859,8 @@ async function scaffold(rawOpts, templatesDir) {
1298
1859
  await cleanupUnusedAuth(opts.targetDir, opts.authProvider);
1299
1860
  await writeAuthProvider(opts.targetDir, opts.authProvider);
1300
1861
  } else {
1301
- await removeAuthStack(opts.targetDir);
1862
+ await removeAuthTsconfigPaths(opts.targetDir);
1863
+ await removeDockerComposeAuthService(opts.targetDir);
1302
1864
  }
1303
1865
  if (opts.upload !== "none") {
1304
1866
  await cleanupUnusedStorage(opts.targetDir, opts.upload);
@@ -1311,25 +1873,28 @@ async function scaffold(rawOpts, templatesDir) {
1311
1873
  await writeDbProvider(opts.targetDir, opts.dbProvider);
1312
1874
  }
1313
1875
  await pruneRootProviderDeps(opts.targetDir, opts);
1314
- if (opts.authProvider === "none" && opts.upload === "none" && opts.dbProvider === "none") {
1876
+ if (opts.authProvider === "none" && opts.upload === "none" && opts.dbProvider === "none" && opts.payment === "none") {
1315
1877
  await removeStrategiesLib(opts.targetDir);
1316
1878
  }
1317
1879
  try {
1318
- await (0, import_promises8.rmdir)((0, import_node_path8.join)(opts.targetDir, "apps/microservices"));
1880
+ await (0, import_promises9.rmdir)((0, import_node_path9.join)(opts.targetDir, "apps/microservices"));
1319
1881
  } catch {
1320
1882
  }
1321
1883
  await writeBlueprintJson(opts.targetDir, opts);
1322
1884
  await writeServiceBlueprints(opts.targetDir, opts);
1323
1885
  if (opts.packageManager === "yarn") {
1324
- await (0, import_promises8.writeFile)((0, import_node_path8.join)(opts.targetDir, "yarn.lock"), "");
1886
+ await (0, import_promises9.writeFile)((0, import_node_path9.join)(opts.targetDir, "yarn.lock"), "");
1325
1887
  } else {
1326
- await (0, import_promises8.rm)((0, import_node_path8.join)(opts.targetDir, ".yarn"), { recursive: true, force: true });
1327
- await (0, import_promises8.rm)((0, import_node_path8.join)(opts.targetDir, ".yarnrc.yml"), { force: true });
1888
+ await (0, import_promises9.rm)((0, import_node_path9.join)(opts.targetDir, ".yarn"), { recursive: true, force: true });
1889
+ await (0, import_promises9.rm)((0, import_node_path9.join)(opts.targetDir, ".yarnrc.yml"), { force: true });
1328
1890
  }
1329
1891
  if (opts.packageManager === "pnpm") {
1330
1892
  await writePnpmWorkspace(opts.targetDir);
1331
1893
  await rewritePnpmWorkspaceDeps(opts.targetDir);
1332
1894
  }
1895
+ if (opts.packageManager === "npm") {
1896
+ await (0, import_promises9.writeFile)((0, import_node_path9.join)(opts.targetDir, ".npmrc"), "legacy-peer-deps=true\n");
1897
+ }
1333
1898
  await patchGitignoreForPm(opts.targetDir, opts.packageManager);
1334
1899
  await writeAiFiles(opts.targetDir, opts);
1335
1900
  if (opts.install) runInstall(opts.targetDir, opts.packageManager);
@@ -1338,13 +1903,13 @@ async function scaffold(rawOpts, templatesDir) {
1338
1903
 
1339
1904
  // src/lib/prompts.ts
1340
1905
  var p = __toESM(require("@clack/prompts"), 1);
1341
- var import_node_path9 = require("path");
1342
- var import_promises10 = require("fs/promises");
1343
1906
  var import_node_path10 = require("path");
1907
+ var import_promises11 = require("fs/promises");
1908
+ var import_node_path11 = require("path");
1344
1909
  var import_node_url = require("url");
1345
1910
 
1346
1911
  // src/lib/config.ts
1347
- var import_promises9 = require("fs/promises");
1912
+ var import_promises10 = require("fs/promises");
1348
1913
  var ConfigFileError = class extends Error {
1349
1914
  constructor(message) {
1350
1915
  super(message);
@@ -1415,7 +1980,7 @@ function validateConfig(raw) {
1415
1980
  async function loadConfig(filePath) {
1416
1981
  let raw;
1417
1982
  try {
1418
- raw = await (0, import_promises9.readFile)(filePath, "utf8");
1983
+ raw = await (0, import_promises10.readFile)(filePath, "utf8");
1419
1984
  } catch {
1420
1985
  throw new ConfigFileError(`config file not found: ${filePath}`);
1421
1986
  }
@@ -1440,8 +2005,8 @@ function detectPackageManager() {
1440
2005
  }
1441
2006
  async function readSelfVersion() {
1442
2007
  try {
1443
- const here = (0, import_node_path10.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
1444
- const pkgRaw = await (0, import_promises10.readFile)((0, import_node_path10.join)(here, "..", "package.json"), "utf8");
2008
+ const here = (0, import_node_path11.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
2009
+ const pkgRaw = await (0, import_promises11.readFile)((0, import_node_path11.join)(here, "..", "package.json"), "utf8");
1445
2010
  const pkg = JSON.parse(pkgRaw);
1446
2011
  return pkg.version ?? null;
1447
2012
  } catch {
@@ -1649,7 +2214,7 @@ Re-run with @latest to refresh:
1649
2214
  }) === false;
1650
2215
  return {
1651
2216
  projectName,
1652
- targetDir: (0, import_node_path9.resolve)(cwd, projectName),
2217
+ targetDir: (0, import_node_path10.resolve)(cwd, projectName),
1653
2218
  authProvider,
1654
2219
  dbProvider,
1655
2220
  upload,
@@ -1665,23 +2230,23 @@ Re-run with @latest to refresh:
1665
2230
  }
1666
2231
 
1667
2232
  // src/manifest/audit.ts
1668
- var import_promises11 = require("fs/promises");
1669
- var import_node_path11 = require("path");
2233
+ var import_promises12 = require("fs/promises");
2234
+ var import_node_path12 = require("path");
1670
2235
  var IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".nx"]);
1671
2236
  async function walk(dir, out = []) {
1672
- const entries = await (0, import_promises11.readdir)(dir, { withFileTypes: true });
2237
+ const entries = await (0, import_promises12.readdir)(dir, { withFileTypes: true });
1673
2238
  for (const e of entries) {
1674
2239
  if (e.isDirectory()) {
1675
- if (!IGNORE_DIRS.has(e.name)) await walk((0, import_node_path11.join)(dir, e.name), out);
2240
+ if (!IGNORE_DIRS.has(e.name)) await walk((0, import_node_path12.join)(dir, e.name), out);
1676
2241
  } else if (/\.(ts|tsx|mjs)$/.test(e.name)) {
1677
- out.push((0, import_node_path11.join)(dir, e.name));
2242
+ out.push((0, import_node_path12.join)(dir, e.name));
1678
2243
  }
1679
2244
  }
1680
2245
  return out;
1681
2246
  }
1682
2247
  async function tsconfigAliases(dir) {
1683
2248
  try {
1684
- const raw = await (0, import_promises11.readFile)((0, import_node_path11.join)(dir, "tsconfig.base.json"), "utf8");
2249
+ const raw = await (0, import_promises12.readFile)((0, import_node_path12.join)(dir, "tsconfig.base.json"), "utf8");
1685
2250
  const aliases = /* @__PURE__ */ new Set();
1686
2251
  for (const m of raw.matchAll(/"(@icore\/[a-z0-9.-]+)"\s*:/g)) {
1687
2252
  if (m[1]) aliases.add(m[1]);
@@ -1699,7 +2264,7 @@ var PROVIDER_SDKS = {
1699
2264
  };
1700
2265
  async function readBlueprint(dir) {
1701
2266
  try {
1702
- return JSON.parse(await (0, import_promises11.readFile)((0, import_node_path11.join)(dir, "blueprint.json"), "utf8"));
2267
+ return JSON.parse(await (0, import_promises12.readFile)((0, import_node_path12.join)(dir, "blueprint.json"), "utf8"));
1703
2268
  } catch {
1704
2269
  return null;
1705
2270
  }
@@ -1716,29 +2281,29 @@ function forbiddenFromBlueprint(bp) {
1716
2281
  }
1717
2282
  async function allPackageJsons(dir) {
1718
2283
  const out = [];
1719
- const root = (0, import_node_path11.join)(dir, "package.json");
2284
+ const root = (0, import_node_path12.join)(dir, "package.json");
1720
2285
  out.push(root);
1721
2286
  async function walk2(d) {
1722
2287
  let entries;
1723
2288
  try {
1724
- entries = await (0, import_promises11.readdir)(d, { withFileTypes: true });
2289
+ entries = await (0, import_promises12.readdir)(d, { withFileTypes: true });
1725
2290
  } catch {
1726
2291
  return;
1727
2292
  }
1728
2293
  for (const e of entries) {
1729
2294
  if (e.isDirectory()) {
1730
- if (!IGNORE_DIRS.has(e.name)) await walk2((0, import_node_path11.join)(d, e.name));
2295
+ if (!IGNORE_DIRS.has(e.name)) await walk2((0, import_node_path12.join)(d, e.name));
1731
2296
  } else if (e.name === "package.json") {
1732
- out.push((0, import_node_path11.join)(d, e.name));
2297
+ out.push((0, import_node_path12.join)(d, e.name));
1733
2298
  }
1734
2299
  }
1735
2300
  }
1736
- await walk2((0, import_node_path11.join)(dir, "apps"));
2301
+ await walk2((0, import_node_path12.join)(dir, "apps"));
1737
2302
  return out;
1738
2303
  }
1739
2304
  async function depKeys(pkgPath) {
1740
2305
  try {
1741
- const pkg = JSON.parse(await (0, import_promises11.readFile)(pkgPath, "utf8"));
2306
+ const pkg = JSON.parse(await (0, import_promises12.readFile)(pkgPath, "utf8"));
1742
2307
  return /* @__PURE__ */ new Set([
1743
2308
  ...Object.keys(pkg.dependencies ?? {}),
1744
2309
  ...Object.keys(pkg.devDependencies ?? {})
@@ -1752,7 +2317,7 @@ async function auditProject(dir, opts = {}) {
1752
2317
  const violations = [];
1753
2318
  const aliases = await tsconfigAliases(dir);
1754
2319
  for (const file of await walk(dir)) {
1755
- const src = await (0, import_promises11.readFile)(file, "utf8");
2320
+ const src = await (0, import_promises12.readFile)(file, "utf8");
1756
2321
  for (const m of src.matchAll(ICORE_IMPORT)) {
1757
2322
  const alias = m[1];
1758
2323
  if (alias && !aliases.has(alias)) {