forgebook 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +914 -72
- package/dist/bin/forgebook/agentClient.d.ts +2 -1
- package/dist/bin/forgebook/agentClient.js +13 -6
- package/dist/bin/forgebook/agentGuide.d.ts +59 -0
- package/dist/bin/forgebook/agentGuide.js +203 -0
- package/dist/bin/forgebook/agentLoopCommands.mjs +22 -42
- package/dist/bin/forgebook/agentSetup/agentFiles.d.ts +55 -0
- package/dist/bin/forgebook/agentSetup/agentFiles.js +319 -0
- package/dist/bin/forgebook/agentSetup/assistantHooks.d.ts +71 -0
- package/dist/bin/forgebook/agentSetup/assistantHooks.js +125 -0
- package/dist/bin/forgebook/agentSetup/ciWorkflow.d.ts +23 -0
- package/dist/bin/forgebook/agentSetup/ciWorkflow.js +55 -0
- package/dist/bin/forgebook/agentSetup/drawCandidates.d.ts +25 -0
- package/dist/bin/forgebook/agentSetup/drawCandidates.js +116 -0
- package/dist/bin/forgebook/agentSetup/drawDiagnosis.d.ts +28 -0
- package/dist/bin/forgebook/agentSetup/drawDiagnosis.js +134 -0
- package/dist/bin/forgebook/agentSetup/drawRun.d.ts +91 -0
- package/dist/bin/forgebook/agentSetup/drawRun.js +353 -0
- package/dist/bin/forgebook/agentSetup/hookNames.d.ts +7 -0
- package/dist/bin/forgebook/agentSetup/hookNames.js +7 -0
- package/dist/bin/forgebook/agentSetup/initAgentSteps.d.ts +48 -0
- package/dist/bin/forgebook/agentSetup/initAgentSteps.js +104 -0
- package/dist/bin/forgebook/agentSetup/liftedProviders.d.ts +17 -0
- package/dist/bin/forgebook/agentSetup/liftedProviders.js +186 -0
- package/dist/bin/forgebook/agentSetup/projectRunner.d.ts +46 -0
- package/dist/bin/forgebook/agentSetup/projectRunner.js +85 -0
- package/dist/bin/forgebook/agentSetup/stopHook.d.ts +65 -0
- package/dist/bin/forgebook/agentSetup/stopHook.js +202 -0
- package/dist/bin/forgebook/agentSetup/uniformPicture.d.ts +7 -0
- package/dist/bin/forgebook/agentSetup/uniformPicture.js +98 -0
- package/dist/bin/forgebook/agentSetupCommands.d.mts +14 -0
- package/dist/bin/forgebook/agentSetupCommands.mjs +98 -0
- package/dist/bin/forgebook/agentText.d.ts +23 -3
- package/dist/bin/forgebook/agentText.js +175 -28
- package/dist/bin/forgebook/agents.md +20 -191
- package/dist/bin/forgebook/agentsText.js +2 -1
- package/dist/bin/forgebook/appBuild/appBuild.d.ts +59 -0
- package/dist/bin/forgebook/appBuild/appBuild.js +213 -0
- package/dist/bin/forgebook/appBuild/appViteConfig.d.ts +96 -0
- package/dist/bin/forgebook/appBuild/appViteConfig.js +320 -0
- package/dist/bin/forgebook/appBuild/tsconfigPaths.d.ts +14 -0
- package/dist/bin/forgebook/appBuild/tsconfigPaths.js +80 -0
- package/dist/bin/forgebook/auditCommand.d.mts +8 -0
- package/dist/bin/forgebook/auditCommand.mjs +75 -0
- package/dist/bin/forgebook/auditRun.d.ts +95 -0
- package/dist/bin/forgebook/auditRun.js +270 -0
- package/dist/bin/forgebook/browserRun.d.ts +21 -0
- package/dist/bin/forgebook/browserRun.js +57 -0
- package/dist/bin/forgebook/buildFailure.d.ts +7 -0
- package/dist/bin/forgebook/buildFailure.js +47 -0
- package/dist/bin/forgebook/buildWatch.d.ts +52 -0
- package/dist/bin/forgebook/buildWatch.js +137 -0
- package/dist/bin/forgebook/builtCatalogue.js +9 -5
- package/dist/bin/forgebook/catalogueCommands.d.ts +9 -0
- package/dist/bin/forgebook/catalogueCommands.js +23 -0
- package/dist/bin/forgebook/catalogueVite.d.ts +5 -1
- package/dist/bin/forgebook/catalogueVite.js +14 -6
- package/dist/bin/forgebook/commandCacheClaim.d.ts +18 -0
- package/dist/bin/forgebook/commandCacheClaim.js +170 -0
- package/dist/bin/forgebook/commandServer.d.ts +8 -0
- package/dist/bin/forgebook/commandServer.js +61 -13
- package/dist/bin/forgebook/forgebookCommands.mjs +105 -28
- package/dist/bin/forgebook/graphCommand.d.mts +8 -0
- package/dist/bin/forgebook/graphCommand.mjs +84 -0
- package/dist/bin/forgebook/guide/commands.md +57 -0
- package/dist/bin/forgebook/guide/devices.md +17 -0
- package/dist/bin/forgebook/guide/docs-pages.md +13 -0
- package/dist/bin/forgebook/guide/frameworks/angular.md +22 -0
- package/dist/bin/forgebook/guide/frameworks/html.md +22 -0
- package/dist/bin/forgebook/guide/frameworks/nextjs.md +23 -0
- package/dist/bin/forgebook/guide/frameworks/nuxt.md +22 -0
- package/dist/bin/forgebook/guide/frameworks/preact.md +16 -0
- package/dist/bin/forgebook/guide/frameworks/react-native-web.md +21 -0
- package/dist/bin/forgebook/guide/frameworks/react.md +16 -0
- package/dist/bin/forgebook/guide/frameworks/solid.md +18 -0
- package/dist/bin/forgebook/guide/frameworks/svelte.md +18 -0
- package/dist/bin/forgebook/guide/frameworks/sveltekit.md +23 -0
- package/dist/bin/forgebook/guide/frameworks/vue.md +18 -0
- package/dist/bin/forgebook/guide/frameworks/web-components.md +21 -0
- package/dist/bin/forgebook/guide/links.md +29 -0
- package/dist/bin/forgebook/guide/setup.md +23 -0
- package/dist/bin/forgebook/guide/stories.md +90 -0
- package/dist/bin/forgebook/guide/switches.md +43 -0
- package/dist/bin/forgebook/guideCommand.d.mts +13 -0
- package/dist/bin/forgebook/guideCommand.mjs +37 -0
- package/dist/bin/forgebook/importers/storybook.d.ts +21 -0
- package/dist/bin/forgebook/importers/storybook.js +11 -5
- package/dist/bin/forgebook/importers/storybookFrameworks.js +1 -1
- package/dist/bin/forgebook/initCommands.d.mts +11 -0
- package/dist/bin/forgebook/initCommands.mjs +51 -78
- package/dist/bin/forgebook/initConfig.d.ts +5 -3
- package/dist/bin/forgebook/initConfig.js +6 -3
- package/dist/bin/forgebook/initInstall.d.ts +15 -0
- package/dist/bin/forgebook/initInstall.js +77 -0
- package/dist/bin/forgebook/initPrint.d.ts +9 -0
- package/dist/bin/forgebook/initPrint.js +60 -0
- package/dist/bin/forgebook/initRefusals.d.ts +45 -0
- package/dist/bin/forgebook/initRefusals.js +91 -0
- package/dist/bin/forgebook/initRun.d.ts +28 -0
- package/dist/bin/forgebook/initRun.js +311 -0
- package/dist/bin/forgebook/mcpCommand.mjs +38 -4
- package/dist/bin/forgebook/mcpGraph.d.ts +13 -0
- package/dist/bin/forgebook/mcpGraph.js +24 -0
- package/dist/bin/forgebook/mcpTokens.d.ts +14 -0
- package/dist/bin/forgebook/mcpTokens.js +58 -0
- package/dist/bin/forgebook/mcpToolParts.d.ts +7 -0
- package/dist/bin/forgebook/mcpToolParts.js +10 -0
- package/dist/bin/forgebook/mcpTools.d.ts +13 -6
- package/dist/bin/forgebook/mcpTools.js +57 -90
- package/dist/bin/forgebook/mcpVerify.d.ts +16 -0
- package/dist/bin/forgebook/mcpVerify.js +36 -0
- package/dist/bin/forgebook/migrate/codemods.d.ts +11 -0
- package/dist/bin/forgebook/migrate/codemods.js +61 -0
- package/dist/bin/forgebook/migrate/migrate.types.d.ts +117 -0
- package/dist/bin/forgebook/migrate/migrate.types.js +5 -0
- package/dist/bin/forgebook/migrate/migrateCommand.d.mts +8 -0
- package/dist/bin/forgebook/migrate/migrateCommand.mjs +76 -0
- package/dist/bin/forgebook/migrate/migrateRun.d.ts +61 -0
- package/dist/bin/forgebook/migrate/migrateRun.js +210 -0
- package/dist/bin/forgebook/migrate/migrateText.d.ts +12 -0
- package/dist/bin/forgebook/migrate/migrateText.js +30 -0
- package/dist/bin/forgebook/migrate/migrateWrite.d.ts +27 -0
- package/dist/bin/forgebook/migrate/migrateWrite.js +66 -0
- package/dist/bin/forgebook/migrate/objectEdits.d.ts +70 -0
- package/dist/bin/forgebook/migrate/objectEdits.js +241 -0
- package/dist/bin/forgebook/migrate/playOnInBuilds.d.ts +3 -0
- package/dist/bin/forgebook/migrate/playOnInBuilds.js +86 -0
- package/dist/bin/forgebook/migrate/propGroupStrings.d.ts +5 -0
- package/dist/bin/forgebook/migrate/propGroupStrings.js +81 -0
- package/dist/bin/forgebook/newProject/newProject.d.ts +39 -0
- package/dist/bin/forgebook/newProject/newProject.js +180 -0
- package/dist/bin/forgebook/newProject/newProject.types.d.ts +97 -0
- package/dist/bin/forgebook/newProject/newProject.types.js +6 -0
- package/dist/bin/forgebook/newProject/packageManagers.d.ts +51 -0
- package/dist/bin/forgebook/newProject/packageManagers.js +121 -0
- package/dist/bin/forgebook/newProject/projectEntries.d.ts +62 -0
- package/dist/bin/forgebook/newProject/projectEntries.js +191 -0
- package/dist/bin/forgebook/newProject/projectFrameworks.d.ts +57 -0
- package/dist/bin/forgebook/newProject/projectFrameworks.js +148 -0
- package/dist/bin/forgebook/newProject/projectLook.d.ts +23 -0
- package/dist/bin/forgebook/newProject/projectLook.js +293 -0
- package/dist/bin/forgebook/newProject/projectPackages.d.ts +66 -0
- package/dist/bin/forgebook/newProject/projectPackages.js +178 -0
- package/dist/bin/forgebook/newRepair.d.ts +45 -0
- package/dist/bin/forgebook/newRepair.js +157 -0
- package/dist/bin/forgebook/newRepairRun.d.ts +69 -0
- package/dist/bin/forgebook/newRepairRun.js +148 -0
- package/dist/bin/forgebook/newStories.d.ts +23 -1
- package/dist/bin/forgebook/newStories.js +101 -11
- package/dist/bin/forgebook/newStoriesFile.d.ts +20 -1
- package/dist/bin/forgebook/newStoriesFile.js +43 -4
- package/dist/bin/forgebook/prebundleRun.d.ts +3 -1
- package/dist/bin/forgebook/prebundleRun.js +28 -8
- package/dist/bin/forgebook/proofCommand.d.mts +15 -0
- package/dist/bin/forgebook/proofCommand.mjs +212 -0
- package/dist/bin/forgebook/proofRun.d.ts +63 -0
- package/dist/bin/forgebook/proofRun.js +412 -0
- package/dist/bin/forgebook/proofText.d.ts +36 -0
- package/dist/bin/forgebook/proofText.js +131 -0
- package/dist/bin/forgebook/proofWorkflow.d.ts +29 -0
- package/dist/bin/forgebook/proofWorkflow.js +205 -0
- package/dist/bin/forgebook/setArgsTool.d.ts +8 -0
- package/dist/bin/forgebook/setArgsTool.js +70 -0
- package/dist/bin/forgebook/storyCheckCommands.mjs +42 -3
- package/dist/bin/forgebook/storyCheckRun.d.ts +50 -0
- package/dist/bin/forgebook/storyCheckRun.js +83 -9
- package/dist/bin/forgebook/storyFileIds.d.ts +15 -0
- package/dist/bin/forgebook/storyFileIds.js +14 -0
- package/dist/bin/forgebook/stressCases.d.ts +31 -0
- package/dist/bin/forgebook/stressCases.js +79 -0
- package/dist/bin/forgebook/stressRun.d.ts +12 -0
- package/dist/bin/forgebook/stressRun.js +61 -0
- package/dist/bin/forgebook/stressText.d.ts +27 -0
- package/dist/bin/forgebook/stressText.js +46 -0
- package/dist/bin/forgebook/verifyBase.d.ts +45 -0
- package/dist/bin/forgebook/verifyBase.js +196 -0
- package/dist/bin/forgebook/verifyCommand.d.mts +13 -0
- package/dist/bin/forgebook/verifyCommand.mjs +125 -0
- package/dist/bin/forgebook/verifyRun.d.ts +63 -0
- package/dist/bin/forgebook/verifyRun.js +108 -0
- package/dist/bin/forgebook/verifyVerdict.d.ts +40 -0
- package/dist/bin/forgebook/verifyVerdict.js +297 -0
- package/dist/bin/forgebook/workflowActions.d.ts +23 -0
- package/dist/bin/forgebook/workflowActions.js +23 -0
- package/dist/bin/forgebook-docs/catalogueMarkdown.js +12 -1
- package/dist/src/addressArgs.d.ts +29 -5
- package/dist/src/addressArgs.js +58 -16
- package/dist/src/addressArgsParam.d.ts +54 -0
- package/dist/src/addressArgsParam.js +51 -0
- package/dist/src/addressTexts.d.ts +14 -0
- package/dist/src/addressTexts.js +28 -21
- package/dist/src/agentIndexFile.d.ts +11 -0
- package/dist/src/agentIndexFile.js +11 -0
- package/dist/src/argConditions.d.ts +52 -0
- package/dist/src/argConditions.js +80 -0
- package/dist/src/argControl.d.ts +100 -0
- package/dist/src/argControl.js +0 -0
- package/dist/src/argExpression.d.ts +21 -0
- package/dist/src/argExpression.js +30 -0
- package/dist/src/argTypes.d.ts +40 -51
- package/dist/src/argTypes.js +66 -184
- package/dist/src/argsProps.d.ts +3 -3
- package/dist/src/argsProps.js +11 -5
- package/dist/src/bundlerErrors.d.ts +29 -0
- package/dist/src/bundlerErrors.js +49 -0
- package/dist/src/catalogue.d.ts +31 -0
- package/dist/src/catalogue.js +13 -2
- package/dist/src/catalogueRefs.d.ts +75 -0
- package/dist/src/catalogueRefs.js +122 -0
- package/dist/src/componentDocs.d.ts +71 -0
- package/dist/src/componentDocs.js +15 -2
- package/dist/src/frame/callValues.d.ts +19 -0
- package/dist/src/frame/callValues.js +58 -0
- package/dist/src/frame/canvasScheme.d.ts +33 -0
- package/dist/src/frame/canvasScheme.js +67 -0
- package/dist/src/frame/frame.css +36 -3
- package/dist/src/frame/frameStatus.d.ts +16 -1
- package/dist/src/frame/frameStatus.js +16 -1
- package/dist/src/frame/frameView.js +4 -3
- package/dist/src/frame/mountFrame.d.ts +7 -1
- package/dist/src/frame/mountFrame.js +153 -46
- package/dist/src/frame/panelValues.d.ts +35 -0
- package/dist/src/frame/panelValues.js +127 -0
- package/dist/src/frame/playActions.d.ts +39 -0
- package/dist/src/frame/playActions.js +98 -0
- package/dist/src/frame/playStepper.d.ts +28 -0
- package/dist/src/frame/playStepper.js +38 -0
- package/dist/src/frame/playStory.d.ts +9 -1
- package/dist/src/frame/playStory.js +49 -3
- package/dist/src/frame/renderer.d.ts +34 -1
- package/dist/src/frame/renderer.js +24 -0
- package/dist/src/frame/shellChannel.d.ts +1 -1
- package/dist/src/frame/shellChannel.js +1 -1
- package/dist/src/frame/shellCheck.d.ts +17 -0
- package/dist/src/frame/shellCheck.js +25 -0
- package/dist/src/frame/shellMessageCheck.d.ts +7 -0
- package/dist/src/frame/shellMessageCheck.js +53 -0
- package/dist/src/frame/storyContent.d.ts +50 -0
- package/dist/src/frame/storyContent.js +73 -0
- package/dist/src/frame/storyModule.d.ts +9 -0
- package/dist/src/frame/storyModule.js +20 -2
- package/dist/src/frame/storyRun.d.ts +15 -7
- package/dist/src/frame/storyRun.js +64 -15
- package/dist/src/frame/valueSheets.d.ts +35 -0
- package/dist/src/frame/valueSheets.js +99 -0
- package/dist/src/hotModules.d.ts +20 -0
- package/dist/src/hotModules.js +23 -0
- package/dist/src/jsxCode.d.ts +1 -14
- package/dist/src/jsxCode.js +46 -10
- package/dist/src/liveErrors.d.ts +30 -4
- package/dist/src/liveErrors.js +18 -3
- package/dist/src/messages.d.ts +77 -27
- package/dist/src/messages.js +58 -100
- package/dist/src/namedValues.d.ts +2 -26
- package/dist/src/namedValues.js +0 -47
- package/dist/src/pageConfig.d.ts +2 -0
- package/dist/src/playTrace.d.ts +19 -2
- package/dist/src/playTrace.js +10 -5
- package/dist/src/plugin.d.ts +10 -3
- package/dist/src/previewRelay.js +9 -1
- package/dist/src/printable.d.ts +12 -0
- package/dist/src/printable.js +22 -0
- package/dist/src/propsSignature.d.ts +37 -0
- package/dist/src/propsSignature.js +40 -0
- package/dist/src/search.d.ts +41 -5
- package/dist/src/search.js +93 -23
- package/dist/src/searchMatch.d.ts +4 -1
- package/dist/src/searchMatch.js +26 -5
- package/dist/src/searchTypos.d.ts +88 -0
- package/dist/src/searchTypos.js +178 -0
- package/dist/src/shapeValues.d.ts +86 -0
- package/dist/src/shapeValues.js +295 -0
- package/dist/src/shell/ApiReference.js +6 -3
- package/dist/src/shell/ApiTableBox.d.ts +15 -0
- package/dist/src/shell/ApiTableBox.js +11 -0
- package/dist/src/shell/AppearanceMenu.d.ts +4 -1
- package/dist/src/shell/AppearanceMenu.js +9 -6
- package/dist/src/shell/CodeTab.d.ts +3 -2
- package/dist/src/shell/CodeTab.js +3 -2
- package/dist/src/shell/CodeText.d.ts +1 -1
- package/dist/src/shell/CodeText.js +2 -3
- package/dist/src/shell/CompareGrid.js +1 -1
- package/dist/src/shell/ComponentPage.d.ts +1 -1
- package/dist/src/shell/ComponentPage.js +5 -1
- package/dist/src/shell/CustomControl.d.ts +34 -0
- package/dist/src/shell/CustomControl.js +132 -0
- package/dist/src/shell/DocContainers.js +1 -1
- package/dist/src/shell/DocPage.js +2 -2
- package/dist/src/shell/DroppedArgsList.d.ts +2 -2
- package/dist/src/shell/DroppedArgsList.js +1 -1
- package/dist/src/shell/EmbedPage.js +30 -12
- package/dist/src/shell/Example.d.ts +5 -1
- package/dist/src/shell/Example.js +16 -8
- package/dist/src/shell/FrameView.d.ts +6 -3
- package/dist/src/shell/FrameView.js +2 -2
- package/dist/src/shell/HomePage.d.ts +3 -1
- package/dist/src/shell/HomePage.js +16 -6
- package/dist/src/shell/InfoTip.js +2 -2
- package/dist/src/shell/InteractionsTab.d.ts +11 -4
- package/dist/src/shell/InteractionsTab.js +18 -2
- package/dist/src/shell/LazyPage.js +1 -1
- package/dist/src/shell/PackageHtml.js +3 -1
- package/dist/src/shell/PinnedControl.js +14 -62
- package/dist/src/shell/PinnedControlMenu.d.ts +44 -0
- package/dist/src/shell/PinnedControlMenu.js +72 -0
- package/dist/src/shell/PropFields.d.ts +3 -1
- package/dist/src/shell/PropFields.js +9 -6
- package/dist/src/shell/PropRows.d.ts +23 -2
- package/dist/src/shell/PropRows.js +58 -19
- package/dist/src/shell/PropsTab.d.ts +12 -5
- package/dist/src/shell/PropsTab.js +9 -21
- package/dist/src/shell/RefStoryPage.d.ts +33 -0
- package/dist/src/shell/RefStoryPage.js +123 -0
- package/dist/src/shell/SearchPanel.js +51 -24
- package/dist/src/shell/Shell.d.ts +18 -0
- package/dist/src/shell/Shell.js +137 -22
- package/dist/src/shell/ShortcutHelp.d.ts +22 -0
- package/dist/src/shell/ShortcutHelp.js +66 -0
- package/dist/src/shell/Sidebar.d.ts +17 -4
- package/dist/src/shell/Sidebar.js +92 -41
- package/dist/src/shell/SidebarDocs.js +2 -2
- package/dist/src/shell/SidebarEntries.js +5 -3
- package/dist/src/shell/SidebarHandle.d.ts +3 -5
- package/dist/src/shell/SidebarHandle.js +4 -4
- package/dist/src/shell/SidebarRefs.d.ts +39 -0
- package/dist/src/shell/SidebarRefs.js +99 -0
- package/dist/src/shell/SidebarSearch.js +37 -9
- package/dist/src/shell/SignatureReference.js +3 -1
- package/dist/src/shell/Stage.d.ts +10 -2
- package/dist/src/shell/Stage.js +29 -49
- package/dist/src/shell/StatusBadges.d.ts +54 -0
- package/dist/src/shell/StatusBadges.js +77 -0
- package/dist/src/shell/StoryCodeBlock.d.ts +8 -19
- package/dist/src/shell/StoryCodeBlock.js +7 -6
- package/dist/src/shell/SwitchGallery.d.ts +36 -0
- package/dist/src/shell/SwitchGallery.js +17 -0
- package/dist/src/shell/SwitchGalleryPanel.d.ts +37 -0
- package/dist/src/shell/SwitchGalleryPanel.js +99 -0
- package/dist/src/shell/TagFilter.d.ts +24 -0
- package/dist/src/shell/TagFilter.js +45 -0
- package/dist/src/shell/TagViews.d.ts +39 -0
- package/dist/src/shell/TagViews.js +20 -0
- package/dist/src/shell/Toolbar.d.ts +4 -1
- package/dist/src/shell/Toolbar.js +17 -7
- package/dist/src/shell/ToolbarControl.d.ts +3 -0
- package/dist/src/shell/ToolbarControl.js +23 -6
- package/dist/src/shell/ViewMenuPanel.js +6 -1
- package/dist/src/shell/argChecks.d.ts +22 -0
- package/dist/src/shell/argChecks.js +20 -0
- package/dist/src/shell/asideStory.js +7 -2
- package/dist/src/shell/audienceSections.css +9 -9
- package/dist/src/shell/catalogueContext.d.ts +1 -1
- package/dist/src/shell/catalogueContext.js +6 -1
- package/dist/src/shell/codeSpans.d.ts +27 -0
- package/dist/src/shell/codeSpans.js +76 -0
- package/dist/src/shell/compareVariants.d.ts +4 -2
- package/dist/src/shell/compareVariants.js +16 -8
- package/dist/src/shell/composition.d.ts +23 -0
- package/dist/src/shell/composition.js +26 -0
- package/dist/src/shell/controlCycle.d.ts +1 -1
- package/dist/src/shell/controlCycle.js +3 -2
- package/dist/src/shell/customControls.d.ts +55 -0
- package/dist/src/shell/customControls.js +70 -0
- package/dist/src/shell/docPage.css +22 -22
- package/dist/src/shell/dockTabs.d.ts +19 -3
- package/dist/src/shell/dockTabs.js +28 -20
- package/dist/src/shell/embed.css +7 -7
- package/dist/src/shell/framesOrigin.d.ts +7 -0
- package/dist/src/shell/framesOrigin.js +1 -1
- package/dist/src/shell/galleryPlace.d.ts +20 -0
- package/dist/src/shell/galleryPlace.js +26 -0
- package/dist/src/shell/icons.d.ts +1 -0
- package/dist/src/shell/icons.js +1 -0
- package/dist/src/shell/keyboard.d.ts +14 -12
- package/dist/src/shell/keyboard.js +21 -6
- package/dist/src/shell/laterStrings.d.ts +29 -0
- package/dist/src/shell/laterStrings.js +42 -3
- package/dist/src/shell/mountShell.js +3 -0
- package/dist/src/shell/pageStrings.d.ts +4 -0
- package/dist/src/shell/pageStrings.js +4 -0
- package/dist/src/shell/pageTagView.d.ts +18 -0
- package/dist/src/shell/pageTagView.js +10 -0
- package/dist/src/shell/playMemory.d.ts +14 -0
- package/dist/src/shell/playMemory.js +8 -0
- package/dist/src/shell/propNotes.d.ts +23 -0
- package/dist/src/shell/propNotes.js +37 -0
- package/dist/src/shell/refIndexLoad.d.ts +17 -0
- package/dist/src/shell/refIndexLoad.js +38 -0
- package/dist/src/shell/refParts.d.ts +34 -0
- package/dist/src/shell/refParts.js +9 -0
- package/dist/src/shell/refStory.css +21 -0
- package/dist/src/shell/refStrings.d.ts +13 -0
- package/dist/src/shell/refStrings.js +21 -0
- package/dist/src/shell/search.css +11 -11
- package/dist/src/shell/shell.css +348 -168
- package/dist/src/shell/shellScheme.js +2 -2
- package/dist/src/shell/shortcutHelp.css +64 -0
- package/dist/src/shell/stageArgs.d.ts +53 -0
- package/dist/src/shell/stageArgs.js +64 -0
- package/dist/src/shell/statusBadges.css +51 -0
- package/dist/src/shell/strings.d.ts +7 -16
- package/dist/src/shell/strings.js +12 -17
- package/dist/src/shell/switchGallery.css +104 -0
- package/dist/src/shell/tagFilter.css +46 -0
- package/dist/src/shell/tagView.d.ts +20 -0
- package/dist/src/shell/tagView.js +10 -0
- package/dist/src/shell/useAddressArgs.d.ts +9 -0
- package/dist/src/shell/useAddressArgs.js +56 -11
- package/dist/src/shell/useControlKeys.js +2 -2
- package/dist/src/shell/useEditedProblems.d.ts +6 -0
- package/dist/src/shell/useEditedProblems.js +40 -0
- package/dist/src/shell/useFrameMessages.js +3 -0
- package/dist/src/shell/useListedTree.d.ts +13 -0
- package/dist/src/shell/useListedTree.js +32 -0
- package/dist/src/shell/usePageFrames.js +2 -2
- package/dist/src/shell/usePopover.d.ts +5 -0
- package/dist/src/shell/usePopover.js +7 -1
- package/dist/src/shell/useRefIndex.d.ts +22 -0
- package/dist/src/shell/useRefIndex.js +36 -0
- package/dist/src/shell/useScrollStops.d.ts +20 -0
- package/dist/src/shell/useScrollStops.js +41 -0
- package/dist/src/shell/useShortcutHelp.d.ts +18 -0
- package/dist/src/shell/useShortcutHelp.js +32 -0
- package/dist/src/shell/useSidebarOverlay.d.ts +2 -1
- package/dist/src/shell/useSidebarOverlay.js +12 -4
- package/dist/src/shell/useStoryCode.d.ts +2 -1
- package/dist/src/shell/useStoryCode.js +12 -7
- package/dist/src/shell/useToolbarLayout.d.ts +5 -1
- package/dist/src/shell/useToolbarLayout.js +2 -2
- package/dist/src/shell/useWorstCase.d.ts +8 -2
- package/dist/src/shell/useWorstCase.js +2 -2
- package/dist/src/shell/valueEditors/FileEditor.d.ts +28 -0
- package/dist/src/shell/valueEditors/FileEditor.js +66 -0
- package/dist/src/shell/valueEditors/JsonEditor.d.ts +14 -0
- package/dist/src/shell/valueEditors/JsonEditor.js +53 -0
- package/dist/src/shell/valueEditors/ListEditor.d.ts +24 -0
- package/dist/src/shell/valueEditors/ListEditor.js +82 -0
- package/dist/src/shell/valueEditors/ObjectEditor.d.ts +32 -0
- package/dist/src/shell/valueEditors/ObjectEditor.js +70 -0
- package/dist/src/shell/valueEditors/PropEditor.d.ts +37 -0
- package/dist/src/shell/valueEditors/PropEditor.js +53 -0
- package/dist/src/shell/valueEditors/RecordEditor.d.ts +20 -0
- package/dist/src/shell/valueEditors/RecordEditor.js +84 -0
- package/dist/src/shell/valueEditors/SearchSelect.d.ts +42 -0
- package/dist/src/shell/valueEditors/SearchSelect.js +80 -0
- package/dist/src/shell/valueEditors/TokenEditor.d.ts +49 -0
- package/dist/src/shell/valueEditors/TokenEditor.js +74 -0
- package/dist/src/shell/valueEditors/UnionEditor.d.ts +20 -0
- package/dist/src/shell/valueEditors/UnionEditor.js +64 -0
- package/dist/src/shell/valueEditors/ValueField.d.ts +15 -0
- package/dist/src/shell/valueEditors/ValueField.js +147 -0
- package/dist/src/shell/valueEditors/editorStrings.d.ts +56 -0
- package/dist/src/shell/valueEditors/editorStrings.js +66 -0
- package/dist/src/shell/valueEditors/fieldTypes.d.ts +31 -0
- package/dist/src/shell/valueEditors/fieldTypes.js +0 -0
- package/dist/src/shell/valueEditors/valueEditors.css +153 -0
- package/dist/src/shell/worstArgs.d.ts +8 -5
- package/dist/src/shell/worstArgs.js +14 -7
- package/dist/src/shellTheme.d.ts +1 -1
- package/dist/src/shellTheme.js +15 -1
- package/dist/src/shellTheme.types.d.ts +4 -0
- package/dist/src/shellWord.d.ts +12 -0
- package/dist/src/shellWord.js +15 -0
- package/dist/src/sourceFiles.js +2 -1
- package/dist/src/storyArgTypes.d.ts +57 -0
- package/dist/src/storyArgTypes.js +195 -0
- package/dist/src/storyBackground.js +14 -3
- package/dist/src/storyCheck.d.ts +85 -3
- package/dist/src/storyCheck.js +23 -1
- package/dist/src/storyCodeText.d.ts +46 -0
- package/dist/src/storyCodeText.js +27 -0
- package/dist/src/storyControls.d.ts +100 -0
- package/dist/src/storyControls.js +100 -0
- package/dist/src/storyStatuses.d.ts +55 -0
- package/dist/src/storyStatuses.js +104 -0
- package/dist/src/storyTagNames.d.ts +25 -0
- package/dist/src/storyTagNames.js +25 -0
- package/dist/src/storyTags.d.ts +29 -0
- package/dist/src/storyTags.js +85 -0
- package/dist/src/storyTree.d.ts +13 -0
- package/dist/src/storyTree.js +24 -4
- package/dist/src/storybookArgs.d.ts +24 -0
- package/dist/src/storybookArgs.js +185 -0
- package/dist/src/switches.d.ts +66 -3
- package/dist/src/switches.js +42 -1
- package/dist/src/valueSchema.d.ts +28 -0
- package/dist/src/valueSchema.js +196 -0
- package/dist/src/valueShape.d.ts +94 -0
- package/dist/src/valueShape.js +25 -0
- package/dist/src/viewState.d.ts +8 -3
- package/dist/src/viewState.js +27 -10
- package/dist/src/vite/adapter.d.ts +40 -2
- package/dist/src/vite/adapter.js +1 -0
- package/dist/src/vite/agent.types.d.ts +347 -7
- package/dist/src/vite/agentApi.d.ts +23 -0
- package/dist/src/vite/agentApi.js +90 -17
- package/dist/src/vite/agentIndex.d.ts +0 -2
- package/dist/src/vite/agentIndex.js +5 -6
- package/dist/src/vite/agentRoutes.d.ts +20 -1
- package/dist/src/vite/agentRoutes.js +106 -65
- package/dist/src/vite/agentStatuses.d.ts +42 -0
- package/dist/src/vite/agentStatuses.js +67 -0
- package/dist/src/vite/agentStoryCode.d.ts +48 -0
- package/dist/src/vite/agentStoryCode.js +38 -0
- package/dist/src/vite/agentVisibility.d.ts +47 -0
- package/dist/src/vite/agentVisibility.js +174 -0
- package/dist/src/vite/appAudit.d.ts +134 -0
- package/dist/src/vite/appAudit.js +333 -0
- package/dist/src/vite/appBuildOption.d.ts +53 -0
- package/dist/src/vite/appBuildOption.js +55 -0
- package/dist/src/vite/appTokenFiles.d.ts +92 -0
- package/dist/src/vite/appTokenFiles.js +433 -0
- package/dist/src/vite/appTokens.d.ts +23 -0
- package/dist/src/vite/appTokens.js +275 -0
- package/dist/src/vite/builtTexts.d.ts +10 -0
- package/dist/src/vite/builtTexts.js +59 -22
- package/dist/src/vite/catalogueConfig.d.ts +3 -1
- package/dist/src/vite/catalogueConfig.js +15 -3
- package/dist/src/vite/changeCoverage.d.ts +74 -0
- package/dist/src/vite/changeCoverage.js +120 -0
- package/dist/src/vite/changedRoute.d.ts +30 -0
- package/dist/src/vite/changedRoute.js +197 -0
- package/dist/src/vite/checkCode.d.ts +105 -3
- package/dist/src/vite/checkCode.js +323 -36
- package/dist/src/vite/checkoutWatch.d.ts +97 -0
- package/dist/src/vite/checkoutWatch.js +287 -0
- package/dist/src/vite/closeWatch.d.ts +8 -0
- package/dist/src/vite/closeWatch.js +1 -1
- package/dist/src/vite/componentCache.d.ts +8 -0
- package/dist/src/vite/componentCache.js +66 -0
- package/dist/src/vite/componentGraph.d.ts +71 -0
- package/dist/src/vite/componentGraph.js +133 -0
- package/dist/src/vite/componentRules.d.ts +33 -0
- package/dist/src/vite/componentRules.js +105 -0
- package/dist/src/vite/componentScan.d.ts +69 -0
- package/dist/src/vite/componentScan.js +418 -0
- package/dist/src/vite/compositionCheck.d.ts +15 -0
- package/dist/src/vite/compositionCheck.js +243 -0
- package/dist/src/vite/config.d.ts +32 -1
- package/dist/src/vite/configFile.d.ts +14 -2
- package/dist/src/vite/configFile.js +124 -40
- package/dist/src/vite/configKeys.d.ts +15 -0
- package/dist/src/vite/configKeys.js +171 -0
- package/dist/src/vite/configLoadError.d.ts +23 -0
- package/dist/src/vite/configLoadError.js +71 -0
- package/dist/src/vite/cssDeclarations.d.ts +71 -0
- package/dist/src/vite/cssDeclarations.js +290 -0
- package/dist/src/vite/cssImports.d.ts +14 -0
- package/dist/src/vite/cssImports.js +48 -0
- package/dist/src/vite/cssReferences.d.ts +54 -0
- package/dist/src/vite/cssReferences.js +157 -0
- package/dist/src/vite/cssTokenValues.d.ts +50 -0
- package/dist/src/vite/cssTokenValues.js +233 -0
- package/dist/src/vite/designTokens.d.ts +24 -0
- package/dist/src/vite/designTokens.js +5 -1
- package/dist/src/vite/docsExtractor.d.ts +9 -3
- package/dist/src/vite/docsExtractor.js +11 -3
- package/dist/src/vite/docsProgram.d.ts +17 -4
- package/dist/src/vite/docsProgram.js +52 -11
- package/dist/src/vite/docsWorker.js +7 -2
- package/dist/src/vite/emptyStoryGlobs.d.ts +41 -0
- package/dist/src/vite/emptyStoryGlobs.js +52 -0
- package/dist/src/vite/fileImports.d.ts +17 -0
- package/dist/src/vite/fileImports.js +57 -0
- package/dist/src/vite/findComponent.d.ts +10 -2
- package/dist/src/vite/findComponent.js +27 -22
- package/dist/src/vite/findRoute.js +3 -2
- package/dist/src/vite/forcedStates.d.ts +9 -2
- package/dist/src/vite/forcedStates.js +12 -3
- package/dist/src/vite/forgebookPlugin.d.ts +2 -0
- package/dist/src/vite/forgebookPlugin.js +52 -72
- package/dist/src/vite/frameErrors.d.ts +19 -0
- package/dist/src/vite/frameErrors.js +70 -0
- package/dist/src/vite/framesServer.d.ts +12 -0
- package/dist/src/vite/framesServer.js +21 -4
- package/dist/src/vite/functionComponentDocs.js +81 -12
- package/dist/src/vite/generatedModules.js +4 -2
- package/dist/src/vite/gitChange.d.ts +38 -5
- package/dist/src/vite/gitChange.js +71 -11
- package/dist/src/vite/hiddenStoryFiles.d.ts +23 -0
- package/dist/src/vite/hiddenStoryFiles.js +107 -0
- package/dist/src/vite/hotSnippets.d.ts +38 -14
- package/dist/src/vite/hotSnippets.js +137 -39
- package/dist/src/vite/importedNames.d.ts +37 -0
- package/dist/src/vite/importedNames.js +138 -0
- package/dist/src/vite/indexFields.d.ts +6 -0
- package/dist/src/vite/indexFields.js +21 -0
- package/dist/src/vite/indexStoryFile.d.ts +8 -1
- package/dist/src/vite/indexStoryFile.js +22 -157
- package/dist/src/vite/jsxCallSites.d.ts +33 -0
- package/dist/src/vite/jsxCallSites.js +200 -0
- package/dist/src/vite/jsxInScripts.d.ts +67 -0
- package/dist/src/vite/jsxInScripts.js +138 -0
- package/dist/src/vite/jsxTree.d.ts +20 -0
- package/dist/src/vite/jsxTree.js +163 -0
- package/dist/src/vite/lineAndColumn.d.ts +13 -0
- package/dist/src/vite/lineAndColumn.js +18 -0
- package/dist/src/vite/lookAlikes.d.ts +65 -0
- package/dist/src/vite/lookAlikes.js +228 -0
- package/dist/src/vite/nearestToken.d.ts +17 -0
- package/dist/src/vite/nearestToken.js +9 -2
- package/dist/src/vite/packageEntries.d.ts +42 -0
- package/dist/src/vite/packageEntries.js +127 -0
- package/dist/src/vite/pages.d.ts +9 -1
- package/dist/src/vite/pages.js +108 -4
- package/dist/src/vite/pluginConfig.js +4 -0
- package/dist/src/vite/pluginIds.d.ts +2 -0
- package/dist/src/vite/pluginIds.js +5 -1
- package/dist/src/vite/pluginModules.d.ts +81 -11
- package/dist/src/vite/pluginModules.js +109 -21
- package/dist/src/vite/prebundled.d.ts +57 -15
- package/dist/src/vite/prebundled.js +80 -0
- package/dist/src/vite/previewTags.d.ts +25 -0
- package/dist/src/vite/previewTags.js +56 -0
- package/dist/src/vite/projectFiles.d.ts +54 -0
- package/dist/src/vite/projectFiles.js +116 -0
- package/dist/src/vite/projectPostcss.d.ts +70 -0
- package/dist/src/vite/projectPostcss.js +250 -0
- package/dist/src/vite/propDocs.d.ts +12 -0
- package/dist/src/vite/propDocs.js +130 -58
- package/dist/src/vite/propKind.d.ts +40 -0
- package/dist/src/vite/propKind.js +71 -0
- package/dist/src/vite/propTypeNotes.d.ts +22 -0
- package/dist/src/vite/propTypeNotes.js +51 -0
- package/dist/src/vite/publishedExports.d.ts +27 -0
- package/dist/src/vite/publishedExports.js +298 -0
- package/dist/src/vite/realFolder.d.ts +6 -0
- package/dist/src/vite/realFolder.js +25 -0
- package/dist/src/vite/refsConfig.d.ts +39 -0
- package/dist/src/vite/refsConfig.js +54 -0
- package/dist/src/vite/reuseCheck.d.ts +45 -0
- package/dist/src/vite/reuseCheck.js +260 -0
- package/dist/src/vite/runningVersions.d.ts +33 -0
- package/dist/src/vite/runningVersions.js +25 -0
- package/dist/src/vite/scriptProblems.d.ts +60 -0
- package/dist/src/vite/scriptProblems.js +155 -0
- package/dist/src/vite/searchModule.js +3 -2
- package/dist/src/vite/searchRoute.js +4 -2
- package/dist/src/vite/shapeDocs.d.ts +36 -0
- package/dist/src/vite/shapeDocs.js +177 -0
- package/dist/src/vite/singleFileComponent.d.ts +17 -0
- package/dist/src/vite/singleFileComponent.js +83 -0
- package/dist/src/vite/sourceText.d.ts +34 -0
- package/dist/src/vite/sourceText.js +72 -0
- package/dist/src/vite/sourceTokens.d.ts +7 -0
- package/dist/src/vite/sourceTokens.js +7 -2
- package/dist/src/vite/stackLines.d.ts +49 -0
- package/dist/src/vite/stackLines.js +96 -0
- package/dist/src/vite/storyCode.d.ts +22 -7
- package/dist/src/vite/storyCode.js +263 -37
- package/dist/src/vite/storyCoverage.d.ts +48 -0
- package/dist/src/vite/storyCoverage.js +179 -0
- package/dist/src/vite/storyFilesModule.d.ts +48 -3
- package/dist/src/vite/storyFilesModule.js +105 -15
- package/dist/src/vite/storyPatterns.d.ts +31 -0
- package/dist/src/vite/storyPatterns.js +140 -5
- package/dist/src/vite/storyReach.d.ts +10 -2
- package/dist/src/vite/storyReach.js +15 -11
- package/dist/src/vite/storyTopLevel.d.ts +51 -0
- package/dist/src/vite/storyTopLevel.js +146 -0
- package/dist/src/vite/storylessRoutes.d.ts +4 -3
- package/dist/src/vite/storylessRoutes.js +210 -19
- package/dist/src/vite/switchValuesCheck.d.ts +19 -0
- package/dist/src/vite/switchValuesCheck.js +164 -0
- package/dist/src/vite/switchesDocument.d.ts +15 -0
- package/dist/src/vite/switchesDocument.js +47 -0
- package/dist/src/vite/tailwindConfigTokens.d.ts +41 -0
- package/dist/src/vite/tailwindConfigTokens.js +306 -0
- package/dist/src/vite/textImports.d.ts +15 -0
- package/dist/src/vite/textImports.js +58 -0
- package/dist/src/vite/textModules.d.ts +6 -5
- package/dist/src/vite/textModules.js +13 -8
- package/dist/src/vite/tokenAnswers.d.ts +6 -2
- package/dist/src/vite/tokenAnswers.js +11 -7
- package/dist/src/vite/typeParameters.d.ts +83 -0
- package/dist/src/vite/typeParameters.js +270 -0
- package/dist/src/vite/unionProps.d.ts +37 -0
- package/dist/src/vite/unionProps.js +121 -0
- package/dist/src/vite/unresolvedTokens.d.ts +20 -0
- package/dist/src/vite/unresolvedTokens.js +193 -0
- package/dist/src/vite/usageGraph.js +10 -52
- package/dist/src/vite/usageGuidance.d.ts +9 -2
- package/dist/src/vite/usageGuidance.js +36 -8
- package/dist/src/vite/usageImports.d.ts +35 -0
- package/dist/src/vite/usageImports.js +280 -0
- package/dist/src/vite/visibilityRoute.d.ts +16 -0
- package/dist/src/vite/visibilityRoute.js +320 -0
- package/dist/src/worstCase.d.ts +2 -0
- package/dist/src/worstCase.js +2 -0
- package/package.json +28 -8
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `forgebook init --agents` writes for a project's coding agents: `.mcp.json`, the instructions and the skill, the CI
|
|
3
|
+
* workflow, and a hook that runs `verify` when an assistant finishes or before a commit.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Every file is merged or left as it is, never replaced: `.mcp.json` and the assistants' settings keep what they hold, the
|
|
7
|
+
* instructions go between their markers, a workflow or a pre-commit hook already there stays and is named. They go at the
|
|
8
|
+
* repository's root, where assistants and CI start, and they find a package's catalogue through its folder. Which hooks is
|
|
9
|
+
* asked with `--hooks`; by default those of the assistants the repository shows signs of, and otherwise a pre-commit hook,
|
|
10
|
+
* which any assistant meets. A file that is a link is never written through. Nothing here runs the project's code.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { execFileSync } from "node:child_process";
|
|
15
|
+
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { dirname, join, relative } from "node:path";
|
|
18
|
+
import { VITE_PATHS } from "../../../src/vite/vitePaths.js";
|
|
19
|
+
import { agentsSection } from "../agentGuide.js";
|
|
20
|
+
import { agentsSkill, SKILL_FOLDERS, withAgentsSection } from "../agentsText.js";
|
|
21
|
+
import { ASSISTANT_NAMES, ASSISTANTS, withMcpServer, withStopHook } from "./assistantHooks.js";
|
|
22
|
+
import { WORKFLOW_FILE, workflowText } from "./ciWorkflow.js";
|
|
23
|
+
import { forgebookCommandLine, forgebookInstalledLine, isPlainFolder, mcpServerOf } from "./projectRunner.js";
|
|
24
|
+
/** The lock files a locked install reads. */
|
|
25
|
+
const LOCK_FILES = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb"];
|
|
26
|
+
/** How an assistant's hook names the project's root, for those whose documentation gives one. */
|
|
27
|
+
const PROJECT_ROOT_VARIABLE = {
|
|
28
|
+
claude: "$CLAUDE_PROJECT_DIR/",
|
|
29
|
+
gemini: "$GEMINI_PROJECT_DIR/"
|
|
30
|
+
};
|
|
31
|
+
/** What marks a pre-commit hook as written here. */
|
|
32
|
+
const OWN_PRE_COMMIT = /forgebook\b.*\bverify/;
|
|
33
|
+
/**
|
|
34
|
+
* A project's repository root: the nearest folder holding `.git` whose repository tracks it, or the project's otherwise.
|
|
35
|
+
*
|
|
36
|
+
* @param projectDir - the project's folder.
|
|
37
|
+
*/
|
|
38
|
+
export const repositoryRoot = (projectDir) => {
|
|
39
|
+
let dir = projectDir;
|
|
40
|
+
while (true) {
|
|
41
|
+
if (existsSync(join(dir, ".git")))
|
|
42
|
+
return isTrackedBy(dir, projectDir) ? dir : projectDir;
|
|
43
|
+
const parent = dirname(dir);
|
|
44
|
+
if (parent === dir || dir === homedir())
|
|
45
|
+
return projectDir;
|
|
46
|
+
dir = parent;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Whether a repository holds a project: a home folder kept in git is above many projects it knows nothing of, and what is
|
|
51
|
+
* written at its root would be that person's settings for every project.
|
|
52
|
+
*
|
|
53
|
+
* @param root - the repository's folder.
|
|
54
|
+
* @param projectDir - the project's folder.
|
|
55
|
+
*/
|
|
56
|
+
const isTrackedBy = (root, projectDir) => {
|
|
57
|
+
if (root === projectDir)
|
|
58
|
+
return true;
|
|
59
|
+
try {
|
|
60
|
+
execFileSync("git", ["ls-files", "--error-unmatch", join(projectDir, "package.json")], {
|
|
61
|
+
cwd: root,
|
|
62
|
+
stdio: "pipe"
|
|
63
|
+
});
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* The hooks to write when none are named: those of the assistants the repository shows signs of, otherwise the commit's.
|
|
72
|
+
*
|
|
73
|
+
* @param root - the repository's root.
|
|
74
|
+
*/
|
|
75
|
+
export const detectedHooks = (root) => {
|
|
76
|
+
const used = ASSISTANT_NAMES.filter((name) => ASSISTANTS[name].markers.some((marker) => existsSync(join(root, marker))));
|
|
77
|
+
return used.length === 0 ? ["pre-commit"] : used;
|
|
78
|
+
};
|
|
79
|
+
/** Whether a path, or a folder on the way to it from the root, is a link: writing through one would change a file elsewhere. */
|
|
80
|
+
const isLink = (root, name) => {
|
|
81
|
+
const parts = name.split("/");
|
|
82
|
+
return parts.some((_, index) => lstatSync(join(root, ...parts.slice(0, index + 1)), { throwIfNoEntry: false })?.isSymbolicLink() ===
|
|
83
|
+
true);
|
|
84
|
+
};
|
|
85
|
+
/** A file's text; none when it is not there. */
|
|
86
|
+
const readIfThere = (file) => existsSync(file) ? readFileSync(file, "utf8") : undefined;
|
|
87
|
+
/** Writes a file, its folder made. */
|
|
88
|
+
const writeInto = (file, text) => {
|
|
89
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
90
|
+
writeFileSync(file, text);
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Applies a merge to a file.
|
|
94
|
+
*
|
|
95
|
+
* @param root - the repository's root.
|
|
96
|
+
* @param name - the file, from there.
|
|
97
|
+
* @param merge - what to make of its text.
|
|
98
|
+
* @param done - what the run has done.
|
|
99
|
+
* @returns whether the file holds what it should now.
|
|
100
|
+
*/
|
|
101
|
+
const mergeFile = (root, name, merge, done) => {
|
|
102
|
+
const file = join(root, name);
|
|
103
|
+
if (isLink(root, name)) {
|
|
104
|
+
done.nextSteps.push({
|
|
105
|
+
kind: "setup",
|
|
106
|
+
file: name,
|
|
107
|
+
message: `${name} is a link, so it was left as it is: add Forgebook to it by hand`
|
|
108
|
+
});
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const text = readIfThere(file);
|
|
112
|
+
const merged = merge(text);
|
|
113
|
+
if (merged.kind === "unreadable") {
|
|
114
|
+
done.nextSteps.push({
|
|
115
|
+
kind: "setup",
|
|
116
|
+
file: name,
|
|
117
|
+
message: `${name} could not be read as the JSON it should be, so it was left as it is: add Forgebook to it by hand`
|
|
118
|
+
});
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (merged.kind === "unchanged" || merged.text === text) {
|
|
122
|
+
done.unchanged.push(name);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
writeInto(file, merged.text);
|
|
126
|
+
done.written.push(name);
|
|
127
|
+
return true;
|
|
128
|
+
};
|
|
129
|
+
/** Writes the instructions into `AGENTS.md`, between their markers, and the skill. */
|
|
130
|
+
const writeInstructions = (root, framework, done) => {
|
|
131
|
+
const section = agentsSection([framework]);
|
|
132
|
+
mergeFile(root, "AGENTS.md", (text) => ({ kind: "written", text: withAgentsSection(text, section) }), done);
|
|
133
|
+
for (const folder of SKILL_FOLDERS)
|
|
134
|
+
mergeFile(root, `${folder}/SKILL.md`, () => ({ kind: "written", text: agentsSkill(section) }), done);
|
|
135
|
+
};
|
|
136
|
+
/** Writes the workflow on a repository with GitHub's signs, leaving one there; another host is told. */
|
|
137
|
+
const writeWorkflow = (root, manager, folder, done) => {
|
|
138
|
+
const file = join(root, WORKFLOW_FILE);
|
|
139
|
+
if (isLink(root, WORKFLOW_FILE)) {
|
|
140
|
+
done.nextSteps.push({
|
|
141
|
+
kind: "setup",
|
|
142
|
+
file: WORKFLOW_FILE,
|
|
143
|
+
message: `${WORKFLOW_FILE} is a link, so no workflow was written`
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (existsSync(file)) {
|
|
148
|
+
done.unchanged.push(WORKFLOW_FILE);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const isGitHub = existsSync(join(root, ".github")) ||
|
|
152
|
+
/github\.com/.test(readIfThere(join(root, ".git", "config")) ?? "") ||
|
|
153
|
+
!existsSync(join(root, ".git"));
|
|
154
|
+
if (!isGitHub) {
|
|
155
|
+
done.nextSteps.push({
|
|
156
|
+
kind: "setup",
|
|
157
|
+
file: undefined,
|
|
158
|
+
message: `This repository is not on GitHub, so no workflow was written: in its CI, run ${forgebookCommandLine(manager, folder, "browser --with-deps")}, then ${forgebookCommandLine(manager, folder, "verify --since <target branch>")}`
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const hasLockFile = LOCK_FILES.some((name) => existsSync(join(root, name)));
|
|
163
|
+
writeInto(file, workflowText(manager, folder, hasLockFile));
|
|
164
|
+
done.written.push(WORKFLOW_FILE);
|
|
165
|
+
};
|
|
166
|
+
/** The folder a repository's git hooks are read from, as git says; none outside a repository or with `core.hooksPath`. */
|
|
167
|
+
const gitHooksFolder = (root) => {
|
|
168
|
+
try {
|
|
169
|
+
const custom = execFileSync("git", ["config", "core.hooksPath"], {
|
|
170
|
+
cwd: root,
|
|
171
|
+
encoding: "utf8",
|
|
172
|
+
stdio: "pipe"
|
|
173
|
+
});
|
|
174
|
+
if (custom.trim() !== "")
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// git says nothing when it is not set, by failing
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const path = execFileSync("git", ["rev-parse", "--path-format=absolute", "--git-path", "hooks"], {
|
|
182
|
+
cwd: root,
|
|
183
|
+
encoding: "utf8",
|
|
184
|
+
stdio: "pipe"
|
|
185
|
+
});
|
|
186
|
+
// git may name the folder in a short form (Windows' 8.3 names): the long one, as the root is named, compares
|
|
187
|
+
const folder = path.trim();
|
|
188
|
+
return existsSync(folder) ? realpathSync.native(folder) : folder;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
/** The text of a pre-commit hook. */
|
|
195
|
+
const preCommitLines = ({ installed, verify }) => "# Written by forgebook init --agents: a change whose UI is red does not get committed\n" +
|
|
196
|
+
// a teammate who has not installed yet commits as before: a hook that cannot run must not stop every commit
|
|
197
|
+
`if ${installed} >/dev/null 2>&1; then\n ${verify}\nfi\n`;
|
|
198
|
+
/** Adds `verify` to Husky's hook, which the repository keeps under version control. */
|
|
199
|
+
const writeHusky = (root, commands, done) => {
|
|
200
|
+
const name = ".husky/pre-commit";
|
|
201
|
+
const file = join(root, name);
|
|
202
|
+
if (isLink(root, name)) {
|
|
203
|
+
done.nextSteps.push({
|
|
204
|
+
kind: "setup",
|
|
205
|
+
file: name,
|
|
206
|
+
message: `${name} is a link, so it was left as it is: add \`${commands.verify}\` to it`
|
|
207
|
+
});
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
const text = readIfThere(file) ?? "";
|
|
211
|
+
if (OWN_PRE_COMMIT.test(text))
|
|
212
|
+
done.unchanged.push(name);
|
|
213
|
+
else {
|
|
214
|
+
writeInto(file, `${text.replace(/\n*$/, text === "" ? "" : "\n")}${preCommitLines(commands)}`);
|
|
215
|
+
chmodSync(file, 0o755);
|
|
216
|
+
done.written.push(name);
|
|
217
|
+
}
|
|
218
|
+
return { name: "pre-commit", file: name, effect: "blocks-commit" };
|
|
219
|
+
};
|
|
220
|
+
/** Writes the commit's hook where the repository's tools keep it, or says why it did not. */
|
|
221
|
+
const writePreCommit = (root, commands, done) => {
|
|
222
|
+
if (existsSync(join(root, ".husky")))
|
|
223
|
+
return writeHusky(root, commands, done);
|
|
224
|
+
const other = ["lefthook.yml", ".lefthook.yml", ".pre-commit-config.yaml"].find((name) => existsSync(join(root, name)));
|
|
225
|
+
const folder = other === undefined ? gitHooksFolder(root) : undefined;
|
|
226
|
+
const file = folder === undefined ? undefined : join(folder, "pre-commit");
|
|
227
|
+
// set up again, a hook that already runs verify (an earlier run's) is this one's own, not a setup of the repository's
|
|
228
|
+
if (file !== undefined &&
|
|
229
|
+
lstatSync(file, { throwIfNoEntry: false })?.isFile() === true &&
|
|
230
|
+
OWN_PRE_COMMIT.test(readIfThere(file) ?? "")) {
|
|
231
|
+
const shown = VITE_PATHS.normalize(relative(realpathSync.native(root), file));
|
|
232
|
+
done.unchanged.push(shown);
|
|
233
|
+
return { name: "pre-commit", file: shown, effect: "blocks-commit" };
|
|
234
|
+
}
|
|
235
|
+
const isTaken = file === undefined ||
|
|
236
|
+
existsSync(file) ||
|
|
237
|
+
lstatSync(file, { throwIfNoEntry: false })?.isSymbolicLink() === true;
|
|
238
|
+
if (isTaken) {
|
|
239
|
+
done.nextSteps.push({
|
|
240
|
+
kind: "setup",
|
|
241
|
+
file: other,
|
|
242
|
+
message: `The repository's commits have a hook setup of their own${other === undefined ? "" : ` (${other})`}, which was left as it is: add \`${commands.verify}\` to it`
|
|
243
|
+
});
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
writeInto(file, `#!/bin/sh\n${preCommitLines(commands)}`);
|
|
247
|
+
chmodSync(file, 0o755);
|
|
248
|
+
const shown = VITE_PATHS.normalize(relative(realpathSync.native(root), file));
|
|
249
|
+
done.written.push(shown);
|
|
250
|
+
done.nextSteps.push({
|
|
251
|
+
kind: "setup",
|
|
252
|
+
file: shown,
|
|
253
|
+
message: `${shown} holds the commit's hook, and git does not share that folder: a teammate's clone has none, so commit a hook setup (Husky, Lefthook) if they should have it too`
|
|
254
|
+
});
|
|
255
|
+
return { name: "pre-commit", file: shown, effect: "blocks-commit" };
|
|
256
|
+
};
|
|
257
|
+
/** Writes one hook. */
|
|
258
|
+
const writeHook = (root, name, manager, folder, done) => {
|
|
259
|
+
if (name === "pre-commit")
|
|
260
|
+
return writePreCommit(root, {
|
|
261
|
+
installed: forgebookInstalledLine(manager, folder),
|
|
262
|
+
verify: forgebookCommandLine(manager, folder, "verify --quick")
|
|
263
|
+
}, done);
|
|
264
|
+
const assistant = ASSISTANTS[name];
|
|
265
|
+
// these two name their project's root, so a hook started from another folder still finds the package
|
|
266
|
+
const base = PROJECT_ROOT_VARIABLE[name] ?? "";
|
|
267
|
+
const command = forgebookCommandLine(manager, folder, `hook ${name}`, base);
|
|
268
|
+
if (!mergeFile(root, assistant.file, (text) => withStopHook(name, text, command), done))
|
|
269
|
+
return undefined;
|
|
270
|
+
if (assistant.caveat !== undefined)
|
|
271
|
+
done.nextSteps.push({
|
|
272
|
+
kind: "setup",
|
|
273
|
+
file: assistant.file,
|
|
274
|
+
message: `${assistant.caveat}: ${assistant.file}`
|
|
275
|
+
});
|
|
276
|
+
return { name, file: assistant.file, effect: assistant.effect };
|
|
277
|
+
};
|
|
278
|
+
/**
|
|
279
|
+
* Writes what a project's coding agents need.
|
|
280
|
+
*
|
|
281
|
+
* @param request - what for.
|
|
282
|
+
*/
|
|
283
|
+
export const writeAgentFiles = ({ projectDir, framework, manager, hooks }) => {
|
|
284
|
+
const root = repositoryRoot(projectDir);
|
|
285
|
+
const folder = VITE_PATHS.normalize(relative(root, projectDir));
|
|
286
|
+
const done = { written: [], unchanged: [], nextSteps: [] };
|
|
287
|
+
if (!isPlainFolder(folder))
|
|
288
|
+
return {
|
|
289
|
+
root: VITE_PATHS.normalize(relative(projectDir, root)) || ".",
|
|
290
|
+
written: [],
|
|
291
|
+
unchanged: [],
|
|
292
|
+
hooks: [],
|
|
293
|
+
nextSteps: [
|
|
294
|
+
{
|
|
295
|
+
kind: "setup",
|
|
296
|
+
file: undefined,
|
|
297
|
+
message: "This folder's name holds characters a shell or a workflow would read as code, so nothing was written for the agents: run forgebook init --agents from a folder with a plain name"
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
};
|
|
301
|
+
// before anything is written: the skill's own folder must not read as a sign of an assistant
|
|
302
|
+
const names = hooks === undefined
|
|
303
|
+
? detectedHooks(root)
|
|
304
|
+
: [...ASSISTANT_NAMES, "pre-commit"].filter((name) => hooks.includes(name));
|
|
305
|
+
mergeFile(root, ".mcp.json", (text) => withMcpServer(text, mcpServerOf(manager, folder)), done);
|
|
306
|
+
writeInstructions(root, framework, done);
|
|
307
|
+
writeWorkflow(root, manager, folder, done);
|
|
308
|
+
const written = names.flatMap((name) => {
|
|
309
|
+
const hook = writeHook(root, name, manager, folder, done);
|
|
310
|
+
return hook === undefined ? [] : [hook];
|
|
311
|
+
});
|
|
312
|
+
return {
|
|
313
|
+
root: VITE_PATHS.normalize(relative(projectDir, root)) || ".",
|
|
314
|
+
written: done.written,
|
|
315
|
+
unchanged: done.unchanged,
|
|
316
|
+
hooks: written,
|
|
317
|
+
nextSteps: done.nextSteps
|
|
318
|
+
};
|
|
319
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The assistants whose hook format `forgebook init --agents` writes, and what it writes for each: a hook that runs
|
|
3
|
+
* `forgebook hook <assistant>` when the assistant is about to finish.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Only formats read in each assistant's own documentation are here; another assistant gets the pre-commit hook or the
|
|
7
|
+
* instructions. All four read JSON, so a file the project already has is merged, and one that cannot be parsed is left
|
|
8
|
+
* as it is and named. Cursor's `stop` hook cannot refuse to finish: it starts another turn with a message, so what it
|
|
9
|
+
* does is said separately (`effect`). Pure: text in, text out.
|
|
10
|
+
*
|
|
11
|
+
* @see https://code.claude.com/docs/en/hooks
|
|
12
|
+
* @see https://developers.openai.com/codex/hooks
|
|
13
|
+
* @see https://cursor.com/docs/agent/hooks
|
|
14
|
+
* @see https://geminicli.com/docs/hooks/reference/
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/** An assistant with a hook format. */
|
|
18
|
+
export type AssistantName = "claude" | "codex" | "cursor" | "gemini";
|
|
19
|
+
/** What a person reads about an assistant's hook, and where it goes. */
|
|
20
|
+
export type Assistant = {
|
|
21
|
+
/** Its name, for a person. */
|
|
22
|
+
readonly label: string;
|
|
23
|
+
/** The file holding its project hooks, from the repository's root. */
|
|
24
|
+
readonly file: string;
|
|
25
|
+
/** What in a repository says it is used. */
|
|
26
|
+
readonly markers: readonly string[];
|
|
27
|
+
/** What the hook can do: refuse to finish, or start another turn. */
|
|
28
|
+
readonly effect: "blocks" | "continues";
|
|
29
|
+
/** What the assistant asks before the hook runs; none when it runs at once. */
|
|
30
|
+
readonly caveat: string | undefined;
|
|
31
|
+
};
|
|
32
|
+
/** The assistants, by the name `forgebook hook` takes. */
|
|
33
|
+
export declare const ASSISTANTS: Readonly<Record<AssistantName, Assistant>>;
|
|
34
|
+
/** The names, in the order they are listed. */
|
|
35
|
+
export declare const ASSISTANT_NAMES: readonly AssistantName[];
|
|
36
|
+
/** What came of merging a file. */
|
|
37
|
+
export type MergedFile = {
|
|
38
|
+
/** The file's new text. */
|
|
39
|
+
readonly kind: "written";
|
|
40
|
+
/** Its text. */
|
|
41
|
+
readonly text: string;
|
|
42
|
+
} | {
|
|
43
|
+
/** It already holds it. */
|
|
44
|
+
readonly kind: "unchanged";
|
|
45
|
+
} | {
|
|
46
|
+
/** It cannot be parsed, or its shape is not the documented one: left as it is. */
|
|
47
|
+
readonly kind: "unreadable";
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* An assistant's hooks file with Forgebook's hook in it: everything else stays as it was.
|
|
51
|
+
*
|
|
52
|
+
* @param assistant - the assistant.
|
|
53
|
+
* @param text - the file's text; none when there is no file.
|
|
54
|
+
* @param command - the command the hook runs.
|
|
55
|
+
*/
|
|
56
|
+
export declare const withStopHook: (assistant: AssistantName, text: string | undefined, command: string) => MergedFile;
|
|
57
|
+
/** The command of an MCP server, as a client starts it. */
|
|
58
|
+
export type McpServer = {
|
|
59
|
+
/** The program. */
|
|
60
|
+
readonly command: string;
|
|
61
|
+
/** Its arguments. */
|
|
62
|
+
readonly args: readonly string[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A `.mcp.json` with Forgebook's server in it: the other servers stay, and a server already named `forgebook` is the
|
|
66
|
+
* project's own choice, so it stays as well.
|
|
67
|
+
*
|
|
68
|
+
* @param text - the file's text; none when there is no file.
|
|
69
|
+
* @param server - how the client starts Forgebook's server.
|
|
70
|
+
*/
|
|
71
|
+
export declare const withMcpServer: (text: string | undefined, server: McpServer) => MergedFile;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The assistants whose hook format `forgebook init --agents` writes, and what it writes for each: a hook that runs
|
|
3
|
+
* `forgebook hook <assistant>` when the assistant is about to finish.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Only formats read in each assistant's own documentation are here; another assistant gets the pre-commit hook or the
|
|
7
|
+
* instructions. All four read JSON, so a file the project already has is merged, and one that cannot be parsed is left
|
|
8
|
+
* as it is and named. Cursor's `stop` hook cannot refuse to finish: it starts another turn with a message, so what it
|
|
9
|
+
* does is said separately (`effect`). Pure: text in, text out.
|
|
10
|
+
*
|
|
11
|
+
* @see https://code.claude.com/docs/en/hooks
|
|
12
|
+
* @see https://developers.openai.com/codex/hooks
|
|
13
|
+
* @see https://cursor.com/docs/agent/hooks
|
|
14
|
+
* @see https://geminicli.com/docs/hooks/reference/
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/** The assistants, by the name `forgebook hook` takes. */
|
|
18
|
+
export const ASSISTANTS = {
|
|
19
|
+
claude: {
|
|
20
|
+
label: "Claude Code",
|
|
21
|
+
file: ".claude/settings.json",
|
|
22
|
+
markers: [".claude", "CLAUDE.md"],
|
|
23
|
+
effect: "blocks",
|
|
24
|
+
caveat: undefined
|
|
25
|
+
},
|
|
26
|
+
codex: {
|
|
27
|
+
label: "Codex",
|
|
28
|
+
file: ".codex/hooks.json",
|
|
29
|
+
markers: [".codex"],
|
|
30
|
+
effect: "blocks",
|
|
31
|
+
caveat: "Codex runs a project's hooks once they are reviewed and trusted"
|
|
32
|
+
},
|
|
33
|
+
cursor: {
|
|
34
|
+
label: "Cursor",
|
|
35
|
+
file: ".cursor/hooks.json",
|
|
36
|
+
markers: [".cursor", ".cursorrules"],
|
|
37
|
+
effect: "continues",
|
|
38
|
+
caveat: undefined
|
|
39
|
+
},
|
|
40
|
+
gemini: {
|
|
41
|
+
label: "Gemini CLI",
|
|
42
|
+
file: ".gemini/settings.json",
|
|
43
|
+
markers: [".gemini", "GEMINI.md"],
|
|
44
|
+
effect: "blocks",
|
|
45
|
+
caveat: undefined
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/** The names, in the order they are listed. */
|
|
49
|
+
export const ASSISTANT_NAMES = ["claude", "codex", "cursor", "gemini"];
|
|
50
|
+
/** How long a hook may run, in seconds: a first start pre-bundles, and every view of every story runs. */
|
|
51
|
+
const HOOK_SECONDS = 600;
|
|
52
|
+
/** Whether a value is a plain object. */
|
|
53
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
54
|
+
/** Whether a list of an event's entries already holds this very command: another package's catalogue has its own. */
|
|
55
|
+
const holdsOwnHook = (entries, command) => JSON.stringify(entries).includes(JSON.stringify(command));
|
|
56
|
+
/** What an assistant's file holds for one event: its name and the entry to add. */
|
|
57
|
+
const eventEntry = (assistant, command) => {
|
|
58
|
+
const hook = { type: "command", command };
|
|
59
|
+
if (assistant === "cursor")
|
|
60
|
+
return { event: "stop", entry: { command, timeout: HOOK_SECONDS, loop_limit: 5 } };
|
|
61
|
+
if (assistant === "gemini")
|
|
62
|
+
return {
|
|
63
|
+
event: "AfterAgent",
|
|
64
|
+
entry: { hooks: [{ ...hook, name: "forgebook-verify", timeout: HOOK_SECONDS * 1000 }] }
|
|
65
|
+
};
|
|
66
|
+
return { event: "Stop", entry: { hooks: [{ ...hook, timeout: HOOK_SECONDS }] } };
|
|
67
|
+
};
|
|
68
|
+
/** The text of a parsed JSON file, or why it stays as it is: a file's top level must be an object. */
|
|
69
|
+
const parsedObject = (text) => {
|
|
70
|
+
if (text === undefined || text.trim() === "")
|
|
71
|
+
return {};
|
|
72
|
+
try {
|
|
73
|
+
const parsed = JSON.parse(text);
|
|
74
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* An assistant's hooks file with Forgebook's hook in it: everything else stays as it was.
|
|
82
|
+
*
|
|
83
|
+
* @param assistant - the assistant.
|
|
84
|
+
* @param text - the file's text; none when there is no file.
|
|
85
|
+
* @param command - the command the hook runs.
|
|
86
|
+
*/
|
|
87
|
+
export const withStopHook = (assistant, text, command) => {
|
|
88
|
+
const file = parsedObject(text);
|
|
89
|
+
if (file === undefined)
|
|
90
|
+
return { kind: "unreadable" };
|
|
91
|
+
const hooks = file["hooks"] ?? {};
|
|
92
|
+
if (!isRecord(hooks))
|
|
93
|
+
return { kind: "unreadable" };
|
|
94
|
+
const { event, entry } = eventEntry(assistant, command);
|
|
95
|
+
const entries = hooks[event] ?? [];
|
|
96
|
+
if (!Array.isArray(entries))
|
|
97
|
+
return { kind: "unreadable" };
|
|
98
|
+
if (holdsOwnHook(entries, command))
|
|
99
|
+
return { kind: "unchanged" };
|
|
100
|
+
const merged = {
|
|
101
|
+
...(assistant === "cursor" ? { version: 1 } : {}),
|
|
102
|
+
...file,
|
|
103
|
+
hooks: { ...hooks, [event]: [...entries, entry] }
|
|
104
|
+
};
|
|
105
|
+
return { kind: "written", text: `${JSON.stringify(merged, null, 2)}\n` };
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* A `.mcp.json` with Forgebook's server in it: the other servers stay, and a server already named `forgebook` is the
|
|
109
|
+
* project's own choice, so it stays as well.
|
|
110
|
+
*
|
|
111
|
+
* @param text - the file's text; none when there is no file.
|
|
112
|
+
* @param server - how the client starts Forgebook's server.
|
|
113
|
+
*/
|
|
114
|
+
export const withMcpServer = (text, server) => {
|
|
115
|
+
const file = parsedObject(text);
|
|
116
|
+
if (file === undefined)
|
|
117
|
+
return { kind: "unreadable" };
|
|
118
|
+
const servers = file["mcpServers"] ?? {};
|
|
119
|
+
if (!isRecord(servers))
|
|
120
|
+
return { kind: "unreadable" };
|
|
121
|
+
if ("forgebook" in servers)
|
|
122
|
+
return { kind: "unchanged" };
|
|
123
|
+
const merged = { ...file, mcpServers: { ...servers, forgebook: server } };
|
|
124
|
+
return { kind: "written", text: `${JSON.stringify(merged, null, 2)}\n` };
|
|
125
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The GitHub Actions workflow `forgebook init --agents` writes: on every pull request it installs the project, its browser,
|
|
3
|
+
* and runs `forgebook verify` against the branch the pull request targets.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The whole history is fetched, since `verify` compares with where the branch left its target. The target's name comes
|
|
7
|
+
* through the environment and not into the script, where a branch's name could be read as shell. Its permissions are the
|
|
8
|
+
* least a read needs, and its actions are pinned as `workflowActions.ts` says. Pure.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { PackageManagerName } from "../newProject/newProject.types.ts";
|
|
13
|
+
/** The workflow's file, from the repository's root. */
|
|
14
|
+
export declare const WORKFLOW_FILE = ".github/workflows/forgebook-verify.yml";
|
|
15
|
+
/**
|
|
16
|
+
* The workflow's text.
|
|
17
|
+
*
|
|
18
|
+
* @param manager - the package manager.
|
|
19
|
+
* @param folder - the catalogue's folder from the repository's root, with forward slashes, plain (`isPlainFolder`); empty
|
|
20
|
+
* when it is the root.
|
|
21
|
+
* @param hasLockFile - whether the repository keeps a lock file, which a locked install needs.
|
|
22
|
+
*/
|
|
23
|
+
export declare const workflowText: (manager: PackageManagerName, folder: string, hasLockFile?: boolean) => string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CHECKOUT, SETUP_BUN, SETUP_NODE } from "../workflowActions.js";
|
|
2
|
+
import { forgebookCommandLine } from "./projectRunner.js";
|
|
3
|
+
/** The workflow's file, from the repository's root. */
|
|
4
|
+
export const WORKFLOW_FILE = ".github/workflows/forgebook-verify.yml";
|
|
5
|
+
/** The steps that bring a package manager, and its install with the lock file. */
|
|
6
|
+
const SETUP = {
|
|
7
|
+
npm: { steps: [], install: "npm ci" },
|
|
8
|
+
pnpm: { steps: [" - run: corepack enable"], install: "pnpm install --frozen-lockfile" },
|
|
9
|
+
yarn: { steps: [" - run: corepack enable"], install: "yarn install --immutable" },
|
|
10
|
+
bun: { steps: [` - uses: ${SETUP_BUN}`], install: "bun install --frozen-lockfile" }
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The workflow's text.
|
|
14
|
+
*
|
|
15
|
+
* @param manager - the package manager.
|
|
16
|
+
* @param folder - the catalogue's folder from the repository's root, with forward slashes, plain (`isPlainFolder`); empty
|
|
17
|
+
* when it is the root.
|
|
18
|
+
* @param hasLockFile - whether the repository keeps a lock file, which a locked install needs.
|
|
19
|
+
*/
|
|
20
|
+
export const workflowText = (manager, folder, hasLockFile = true) => {
|
|
21
|
+
const { steps, install: lockedInstall } = SETUP[manager];
|
|
22
|
+
const install = hasLockFile ? lockedInstall : `${manager} install`;
|
|
23
|
+
const browser = forgebookCommandLine(manager, folder, "browser --with-deps");
|
|
24
|
+
const verify = forgebookCommandLine(manager, folder, 'verify --since "origin/$BASE_BRANCH"');
|
|
25
|
+
return [
|
|
26
|
+
"# Written by `forgebook init --agents`: a pull request is not done until its changed UI ran in its stories.",
|
|
27
|
+
"name: Forgebook verify",
|
|
28
|
+
"",
|
|
29
|
+
"on:",
|
|
30
|
+
" pull_request:",
|
|
31
|
+
"",
|
|
32
|
+
"permissions:",
|
|
33
|
+
" contents: read",
|
|
34
|
+
"",
|
|
35
|
+
"jobs:",
|
|
36
|
+
" verify:",
|
|
37
|
+
" runs-on: ubuntu-latest",
|
|
38
|
+
" timeout-minutes: 30",
|
|
39
|
+
" steps:",
|
|
40
|
+
` - uses: ${CHECKOUT}`,
|
|
41
|
+
" with:",
|
|
42
|
+
" fetch-depth: 0",
|
|
43
|
+
` - uses: ${SETUP_NODE}`,
|
|
44
|
+
" with:",
|
|
45
|
+
" node-version: 24",
|
|
46
|
+
...steps,
|
|
47
|
+
` - run: ${install}`,
|
|
48
|
+
` - run: ${browser}`,
|
|
49
|
+
` - run: ${verify}`,
|
|
50
|
+
" env:",
|
|
51
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: this is GitHub Actions' syntax, in the file it reads
|
|
52
|
+
" BASE_BRANCH: ${{ github.base_ref }}",
|
|
53
|
+
""
|
|
54
|
+
].join("\n");
|
|
55
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** How many candidates come back: past these, the reason is rarely the component. */
|
|
2
|
+
export declare const CANDIDATE_LIMIT = 8;
|
|
3
|
+
/**
|
|
4
|
+
* How promising a component's path is: lower comes first.
|
|
5
|
+
*
|
|
6
|
+
* @param path - the file, from the project's folder, with forward slashes.
|
|
7
|
+
* @param size - its size in bytes.
|
|
8
|
+
*/
|
|
9
|
+
export declare const candidateRank: (path: string, size: number) => number;
|
|
10
|
+
/**
|
|
11
|
+
* The top folders story patterns cover: a component outside them gets stories the catalogue does not list.
|
|
12
|
+
*
|
|
13
|
+
* @param patterns - the patterns (`{app,components}/**\/*.stories.tsx`).
|
|
14
|
+
* @returns the folders; none when any pattern covers more than folders can say, so nothing is left out.
|
|
15
|
+
*/
|
|
16
|
+
export declare const storyFolders: (patterns: readonly string[]) => readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* The project's component files to try, the most promising first.
|
|
19
|
+
*
|
|
20
|
+
* @param projectDir - the project's folder.
|
|
21
|
+
* @param framework - the adapter's name.
|
|
22
|
+
* @param folders - the top folders to look in; every one when none.
|
|
23
|
+
* @returns the files, from the project's folder.
|
|
24
|
+
*/
|
|
25
|
+
export declare const drawCandidates: (projectDir: string, framework: string, folders?: readonly string[]) => readonly string[];
|