84 lines
2.3 KiB
TypeScript
84 lines
2.3 KiB
TypeScript
import memoize from 'lodash-es/memoize.js'
|
|
import { join } from 'path'
|
|
import {
|
|
getCurrentProjectConfig,
|
|
saveCurrentProjectConfig,
|
|
} from './utils/config.js'
|
|
import { getCwd } from './utils/cwd.js'
|
|
import { isDirEmpty } from './utils/file.js'
|
|
import { getFsImplementation } from './utils/fsOperations.js'
|
|
|
|
export type Step = {
|
|
key: string
|
|
text: string
|
|
isComplete: boolean
|
|
isCompletable: boolean
|
|
isEnabled: boolean
|
|
}
|
|
|
|
export function getSteps(): Step[] {
|
|
const hasClaudeMd = getFsImplementation().existsSync(
|
|
join(getCwd(), 'CLAUDE.md'),
|
|
)
|
|
const isWorkspaceDirEmpty = isDirEmpty(getCwd())
|
|
|
|
return [
|
|
{
|
|
key: 'workspace',
|
|
text: 'Ask Claude to create a new app or clone a repository',
|
|
isComplete: false,
|
|
isCompletable: true,
|
|
isEnabled: isWorkspaceDirEmpty,
|
|
},
|
|
{
|
|
key: 'claudemd',
|
|
text: 'Run /init to create a CLAUDE.md file with instructions for Claude',
|
|
isComplete: hasClaudeMd,
|
|
isCompletable: true,
|
|
isEnabled: !isWorkspaceDirEmpty,
|
|
},
|
|
]
|
|
}
|
|
|
|
export function isProjectOnboardingComplete(): boolean {
|
|
return getSteps()
|
|
.filter(({ isCompletable, isEnabled }) => isCompletable && isEnabled)
|
|
.every(({ isComplete }) => isComplete)
|
|
}
|
|
|
|
export function maybeMarkProjectOnboardingComplete(): void {
|
|
// Short-circuit on cached config — isProjectOnboardingComplete() hits
|
|
// the filesystem, and REPL.tsx calls this on every prompt submit.
|
|
if (getCurrentProjectConfig().hasCompletedProjectOnboarding) {
|
|
return
|
|
}
|
|
if (isProjectOnboardingComplete()) {
|
|
saveCurrentProjectConfig(current => ({
|
|
...current,
|
|
hasCompletedProjectOnboarding: true,
|
|
}))
|
|
}
|
|
}
|
|
|
|
export const shouldShowProjectOnboarding = memoize((): boolean => {
|
|
const projectConfig = getCurrentProjectConfig()
|
|
// Short-circuit on cached config before isProjectOnboardingComplete()
|
|
// hits the filesystem — this runs during first render.
|
|
if (
|
|
projectConfig.hasCompletedProjectOnboarding ||
|
|
projectConfig.projectOnboardingSeenCount >= 4 ||
|
|
process.env.IS_DEMO
|
|
) {
|
|
return false
|
|
}
|
|
|
|
return !isProjectOnboardingComplete()
|
|
})
|
|
|
|
export function incrementProjectOnboardingSeenCount(): void {
|
|
saveCurrentProjectConfig(current => ({
|
|
...current,
|
|
projectOnboardingSeenCount: current.projectOnboardingSeenCount + 1,
|
|
}))
|
|
}
|