@codeyam/codeyam-cli 0.1.8 → 0.1.9
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/analyzer-template/.build-info.json +8 -8
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +4 -4
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +0 -33
- package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +13 -7
- package/analyzer-template/packages/analyze/src/lib/asts/index.ts +7 -2
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +0 -98
- package/analyzer-template/packages/aws/package.json +1 -1
- package/analyzer-template/packages/database/src/lib/kysely/tables/editorScenariosTable.ts +31 -0
- package/analyzer-template/packages/database/src/lib/loadEntities.ts +0 -6
- package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +0 -65
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts +5 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js +31 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +0 -6
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +0 -25
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.js +2 -0
- package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.js.map +1 -1
- package/analyzer-template/packages/types/src/enums/ProjectFramework.ts +2 -0
- package/analyzer-template/packages/ui-components/package.json +1 -1
- package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.js +2 -0
- package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.js.map +1 -1
- package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js +196 -0
- package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js.map +1 -0
- package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js +114 -0
- package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js.map +1 -0
- package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js +149 -0
- package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js +45 -0
- package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js +101 -47
- package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +3 -46
- package/codeyam-cli/src/commands/default.js.map +1 -1
- package/codeyam-cli/src/commands/editor.js +1619 -243
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/init.js +67 -34
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/data/techStacks.js +77 -0
- package/codeyam-cli/src/data/techStacks.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js +144 -0
- package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js +46 -0
- package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/devServerState.test.js +134 -0
- package/codeyam-cli/src/utils/__tests__/devServerState.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js +127 -0
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +610 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorCapture.test.js +93 -0
- package/codeyam-cli/src/utils/__tests__/editorCapture.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js +181 -3
- package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +121 -0
- package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorImageVerifier.test.js +294 -0
- package/codeyam-cli/src/utils/__tests__/editorImageVerifier.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorJournal.test.js +249 -2
- package/codeyam-cli/src/utils/__tests__/editorJournal.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js +520 -0
- package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js +118 -1
- package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +195 -3
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js +153 -0
- package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioLookup.test.js +139 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioLookup.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +221 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +781 -2
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +213 -0
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +1742 -0
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js +107 -0
- package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js +101 -0
- package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +227 -0
- package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +300 -0
- package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +25 -5
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/templateConsistency.test.js +51 -0
- package/codeyam-cli/src/utils/__tests__/templateConsistency.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/webappDetection.test.js +142 -0
- package/codeyam-cli/src/utils/__tests__/webappDetection.test.js.map +1 -0
- package/codeyam-cli/src/utils/analyzer.js +9 -0
- package/codeyam-cli/src/utils/analyzer.js.map +1 -1
- package/codeyam-cli/src/utils/analyzerFinalization.js +96 -0
- package/codeyam-cli/src/utils/analyzerFinalization.js.map +1 -0
- package/codeyam-cli/src/utils/backgroundServer.js +94 -18
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/database.js +37 -2
- package/codeyam-cli/src/utils/database.js.map +1 -1
- package/codeyam-cli/src/utils/devServerState.js +71 -0
- package/codeyam-cli/src/utils/devServerState.js.map +1 -0
- package/codeyam-cli/src/utils/editorApi.js +73 -0
- package/codeyam-cli/src/utils/editorApi.js.map +1 -0
- package/codeyam-cli/src/utils/editorAudit.js +101 -7
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorCapture.js +102 -0
- package/codeyam-cli/src/utils/editorCapture.js.map +1 -0
- package/codeyam-cli/src/utils/editorDevServer.js +100 -1
- package/codeyam-cli/src/utils/editorDevServer.js.map +1 -1
- package/codeyam-cli/src/utils/editorEntityChangeStatus.js +44 -0
- package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -0
- package/codeyam-cli/src/utils/editorImageVerifier.js +155 -0
- package/codeyam-cli/src/utils/editorImageVerifier.js.map +1 -0
- package/codeyam-cli/src/utils/editorJournal.js +92 -4
- package/codeyam-cli/src/utils/editorJournal.js.map +1 -1
- package/codeyam-cli/src/utils/editorLoaderHelpers.js +113 -0
- package/codeyam-cli/src/utils/editorLoaderHelpers.js.map +1 -0
- package/codeyam-cli/src/utils/editorMockState.js +1 -1
- package/codeyam-cli/src/utils/editorPreloadHelpers.js +72 -1
- package/codeyam-cli/src/utils/editorPreloadHelpers.js.map +1 -1
- package/codeyam-cli/src/utils/editorPreview.js +67 -1
- package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarioSwitch.js +112 -0
- package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -0
- package/codeyam-cli/src/utils/editorScenarios.js +276 -0
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/editorSeedAdapter.js +173 -0
- package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -0
- package/codeyam-cli/src/utils/entityChangeStatus.js +349 -0
- package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -0
- package/codeyam-cli/src/utils/entityChangeStatus.server.js +158 -0
- package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -0
- package/codeyam-cli/src/utils/install-skills.js +1 -1
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/parseRegisterArg.js +31 -0
- package/codeyam-cli/src/utils/parseRegisterArg.js.map +1 -0
- package/codeyam-cli/src/utils/scenarioCoverage.js +75 -0
- package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -0
- package/codeyam-cli/src/utils/scenariosManifest.js +159 -0
- package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -0
- package/codeyam-cli/src/utils/serverState.js +30 -0
- package/codeyam-cli/src/utils/serverState.js.map +1 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +46 -16
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/utils/simulationGateMiddleware.js +8 -1
- package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
- package/codeyam-cli/src/utils/slugUtils.js +25 -0
- package/codeyam-cli/src/utils/slugUtils.js.map +1 -0
- package/codeyam-cli/src/utils/syncMocksMiddleware.js +2 -2
- package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
- package/codeyam-cli/src/utils/webappDetection.js +21 -0
- package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +40 -0
- package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +567 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -0
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js +65 -0
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -0
- package/codeyam-cli/src/webserver/app/lib/git.js +397 -0
- package/codeyam-cli/src/webserver/app/lib/git.js.map +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-DmJveP3T.js → CopyButton-BPXZwM4t.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-C76mRRiF.js → EntityItem-BcgbViKV.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-CobE682z.js → EntityTypeIcon-CQIG2qda.js} +9 -9
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-djPLI-WV.js → ReportIssueModal-BzHcG7SE.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-B76aig_2.js → ScenarioViewer-Bd-hxofb.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-oAf2Kqsf.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{_index-C96V0n15.js → _index-DLxKhri3.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BpKzcsJz.js → activity.(_tab)-BcY3q6nt.js} +6 -6
- package/codeyam-cli/src/webserver/build/client/assets/addon-canvas-DpzMmAy5.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/addon-fit-YJmn1quW.js +12 -0
- package/codeyam-cli/src/webserver/build/client/assets/addon-webgl-DI8QOUvO.js +58 -0
- package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-D9hemwl6.js → agent-transcripts-Bni3iiUj.js} +5 -5
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-diff-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-project-info-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-coverage-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-D_nMCFmP.js → book-open-BYOypzCa.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-BH2h1Ea2.js → chevron-down-C_Pmso5S.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-DyIKORY6.js → circle-check-BVMi9VA5.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{copy-NDbZjXao.js → copy-n2FB0_Sw.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CC6AbExI.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BsDh6TSF.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/editor-PBc_6L9R.js +10 -0
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-4FzHlcNn.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CrjR3zZW.js → entity._sha._-BsDXNp45.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-BgAqUtTZ.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-Bmshgrij.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{files-DO4CZ16O.js → files-BZrlFE1F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-DdZcvjGh.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-B8vTTNy2.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-yHOVb4rc.js +15 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BAXYRVEO.js → loader-circle-DaAZ_H2w.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/manifest-65850841.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-9gnxSZlb.js +101 -0
- package/codeyam-cli/src/webserver/build/client/assets/{pause-DTAcYxBt.js → pause-f5-1lKBt.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/root-BwX8YgFb.js +67 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-fKo7v0Zo.js → search-Di64LWVb.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{settings-DfuTtcJP.js → settings-0OrEMU6J.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-B3aOzpCZ.js → simulations-DWT-CvLy.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-BG4heKCG.js → terminal-Br7MOqts.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-DtSmdtM4.js → triangle-alert-BLdiCuG-.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BE43Hjti.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/index-DEEQf4pi.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/init-CkWmyFY2.js +10 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BHi-9O8W.js +439 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/editorProxy.js +487 -50
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/scripts/codeyam-preload.mjs +242 -3
- package/codeyam-cli/src/webserver/scripts/journalCapture.ts +94 -4
- package/codeyam-cli/src/webserver/server.js +46 -14
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +39 -11
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/chrome-extension-react/EXTENSION_SETUP.md +75 -0
- package/codeyam-cli/templates/chrome-extension-react/README.md +46 -0
- package/codeyam-cli/templates/chrome-extension-react/gitignore +15 -0
- package/codeyam-cli/templates/chrome-extension-react/index.html +12 -0
- package/codeyam-cli/templates/chrome-extension-react/package.json +27 -0
- package/codeyam-cli/templates/chrome-extension-react/popup.html +12 -0
- package/codeyam-cli/templates/chrome-extension-react/public/manifest.json +15 -0
- package/codeyam-cli/templates/chrome-extension-react/src/background/service-worker.ts +7 -0
- package/codeyam-cli/templates/chrome-extension-react/src/globals.css +6 -0
- package/codeyam-cli/templates/chrome-extension-react/src/lib/storage.ts +37 -0
- package/codeyam-cli/templates/chrome-extension-react/src/popup/App.tsx +12 -0
- package/codeyam-cli/templates/chrome-extension-react/src/popup/main.tsx +10 -0
- package/codeyam-cli/templates/chrome-extension-react/tsconfig.json +24 -0
- package/codeyam-cli/templates/chrome-extension-react/vite.config.ts +41 -0
- package/codeyam-cli/templates/codeyam-editor-claude.md +84 -5
- package/codeyam-cli/templates/editor-step-hook.py +97 -8
- package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +89 -0
- package/codeyam-cli/templates/expo-react-native/README.md +41 -0
- package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +33 -0
- package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +12 -0
- package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +12 -0
- package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +12 -0
- package/codeyam-cli/templates/expo-react-native/app.json +18 -0
- package/codeyam-cli/templates/expo-react-native/babel.config.js +9 -0
- package/codeyam-cli/templates/expo-react-native/gitignore +12 -0
- package/codeyam-cli/templates/expo-react-native/global.css +3 -0
- package/codeyam-cli/templates/expo-react-native/lib/storage.ts +32 -0
- package/codeyam-cli/templates/expo-react-native/metro.config.js +6 -0
- package/codeyam-cli/templates/expo-react-native/nativewind-env.d.ts +1 -0
- package/codeyam-cli/templates/expo-react-native/package.json +38 -0
- package/codeyam-cli/templates/expo-react-native/tailwind.config.js +10 -0
- package/codeyam-cli/templates/expo-react-native/tsconfig.json +10 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/AUTH_PATTERNS.md +308 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/AUTH_UPGRADE.md +304 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/DATABASE.md +126 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/FEATURE_PATTERNS.md +37 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/README.md +53 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/app/codeyam-isolate/layout.tsx +12 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/app/lib/prisma.ts +9 -4
- package/codeyam-cli/templates/nextjs-prisma-sqlite/env +4 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +21 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +5 -1
- package/codeyam-cli/templates/nextjs-prisma-sqlite/prisma/seed.ts +4 -1
- package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +92 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/vitest.config.ts +13 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/README.md +52 -0
- package/codeyam-cli/templates/{nextjs-prisma-sqlite/PRISMA_SETUP.md → nextjs-prisma-supabase/SUPABASE_SETUP.md} +37 -17
- package/codeyam-cli/templates/nextjs-prisma-supabase/app/api/todos/route.ts +17 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/app/globals.css +26 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/app/layout.tsx +34 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/app/lib/prisma.ts +20 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/app/lib/supabase.ts +12 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/app/page.tsx +10 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/env +9 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/eslint.config.mjs +11 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/gitignore +40 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/next.config.ts +11 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +37 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/postcss.config.mjs +7 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/prisma/schema.prisma +27 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/prisma/seed.ts +39 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/prisma.config.ts +12 -0
- package/codeyam-cli/templates/nextjs-prisma-supabase/tsconfig.json +34 -0
- package/codeyam-cli/templates/skills/codeyam-dev-mode/SKILL.md +2 -2
- package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +96 -17
- package/codeyam-cli/templates/skills/codeyam-memory/SKILL.md +10 -10
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.mjs +139 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.mjs +52 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/read-json-field.mjs +61 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/ripgrep-fallback.mjs +155 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.mjs +13 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter-session.mjs +95 -0
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.mjs +160 -0
- package/package.json +14 -9
- package/packages/ai/src/lib/generateExecutionFlows.js +0 -11
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
- package/packages/analyze/src/lib/ProjectAnalyzer.js +10 -4
- package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/asts/index.js +4 -2
- package/packages/analyze/src/lib/asts/index.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +0 -40
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/editorScenariosTable.js +31 -0
- package/packages/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
- package/packages/database/src/lib/loadEntities.js +0 -6
- package/packages/database/src/lib/loadEntities.js.map +1 -1
- package/packages/database/src/lib/updateCommitMetadata.js +0 -25
- package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/packages/types/src/enums/ProjectFramework.js +2 -0
- package/packages/types/src/enums/ProjectFramework.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/Terminal-Dnj5CY9R.js +0 -41
- package/codeyam-cli/src/webserver/build/client/assets/addon-fit-CUXOrorO.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CMT1jU2q.js +0 -21
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BiM6z3Do.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor-D1DAKXtT.js +0 -8
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-DkzqFzFj.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-C28BiQzt.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/git-CFCTYk9I.js +0 -15
- package/codeyam-cli/src/webserver/build/client/assets/globals-B17TBSS6.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-a632de18.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/memory-Dg0mvYrI.js +0 -96
- package/codeyam-cli/src/webserver/build/client/assets/root-DUKqhFlb.js +0 -67
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-ByhSyh0W.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-HfLydfDq.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-CUu_F-oo.js +0 -366
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.sh +0 -108
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.sh +0 -69
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.sh +0 -12
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter.jq +0 -45
- package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.sh +0 -139
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Auth Patterns for Dev Prototyping
|
|
2
|
+
|
|
3
|
+
This project uses a simple cookie + database auth pattern designed for local development.
|
|
4
|
+
It is **intentionally simple** — built for easy upgrade to a real provider later.
|
|
5
|
+
|
|
6
|
+
## DO NOT use external auth providers during prototyping
|
|
7
|
+
|
|
8
|
+
**Do NOT use NextAuth, Auth.js, Clerk, better-auth, Supabase Auth, or any external auth provider.**
|
|
9
|
+
|
|
10
|
+
These providers require external infrastructure (OAuth endpoints, JWT signing keys, callback URLs)
|
|
11
|
+
that is unavailable in the local SQLite development environment. They will fail silently or produce
|
|
12
|
+
confusing errors. Use the pattern below instead — it works immediately and upgrades cleanly later.
|
|
13
|
+
|
|
14
|
+
See `AUTH_UPGRADE.md` for how to swap in a real provider when going to production.
|
|
15
|
+
|
|
16
|
+
## Interfaces
|
|
17
|
+
|
|
18
|
+
All consumer code imports from `@/app/lib/auth`. The interface is:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
export interface AuthUser {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
email: string;
|
|
25
|
+
image?: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Session {
|
|
29
|
+
user: AuthUser;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function getSession(): Promise<Session | null>;
|
|
33
|
+
export async function requireAuth(): Promise<Session>; // redirects to /login if no session
|
|
34
|
+
export async function signIn(
|
|
35
|
+
email: string,
|
|
36
|
+
password: string,
|
|
37
|
+
): Promise<Session | null>;
|
|
38
|
+
export async function signOut(): Promise<void>;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Prisma Schema Additions
|
|
42
|
+
|
|
43
|
+
Add these models to `prisma/schema.prisma`:
|
|
44
|
+
|
|
45
|
+
```prisma
|
|
46
|
+
model User {
|
|
47
|
+
id String @id @default(cuid())
|
|
48
|
+
name String
|
|
49
|
+
email String @unique
|
|
50
|
+
password String
|
|
51
|
+
image String?
|
|
52
|
+
sessions Session[]
|
|
53
|
+
createdAt DateTime @default(now())
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
model Session {
|
|
57
|
+
id String @id @default(cuid())
|
|
58
|
+
token String @unique
|
|
59
|
+
userId String
|
|
60
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
61
|
+
createdAt DateTime @default(now())
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
After editing the schema, run: `npm run db:push`
|
|
66
|
+
|
|
67
|
+
## Dev Implementation: `app/lib/auth.ts`
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { cookies } from 'next/headers';
|
|
71
|
+
import { redirect } from 'next/navigation';
|
|
72
|
+
import { prisma } from '@/app/lib/prisma';
|
|
73
|
+
|
|
74
|
+
export interface AuthUser {
|
|
75
|
+
id: string;
|
|
76
|
+
name: string;
|
|
77
|
+
email: string;
|
|
78
|
+
image?: string | null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface Session {
|
|
82
|
+
user: AuthUser;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const COOKIE_NAME = 'session-token';
|
|
86
|
+
|
|
87
|
+
export async function getSession(): Promise<Session | null> {
|
|
88
|
+
const cookieStore = await cookies();
|
|
89
|
+
const token = cookieStore.get(COOKIE_NAME)?.value;
|
|
90
|
+
if (!token) return null;
|
|
91
|
+
|
|
92
|
+
const session = await prisma.session.findUnique({
|
|
93
|
+
where: { token },
|
|
94
|
+
include: { user: true },
|
|
95
|
+
});
|
|
96
|
+
if (!session) return null;
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
user: {
|
|
100
|
+
id: session.user.id,
|
|
101
|
+
name: session.user.name,
|
|
102
|
+
email: session.user.email,
|
|
103
|
+
image: session.user.image,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function requireAuth(): Promise<Session> {
|
|
109
|
+
const session = await getSession();
|
|
110
|
+
if (!session) redirect('/login');
|
|
111
|
+
return session;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function signIn(
|
|
115
|
+
email: string,
|
|
116
|
+
password: string,
|
|
117
|
+
): Promise<Session | null> {
|
|
118
|
+
const user = await prisma.user.findUnique({ where: { email } });
|
|
119
|
+
if (!user || user.password !== password) return null;
|
|
120
|
+
|
|
121
|
+
const token = crypto.randomUUID();
|
|
122
|
+
await prisma.session.create({
|
|
123
|
+
data: { token, userId: user.id },
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const cookieStore = await cookies();
|
|
127
|
+
cookieStore.set(COOKIE_NAME, token, {
|
|
128
|
+
httpOnly: true,
|
|
129
|
+
path: '/',
|
|
130
|
+
sameSite: 'lax',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
user: {
|
|
135
|
+
id: user.id,
|
|
136
|
+
name: user.name,
|
|
137
|
+
email: user.email,
|
|
138
|
+
image: user.image,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export async function signOut(): Promise<void> {
|
|
144
|
+
const cookieStore = await cookies();
|
|
145
|
+
const token = cookieStore.get(COOKIE_NAME)?.value;
|
|
146
|
+
if (token) {
|
|
147
|
+
await prisma.session.deleteMany({ where: { token } });
|
|
148
|
+
}
|
|
149
|
+
cookieStore.delete(COOKIE_NAME);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Cookie Name
|
|
154
|
+
|
|
155
|
+
The cookie name **must be `session-token`**. The CodeYam proxy uses this name for
|
|
156
|
+
scenario auto-login (injecting/clearing the cookie when switching between scenarios).
|
|
157
|
+
|
|
158
|
+
## API Routes
|
|
159
|
+
|
|
160
|
+
### `/api/auth/login` (POST)
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { signIn } from '@/app/lib/auth';
|
|
164
|
+
import { NextResponse } from 'next/server';
|
|
165
|
+
|
|
166
|
+
export async function POST(request: Request) {
|
|
167
|
+
const { email, password } = await request.json();
|
|
168
|
+
const session = await signIn(email, password);
|
|
169
|
+
if (!session) {
|
|
170
|
+
return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 });
|
|
171
|
+
}
|
|
172
|
+
return NextResponse.json({ user: session.user });
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### `/api/auth/logout` (POST)
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { signOut } from '@/app/lib/auth';
|
|
180
|
+
import { NextResponse } from 'next/server';
|
|
181
|
+
|
|
182
|
+
export async function POST() {
|
|
183
|
+
await signOut();
|
|
184
|
+
return NextResponse.json({ success: true });
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### `/api/auth/session` (GET) — for client components
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { getSession } from '@/app/lib/auth';
|
|
192
|
+
import { NextResponse } from 'next/server';
|
|
193
|
+
|
|
194
|
+
export async function GET() {
|
|
195
|
+
const session = await getSession();
|
|
196
|
+
return NextResponse.json({ session });
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Usage in Server Components
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { getSession } from '@/app/lib/auth';
|
|
204
|
+
|
|
205
|
+
export default async function Dashboard() {
|
|
206
|
+
const session = await getSession();
|
|
207
|
+
if (!session) redirect('/login');
|
|
208
|
+
|
|
209
|
+
return <h1>Welcome, {session.user.name}</h1>;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Usage in Client Components
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
'use client';
|
|
217
|
+
import { useEffect, useState } from 'react';
|
|
218
|
+
|
|
219
|
+
export function UserNav() {
|
|
220
|
+
const [user, setUser] = useState(null);
|
|
221
|
+
|
|
222
|
+
useEffect(() => {
|
|
223
|
+
fetch('/api/auth/session')
|
|
224
|
+
.then(res => res.json())
|
|
225
|
+
.then(data => setUser(data.session?.user ?? null));
|
|
226
|
+
}, []);
|
|
227
|
+
|
|
228
|
+
if (!user) return <a href="/login">Sign In</a>;
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<div>
|
|
232
|
+
<span>{user.name}</span>
|
|
233
|
+
<button onClick={() => {
|
|
234
|
+
fetch('/api/auth/logout', { method: 'POST' })
|
|
235
|
+
.then(() => window.location.href = '/');
|
|
236
|
+
}}>
|
|
237
|
+
Sign Out
|
|
238
|
+
</button>
|
|
239
|
+
</div>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Login Page Pattern
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
'use client';
|
|
248
|
+
import { useState } from 'react';
|
|
249
|
+
import { useRouter } from 'next/navigation';
|
|
250
|
+
|
|
251
|
+
export default function LoginPage() {
|
|
252
|
+
const [email, setEmail] = useState('');
|
|
253
|
+
const [password, setPassword] = useState('');
|
|
254
|
+
const [error, setError] = useState('');
|
|
255
|
+
const router = useRouter();
|
|
256
|
+
|
|
257
|
+
async function handleSubmit(e: React.FormEvent) {
|
|
258
|
+
e.preventDefault();
|
|
259
|
+
const res = await fetch('/api/auth/login', {
|
|
260
|
+
method: 'POST',
|
|
261
|
+
headers: { 'Content-Type': 'application/json' },
|
|
262
|
+
body: JSON.stringify({ email, password }),
|
|
263
|
+
});
|
|
264
|
+
if (res.ok) {
|
|
265
|
+
router.push('/');
|
|
266
|
+
router.refresh();
|
|
267
|
+
} else {
|
|
268
|
+
setError('Invalid email or password');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<form onSubmit={handleSubmit}>
|
|
274
|
+
<input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" required />
|
|
275
|
+
<input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="Password" required />
|
|
276
|
+
{error && <p style={{ color: 'red' }}>{error}</p>}
|
|
277
|
+
<button type="submit">Sign In</button>
|
|
278
|
+
</form>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Seed Data for Scenarios
|
|
284
|
+
|
|
285
|
+
When creating scenarios with auth, include both `User` and `Session` rows in seed data:
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"name": "Logged In User",
|
|
290
|
+
"type": "application",
|
|
291
|
+
"url": "/",
|
|
292
|
+
"seed": {
|
|
293
|
+
"user": [
|
|
294
|
+
{
|
|
295
|
+
"id": "user_1",
|
|
296
|
+
"name": "Alice",
|
|
297
|
+
"email": "alice@example.com",
|
|
298
|
+
"password": "password123"
|
|
299
|
+
}
|
|
300
|
+
],
|
|
301
|
+
"session": [{ "id": "sess_1", "token": "sess_alice", "userId": "user_1" }]
|
|
302
|
+
},
|
|
303
|
+
"session": { "cookieValue": "sess_alice" }
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The top-level `"session"` field tells the proxy to set the `session-token` cookie,
|
|
308
|
+
auto-logging the user in when this scenario is active.
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Upgrading Auth for Production
|
|
2
|
+
|
|
3
|
+
The dev auth pattern in `app/lib/auth.ts` is designed for easy replacement.
|
|
4
|
+
All consumer code imports from `@/app/lib/auth` — only the internals of that file change.
|
|
5
|
+
|
|
6
|
+
## What Stays the Same
|
|
7
|
+
|
|
8
|
+
Every file that imports from `@/app/lib/auth` continues to work unchanged:
|
|
9
|
+
|
|
10
|
+
- Server components calling `getSession()` and `requireAuth()`
|
|
11
|
+
- Client components fetching `/api/auth/session`
|
|
12
|
+
- API routes using `signIn()` and `signOut()`
|
|
13
|
+
- Login/logout forms
|
|
14
|
+
|
|
15
|
+
## What Changes
|
|
16
|
+
|
|
17
|
+
Only `app/lib/auth.ts` internals. Replace the cookie+DB implementation with your chosen provider.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## NextAuth v5
|
|
22
|
+
|
|
23
|
+
### Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install next-auth @auth/prisma-adapter
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Replace `app/lib/auth.ts`
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import NextAuth from 'next-auth';
|
|
33
|
+
import { PrismaAdapter } from '@auth/prisma-adapter';
|
|
34
|
+
import { prisma } from '@/app/lib/prisma';
|
|
35
|
+
import Credentials from 'next-auth/providers/credentials';
|
|
36
|
+
// Add other providers: Google, GitHub, etc.
|
|
37
|
+
|
|
38
|
+
export interface AuthUser {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
email: string;
|
|
42
|
+
image?: string | null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Session {
|
|
46
|
+
user: AuthUser;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const {
|
|
50
|
+
auth,
|
|
51
|
+
signIn: nextAuthSignIn,
|
|
52
|
+
signOut: nextAuthSignOut,
|
|
53
|
+
} = NextAuth({
|
|
54
|
+
adapter: PrismaAdapter(prisma),
|
|
55
|
+
providers: [
|
|
56
|
+
Credentials({
|
|
57
|
+
credentials: { email: {}, password: {} },
|
|
58
|
+
authorize: async (credentials) => {
|
|
59
|
+
const user = await prisma.user.findUnique({
|
|
60
|
+
where: { email: credentials.email as string },
|
|
61
|
+
});
|
|
62
|
+
if (!user) return null;
|
|
63
|
+
// In production, use bcrypt: await bcrypt.compare(password, user.password)
|
|
64
|
+
return user;
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
// Add: Google({ clientId: ..., clientSecret: ... })
|
|
68
|
+
// Add: GitHub({ clientId: ..., clientSecret: ... })
|
|
69
|
+
],
|
|
70
|
+
session: { strategy: 'jwt' },
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export async function getSession(): Promise<Session | null> {
|
|
74
|
+
const session = await auth();
|
|
75
|
+
if (!session?.user) return null;
|
|
76
|
+
return {
|
|
77
|
+
user: {
|
|
78
|
+
id: session.user.id!,
|
|
79
|
+
name: session.user.name!,
|
|
80
|
+
email: session.user.email!,
|
|
81
|
+
image: session.user.image,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function requireAuth(): Promise<Session> {
|
|
87
|
+
const session = await getSession();
|
|
88
|
+
if (!session) {
|
|
89
|
+
const { redirect } = await import('next/navigation');
|
|
90
|
+
redirect('/login');
|
|
91
|
+
}
|
|
92
|
+
return session;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function signIn(
|
|
96
|
+
email: string,
|
|
97
|
+
password: string,
|
|
98
|
+
): Promise<Session | null> {
|
|
99
|
+
try {
|
|
100
|
+
await nextAuthSignIn('credentials', { email, password, redirect: false });
|
|
101
|
+
return getSession();
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function signOut(): Promise<void> {
|
|
108
|
+
await nextAuthSignOut({ redirect: false });
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Add route handler
|
|
113
|
+
|
|
114
|
+
Create `app/api/auth/[...nextauth]/route.ts`:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { handlers } from '@/app/lib/auth';
|
|
118
|
+
export const { GET, POST } = handlers;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## better-auth
|
|
124
|
+
|
|
125
|
+
### Install
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm install better-auth
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Replace `app/lib/auth.ts`
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { betterAuth } from 'better-auth';
|
|
135
|
+
import { prismaAdapter } from 'better-auth/adapters/prisma';
|
|
136
|
+
import { prisma } from '@/app/lib/prisma';
|
|
137
|
+
import { cookies } from 'next/headers';
|
|
138
|
+
|
|
139
|
+
export interface AuthUser {
|
|
140
|
+
id: string;
|
|
141
|
+
name: string;
|
|
142
|
+
email: string;
|
|
143
|
+
image?: string | null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface Session {
|
|
147
|
+
user: AuthUser;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const auth = betterAuth({
|
|
151
|
+
database: prismaAdapter(prisma, { provider: 'sqlite' }),
|
|
152
|
+
emailAndPassword: { enabled: true },
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export async function getSession(): Promise<Session | null> {
|
|
156
|
+
const cookieStore = await cookies();
|
|
157
|
+
const session = await auth.api.getSession({
|
|
158
|
+
headers: new Headers({ cookie: cookieStore.toString() }),
|
|
159
|
+
});
|
|
160
|
+
if (!session?.user) return null;
|
|
161
|
+
return {
|
|
162
|
+
user: {
|
|
163
|
+
id: session.user.id,
|
|
164
|
+
name: session.user.name,
|
|
165
|
+
email: session.user.email,
|
|
166
|
+
image: session.user.image ?? null,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export async function requireAuth(): Promise<Session> {
|
|
172
|
+
const session = await getSession();
|
|
173
|
+
if (!session) {
|
|
174
|
+
const { redirect } = await import('next/navigation');
|
|
175
|
+
redirect('/login');
|
|
176
|
+
}
|
|
177
|
+
return session;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export async function signIn(
|
|
181
|
+
email: string,
|
|
182
|
+
password: string,
|
|
183
|
+
): Promise<Session | null> {
|
|
184
|
+
try {
|
|
185
|
+
await auth.api.signInEmail({ body: { email, password } });
|
|
186
|
+
return getSession();
|
|
187
|
+
} catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export async function signOut(): Promise<void> {
|
|
193
|
+
const cookieStore = await cookies();
|
|
194
|
+
await auth.api.signOut({
|
|
195
|
+
headers: new Headers({ cookie: cookieStore.toString() }),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Supabase Auth
|
|
203
|
+
|
|
204
|
+
### Install
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm install @supabase/supabase-js @supabase/ssr
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Replace `app/lib/auth.ts`
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { createServerClient } from '@supabase/ssr';
|
|
214
|
+
import { cookies } from 'next/headers';
|
|
215
|
+
|
|
216
|
+
export interface AuthUser {
|
|
217
|
+
id: string;
|
|
218
|
+
name: string;
|
|
219
|
+
email: string;
|
|
220
|
+
image?: string | null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface Session {
|
|
224
|
+
user: AuthUser;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function createClient() {
|
|
228
|
+
const cookieStore = cookies();
|
|
229
|
+
return createServerClient(
|
|
230
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
231
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
232
|
+
{
|
|
233
|
+
cookies: {
|
|
234
|
+
getAll: () => cookieStore.then((c) => c.getAll()),
|
|
235
|
+
setAll: (cookies) =>
|
|
236
|
+
cookieStore.then((c) => {
|
|
237
|
+
cookies.forEach(({ name, value, options }) =>
|
|
238
|
+
c.set(name, value, options),
|
|
239
|
+
);
|
|
240
|
+
}),
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export async function getSession(): Promise<Session | null> {
|
|
247
|
+
const supabase = createClient();
|
|
248
|
+
const {
|
|
249
|
+
data: { user },
|
|
250
|
+
} = await supabase.auth.getUser();
|
|
251
|
+
if (!user) return null;
|
|
252
|
+
return {
|
|
253
|
+
user: {
|
|
254
|
+
id: user.id,
|
|
255
|
+
name: user.user_metadata.name || user.email?.split('@')[0] || '',
|
|
256
|
+
email: user.email!,
|
|
257
|
+
image: user.user_metadata.avatar_url ?? null,
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export async function requireAuth(): Promise<Session> {
|
|
263
|
+
const session = await getSession();
|
|
264
|
+
if (!session) {
|
|
265
|
+
const { redirect } = await import('next/navigation');
|
|
266
|
+
redirect('/login');
|
|
267
|
+
}
|
|
268
|
+
return session;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export async function signIn(
|
|
272
|
+
email: string,
|
|
273
|
+
password: string,
|
|
274
|
+
): Promise<Session | null> {
|
|
275
|
+
const supabase = createClient();
|
|
276
|
+
const { error } = await supabase.auth.signInWithPassword({ email, password });
|
|
277
|
+
if (error) return null;
|
|
278
|
+
return getSession();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export async function signOut(): Promise<void> {
|
|
282
|
+
const supabase = createClient();
|
|
283
|
+
await supabase.auth.signOut();
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Environment variables
|
|
288
|
+
|
|
289
|
+
Add to `.env.local`:
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
|
|
293
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## After Upgrading
|
|
299
|
+
|
|
300
|
+
1. Remove the `Session` model from `prisma/schema.prisma` (the provider manages sessions)
|
|
301
|
+
2. Keep the `User` model if your provider uses it, or migrate to the provider's user table
|
|
302
|
+
3. Run `npm run db:push` to apply schema changes
|
|
303
|
+
4. Test sign-in and sign-out flows
|
|
304
|
+
5. Update scenario seed data if the session table structure changed
|