@mr.dj2u/cli 0.1.15 → 0.1.16

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.
@@ -76,6 +76,7 @@ const CESS_QUESTIONS = [
76
76
  options: () => [
77
77
  { value: 'uniwind', label: 'Uniwind', hint: 'Default and MDS preference' },
78
78
  { value: 'nativewind', label: 'NativeWind' },
79
+ { value: 'nativewindui', label: 'NativeWindUI' },
79
80
  { value: 'tamagui', label: 'Tamagui' },
80
81
  { value: 'restyle', label: 'Restyle' },
81
82
  { value: 'stylesheet', label: 'StyleSheet only' },
@@ -422,6 +423,18 @@ export function extractCessInfoFromMarkdown(input) {
422
423
  if (snapshot) {
423
424
  recordEvidence('snapshot', 'Parsed machine-readable MDS snapshot block.');
424
425
  }
426
+ const appNameSection = getMarkdownSection(sections, 'App Name');
427
+ if (!derivedDisplayName && appNameSection) {
428
+ const appNameFromSection = normalizeSectionText(appNameSection);
429
+ if (appNameFromSection && !isGenericTextValue(appNameFromSection)) {
430
+ derivedDisplayName = appNameFromSection;
431
+ derivedDisplayNamePriority = VISIBLE_SECTION_PRIORITY;
432
+ derivedDisplayNameNote = 'App Name section';
433
+ derivedFolderSlug = slugifyAppName(appNameFromSection);
434
+ recordEvidence('appName', `Derived app name from App Name section: ${appNameFromSection}`);
435
+ }
436
+ usedSections.add('App Name');
437
+ }
425
438
  const title = extractProjectTitle(infoMarkdown);
426
439
  if (!derivedDisplayName && title) {
427
440
  derivedDisplayName = title;
@@ -432,30 +445,46 @@ export function extractCessInfoFromMarkdown(input) {
432
445
  if (!derivedFolderSlug && derivedDisplayName) {
433
446
  derivedFolderSlug = slugifyAppName(derivedDisplayName);
434
447
  }
435
- const targetUsers = sections.get('Target Users');
448
+ const targetUsers = getMarkdownSection(sections, 'Target Users');
436
449
  if (targetUsers) {
437
450
  usedSections.add('Target Users');
438
451
  assignValue('audience', normalizeSectionText(targetUsers), 'Target Users section', VISIBLE_SECTION_PRIORITY);
439
452
  }
440
453
  else {
441
- const overview = sections.get('Overview');
454
+ const overview = getMarkdownSection(sections, 'Overview');
442
455
  const overviewAudience = extractAudienceFromOverview(overview);
443
456
  if (overviewAudience) {
444
457
  usedSections.add('Overview');
445
458
  assignValue('audience', overviewAudience, 'Overview section', VISIBLE_SECTION_PRIORITY);
446
459
  }
447
460
  }
448
- const coreUserFlows = sections.get('Core User Flows');
449
- if (coreUserFlows) {
461
+ const firstUserFlow = getMarkdownSection(sections, 'First User Flow');
462
+ const coreFlowsAndFeatures = getMarkdownSection(sections, 'Core Flows and Features');
463
+ const coreUserFlows = getMarkdownSection(sections, 'Core User Flows');
464
+ if (firstUserFlow || coreFlowsAndFeatures) {
465
+ const combinedFlows = [normalizeListSection(firstUserFlow), normalizeListSection(coreFlowsAndFeatures)]
466
+ .filter(Boolean)
467
+ .join('\n');
468
+ if (combinedFlows) {
469
+ assignValue('coreFlows', combinedFlows, 'First User Flow and Core Flows and Features sections', VISIBLE_SECTION_PRIORITY);
470
+ }
471
+ if (firstUserFlow) {
472
+ usedSections.add('First User Flow');
473
+ }
474
+ if (coreFlowsAndFeatures) {
475
+ usedSections.add('Core Flows and Features');
476
+ }
477
+ }
478
+ else if (coreUserFlows) {
450
479
  usedSections.add('Core User Flows');
451
480
  assignValue('coreFlows', normalizeListSection(coreUserFlows), 'Core User Flows section', VISIBLE_SECTION_PRIORITY);
452
481
  }
453
- const mustIncludeScreens = sections.get('Must-Include Screens Or Flows');
482
+ const mustIncludeScreens = getMarkdownSection(sections, 'Screens', 'Must-Include Screens Or Flows');
454
483
  if (mustIncludeScreens) {
455
- usedSections.add('Must-Include Screens Or Flows');
456
- assignValue('screens', normalizeListSection(mustIncludeScreens), 'Must-Include Screens Or Flows section', VISIBLE_SECTION_PRIORITY);
484
+ usedSections.add(sections.has('Screens') ? 'Screens' : 'Must-Include Screens Or Flows');
485
+ assignValue('screens', normalizeListSection(mustIncludeScreens), 'Screens section', VISIBLE_SECTION_PRIORITY);
457
486
  }
458
- const dataAndBackend = sections.get('Data And Backend');
487
+ const dataAndBackend = getMarkdownSection(sections, 'Data And Backend');
459
488
  if (dataAndBackend) {
460
489
  usedSections.add('Data And Backend');
461
490
  const inferredDataNeeds = inferDataNeedSelections(dataAndBackend);
@@ -471,17 +500,17 @@ export function extractCessInfoFromMarkdown(input) {
471
500
  assignValue('authBackend', authBackend, 'Data And Backend section', VISIBLE_SECTION_PRIORITY);
472
501
  }
473
502
  }
474
- const platforms = sections.get('Platforms');
503
+ const platforms = getMarkdownSection(sections, 'Platforms');
475
504
  if (platforms) {
476
505
  usedSections.add('Platforms');
477
506
  extractPlatformDecisions(platforms, assignValue, VISIBLE_SECTION_PRIORITY);
478
507
  }
479
- const packageChoices = sections.get('Package Choices');
508
+ const packageChoices = getMarkdownSection(sections, 'Package Choices');
480
509
  if (packageChoices) {
481
510
  usedSections.add('Package Choices');
482
511
  extractPackageChoices(packageChoices, assignValue, VISIBLE_SECTION_PRIORITY);
483
512
  }
484
- const releaseStrategy = sections.get('Release Strategy');
513
+ const releaseStrategy = getMarkdownSection(sections, 'Release Strategy');
485
514
  if (releaseStrategy) {
486
515
  usedSections.add('Release Strategy');
487
516
  const deploymentTarget = extractBulletValue(releaseStrategy, 'Deployment plan');
@@ -498,9 +527,9 @@ export function extractCessInfoFromMarkdown(input) {
498
527
  assignValue('testToMainSafeguards', testToMain, 'Release Strategy section', VISIBLE_SECTION_PRIORITY);
499
528
  }
500
529
  }
501
- const techStackSection = sections.get('Tech Stack & MDS Onboarding');
530
+ const techStackSection = getMarkdownSection(sections, 'Tech Stack & CESS Onboarding', 'Tech Stack & MDS Onboarding');
502
531
  if (techStackSection) {
503
- usedSections.add('Tech Stack & MDS Onboarding');
532
+ usedSections.add(sections.has('Tech Stack & CESS Onboarding') ? 'Tech Stack & CESS Onboarding' : 'Tech Stack & MDS Onboarding');
504
533
  extractTechStackDecisions(techStackSection, assignValue, TECH_STACK_PRIORITY);
505
534
  }
506
535
  const onboardingDecisionsSection = sections.get('Onboarding Decisions');
@@ -585,14 +614,16 @@ function extractProjectTitle(infoMarkdown) {
585
614
  }
586
615
  function parseMarkdownSections(markdown) {
587
616
  const sections = new Map();
588
- const matches = [...markdown.matchAll(/^##\s+(.+?)\s*$/gmu)];
617
+ const matches = [...markdown.matchAll(/^(#{1,2})\s+(.+?)\s*$/gmu)].filter((match) => {
618
+ return !(match.index === 0 && match[1] === '#');
619
+ });
589
620
  for (let index = 0; index < matches.length; index += 1) {
590
621
  const match = matches[index];
591
622
  const next = matches[index + 1];
592
623
  if (!match) {
593
624
  continue;
594
625
  }
595
- const heading = match?.[1]?.trim();
626
+ const heading = match?.[2]?.trim();
596
627
  if (!heading || match.index === undefined) {
597
628
  continue;
598
629
  }
@@ -602,6 +633,24 @@ function parseMarkdownSections(markdown) {
602
633
  }
603
634
  return sections;
604
635
  }
636
+ function getMarkdownSection(sections, ...headings) {
637
+ for (const heading of headings) {
638
+ const exact = sections.get(heading);
639
+ if (exact !== undefined) {
640
+ return exact;
641
+ }
642
+ const normalizedHeading = normalizeHeadingKey(heading);
643
+ for (const [candidate, body] of sections.entries()) {
644
+ if (normalizeHeadingKey(candidate) === normalizedHeading) {
645
+ return body;
646
+ }
647
+ }
648
+ }
649
+ return undefined;
650
+ }
651
+ function normalizeHeadingKey(value) {
652
+ return value.trim().toLowerCase().replace(/\s+/gu, ' ');
653
+ }
605
654
  function extractAudienceFromOverview(overview) {
606
655
  const text = normalizeSectionText(overview);
607
656
  if (!text) {
@@ -770,6 +819,9 @@ function extractPackageChoices(value, assignValue, priority = VISIBLE_SECTION_PR
770
819
  else if (entry === 'nativewind') {
771
820
  assignValue('stylingSystem', 'nativewind', 'Package Choices section', priority);
772
821
  }
822
+ else if (entry === 'nativewindui') {
823
+ assignValue('stylingSystem', 'nativewindui', 'Package Choices section', priority);
824
+ }
773
825
  else if (entry === 'tamagui') {
774
826
  assignValue('stylingSystem', 'tamagui', 'Package Choices section', priority);
775
827
  }
@@ -785,6 +837,132 @@ function extractPackageChoices(value, assignValue, priority = VISIBLE_SECTION_PR
785
837
  }
786
838
  }
787
839
  function extractTechStackDecisions(value, assignValue, priority = TECH_STACK_PRIORITY) {
840
+ const typeScriptChoice = parseBooleanValue(extractKeyValue(value, 'TypeScript'));
841
+ if (typeof typeScriptChoice === 'boolean') {
842
+ assignValue('scriptLanguage', typeScriptChoice ? 'typescript' : 'javascript', 'Tech Stack & CESS Onboarding section', priority);
843
+ }
844
+ const packageManagerChoice = normalizeChoiceLabel(extractKeyValue(value, 'Package Manager'), ['npm', 'pnpm', 'yarn', 'bun']);
845
+ if (packageManagerChoice) {
846
+ assignValue('packageManager', packageManagerChoice, 'Tech Stack & CESS Onboarding section', priority);
847
+ }
848
+ const navigationChoice = (extractKeyValue(value, 'Navigation') ?? '').toLowerCase();
849
+ if (isConcreteChoiceValue(navigationChoice)) {
850
+ if (navigationChoice.includes('react navigation')) {
851
+ assignValue('navigationLibrary', 'react-navigation', 'Tech Stack & CESS Onboarding section', priority);
852
+ }
853
+ else if (navigationChoice.includes('expo router')) {
854
+ assignValue('navigationLibrary', 'expo-router', 'Tech Stack & CESS Onboarding section', priority);
855
+ }
856
+ }
857
+ const navigationType = (extractKeyValue(value, 'Type of Navigation') ?? '').toLowerCase();
858
+ if (isConcreteChoiceValue(navigationType)) {
859
+ if (navigationType.includes('drawer')) {
860
+ assignValue('reactNavigationLayout', 'drawer', 'Tech Stack & CESS Onboarding section', priority);
861
+ }
862
+ else if (navigationType.includes('tabs')) {
863
+ assignValue('reactNavigationLayout', 'tabs', 'Tech Stack & CESS Onboarding section', priority);
864
+ }
865
+ else if (navigationType.includes('stack')) {
866
+ assignValue('reactNavigationLayout', 'stack', 'Tech Stack & CESS Onboarding section', priority);
867
+ }
868
+ }
869
+ const appDirectoryValue = extractKeyValue(value, 'Expo Router app directory');
870
+ if (appDirectoryValue?.includes('src/app')) {
871
+ assignValue('appDirectory', 'src', 'Tech Stack & CESS Onboarding section', priority);
872
+ }
873
+ else if (appDirectoryValue === 'app' || appDirectoryValue?.includes('`app`')) {
874
+ assignValue('appDirectory', 'root', 'Tech Stack & CESS Onboarding section', priority);
875
+ }
876
+ const organization = (extractKeyValue(value, 'Platform-specific organization (folders, files, or inline)') ?? '').toLowerCase();
877
+ if (isConcreteChoiceValue(organization)) {
878
+ if (organization.includes('folder')) {
879
+ assignValue('platformStrategy', 'folders', 'Tech Stack & CESS Onboarding section', priority);
880
+ }
881
+ else if (organization.includes('file')) {
882
+ assignValue('platformStrategy', 'files-only', 'Tech Stack & CESS Onboarding section', priority);
883
+ }
884
+ }
885
+ const layoutMode = (extractKeyValue(value, 'Platform layout mode') ?? '').toLowerCase();
886
+ if (isConcreteChoiceValue(layoutMode)) {
887
+ if (layoutMode.includes('platform-specific')) {
888
+ assignValue('platformLayouts', 'platform-specific', 'Tech Stack & CESS Onboarding section', priority);
889
+ }
890
+ else if (layoutMode.includes('shared')) {
891
+ assignValue('platformLayouts', 'shared', 'Tech Stack & CESS Onboarding section', priority);
892
+ }
893
+ }
894
+ const webOutput = normalizeChoiceLabel(extractKeyValue(value, 'Web output'), ['static', 'server', 'spa', 'none']);
895
+ if (webOutput) {
896
+ assignValue('webOutput', webOutput, 'Tech Stack & CESS Onboarding section', priority);
897
+ }
898
+ const styleLibrary = (extractKeyValue(value, 'Style Library') ?? '').toLowerCase();
899
+ if (isConcreteChoiceValue(styleLibrary)) {
900
+ if (styleLibrary.includes('nativewindui')) {
901
+ assignValue('stylingSystem', 'nativewindui', 'Tech Stack & CESS Onboarding section', priority);
902
+ }
903
+ else if (styleLibrary.includes('nativewind')) {
904
+ assignValue('stylingSystem', 'nativewind', 'Tech Stack & CESS Onboarding section', priority);
905
+ }
906
+ else if (styleLibrary.includes('uniwind')) {
907
+ assignValue('stylingSystem', 'uniwind', 'Tech Stack & CESS Onboarding section', priority);
908
+ }
909
+ else if (styleLibrary.includes('tamagui')) {
910
+ assignValue('stylingSystem', 'tamagui', 'Tech Stack & CESS Onboarding section', priority);
911
+ }
912
+ else if (styleLibrary.includes('restyle')) {
913
+ assignValue('stylingSystem', 'restyle', 'Tech Stack & CESS Onboarding section', priority);
914
+ }
915
+ else if (styleLibrary.includes('stylesheet')) {
916
+ assignValue('stylingSystem', 'stylesheet', 'Tech Stack & CESS Onboarding section', priority);
917
+ }
918
+ }
919
+ assignBooleanKey(value, 'Components from create-expo-app', 'includeCreateExpoComponents', assignValue, priority);
920
+ assignBooleanKey(value, 'Expo UI', 'usesExpoUi', assignValue, priority);
921
+ assignBooleanKey(value, 'Expo UI Universal components', 'usesExpoUiUniversalComponents', assignValue, priority);
922
+ assignBooleanKey(value, 'Expo Native Tabs', 'usesExpoNativeTabs', assignValue, priority);
923
+ const stateManagementChoice = (extractKeyValue(value, 'State management library') ?? '').toLowerCase();
924
+ if (isConcreteChoiceValue(stateManagementChoice)) {
925
+ if (stateManagementChoice.includes('zustand')) {
926
+ assignValue('stateManagement', 'zustand', 'Tech Stack & CESS Onboarding section', priority);
927
+ }
928
+ else if (stateManagementChoice.includes('none')) {
929
+ assignValue('stateManagement', 'none', 'Tech Stack & CESS Onboarding section', priority);
930
+ }
931
+ }
932
+ const authChoice = inferAuthBackend(extractKeyValue(value, 'Auth') ?? '');
933
+ if (authChoice) {
934
+ assignValue('authBackend', authChoice, 'Tech Stack & CESS Onboarding section', priority);
935
+ }
936
+ else if ((extractKeyValue(value, 'Auth') ?? '').toLowerCase().includes('none')) {
937
+ assignValue('authBackend', 'none', 'Tech Stack & CESS Onboarding section', priority);
938
+ }
939
+ const dataCategories = extractKeyValue(value, 'Data Categories');
940
+ if (dataCategories) {
941
+ const inferredDataNeeds = inferDataNeedSelections(dataCategories);
942
+ if (inferredDataNeeds.length > 0) {
943
+ assignValue('dataNeedSelections', inferredDataNeeds, 'Tech Stack & CESS Onboarding section', priority);
944
+ }
945
+ }
946
+ const startingDataMode = inferDataStart(extractKeyValue(value, 'Starting Data mode') ?? '');
947
+ if (startingDataMode) {
948
+ assignValue('dataStart', startingDataMode, 'Tech Stack & CESS Onboarding section', priority);
949
+ }
950
+ const easChoice = parseBooleanValue(extractKeyValue(value, 'EAS'));
951
+ if (typeof easChoice === 'boolean') {
952
+ assignValue('easSetup', easChoice, 'Tech Stack & CESS Onboarding section', priority);
953
+ }
954
+ const newEasUses = inferEasUses(extractKeyValue(value, 'EAS Usage') ?? '');
955
+ if (newEasUses.length > 0) {
956
+ assignValue('easUses', newEasUses, 'Tech Stack & CESS Onboarding section', priority);
957
+ assignValue('easSetup', true, 'Tech Stack & CESS Onboarding section', priority);
958
+ }
959
+ extractPlatformDecisions(`- Deployed server: ${extractKeyValue(value, 'Deployed server') ?? ''}`, assignValue, priority);
960
+ const initialDeploymentPlan = extractKeyValue(value, 'Initial Deployment plan');
961
+ if (initialDeploymentPlan && isConcreteChoiceValue(initialDeploymentPlan)) {
962
+ assignValue('deploymentTarget', initialDeploymentPlan, 'Tech Stack & CESS Onboarding section', priority);
963
+ }
964
+ assignBooleanKey(value, 'Start with MDS project guidelines template', 'guidelinesTemplate', assignValue, priority);
965
+ assignBooleanKey(value, 'Use test-to-main safeguards', 'testToMainSafeguards', assignValue, priority);
788
966
  const language = normalizeChoice(extractKeyValue(value, 'Language'), ['typescript', 'javascript']);
789
967
  if (language) {
790
968
  assignValue('scriptLanguage', language, 'Tech Stack & MDS Onboarding section', priority);
@@ -926,9 +1104,29 @@ function extractKeyValue(value, label) {
926
1104
  const match = new RegExp(`^-\\s+(?:\\*\\*)?${escapeRegExp(label)}(?:\\*\\*)?:\\s+(.+)$`, 'imu').exec(value);
927
1105
  return normalizeText(match?.[1]);
928
1106
  }
1107
+ function assignBooleanKey(value, label, id, assignValue, priority) {
1108
+ const bool = parseBooleanValue(extractKeyValue(value, label));
1109
+ if (typeof bool === 'boolean') {
1110
+ assignValue(id, bool, 'Tech Stack & CESS Onboarding section', priority);
1111
+ }
1112
+ }
1113
+ function normalizeChoiceLabel(value, choices) {
1114
+ const normalized = normalizeText(value)?.toLowerCase().replace(/[`]/gu, '').trim();
1115
+ if (!normalized || !isConcreteChoiceValue(normalized)) {
1116
+ return undefined;
1117
+ }
1118
+ return choices.find((choice) => choice.toLowerCase() === normalized);
1119
+ }
1120
+ function isConcreteChoiceValue(value) {
1121
+ return !/\s\/\s/u.test(value);
1122
+ }
929
1123
  function inferEasUses(value) {
930
1124
  const normalized = value.toLowerCase();
931
- return EAS_USE_OPTIONS.filter((item) => normalized.includes(item.toLowerCase()));
1125
+ const selected = EAS_USE_OPTIONS.filter((item) => normalized.includes(item.toLowerCase()));
1126
+ if (/\bbuilding mobile apps?\b/u.test(normalized) && !selected.includes('building mobile applications')) {
1127
+ selected.push('building mobile applications');
1128
+ }
1129
+ return selected;
932
1130
  }
933
1131
  function parsePlatformList(value) {
934
1132
  const normalized = value
@@ -983,17 +1181,17 @@ function normalizeExtractedAnswerValue(id, value) {
983
1181
  case 'reactNavigationLayout':
984
1182
  return normalizeEnum(value, ['stack', 'tabs', 'drawer']);
985
1183
  case 'stylingSystem':
986
- return normalizeEnum(value, ['uniwind', 'nativewind', 'tamagui', 'restyle', 'stylesheet']);
1184
+ return normalizeEnum(value, ['uniwind', 'nativewind', 'nativewindui', 'tamagui', 'restyle', 'stylesheet']);
987
1185
  case 'stateManagement':
988
1186
  return normalizeEnum(value, ['zustand', 'none']);
989
1187
  case 'authBackend':
990
1188
  return normalizeEnum(value, ['none', 'supabase', 'firebase']);
991
1189
  case 'platformStrategy':
992
- return normalizeEnum(value, ['folders', 'files-only']);
1190
+ return normalizePlatformStrategyValue(value);
993
1191
  case 'appDirectory':
994
- return normalizeEnum(value, ['src', 'root']);
1192
+ return normalizeAppDirectoryValue(value);
995
1193
  case 'platformLayouts':
996
- return normalizeEnum(value, ['shared', 'platform-specific']);
1194
+ return normalizePlatformLayoutsValue(value);
997
1195
  case 'webOutput':
998
1196
  return normalizeEnum(value, ['static', 'server', 'spa', 'none']);
999
1197
  case 'expoServerAdapter':
@@ -1230,6 +1428,7 @@ export function normalizeCessIntakeAnswers(answers) {
1230
1428
  normalized.stylingSystem = normalizeEnum(answers.stylingSystem, [
1231
1429
  'uniwind',
1232
1430
  'nativewind',
1431
+ 'nativewindui',
1233
1432
  'tamagui',
1234
1433
  'restyle',
1235
1434
  'stylesheet',
@@ -1245,9 +1444,9 @@ export function normalizeCessIntakeAnswers(answers) {
1245
1444
  normalized.dataNeedsOther = normalizeText(answers.dataNeedsOther);
1246
1445
  normalized.targetPlatforms = normalizePlatforms(answers.targetPlatforms);
1247
1446
  normalized.firstTargetPlatform = normalizeText(answers.firstTargetPlatform);
1248
- normalized.platformStrategy = normalizeEnum(answers.platformStrategy, ['folders', 'files-only']);
1249
- normalized.appDirectory = normalizeEnum(answers.appDirectory, ['src', 'root']);
1250
- normalized.platformLayouts = normalizeEnum(answers.platformLayouts, ['shared', 'platform-specific']);
1447
+ normalized.platformStrategy = normalizePlatformStrategyValue(answers.platformStrategy);
1448
+ normalized.appDirectory = normalizeAppDirectoryValue(answers.appDirectory);
1449
+ normalized.platformLayouts = normalizePlatformLayoutsValue(answers.platformLayouts);
1251
1450
  normalized.webOutput = normalizeEnum(answers.webOutput, ['static', 'server', 'spa', 'none']);
1252
1451
  normalized.expoServerAdapter = normalizeEnum(answers.expoServerAdapter, [
1253
1452
  'eas',
@@ -1290,6 +1489,9 @@ export function buildCreateExpoStackFlags(answers) {
1290
1489
  case 'nativewind':
1291
1490
  flags.push('--nativewind');
1292
1491
  break;
1492
+ case 'nativewindui':
1493
+ flags.push('--nativewindui');
1494
+ break;
1293
1495
  case 'tamagui':
1294
1496
  flags.push('--tamagui');
1295
1497
  break;
@@ -1505,8 +1707,40 @@ function buildOnboardArgvFromCess(parentDir, appName, answers) {
1505
1707
  dataStart: answers.dataStart,
1506
1708
  testToMain: answers.testToMainSafeguards,
1507
1709
  saveDefaults: answers.saveDefaults,
1710
+ defaults: buildOnboardDefaultsFromCessAnswers(answers),
1508
1711
  };
1509
1712
  }
1713
+ function buildOnboardDefaultsFromCessAnswers(answers) {
1714
+ const defaults = new Set(['project-docs', 'guidelines']);
1715
+ switch (answers.stylingSystem) {
1716
+ case 'nativewindui':
1717
+ defaults.add('nativewindui');
1718
+ break;
1719
+ case 'nativewind':
1720
+ defaults.add('nativewind');
1721
+ break;
1722
+ case 'tamagui':
1723
+ defaults.add('tamagui');
1724
+ break;
1725
+ case 'restyle':
1726
+ defaults.add('restyle');
1727
+ break;
1728
+ case 'stylesheet':
1729
+ break;
1730
+ case 'uniwind':
1731
+ default:
1732
+ defaults.add('uniwind');
1733
+ break;
1734
+ }
1735
+ if (answers.dataStart === 'supabase' || answers.authBackend === 'supabase') {
1736
+ defaults.add('supabase');
1737
+ }
1738
+ defaults.add('doctor');
1739
+ if (answers.testToMainSafeguards ?? true) {
1740
+ defaults.add('test-to-main');
1741
+ }
1742
+ return [...defaults].join(',');
1743
+ }
1510
1744
  function materializeQuestion(definition, context) {
1511
1745
  return {
1512
1746
  id: definition.id,
@@ -1560,6 +1794,45 @@ function normalizeEnum(value, choices) {
1560
1794
  function normalizeChoice(value, choices) {
1561
1795
  return normalizeEnum(value, choices);
1562
1796
  }
1797
+ function normalizePlatformStrategyValue(value) {
1798
+ const normalized = normalizeText(value)?.toLowerCase();
1799
+ if (!normalized) {
1800
+ return undefined;
1801
+ }
1802
+ if (normalized === 'folders' || normalized.includes('folder')) {
1803
+ return 'folders';
1804
+ }
1805
+ if (normalized === 'files-only' || normalized.includes('file')) {
1806
+ return 'files-only';
1807
+ }
1808
+ return undefined;
1809
+ }
1810
+ function normalizeAppDirectoryValue(value) {
1811
+ const normalized = normalizeText(value)?.toLowerCase().replace(/[`]/gu, '').trim();
1812
+ if (!normalized) {
1813
+ return undefined;
1814
+ }
1815
+ if (normalized === 'src' || normalized === 'src/app') {
1816
+ return 'src';
1817
+ }
1818
+ if (normalized === 'root' || normalized === 'app') {
1819
+ return 'root';
1820
+ }
1821
+ return undefined;
1822
+ }
1823
+ function normalizePlatformLayoutsValue(value) {
1824
+ const normalized = normalizeText(value)?.toLowerCase();
1825
+ if (!normalized) {
1826
+ return undefined;
1827
+ }
1828
+ if (normalized === 'shared' || normalized.includes('shared')) {
1829
+ return 'shared';
1830
+ }
1831
+ if (normalized === 'platform-specific' || normalized.includes('platform-specific')) {
1832
+ return 'platform-specific';
1833
+ }
1834
+ return undefined;
1835
+ }
1563
1836
  function normalizeText(value) {
1564
1837
  if (typeof value !== 'string') {
1565
1838
  return undefined;
@@ -1616,6 +1889,8 @@ function formatStylingLabel(value) {
1616
1889
  return 'Uniwind';
1617
1890
  case 'nativewind':
1618
1891
  return 'NativeWind';
1892
+ case 'nativewindui':
1893
+ return 'NativeWindUI';
1619
1894
  case 'tamagui':
1620
1895
  return 'Tamagui';
1621
1896
  case 'restyle':