@mr.dj2u/cli 0.1.15 → 0.1.17
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.
- package/bundles/claude-code/.claude-plugin/plugin.json +1 -1
- package/bundles/claude-code/.mcp.json +1 -1
- package/bundles/claude-code/commands/create-expo-super-stack.md +36 -11
- package/bundles/claude-code/skills/create-expo-super-stack/SKILL.md +37 -12
- package/bundles/codex/.codex-plugin/plugin.json +1 -1
- package/bundles/codex/.mcp.json +1 -1
- package/bundles/codex/README.md +14 -1
- package/bundles/codex/commands/create-expo-super-stack.md +36 -11
- package/bundles/codex/skills/workflow-create-expo-super-stack/SKILL.md +36 -11
- package/bundles/vscode-copilot/.github/prompts/create-expo-super-stack.prompt.md +36 -11
- package/bundles/vscode-copilot/.vscode/mcp.json +1 -1
- package/bundles/vscode-copilot/README.md +14 -0
- package/bundles/vscode-copilot/user/.copilot/skills/workflow-create-expo-super-stack/SKILL.md +36 -11
- package/dist/cess-intake.d.ts +1 -1
- package/dist/cess-intake.d.ts.map +1 -1
- package/dist/cess-intake.js +302 -28
- package/dist/cess-intake.js.map +1 -1
- package/dist/commands/mcp-install.d.ts +2 -2
- package/dist/commands/mcp-install.js +1 -1
- package/dist/commands/onboard.d.ts +1 -1
- package/dist/commands/onboard.d.ts.map +1 -1
- package/dist/project-memory.d.ts +1 -1
- package/dist/project-memory.d.ts.map +1 -1
- package/dist/project-memory.js +96 -194
- package/dist/project-memory.js.map +1 -1
- package/dist/roadmap.d.ts +7 -2
- package/dist/roadmap.d.ts.map +1 -1
- package/dist/roadmap.js +255 -34
- package/dist/roadmap.js.map +1 -1
- package/package.json +2 -2
package/dist/cess-intake.js
CHANGED
|
@@ -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' },
|
|
@@ -105,7 +106,7 @@ const CESS_QUESTIONS = [
|
|
|
105
106
|
},
|
|
106
107
|
{
|
|
107
108
|
id: 'easSetup',
|
|
108
|
-
prompt: '
|
|
109
|
+
prompt: 'Will this project use EAS later? MDS will remember it and add a Phase 0 setup step, but it will not sign in during generation.',
|
|
109
110
|
kind: 'single-select',
|
|
110
111
|
options: () => [
|
|
111
112
|
{ value: false, label: 'No', hint: 'Default' },
|
|
@@ -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
|
|
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
|
|
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
|
|
449
|
-
|
|
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
|
|
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), '
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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?.[
|
|
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
|
-
|
|
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
|
|
1190
|
+
return normalizePlatformStrategyValue(value);
|
|
993
1191
|
case 'appDirectory':
|
|
994
|
-
return
|
|
1192
|
+
return normalizeAppDirectoryValue(value);
|
|
995
1193
|
case 'platformLayouts':
|
|
996
|
-
return
|
|
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 =
|
|
1249
|
-
normalized.appDirectory =
|
|
1250
|
-
normalized.platformLayouts =
|
|
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;
|
|
@@ -1308,9 +1510,6 @@ export function buildCreateExpoStackFlags(answers) {
|
|
|
1308
1510
|
else if (answers.authBackend === 'firebase') {
|
|
1309
1511
|
flags.push('--firebase');
|
|
1310
1512
|
}
|
|
1311
|
-
if (answers.easSetup) {
|
|
1312
|
-
flags.push('--eas');
|
|
1313
|
-
}
|
|
1314
1513
|
return flags;
|
|
1315
1514
|
}
|
|
1316
1515
|
export function buildMdsFlags(appName, onboardAnswers, intakeAnswers) {
|
|
@@ -1397,7 +1596,9 @@ export function buildCessSummaryLines(parentDir, appName, answers, onboardAnswer
|
|
|
1397
1596
|
answers.authBackend === 'none'
|
|
1398
1597
|
? 'No auth starter'
|
|
1399
1598
|
: formatTitle(answers.authBackend ?? STACK_DEFAULTS.authBackend),
|
|
1400
|
-
answers.easSetup
|
|
1599
|
+
answers.easSetup
|
|
1600
|
+
? 'EAS planned; sign in and set it up manually in Phase 0'
|
|
1601
|
+
: 'No EAS planned',
|
|
1401
1602
|
].join(', ');
|
|
1402
1603
|
const platformLine = [
|
|
1403
1604
|
`platforms: ${onboardAnswers.targetPlatforms.map(formatPlatformLabel).join(', ')}`,
|
|
@@ -1505,8 +1706,40 @@ function buildOnboardArgvFromCess(parentDir, appName, answers) {
|
|
|
1505
1706
|
dataStart: answers.dataStart,
|
|
1506
1707
|
testToMain: answers.testToMainSafeguards,
|
|
1507
1708
|
saveDefaults: answers.saveDefaults,
|
|
1709
|
+
defaults: buildOnboardDefaultsFromCessAnswers(answers),
|
|
1508
1710
|
};
|
|
1509
1711
|
}
|
|
1712
|
+
function buildOnboardDefaultsFromCessAnswers(answers) {
|
|
1713
|
+
const defaults = new Set(['project-docs', 'guidelines']);
|
|
1714
|
+
switch (answers.stylingSystem) {
|
|
1715
|
+
case 'nativewindui':
|
|
1716
|
+
defaults.add('nativewindui');
|
|
1717
|
+
break;
|
|
1718
|
+
case 'nativewind':
|
|
1719
|
+
defaults.add('nativewind');
|
|
1720
|
+
break;
|
|
1721
|
+
case 'tamagui':
|
|
1722
|
+
defaults.add('tamagui');
|
|
1723
|
+
break;
|
|
1724
|
+
case 'restyle':
|
|
1725
|
+
defaults.add('restyle');
|
|
1726
|
+
break;
|
|
1727
|
+
case 'stylesheet':
|
|
1728
|
+
break;
|
|
1729
|
+
case 'uniwind':
|
|
1730
|
+
default:
|
|
1731
|
+
defaults.add('uniwind');
|
|
1732
|
+
break;
|
|
1733
|
+
}
|
|
1734
|
+
if (answers.dataStart === 'supabase' || answers.authBackend === 'supabase') {
|
|
1735
|
+
defaults.add('supabase');
|
|
1736
|
+
}
|
|
1737
|
+
defaults.add('doctor');
|
|
1738
|
+
if (answers.testToMainSafeguards ?? true) {
|
|
1739
|
+
defaults.add('test-to-main');
|
|
1740
|
+
}
|
|
1741
|
+
return [...defaults].join(',');
|
|
1742
|
+
}
|
|
1510
1743
|
function materializeQuestion(definition, context) {
|
|
1511
1744
|
return {
|
|
1512
1745
|
id: definition.id,
|
|
@@ -1560,6 +1793,45 @@ function normalizeEnum(value, choices) {
|
|
|
1560
1793
|
function normalizeChoice(value, choices) {
|
|
1561
1794
|
return normalizeEnum(value, choices);
|
|
1562
1795
|
}
|
|
1796
|
+
function normalizePlatformStrategyValue(value) {
|
|
1797
|
+
const normalized = normalizeText(value)?.toLowerCase();
|
|
1798
|
+
if (!normalized) {
|
|
1799
|
+
return undefined;
|
|
1800
|
+
}
|
|
1801
|
+
if (normalized === 'folders' || normalized.includes('folder')) {
|
|
1802
|
+
return 'folders';
|
|
1803
|
+
}
|
|
1804
|
+
if (normalized === 'files-only' || normalized.includes('file')) {
|
|
1805
|
+
return 'files-only';
|
|
1806
|
+
}
|
|
1807
|
+
return undefined;
|
|
1808
|
+
}
|
|
1809
|
+
function normalizeAppDirectoryValue(value) {
|
|
1810
|
+
const normalized = normalizeText(value)?.toLowerCase().replace(/[`]/gu, '').trim();
|
|
1811
|
+
if (!normalized) {
|
|
1812
|
+
return undefined;
|
|
1813
|
+
}
|
|
1814
|
+
if (normalized === 'src' || normalized === 'src/app') {
|
|
1815
|
+
return 'src';
|
|
1816
|
+
}
|
|
1817
|
+
if (normalized === 'root' || normalized === 'app') {
|
|
1818
|
+
return 'root';
|
|
1819
|
+
}
|
|
1820
|
+
return undefined;
|
|
1821
|
+
}
|
|
1822
|
+
function normalizePlatformLayoutsValue(value) {
|
|
1823
|
+
const normalized = normalizeText(value)?.toLowerCase();
|
|
1824
|
+
if (!normalized) {
|
|
1825
|
+
return undefined;
|
|
1826
|
+
}
|
|
1827
|
+
if (normalized === 'shared' || normalized.includes('shared')) {
|
|
1828
|
+
return 'shared';
|
|
1829
|
+
}
|
|
1830
|
+
if (normalized === 'platform-specific' || normalized.includes('platform-specific')) {
|
|
1831
|
+
return 'platform-specific';
|
|
1832
|
+
}
|
|
1833
|
+
return undefined;
|
|
1834
|
+
}
|
|
1563
1835
|
function normalizeText(value) {
|
|
1564
1836
|
if (typeof value !== 'string') {
|
|
1565
1837
|
return undefined;
|
|
@@ -1616,6 +1888,8 @@ function formatStylingLabel(value) {
|
|
|
1616
1888
|
return 'Uniwind';
|
|
1617
1889
|
case 'nativewind':
|
|
1618
1890
|
return 'NativeWind';
|
|
1891
|
+
case 'nativewindui':
|
|
1892
|
+
return 'NativeWindUI';
|
|
1619
1893
|
case 'tamagui':
|
|
1620
1894
|
return 'Tamagui';
|
|
1621
1895
|
case 'restyle':
|