@xylabs/toolchain 7.10.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/dist/actions/analyze.mjs +140 -0
- package/dist/actions/analyze.mjs.map +1 -0
- package/dist/actions/build.mjs +173 -0
- package/dist/actions/build.mjs.map +1 -0
- package/dist/actions/claude-check.mjs +199 -0
- package/dist/actions/claude-check.mjs.map +1 -0
- package/dist/actions/claude-clean.mjs +70 -0
- package/dist/actions/claude-clean.mjs.map +1 -0
- package/dist/actions/claude-commands.mjs +126 -0
- package/dist/actions/claude-commands.mjs.map +1 -0
- package/dist/actions/claude-rules.mjs +151 -0
- package/dist/actions/claude-rules.mjs.map +1 -0
- package/dist/actions/claude-settings.mjs +99 -0
- package/dist/actions/claude-settings.mjs.map +1 -0
- package/dist/actions/claude-skills.mjs +131 -0
- package/dist/actions/claude-skills.mjs.map +1 -0
- package/dist/actions/clean-docs.mjs +66 -0
- package/dist/actions/clean-docs.mjs.map +1 -0
- package/dist/actions/clean-eslint.mjs +47 -0
- package/dist/actions/clean-eslint.mjs.map +1 -0
- package/dist/actions/clean.mjs +166 -0
- package/dist/actions/clean.mjs.map +1 -0
- package/dist/actions/compile.mjs +184 -0
- package/dist/actions/compile.mjs.map +1 -0
- package/dist/actions/copy-assets.mjs +81 -0
- package/dist/actions/copy-assets.mjs.map +1 -0
- package/dist/actions/cycle.mjs +275 -0
- package/dist/actions/cycle.mjs.map +1 -0
- package/dist/actions/dead.mjs +119 -0
- package/dist/actions/dead.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/checkPackage.mjs +1556 -0
- package/dist/actions/deplint/checkPackage/checkPackage.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/checkPackageTypes.mjs +1 -0
- package/dist/actions/deplint/checkPackage/checkPackageTypes.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getMismatchedPeerDevVersions.mjs +77 -0
- package/dist/actions/deplint/checkPackage/getMismatchedPeerDevVersions.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnlistedDependencies.mjs +158 -0
- package/dist/actions/deplint/checkPackage/getUnlistedDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnlistedDevDependencies.mjs +125 -0
- package/dist/actions/deplint/checkPackage/getUnlistedDevDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnnecessaryPeerDependencies.mjs +207 -0
- package/dist/actions/deplint/checkPackage/getUnnecessaryPeerDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnsatisfiedPeerDependencies.mjs +318 -0
- package/dist/actions/deplint/checkPackage/getUnsatisfiedPeerDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnusedDependencies.mjs +163 -0
- package/dist/actions/deplint/checkPackage/getUnusedDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnusedDevDependencies.mjs +408 -0
- package/dist/actions/deplint/checkPackage/getUnusedDevDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getUnusedPeerDependencies.mjs +75 -0
- package/dist/actions/deplint/checkPackage/getUnusedPeerDependencies.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/getWorkspaceVersionProblems.mjs +128 -0
- package/dist/actions/deplint/checkPackage/getWorkspaceVersionProblems.mjs.map +1 -0
- package/dist/actions/deplint/checkPackage/index.mjs +1609 -0
- package/dist/actions/deplint/checkPackage/index.mjs.map +1 -0
- package/dist/actions/deplint/deplint.mjs +1840 -0
- package/dist/actions/deplint/deplint.mjs.map +1 -0
- package/dist/actions/deplint/engine.mjs +1736 -0
- package/dist/actions/deplint/engine.mjs.map +1 -0
- package/dist/actions/deplint/findFiles.mjs +39 -0
- package/dist/actions/deplint/findFiles.mjs.map +1 -0
- package/dist/actions/deplint/findFilesByGlob.mjs +14 -0
- package/dist/actions/deplint/findFilesByGlob.mjs.map +1 -0
- package/dist/actions/deplint/fixer.mjs +103 -0
- package/dist/actions/deplint/fixer.mjs.map +1 -0
- package/dist/actions/deplint/getBasePackageName.mjs +13 -0
- package/dist/actions/deplint/getBasePackageName.mjs.map +1 -0
- package/dist/actions/deplint/getCliReferencedPackagesFromFiles.mjs +140 -0
- package/dist/actions/deplint/getCliReferencedPackagesFromFiles.mjs.map +1 -0
- package/dist/actions/deplint/getDependenciesFromPackageJson.mjs +29 -0
- package/dist/actions/deplint/getDependenciesFromPackageJson.mjs.map +1 -0
- package/dist/actions/deplint/getExtendsFromTsconfigs.mjs +68 -0
- package/dist/actions/deplint/getExtendsFromTsconfigs.mjs.map +1 -0
- package/dist/actions/deplint/getExternalImportsFromFiles.mjs +143 -0
- package/dist/actions/deplint/getExternalImportsFromFiles.mjs.map +1 -0
- package/dist/actions/deplint/getImportsFromFile.mjs +85 -0
- package/dist/actions/deplint/getImportsFromFile.mjs.map +1 -0
- package/dist/actions/deplint/getRequiredPeerDependencies.mjs +37 -0
- package/dist/actions/deplint/getRequiredPeerDependencies.mjs.map +1 -0
- package/dist/actions/deplint/getScriptReferencedPackages.mjs +83 -0
- package/dist/actions/deplint/getScriptReferencedPackages.mjs.map +1 -0
- package/dist/actions/deplint/implicitDevDependencies.mjs +116 -0
- package/dist/actions/deplint/implicitDevDependencies.mjs.map +1 -0
- package/dist/actions/deplint/index.mjs +1848 -0
- package/dist/actions/deplint/index.mjs.map +1 -0
- package/dist/actions/deplint/packageEditor.mjs +82 -0
- package/dist/actions/deplint/packageEditor.mjs.map +1 -0
- package/dist/actions/deplint/packageJsonEditor.mjs +101 -0
- package/dist/actions/deplint/packageJsonEditor.mjs.map +1 -0
- package/dist/actions/deplint/reporters.mjs +36 -0
- package/dist/actions/deplint/reporters.mjs.map +1 -0
- package/dist/actions/deplint/rules.mjs +1223 -0
- package/dist/actions/deplint/rules.mjs.map +1 -0
- package/dist/actions/deplint/snapshot.mjs +372 -0
- package/dist/actions/deplint/snapshot.mjs.map +1 -0
- package/dist/actions/deplint/tsScriptsAliases.mjs +20 -0
- package/dist/actions/deplint/tsScriptsAliases.mjs.map +1 -0
- package/dist/actions/deplint/types.mjs +1 -0
- package/dist/actions/deplint/types.mjs.map +1 -0
- package/dist/actions/deploy.mjs +194 -0
- package/dist/actions/deploy.mjs.map +1 -0
- package/dist/actions/dupdeps.mjs +226 -0
- package/dist/actions/dupdeps.mjs.map +1 -0
- package/dist/actions/eject.mjs +142 -0
- package/dist/actions/eject.mjs.map +1 -0
- package/dist/actions/fix.mjs +359 -0
- package/dist/actions/fix.mjs.map +1 -0
- package/dist/actions/gen-docs.mjs +155 -0
- package/dist/actions/gen-docs.mjs.map +1 -0
- package/dist/actions/gitignore.mjs +159 -0
- package/dist/actions/gitignore.mjs.map +1 -0
- package/dist/actions/gitlint-fix.mjs +27 -0
- package/dist/actions/gitlint-fix.mjs.map +1 -0
- package/dist/actions/gitlint.mjs +48 -0
- package/dist/actions/gitlint.mjs.map +1 -0
- package/dist/actions/index.mjs +8259 -0
- package/dist/actions/index.mjs.map +1 -0
- package/dist/actions/knip.mjs +119 -0
- package/dist/actions/knip.mjs.map +1 -0
- package/dist/actions/license.mjs +92 -0
- package/dist/actions/license.mjs.map +1 -0
- package/dist/actions/lint-init.mjs +275 -0
- package/dist/actions/lint-init.mjs.map +1 -0
- package/dist/actions/lint.mjs +356 -0
- package/dist/actions/lint.mjs.map +1 -0
- package/dist/actions/lintNext.mjs +209 -0
- package/dist/actions/lintNext.mjs.map +1 -0
- package/dist/actions/lintlint.mjs +341 -0
- package/dist/actions/lintlint.mjs.map +1 -0
- package/dist/actions/npmignore-gen.mjs +90 -0
- package/dist/actions/npmignore-gen.mjs.map +1 -0
- package/dist/actions/orphan.mjs +110 -0
- package/dist/actions/orphan.mjs.map +1 -0
- package/dist/actions/package/clean-outputs.mjs +50 -0
- package/dist/actions/package/clean-outputs.mjs.map +1 -0
- package/dist/actions/package/clean-typescript.mjs +50 -0
- package/dist/actions/package/clean-typescript.mjs.map +1 -0
- package/dist/actions/package/clean.mjs +69 -0
- package/dist/actions/package/clean.mjs.map +1 -0
- package/dist/actions/package/compile/XyConfig.mjs +32 -0
- package/dist/actions/package/compile/XyConfig.mjs.map +1 -0
- package/dist/actions/package/compile/buildEntries.mjs +53 -0
- package/dist/actions/package/compile/buildEntries.mjs.map +1 -0
- package/dist/actions/package/compile/compile.mjs +439 -0
- package/dist/actions/package/compile/compile.mjs.map +1 -0
- package/dist/actions/package/compile/copyTypeFiles.mjs +34 -0
- package/dist/actions/package/compile/copyTypeFiles.mjs.map +1 -0
- package/dist/actions/package/compile/deepMerge.mjs +27 -0
- package/dist/actions/package/compile/deepMerge.mjs.map +1 -0
- package/dist/actions/package/compile/getCompilerOptions.mjs +12 -0
- package/dist/actions/package/compile/getCompilerOptions.mjs.map +1 -0
- package/dist/actions/package/compile/index.mjs +472 -0
- package/dist/actions/package/compile/index.mjs.map +1 -0
- package/dist/actions/package/compile/inputs.mjs +22 -0
- package/dist/actions/package/compile/inputs.mjs.map +1 -0
- package/dist/actions/package/compile/packageCompileTsc.mjs +93 -0
- package/dist/actions/package/compile/packageCompileTsc.mjs.map +1 -0
- package/dist/actions/package/compile/packageCompileTscTypes.mjs +92 -0
- package/dist/actions/package/compile/packageCompileTscTypes.mjs.map +1 -0
- package/dist/actions/package/compile/packageCompileTsup.mjs +402 -0
- package/dist/actions/package/compile/packageCompileTsup.mjs.map +1 -0
- package/dist/actions/package/copy-assets.mjs +69 -0
- package/dist/actions/package/copy-assets.mjs.map +1 -0
- package/dist/actions/package/cycle.mjs +62 -0
- package/dist/actions/package/cycle.mjs.map +1 -0
- package/dist/actions/package/gen-docs.mjs +137 -0
- package/dist/actions/package/gen-docs.mjs.map +1 -0
- package/dist/actions/package/index.mjs +1131 -0
- package/dist/actions/package/index.mjs.map +1 -0
- package/dist/actions/package/lint.mjs +87 -0
- package/dist/actions/package/lint.mjs.map +1 -0
- package/dist/actions/package/publint.mjs +336 -0
- package/dist/actions/package/publint.mjs.map +1 -0
- package/dist/actions/package/recompile.mjs +510 -0
- package/dist/actions/package/recompile.mjs.map +1 -0
- package/dist/actions/package-lint-deps.mjs +348 -0
- package/dist/actions/package-lint-deps.mjs.map +1 -0
- package/dist/actions/package-lint.mjs +774 -0
- package/dist/actions/package-lint.mjs.map +1 -0
- package/dist/actions/packman/clean.mjs +144 -0
- package/dist/actions/packman/clean.mjs.map +1 -0
- package/dist/actions/packman/convert.mjs +1331 -0
- package/dist/actions/packman/convert.mjs.map +1 -0
- package/dist/actions/packman/convertToPnpm.mjs +295 -0
- package/dist/actions/packman/convertToPnpm.mjs.map +1 -0
- package/dist/actions/packman/convertToYarn.mjs +307 -0
- package/dist/actions/packman/convertToYarn.mjs.map +1 -0
- package/dist/actions/packman/index.mjs +1493 -0
- package/dist/actions/packman/index.mjs.map +1 -0
- package/dist/actions/packman/lint.mjs +109 -0
- package/dist/actions/packman/lint.mjs.map +1 -0
- package/dist/actions/packman/rewriteScripts.mjs +52 -0
- package/dist/actions/packman/rewriteScripts.mjs.map +1 -0
- package/dist/actions/packman/rewriteSourceImports.mjs +60 -0
- package/dist/actions/packman/rewriteSourceImports.mjs.map +1 -0
- package/dist/actions/packman/swapTsScriptsDependency.mjs +57 -0
- package/dist/actions/packman/swapTsScriptsDependency.mjs.map +1 -0
- package/dist/actions/publint.mjs +748 -0
- package/dist/actions/publint.mjs.map +1 -0
- package/dist/actions/publish.mjs +208 -0
- package/dist/actions/publish.mjs.map +1 -0
- package/dist/actions/reactTest.mjs +142 -0
- package/dist/actions/reactTest.mjs.map +1 -0
- package/dist/actions/readme-gen.mjs +362 -0
- package/dist/actions/readme-gen.mjs.map +1 -0
- package/dist/actions/readme-init.mjs +89 -0
- package/dist/actions/readme-init.mjs.map +1 -0
- package/dist/actions/readme-lint.mjs +147 -0
- package/dist/actions/readme-lint.mjs.map +1 -0
- package/dist/actions/rebuild.mjs +143 -0
- package/dist/actions/rebuild.mjs.map +1 -0
- package/dist/actions/recompile.mjs +196 -0
- package/dist/actions/recompile.mjs.map +1 -0
- package/dist/actions/reinstall.mjs +283 -0
- package/dist/actions/reinstall.mjs.map +1 -0
- package/dist/actions/relint.mjs +355 -0
- package/dist/actions/relint.mjs.map +1 -0
- package/dist/actions/repo-init.mjs +217 -0
- package/dist/actions/repo-init.mjs.map +1 -0
- package/dist/actions/retest.mjs +150 -0
- package/dist/actions/retest.mjs.map +1 -0
- package/dist/actions/sitemap.mjs +121 -0
- package/dist/actions/sitemap.mjs.map +1 -0
- package/dist/actions/sonar.mjs +119 -0
- package/dist/actions/sonar.mjs.map +1 -0
- package/dist/actions/start.mjs +142 -0
- package/dist/actions/start.mjs.map +1 -0
- package/dist/actions/statics.mjs +225 -0
- package/dist/actions/statics.mjs.map +1 -0
- package/dist/actions/test.mjs +144 -0
- package/dist/actions/test.mjs.map +1 -0
- package/dist/actions/up.mjs +140 -0
- package/dist/actions/up.mjs.map +1 -0
- package/dist/actions/updo.mjs +533 -0
- package/dist/actions/updo.mjs.map +1 -0
- package/dist/actions/upplug.mjs +124 -0
- package/dist/actions/upplug.mjs.map +1 -0
- package/dist/actions/upyarn.mjs +119 -0
- package/dist/actions/upyarn.mjs.map +1 -0
- package/dist/actions/yarn3only.mjs +60 -0
- package/dist/actions/yarn3only.mjs.map +1 -0
- package/dist/bin/package/build-only.mjs +451 -0
- package/dist/bin/package/build-only.mjs.map +1 -0
- package/dist/bin/package/build.mjs +451 -0
- package/dist/bin/package/build.mjs.map +1 -0
- package/dist/bin/package/clean-outputs.mjs +50 -0
- package/dist/bin/package/clean-outputs.mjs.map +1 -0
- package/dist/bin/package/clean-typescript.mjs +50 -0
- package/dist/bin/package/clean-typescript.mjs.map +1 -0
- package/dist/bin/package/clean.mjs +75 -0
- package/dist/bin/package/clean.mjs.map +1 -0
- package/dist/bin/package/compile-only.mjs +447 -0
- package/dist/bin/package/compile-only.mjs.map +1 -0
- package/dist/bin/package/compile-tsup.mjs +409 -0
- package/dist/bin/package/compile-tsup.mjs.map +1 -0
- package/dist/bin/package/compile.mjs +451 -0
- package/dist/bin/package/compile.mjs.map +1 -0
- package/dist/bin/package/copy-assets-cjs.mjs +75 -0
- package/dist/bin/package/copy-assets-cjs.mjs.map +1 -0
- package/dist/bin/package/copy-assets-esm.mjs +75 -0
- package/dist/bin/package/copy-assets-esm.mjs.map +1 -0
- package/dist/bin/package/cycle.mjs +72 -0
- package/dist/bin/package/cycle.mjs.map +1 -0
- package/dist/bin/package/fix.mjs +97 -0
- package/dist/bin/package/fix.mjs.map +1 -0
- package/dist/bin/package/gen-docs.mjs +142 -0
- package/dist/bin/package/gen-docs.mjs.map +1 -0
- package/dist/bin/package/lint-verbose.mjs +97 -0
- package/dist/bin/package/lint-verbose.mjs.map +1 -0
- package/dist/bin/package/lint.mjs +97 -0
- package/dist/bin/package/lint.mjs.map +1 -0
- package/dist/bin/package/publint.mjs +423 -0
- package/dist/bin/package/publint.mjs.map +1 -0
- package/dist/bin/package/recompile.mjs +516 -0
- package/dist/bin/package/recompile.mjs.map +1 -0
- package/dist/bin/package/relint.mjs +97 -0
- package/dist/bin/package/relint.mjs.map +1 -0
- package/dist/bin/run-or-exec.mjs +20 -0
- package/dist/bin/run-or-exec.mjs.map +1 -0
- package/dist/bin/xy.mjs +8885 -0
- package/dist/bin/xy.mjs.map +1 -0
- package/dist/index.d.ts +1102 -0
- package/dist/index.mjs +9986 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/checkResult.mjs +16 -0
- package/dist/lib/checkResult.mjs.map +1 -0
- package/dist/lib/claudeMdTemplate.mjs +69 -0
- package/dist/lib/claudeMdTemplate.mjs.map +1 -0
- package/dist/lib/concurrency.mjs +38 -0
- package/dist/lib/concurrency.mjs.map +1 -0
- package/dist/lib/createBuildConfig.mjs +55 -0
- package/dist/lib/createBuildConfig.mjs.map +1 -0
- package/dist/lib/defaultBuildConfig.mjs +23 -0
- package/dist/lib/defaultBuildConfig.mjs.map +1 -0
- package/dist/lib/deleteGlob.mjs +13 -0
- package/dist/lib/deleteGlob.mjs.map +1 -0
- package/dist/lib/dependencies/DuplicateDetector.mjs +99 -0
- package/dist/lib/dependencies/DuplicateDetector.mjs.map +1 -0
- package/dist/lib/dependencies/detectDuplicateDependencies.mjs +203 -0
- package/dist/lib/dependencies/detectDuplicateDependencies.mjs.map +1 -0
- package/dist/lib/dependencies/index.mjs +281 -0
- package/dist/lib/dependencies/index.mjs.map +1 -0
- package/dist/lib/dependencies/workspaceCycles.mjs +79 -0
- package/dist/lib/dependencies/workspaceCycles.mjs.map +1 -0
- package/dist/lib/file/ReadFileSyncOptions.mjs +6 -0
- package/dist/lib/file/ReadFileSyncOptions.mjs.map +1 -0
- package/dist/lib/file/constants.mjs +8 -0
- package/dist/lib/file/constants.mjs.map +1 -0
- package/dist/lib/file/fileLines.mjs +32 -0
- package/dist/lib/file/fileLines.mjs.map +1 -0
- package/dist/lib/file/index.mjs +42 -0
- package/dist/lib/file/index.mjs.map +1 -0
- package/dist/lib/file/tryReadFileSync.mjs +14 -0
- package/dist/lib/file/tryReadFileSync.mjs.map +1 -0
- package/dist/lib/fillTemplate.mjs +8 -0
- package/dist/lib/fillTemplate.mjs.map +1 -0
- package/dist/lib/generateIgnoreFiles.mjs +86 -0
- package/dist/lib/generateIgnoreFiles.mjs.map +1 -0
- package/dist/lib/generateReadmeFiles.mjs +323 -0
- package/dist/lib/generateReadmeFiles.mjs.map +1 -0
- package/dist/lib/gitignoreTemplate.mjs +12 -0
- package/dist/lib/gitignoreTemplate.mjs.map +1 -0
- package/dist/lib/index.mjs +1627 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/initCwd.mjs +8 -0
- package/dist/lib/initCwd.mjs.map +1 -0
- package/dist/lib/jsonFormatters.mjs +11 -0
- package/dist/lib/jsonFormatters.mjs.map +1 -0
- package/dist/lib/latestVersions.mjs +12 -0
- package/dist/lib/latestVersions.mjs.map +1 -0
- package/dist/lib/loadConfig.mjs +72 -0
- package/dist/lib/loadConfig.mjs.map +1 -0
- package/dist/lib/packageName.mjs +26 -0
- package/dist/lib/packageName.mjs.map +1 -0
- package/dist/lib/parsedPackageJSON.mjs +11 -0
- package/dist/lib/parsedPackageJSON.mjs.map +1 -0
- package/dist/lib/processEx.mjs +36 -0
- package/dist/lib/processEx.mjs.map +1 -0
- package/dist/lib/repoTemplates.mjs +34 -0
- package/dist/lib/repoTemplates.mjs.map +1 -0
- package/dist/lib/runInstall.mjs +30 -0
- package/dist/lib/runInstall.mjs.map +1 -0
- package/dist/lib/runSteps.mjs +118 -0
- package/dist/lib/runSteps.mjs.map +1 -0
- package/dist/lib/runStepsAsync.mjs +136 -0
- package/dist/lib/runStepsAsync.mjs.map +1 -0
- package/dist/lib/runXy.mjs +147 -0
- package/dist/lib/runXy.mjs.map +1 -0
- package/dist/lib/runXyWithWarning.mjs +36 -0
- package/dist/lib/runXyWithWarning.mjs.map +1 -0
- package/dist/lib/safeExit.mjs +61 -0
- package/dist/lib/safeExit.mjs.map +1 -0
- package/dist/lib/string/empty.mjs +8 -0
- package/dist/lib/string/empty.mjs.map +1 -0
- package/dist/lib/string/index.mjs +12 -0
- package/dist/lib/string/index.mjs.map +1 -0
- package/dist/lib/string/union.mjs +6 -0
- package/dist/lib/string/union.mjs.map +1 -0
- package/dist/lib/tryRunLocalScript.mjs +57 -0
- package/dist/lib/tryRunLocalScript.mjs.map +1 -0
- package/dist/lib/updo/applyUpdates.mjs +44 -0
- package/dist/lib/updo/applyUpdates.mjs.map +1 -0
- package/dist/lib/updo/collectWorkspaceDeps.mjs +48 -0
- package/dist/lib/updo/collectWorkspaceDeps.mjs.map +1 -0
- package/dist/lib/updo/fetchRegistryInfo.mjs +53 -0
- package/dist/lib/updo/fetchRegistryInfo.mjs.map +1 -0
- package/dist/lib/updo/index.mjs +594 -0
- package/dist/lib/updo/index.mjs.map +1 -0
- package/dist/lib/updo/interactiveSelect.mjs +185 -0
- package/dist/lib/updo/interactiveSelect.mjs.map +1 -0
- package/dist/lib/updo/interfaces.mjs +1 -0
- package/dist/lib/updo/interfaces.mjs.map +1 -0
- package/dist/lib/updo/renderTable.mjs +79 -0
- package/dist/lib/updo/renderTable.mjs.map +1 -0
- package/dist/lib/updo/resolveVersions.mjs +49 -0
- package/dist/lib/updo/resolveVersions.mjs.map +1 -0
- package/dist/lib/updo/runUpdo.mjs +511 -0
- package/dist/lib/updo/runUpdo.mjs.map +1 -0
- package/dist/lib/withErrnoException.mjs +13 -0
- package/dist/lib/withErrnoException.mjs.map +1 -0
- package/dist/lib/withError.mjs +8 -0
- package/dist/lib/withError.mjs.map +1 -0
- package/dist/lib/yarn/index.mjs +39 -0
- package/dist/lib/yarn/index.mjs.map +1 -0
- package/dist/lib/yarn/isYarnVersionOrGreater.mjs +18 -0
- package/dist/lib/yarn/isYarnVersionOrGreater.mjs.map +1 -0
- package/dist/lib/yarn/workspace/Workspace.mjs +1 -0
- package/dist/lib/yarn/workspace/Workspace.mjs.map +1 -0
- package/dist/lib/yarn/workspace/index.mjs +23 -0
- package/dist/lib/yarn/workspace/index.mjs.map +1 -0
- package/dist/lib/yarn/workspace/yarnWorkspace.mjs +22 -0
- package/dist/lib/yarn/workspace/yarnWorkspace.mjs.map +1 -0
- package/dist/lib/yarn/workspace/yarnWorkspaces.mjs +15 -0
- package/dist/lib/yarn/workspace/yarnWorkspaces.mjs.map +1 -0
- package/dist/lib/yarn/yarnInitCwd.mjs +8 -0
- package/dist/lib/yarn/yarnInitCwd.mjs.map +1 -0
- package/dist/loadPackageConfig.mjs +18 -0
- package/dist/loadPackageConfig.mjs.map +1 -0
- package/dist/pm/PackageManager.mjs +1 -0
- package/dist/pm/PackageManager.mjs.map +1 -0
- package/dist/pm/detectPackageManager.mjs +10 -0
- package/dist/pm/detectPackageManager.mjs.map +1 -0
- package/dist/pm/detectReact.mjs +52 -0
- package/dist/pm/detectReact.mjs.map +1 -0
- package/dist/pm/index.mjs +263 -0
- package/dist/pm/index.mjs.map +1 -0
- package/dist/pm/pnpmPackageManager.mjs +97 -0
- package/dist/pm/pnpmPackageManager.mjs.map +1 -0
- package/dist/pm/registry.mjs +27 -0
- package/dist/pm/registry.mjs.map +1 -0
- package/dist/pm/yarnPackageManager.mjs +112 -0
- package/dist/pm/yarnPackageManager.mjs.map +1 -0
- package/dist/types.d.mjs +1 -0
- package/dist/types.d.mjs.map +1 -0
- package/dist/xy/build/buildCommand.mjs +194 -0
- package/dist/xy/build/buildCommand.mjs.map +1 -0
- package/dist/xy/build/compileCommand.mjs +203 -0
- package/dist/xy/build/compileCommand.mjs.map +1 -0
- package/dist/xy/build/compileOnlyCommand.mjs +204 -0
- package/dist/xy/build/compileOnlyCommand.mjs.map +1 -0
- package/dist/xy/build/copyAssetsCommand.mjs +92 -0
- package/dist/xy/build/copyAssetsCommand.mjs.map +1 -0
- package/dist/xy/build/index.mjs +487 -0
- package/dist/xy/build/index.mjs.map +1 -0
- package/dist/xy/build/rebuildCommand.mjs +156 -0
- package/dist/xy/build/rebuildCommand.mjs.map +1 -0
- package/dist/xy/build/recompileCommand.mjs +215 -0
- package/dist/xy/build/recompileCommand.mjs.map +1 -0
- package/dist/xy/common/checkCommand.mjs +1909 -0
- package/dist/xy/common/checkCommand.mjs.map +1 -0
- package/dist/xy/common/claude/checkCommand.mjs +207 -0
- package/dist/xy/common/claude/checkCommand.mjs.map +1 -0
- package/dist/xy/common/claude/cleanCommand.mjs +78 -0
- package/dist/xy/common/claude/cleanCommand.mjs.map +1 -0
- package/dist/xy/common/claude/commandsCommand.mjs +134 -0
- package/dist/xy/common/claude/commandsCommand.mjs.map +1 -0
- package/dist/xy/common/claude/index.mjs +734 -0
- package/dist/xy/common/claude/index.mjs.map +1 -0
- package/dist/xy/common/claude/initCommand.mjs +458 -0
- package/dist/xy/common/claude/initCommand.mjs.map +1 -0
- package/dist/xy/common/claude/rulesCommand.mjs +167 -0
- package/dist/xy/common/claude/rulesCommand.mjs.map +1 -0
- package/dist/xy/common/claude/settingsCommand.mjs +115 -0
- package/dist/xy/common/claude/settingsCommand.mjs.map +1 -0
- package/dist/xy/common/claude/skillsCommand.mjs +140 -0
- package/dist/xy/common/claude/skillsCommand.mjs.map +1 -0
- package/dist/xy/common/cleanDocsCommand.mjs +74 -0
- package/dist/xy/common/cleanDocsCommand.mjs.map +1 -0
- package/dist/xy/common/deadCommand.mjs +137 -0
- package/dist/xy/common/deadCommand.mjs.map +1 -0
- package/dist/xy/common/genDocsCommand.mjs +175 -0
- package/dist/xy/common/genDocsCommand.mjs.map +1 -0
- package/dist/xy/common/gitignoreCommand.mjs +165 -0
- package/dist/xy/common/gitignoreCommand.mjs.map +1 -0
- package/dist/xy/common/gitlintCommand.mjs +89 -0
- package/dist/xy/common/gitlintCommand.mjs.map +1 -0
- package/dist/xy/common/index.mjs +4654 -0
- package/dist/xy/common/index.mjs.map +1 -0
- package/dist/xy/common/licenseCommand.mjs +108 -0
- package/dist/xy/common/licenseCommand.mjs.map +1 -0
- package/dist/xy/common/npmignoreGenCommand.mjs +100 -0
- package/dist/xy/common/npmignoreGenCommand.mjs.map +1 -0
- package/dist/xy/common/orphan/cleanCommand.mjs +102 -0
- package/dist/xy/common/orphan/cleanCommand.mjs.map +1 -0
- package/dist/xy/common/orphan/index.mjs +138 -0
- package/dist/xy/common/orphan/index.mjs.map +1 -0
- package/dist/xy/common/orphan/listCommand.mjs +100 -0
- package/dist/xy/common/orphan/listCommand.mjs.map +1 -0
- package/dist/xy/common/packmanCommand.mjs +1538 -0
- package/dist/xy/common/packmanCommand.mjs.map +1 -0
- package/dist/xy/common/readme/genCommand.mjs +395 -0
- package/dist/xy/common/readme/genCommand.mjs.map +1 -0
- package/dist/xy/common/readme/index.mjs +538 -0
- package/dist/xy/common/readme/index.mjs.map +1 -0
- package/dist/xy/common/readme/initCommand.mjs +109 -0
- package/dist/xy/common/readme/initCommand.mjs.map +1 -0
- package/dist/xy/common/readme/lintCommand.mjs +181 -0
- package/dist/xy/common/readme/lintCommand.mjs.map +1 -0
- package/dist/xy/common/repo/index.mjs +1070 -0
- package/dist/xy/common/repo/index.mjs.map +1 -0
- package/dist/xy/common/repo/initCommand.mjs +273 -0
- package/dist/xy/common/repo/initCommand.mjs.map +1 -0
- package/dist/xy/common/repo/lintCommand.mjs +789 -0
- package/dist/xy/common/repo/lintCommand.mjs.map +1 -0
- package/dist/xy/common/retestCommand.mjs +163 -0
- package/dist/xy/common/retestCommand.mjs.map +1 -0
- package/dist/xy/common/testCommand.mjs +157 -0
- package/dist/xy/common/testCommand.mjs.map +1 -0
- package/dist/xy/deploy/deployCommand.mjs +214 -0
- package/dist/xy/deploy/deployCommand.mjs.map +1 -0
- package/dist/xy/deploy/index.mjs +289 -0
- package/dist/xy/deploy/index.mjs.map +1 -0
- package/dist/xy/deploy/publishCommand.mjs +218 -0
- package/dist/xy/deploy/publishCommand.mjs.map +1 -0
- package/dist/xy/index.mjs +8887 -0
- package/dist/xy/index.mjs.map +1 -0
- package/dist/xy/install/cleanCommand.mjs +182 -0
- package/dist/xy/install/cleanCommand.mjs.map +1 -0
- package/dist/xy/install/dupdepsCommand.mjs +234 -0
- package/dist/xy/install/dupdepsCommand.mjs.map +1 -0
- package/dist/xy/install/index.mjs +1006 -0
- package/dist/xy/install/index.mjs.map +1 -0
- package/dist/xy/install/reinstallCommand.mjs +292 -0
- package/dist/xy/install/reinstallCommand.mjs.map +1 -0
- package/dist/xy/install/staticsCommand.mjs +233 -0
- package/dist/xy/install/staticsCommand.mjs.map +1 -0
- package/dist/xy/install/upCommand.mjs +150 -0
- package/dist/xy/install/upCommand.mjs.map +1 -0
- package/dist/xy/install/updoCommand.mjs +550 -0
- package/dist/xy/install/updoCommand.mjs.map +1 -0
- package/dist/xy/lint/cycleCommand.mjs +289 -0
- package/dist/xy/lint/cycleCommand.mjs.map +1 -0
- package/dist/xy/lint/deplintCommand.mjs +1897 -0
- package/dist/xy/lint/deplintCommand.mjs.map +1 -0
- package/dist/xy/lint/fixCommand.mjs +398 -0
- package/dist/xy/lint/fixCommand.mjs.map +1 -0
- package/dist/xy/lint/index.mjs +3759 -0
- package/dist/xy/lint/index.mjs.map +1 -0
- package/dist/xy/lint/knipCommand.mjs +142 -0
- package/dist/xy/lint/knipCommand.mjs.map +1 -0
- package/dist/xy/lint/lint/index.mjs +695 -0
- package/dist/xy/lint/lint/index.mjs.map +1 -0
- package/dist/xy/lint/lint/initCommand.mjs +282 -0
- package/dist/xy/lint/lint/initCommand.mjs.map +1 -0
- package/dist/xy/lint/lint/runCommand.mjs +405 -0
- package/dist/xy/lint/lint/runCommand.mjs.map +1 -0
- package/dist/xy/lint/lintCommand.mjs +695 -0
- package/dist/xy/lint/lintCommand.mjs.map +1 -0
- package/dist/xy/lint/lintlintCommand.mjs +359 -0
- package/dist/xy/lint/lintlintCommand.mjs.map +1 -0
- package/dist/xy/lint/publintCommand.mjs +778 -0
- package/dist/xy/lint/publintCommand.mjs.map +1 -0
- package/dist/xy/lint/relintCommand.mjs +381 -0
- package/dist/xy/lint/relintCommand.mjs.map +1 -0
- package/dist/xy/lint/sonarCommand.mjs +137 -0
- package/dist/xy/lint/sonarCommand.mjs.map +1 -0
- package/dist/xy/param.mjs +8 -0
- package/dist/xy/param.mjs.map +1 -0
- package/dist/xy/react/analyzeCommand.mjs +150 -0
- package/dist/xy/react/analyzeCommand.mjs.map +1 -0
- package/dist/xy/react/ejectCommand.mjs +150 -0
- package/dist/xy/react/ejectCommand.mjs.map +1 -0
- package/dist/xy/react/index.mjs +202 -0
- package/dist/xy/react/index.mjs.map +1 -0
- package/dist/xy/react/sitemapCommand.mjs +129 -0
- package/dist/xy/react/sitemapCommand.mjs.map +1 -0
- package/dist/xy/react/startCommand.mjs +150 -0
- package/dist/xy/react/startCommand.mjs.map +1 -0
- package/dist/xy/xy.mjs +8879 -0
- package/dist/xy/xy.mjs.map +1 -0
- package/dist/xy/xyParseOptions.mjs +117 -0
- package/dist/xy/xyParseOptions.mjs.map +1 -0
- package/dist/xy/yarn/index.mjs +188 -0
- package/dist/xy/yarn/index.mjs.map +1 -0
- package/dist/xy/yarn/upplugCommand.mjs +134 -0
- package/dist/xy/yarn/upplugCommand.mjs.map +1 -0
- package/dist/xy/yarn/upyarnCommand.mjs +129 -0
- package/dist/xy/yarn/upyarnCommand.mjs.map +1 -0
- package/dist/xy/yarn/yarn3OnlyCommand.mjs +70 -0
- package/dist/xy/yarn/yarn3OnlyCommand.mjs.map +1 -0
- package/package.json +119 -0
- package/templates/claude/CLAUDE-local.md +4 -0
- package/templates/claude/CLAUDE-project.md +4 -0
- package/templates/claude/commands/xy-build.md +7 -0
- package/templates/claude/commands/xy-clean.md +7 -0
- package/templates/claude/commands/xy-compile.md +7 -0
- package/templates/claude/commands/xy-cycle.md +7 -0
- package/templates/claude/commands/xy-dead.md +7 -0
- package/templates/claude/commands/xy-deplint.md +7 -0
- package/templates/claude/commands/xy-deps.md +24 -0
- package/templates/claude/commands/xy-dupdeps.md +7 -0
- package/templates/claude/commands/xy-fix.md +7 -0
- package/templates/claude/commands/xy-gen-docs.md +7 -0
- package/templates/claude/commands/xy-gitignore.md +7 -0
- package/templates/claude/commands/xy-gitlint.md +7 -0
- package/templates/claude/commands/xy-knip.md +7 -0
- package/templates/claude/commands/xy-license.md +7 -0
- package/templates/claude/commands/xy-lint-rules.md +44 -0
- package/templates/claude/commands/xy-lint.md +7 -0
- package/templates/claude/commands/xy-publint.md +7 -0
- package/templates/claude/commands/xy-rebuild.md +7 -0
- package/templates/claude/commands/xy-recompile.md +7 -0
- package/templates/claude/commands/xy-reinstall.md +7 -0
- package/templates/claude/commands/xy-relint.md +7 -0
- package/templates/claude/commands/xy-retest.md +7 -0
- package/templates/claude/commands/xy-sonar.md +7 -0
- package/templates/claude/commands/xy-test.md +7 -0
- package/templates/claude/commands/xy-up.md +9 -0
- package/templates/claude/rules/xylabs-architecture.md +8 -0
- package/templates/claude/rules/xylabs-git-workflow.md +7 -0
- package/templates/claude/rules/xylabs-naming.md +7 -0
- package/templates/claude/rules/xylabs-style.md +17 -0
- package/templates/claude/skills/xylabs-e2e-setup/SKILL.md +223 -0
- package/templates/claude/skills/xylabs-xy-cli/SKILL.md +236 -0
- package/templates/claude/skills/xylabs-xy-deplint-fix/SKILL.md +122 -0
- package/templates/gitignore/gitignore/template.gitignore +51 -0
- package/templates/gitignore/template.gitignore +51 -0
- package/templates/readme/README.body.md +25 -0
- package/templates/readme/README.template.md +22 -0
- package/templates/repo/cli/package/package.json.tmpl +63 -0
- package/templates/repo/cli/package/src/__packageName__.ts.tmpl +21 -0
- package/templates/repo/cli/package/src/actions/index.ts +1 -0
- package/templates/repo/cli/package/src/actions/printVersion.ts.tmpl +8 -0
- package/templates/repo/cli/package/src/bin/__packageName__.ts.tmpl +12 -0
- package/templates/repo/cli/package/src/commands/index.ts +1 -0
- package/templates/repo/cli/package/src/commands/versionCommand.ts.tmpl +11 -0
- package/templates/repo/cli/package/src/index.ts.tmpl +1 -0
- package/templates/repo/cli/package/tsconfig.build.json +25 -0
- package/templates/repo/cli/package/tsconfig.json +4 -0
- package/templates/repo/cli/package/tsup.config.ts +15 -0
- package/templates/repo/cli/package/xy.config.ts +3 -0
- package/templates/repo/cli/root/CLAUDE.md.tmpl +38 -0
- package/templates/repo/cli/root/cspell.json.tmpl +13 -0
- package/templates/repo/cli/root/eslint.config.ts +28 -0
- package/templates/repo/cli/root/github/workflows/build-pnpm.yml.tmpl +34 -0
- package/templates/repo/cli/root/github/workflows/build-yarn.yml.tmpl +32 -0
- package/templates/repo/cli/root/gitignore.tmpl +47 -0
- package/templates/repo/cli/root/knip.config.ts +16 -0
- package/templates/repo/cli/root/package.json.tmpl +54 -0
- package/templates/repo/cli/root/pnpm-workspace.yaml +2 -0
- package/templates/repo/cli/root/tsconfig.json +4 -0
- package/templates/repo/cli/root/vitest.config.ts +31 -0
- package/templates/repo/cli/root/xy.config.ts.tmpl +5 -0
|
@@ -0,0 +1,4654 @@
|
|
|
1
|
+
// src/xy/common/checkCommand.ts
|
|
2
|
+
import chalk35 from "chalk";
|
|
3
|
+
|
|
4
|
+
// src/lib/checkResult.ts
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
var checkResult = (name, result, level = "error", exitOnFail = false) => {
|
|
7
|
+
if (result) {
|
|
8
|
+
const exiting = exitOnFail ? "[Exiting Process]" : "[Continuing]";
|
|
9
|
+
const chalkFunc = level === "error" ? chalk.red : chalk.yellow;
|
|
10
|
+
console[level](chalkFunc(`${name} had ${result} failures ${exiting}`));
|
|
11
|
+
if (exitOnFail) {
|
|
12
|
+
process.exit(result);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/lib/claudeMdTemplate.ts
|
|
18
|
+
import {
|
|
19
|
+
readdirSync,
|
|
20
|
+
readFileSync,
|
|
21
|
+
statSync
|
|
22
|
+
} from "fs";
|
|
23
|
+
import { createRequire } from "module";
|
|
24
|
+
import PATH from "path";
|
|
25
|
+
var require2 = createRequire(import.meta.url);
|
|
26
|
+
var packageRoot = PATH.dirname(require2.resolve("@xylabs/ts-scripts-common/package.json"));
|
|
27
|
+
var templatesDir = PATH.resolve(packageRoot, "templates", "claude");
|
|
28
|
+
function applyPackageManager(content, pm) {
|
|
29
|
+
return content.replaceAll("yarn xy", `${pm} xy`).replaceAll("yarn add", `${pm} add`);
|
|
30
|
+
}
|
|
31
|
+
var XYLABS_RULES_PREFIX = "xylabs-";
|
|
32
|
+
var XYLABS_COMMANDS_PREFIX = "xy-";
|
|
33
|
+
var LEGACY_COMMANDS_PREFIX = "xylabs-";
|
|
34
|
+
var XYLABS_SKILLS_PREFIX = "xylabs-";
|
|
35
|
+
var claudeMdRuleTemplates = () => {
|
|
36
|
+
const rulesDir = PATH.resolve(templatesDir, "rules");
|
|
37
|
+
const files = readdirSync(rulesDir).filter((f) => f.startsWith(XYLABS_RULES_PREFIX) && f.endsWith(".md"));
|
|
38
|
+
const result = {};
|
|
39
|
+
for (const file of files) {
|
|
40
|
+
result[file] = readFileSync(PATH.resolve(rulesDir, file), "utf8");
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
var claudeCommandTemplates = () => {
|
|
45
|
+
const commandsDir = PATH.resolve(templatesDir, "commands");
|
|
46
|
+
const files = readdirSync(commandsDir).filter((f) => f.startsWith(XYLABS_COMMANDS_PREFIX) && f.endsWith(".md"));
|
|
47
|
+
const result = {};
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
result[file] = readFileSync(PATH.resolve(commandsDir, file), "utf8");
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
var claudeSkillTemplates = () => {
|
|
54
|
+
const skillsDir = PATH.resolve(templatesDir, "skills");
|
|
55
|
+
const dirs = readdirSync(skillsDir).filter(
|
|
56
|
+
(f) => f.startsWith(XYLABS_SKILLS_PREFIX) && statSync(PATH.resolve(skillsDir, f)).isDirectory()
|
|
57
|
+
);
|
|
58
|
+
const result = {};
|
|
59
|
+
for (const dir of dirs) {
|
|
60
|
+
const dirPath = PATH.resolve(skillsDir, dir);
|
|
61
|
+
const files = readdirSync(dirPath, { recursive: true, encoding: "utf8" });
|
|
62
|
+
result[dir] = {};
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
if (statSync(PATH.resolve(dirPath, file)).isFile()) {
|
|
65
|
+
result[dir][file] = readFileSync(PATH.resolve(dirPath, file), "utf8");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
|
+
var claudeMdLocalTemplate = () => readFileSync(PATH.resolve(templatesDir, "CLAUDE-local.md"), "utf8");
|
|
72
|
+
|
|
73
|
+
// src/lib/concurrency.ts
|
|
74
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
75
|
+
var outputStorage = new AsyncLocalStorage();
|
|
76
|
+
var captureInstalled = false;
|
|
77
|
+
function installOutputCapture() {
|
|
78
|
+
if (captureInstalled) return;
|
|
79
|
+
captureInstalled = true;
|
|
80
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
81
|
+
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
82
|
+
function intercept(original) {
|
|
83
|
+
return function(chunk, ...args) {
|
|
84
|
+
const buffer = outputStorage.getStore();
|
|
85
|
+
if (buffer) {
|
|
86
|
+
buffer.push(typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk));
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return original(chunk, ...args);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
process.stdout.write = intercept(originalStdoutWrite);
|
|
93
|
+
process.stderr.write = intercept(originalStderrWrite);
|
|
94
|
+
}
|
|
95
|
+
async function runWithConcurrency(items, concurrency, fn) {
|
|
96
|
+
let next = 0;
|
|
97
|
+
async function worker() {
|
|
98
|
+
while (next < items.length) {
|
|
99
|
+
const i = next++;
|
|
100
|
+
await fn(items[i]);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/lib/deleteGlob.ts
|
|
107
|
+
import fs from "fs";
|
|
108
|
+
import { glob } from "glob";
|
|
109
|
+
var deleteGlob = (globPath) => {
|
|
110
|
+
const files = glob.sync(globPath);
|
|
111
|
+
for (const file of files) {
|
|
112
|
+
fs.rmSync(file, { recursive: true, force: true });
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// src/pm/detectPackageManager.ts
|
|
117
|
+
import { existsSync } from "fs";
|
|
118
|
+
function detectPackageManager() {
|
|
119
|
+
if (existsSync("pnpm-lock.yaml") || existsSync("pnpm-workspace.yaml")) return "pnpm";
|
|
120
|
+
return "yarn";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/pm/registry.ts
|
|
124
|
+
var implementations = /* @__PURE__ */ new Map();
|
|
125
|
+
function getPackageManager(name) {
|
|
126
|
+
const pmName = name ?? detectPackageManager();
|
|
127
|
+
const pm = implementations.get(pmName);
|
|
128
|
+
if (!pm) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`No package manager implementation registered for "${pmName}". Ensure registerPackageManager() has been called before getPackageManager().`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return pm;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/lib/processEx.ts
|
|
137
|
+
import chalk2 from "chalk";
|
|
138
|
+
|
|
139
|
+
// src/lib/withError.ts
|
|
140
|
+
var withError = (ex, closure, predicate = (ex2) => !!ex2.name && !!ex2.message) => {
|
|
141
|
+
return predicate(ex) ? closure(ex) : void 0;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/lib/withErrnoException.ts
|
|
145
|
+
var withErrnoException = (ex, closure) => {
|
|
146
|
+
return withError(ex, closure, (ex2) => ex2.errno !== void 0);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// src/lib/processEx.ts
|
|
150
|
+
var processEx = (ex) => {
|
|
151
|
+
const error = typeof ex === "string" ? new Error(ex) : ex;
|
|
152
|
+
const exitCode = withErrnoException(error, (error2) => {
|
|
153
|
+
if (error2.code === "ENOENT") {
|
|
154
|
+
console.error(chalk2.red(`'${error2.path}' not found.`));
|
|
155
|
+
} else {
|
|
156
|
+
console.error(chalk2.red(`Errno: ${error2.code}`));
|
|
157
|
+
}
|
|
158
|
+
return error2.errno ?? -1;
|
|
159
|
+
}) ?? withError(error, (error2) => {
|
|
160
|
+
console.error(chalk2.red(`${error2.name}: ${error2.message}`));
|
|
161
|
+
return -1;
|
|
162
|
+
}) ?? (() => {
|
|
163
|
+
console.error(chalk2.red(`Unexpected Error: ${JSON.stringify(ex, null, 2)}`));
|
|
164
|
+
return -1;
|
|
165
|
+
})();
|
|
166
|
+
process.exit(process.exitCode ?? exitCode);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// src/lib/safeExit.ts
|
|
170
|
+
var safeExit = (func, exitOnFail = true) => {
|
|
171
|
+
try {
|
|
172
|
+
const result = func();
|
|
173
|
+
if (result && exitOnFail) {
|
|
174
|
+
process.exit(result);
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
} catch (ex) {
|
|
178
|
+
return processEx(ex);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// src/lib/file/constants.ts
|
|
183
|
+
var WINDOWS_NEWLINE_REGEX = /\r\n/g;
|
|
184
|
+
var CROSS_PLATFORM_NEWLINE = "\n";
|
|
185
|
+
|
|
186
|
+
// src/lib/file/fileLines.ts
|
|
187
|
+
import {
|
|
188
|
+
existsSync as existsSync2,
|
|
189
|
+
readFileSync as readFileSync2,
|
|
190
|
+
writeFileSync
|
|
191
|
+
} from "fs";
|
|
192
|
+
|
|
193
|
+
// src/lib/string/empty.ts
|
|
194
|
+
var empty = (value) => value?.trim().length === 0;
|
|
195
|
+
var notEmpty = (value) => !empty(value);
|
|
196
|
+
|
|
197
|
+
// src/lib/string/union.ts
|
|
198
|
+
var union = (a, b) => /* @__PURE__ */ new Set([...new Set(a), ...new Set(b)]);
|
|
199
|
+
|
|
200
|
+
// src/lib/file/ReadFileSyncOptions.ts
|
|
201
|
+
var defaultReadFileSyncOptions = { encoding: "utf8" };
|
|
202
|
+
|
|
203
|
+
// src/lib/file/fileLines.ts
|
|
204
|
+
var readLines = (uri, options = defaultReadFileSyncOptions) => existsSync2(uri) ? readFileSync2(uri, options).replace(WINDOWS_NEWLINE_REGEX, CROSS_PLATFORM_NEWLINE).split(CROSS_PLATFORM_NEWLINE) : [];
|
|
205
|
+
var readNonEmptyLines = (uri, options = defaultReadFileSyncOptions) => readLines(uri, options).filter(notEmpty);
|
|
206
|
+
var writeLines = (uri, lines, options = defaultReadFileSyncOptions) => {
|
|
207
|
+
const existing = existsSync2(uri) ? readFileSync2(uri, options) : void 0;
|
|
208
|
+
const desired = lines.join(CROSS_PLATFORM_NEWLINE);
|
|
209
|
+
if (existing !== desired) writeFileSync(uri, desired, options);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/lib/fillTemplate.ts
|
|
213
|
+
function fillTemplate(template, data) {
|
|
214
|
+
return template.replaceAll(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] ?? "");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/lib/generateIgnoreFiles.ts
|
|
218
|
+
import chalk3 from "chalk";
|
|
219
|
+
|
|
220
|
+
// src/lib/initCwd.ts
|
|
221
|
+
function INIT_CWD() {
|
|
222
|
+
return process.env.INIT_CWD ?? process.cwd();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/lib/generateIgnoreFiles.ts
|
|
226
|
+
var localeCompare = (a, b) => a.localeCompare(b);
|
|
227
|
+
var mergeEntries = (a, b) => [...union(a, b)].toSorted(localeCompare);
|
|
228
|
+
var generateIgnoreFiles = (filename2, pkg) => {
|
|
229
|
+
console.log(chalk3.green(`Generate ${filename2} Files`));
|
|
230
|
+
const cwd = INIT_CWD();
|
|
231
|
+
const pm = getPackageManager();
|
|
232
|
+
const singleWorkspace = pkg ? pm.findWorkspace(pkg) : void 0;
|
|
233
|
+
const workspaces = singleWorkspace ? [singleWorkspace] : pm.listWorkspaces();
|
|
234
|
+
const readEntries = (location) => readNonEmptyLines(`${location}/${filename2}`);
|
|
235
|
+
const writeEntries = (location, entries) => writeLines(`${location}/${filename2}`, entries);
|
|
236
|
+
const results = workspaces.map(({ location, name }) => {
|
|
237
|
+
try {
|
|
238
|
+
writeEntries(location, mergeEntries(readEntries(cwd), readEntries(location)));
|
|
239
|
+
return 0;
|
|
240
|
+
} catch (ex) {
|
|
241
|
+
const error = ex;
|
|
242
|
+
console.error(`Generate ${filename2} Files [${name}] [${error.message}]`);
|
|
243
|
+
return 1;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
const succeeded = results.every((result) => result === 0);
|
|
247
|
+
return succeeded ? 0 : 1;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// src/lib/generateReadmeFiles.ts
|
|
251
|
+
import { execFile } from "child_process";
|
|
252
|
+
import FS, { readFileSync as readFileSync3 } from "fs";
|
|
253
|
+
import {
|
|
254
|
+
mkdir,
|
|
255
|
+
readFile,
|
|
256
|
+
writeFile
|
|
257
|
+
} from "fs/promises";
|
|
258
|
+
import { createRequire as createRequire2 } from "module";
|
|
259
|
+
import PATH2 from "path";
|
|
260
|
+
import { createInterface } from "readline";
|
|
261
|
+
import { promisify } from "util";
|
|
262
|
+
import chalk4 from "chalk";
|
|
263
|
+
var execFileAsync = promisify(execFile);
|
|
264
|
+
var require3 = createRequire2(import.meta.url);
|
|
265
|
+
var packageRoot2 = PATH2.dirname(require3.resolve("@xylabs/ts-scripts-common/package.json"));
|
|
266
|
+
var readmeTemplatesDir = PATH2.resolve(packageRoot2, "templates", "readme");
|
|
267
|
+
function fillReadmeTemplate(template, data) {
|
|
268
|
+
const additionalData = { ...data, safeName: data.name.replaceAll("/", "__").replaceAll("@", "") };
|
|
269
|
+
return fillTemplate(template, additionalData);
|
|
270
|
+
}
|
|
271
|
+
async function generateTypedoc(packageLocation, entryPoints) {
|
|
272
|
+
const tempDir = PATH2.join(packageLocation, ".temp-typedoc");
|
|
273
|
+
try {
|
|
274
|
+
if (!FS.existsSync(tempDir)) {
|
|
275
|
+
FS.mkdirSync(tempDir, { recursive: true });
|
|
276
|
+
}
|
|
277
|
+
const typedocConfig = {
|
|
278
|
+
disableSources: true,
|
|
279
|
+
entryPointStrategy: "expand",
|
|
280
|
+
entryPoints: entryPoints.map((ep) => PATH2.resolve(packageLocation, ep)),
|
|
281
|
+
excludeExternals: true,
|
|
282
|
+
excludeInternal: true,
|
|
283
|
+
excludePrivate: true,
|
|
284
|
+
githubPages: false,
|
|
285
|
+
hideBreadcrumbs: true,
|
|
286
|
+
hideGenerator: true,
|
|
287
|
+
hidePageTitle: true,
|
|
288
|
+
out: tempDir,
|
|
289
|
+
plugin: ["typedoc-plugin-markdown"],
|
|
290
|
+
readme: "none",
|
|
291
|
+
skipErrorChecking: true,
|
|
292
|
+
sort: ["source-order"],
|
|
293
|
+
theme: "markdown",
|
|
294
|
+
useCodeBlocks: true
|
|
295
|
+
};
|
|
296
|
+
const typedocJsonPath = PATH2.join(tempDir, "typedoc.json");
|
|
297
|
+
FS.writeFileSync(typedocJsonPath, JSON.stringify(typedocConfig, null, 2));
|
|
298
|
+
try {
|
|
299
|
+
await execFileAsync("npx", ["typedoc", "--options", typedocJsonPath], { cwd: process.cwd() });
|
|
300
|
+
} catch {
|
|
301
|
+
return "";
|
|
302
|
+
}
|
|
303
|
+
return consolidateMarkdown(tempDir);
|
|
304
|
+
} catch {
|
|
305
|
+
return "";
|
|
306
|
+
} finally {
|
|
307
|
+
try {
|
|
308
|
+
FS.rmSync(tempDir, { force: true, recursive: true });
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function consolidateMarkdown(tempDir) {
|
|
314
|
+
let consolidated = "## Reference\n\n";
|
|
315
|
+
const mainReadmePath = PATH2.join(tempDir, "README.md");
|
|
316
|
+
if (FS.existsSync(mainReadmePath)) {
|
|
317
|
+
const mainContent = FS.readFileSync(mainReadmePath, "utf8").replace(/^---(.|\n)*?---\n/, "").replace(/^# .+\n/, "").replaceAll(/\]\((.+?)\.md\)/g, "](#$1)");
|
|
318
|
+
consolidated += mainContent + "\n\n";
|
|
319
|
+
}
|
|
320
|
+
consolidated += processDirectory(tempDir);
|
|
321
|
+
return consolidated.replaceAll(/\n\n\n+/g, "\n\n").replaceAll(/^#### /gm, "### ").replaceAll(/^##### /gm, "#### ").replaceAll(/^###### /gm, "##### ");
|
|
322
|
+
}
|
|
323
|
+
function processDirectory(dir, level = 0) {
|
|
324
|
+
const indent = " ".repeat(level);
|
|
325
|
+
let content = "";
|
|
326
|
+
try {
|
|
327
|
+
const items = FS.readdirSync(dir, { withFileTypes: true });
|
|
328
|
+
for (const item of items) {
|
|
329
|
+
if (item.isDirectory()) continue;
|
|
330
|
+
if (item.name === "README.md" || !item.name.endsWith(".md")) continue;
|
|
331
|
+
const fileContent = FS.readFileSync(PATH2.join(dir, item.name), "utf8").replace(/^---(.|\n)*?---\n/, "");
|
|
332
|
+
const moduleName = item.name.replace(".md", "");
|
|
333
|
+
content += `
|
|
334
|
+
|
|
335
|
+
${indent}### <a id="${moduleName}"></a>${moduleName}
|
|
336
|
+
|
|
337
|
+
`;
|
|
338
|
+
content += fileContent.replace(/^# .+\n/, "").replaceAll(/\]\((.+?)\.md\)/g, "](#$1)");
|
|
339
|
+
}
|
|
340
|
+
for (const item of items) {
|
|
341
|
+
if (!item.isDirectory()) continue;
|
|
342
|
+
if (item.name === "spec" || item.name.includes(".spec")) continue;
|
|
343
|
+
content += `
|
|
344
|
+
|
|
345
|
+
${indent}### ${item.name}
|
|
346
|
+
`;
|
|
347
|
+
content += processDirectory(PATH2.join(dir, item.name), level + 1);
|
|
348
|
+
}
|
|
349
|
+
} catch {
|
|
350
|
+
}
|
|
351
|
+
return content;
|
|
352
|
+
}
|
|
353
|
+
function askConfirmation(question) {
|
|
354
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
355
|
+
return new Promise((resolve) => {
|
|
356
|
+
rl.question(question, (answer) => {
|
|
357
|
+
rl.close();
|
|
358
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
var DEFAULT_README_TEMPLATE = readFileSync3(PATH2.resolve(readmeTemplatesDir, "README.template.md"), "utf8");
|
|
363
|
+
var DEFAULT_README_BODY = readFileSync3(PATH2.resolve(readmeTemplatesDir, "README.body.md"), "utf8");
|
|
364
|
+
function applyLogoConfig(template, logoUrl, logoLinkUrl) {
|
|
365
|
+
let result = template;
|
|
366
|
+
if (logoUrl) {
|
|
367
|
+
result = result.replace(/\[logo]: .+/, `[logo]: ${logoUrl}`);
|
|
368
|
+
if (logoLinkUrl) {
|
|
369
|
+
result = result.replace(/\[!\[logo]\[]][^)]*\)/, `[![logo][]](${logoLinkUrl})`);
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
result = result.replace(/\[!\[logo]\[]][^\n]*\n*/, "");
|
|
373
|
+
result = result.replace(/\[logo]: [^\n]*\n?/, "");
|
|
374
|
+
}
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
function resolveTemplatePath(templatePath) {
|
|
378
|
+
const cwd = INIT_CWD();
|
|
379
|
+
return templatePath ?? PATH2.join(cwd, ".xy", "README.template.md");
|
|
380
|
+
}
|
|
381
|
+
async function loadOrCreateTemplate(resolvedTemplatePath) {
|
|
382
|
+
try {
|
|
383
|
+
const template = await readFile(resolvedTemplatePath, "utf8");
|
|
384
|
+
return { created: false, template };
|
|
385
|
+
} catch {
|
|
386
|
+
console.log(chalk4.yellow(`Template not found: ${resolvedTemplatePath}`));
|
|
387
|
+
const shouldCreate = await askConfirmation("Would you like to create a stock template? (y/N) ");
|
|
388
|
+
if (!shouldCreate) {
|
|
389
|
+
throw new Error("Template creation declined");
|
|
390
|
+
}
|
|
391
|
+
const template = DEFAULT_README_TEMPLATE;
|
|
392
|
+
await scaffoldTemplate(resolvedTemplatePath, template);
|
|
393
|
+
return { created: true, template };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
async function scaffoldTemplate(resolvedTemplatePath, template) {
|
|
397
|
+
const xyDir = PATH2.dirname(resolvedTemplatePath);
|
|
398
|
+
await mkdir(xyDir, { recursive: true });
|
|
399
|
+
await writeFile(resolvedTemplatePath, template);
|
|
400
|
+
console.log(chalk4.green(`Created template: ${resolvedTemplatePath}`));
|
|
401
|
+
const bodyPath = PATH2.join(xyDir, "README.body.md");
|
|
402
|
+
await writeFile(bodyPath, DEFAULT_README_BODY);
|
|
403
|
+
console.log(chalk4.green(`Created body template: ${bodyPath}`));
|
|
404
|
+
}
|
|
405
|
+
async function resolveBody(location, defaultBody) {
|
|
406
|
+
const localBodyPath = PATH2.join(location, "README.body.md");
|
|
407
|
+
try {
|
|
408
|
+
return await readFile(localBodyPath, "utf8");
|
|
409
|
+
} catch {
|
|
410
|
+
return defaultBody;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
async function generateReadmeForWorkspace(location, name, template, defaultBody, typedoc, verbose, pm) {
|
|
414
|
+
try {
|
|
415
|
+
const pkgJsonPath = PATH2.join(location, "package.json");
|
|
416
|
+
const pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf8"));
|
|
417
|
+
const body = await resolveBody(location, defaultBody);
|
|
418
|
+
const typedocContent = typedoc ? await generateTypedoc(location, ["src/index*.ts"]) : "";
|
|
419
|
+
const readmeContent = fillReadmeTemplate(template, {
|
|
420
|
+
...pkgJson,
|
|
421
|
+
body,
|
|
422
|
+
pm,
|
|
423
|
+
typedoc: typedocContent
|
|
424
|
+
});
|
|
425
|
+
await writeFile(PATH2.join(location, "README.md"), readmeContent);
|
|
426
|
+
if (verbose) console.log(chalk4.green(` ${name}`));
|
|
427
|
+
return true;
|
|
428
|
+
} catch (ex) {
|
|
429
|
+
const error = ex;
|
|
430
|
+
console.warn(chalk4.yellow(` Skipped ${location}: ${error.message}`));
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async function loadDefaultBody(resolvedTemplatePath) {
|
|
435
|
+
const xyBodyPath = PATH2.join(PATH2.dirname(resolvedTemplatePath), "README.body.md");
|
|
436
|
+
try {
|
|
437
|
+
return await readFile(xyBodyPath, "utf8");
|
|
438
|
+
} catch {
|
|
439
|
+
return DEFAULT_README_BODY;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function flushResults(results) {
|
|
443
|
+
let failed = false;
|
|
444
|
+
for (const { output, success } of results) {
|
|
445
|
+
for (const line of output) {
|
|
446
|
+
process.stdout.write(line);
|
|
447
|
+
}
|
|
448
|
+
if (!success) failed = true;
|
|
449
|
+
}
|
|
450
|
+
return failed;
|
|
451
|
+
}
|
|
452
|
+
async function generateReadmeFiles({
|
|
453
|
+
jobs,
|
|
454
|
+
logoLinkUrl,
|
|
455
|
+
logoUrl,
|
|
456
|
+
pkg,
|
|
457
|
+
templatePath,
|
|
458
|
+
typedoc = false,
|
|
459
|
+
verbose = false
|
|
460
|
+
}) {
|
|
461
|
+
console.log(chalk4.green("Generate README Files"));
|
|
462
|
+
const resolvedTemplatePath = resolveTemplatePath(templatePath);
|
|
463
|
+
let template;
|
|
464
|
+
let templateCreated;
|
|
465
|
+
try {
|
|
466
|
+
({ template, created: templateCreated } = await loadOrCreateTemplate(resolvedTemplatePath));
|
|
467
|
+
} catch {
|
|
468
|
+
return 1;
|
|
469
|
+
}
|
|
470
|
+
template = applyLogoConfig(template, logoUrl, logoLinkUrl);
|
|
471
|
+
if (templateCreated) {
|
|
472
|
+
console.log(chalk4.green("Generating README files for all packages..."));
|
|
473
|
+
}
|
|
474
|
+
const defaultBody = await loadDefaultBody(resolvedTemplatePath);
|
|
475
|
+
const pmName = detectPackageManager();
|
|
476
|
+
const pm = getPackageManager();
|
|
477
|
+
const singleWorkspace = pkg && !templateCreated ? pm.findWorkspace(pkg) : void 0;
|
|
478
|
+
const workspaces = singleWorkspace ? [singleWorkspace] : pm.listWorkspaces();
|
|
479
|
+
const concurrency = jobs;
|
|
480
|
+
const results = Array.from({ length: workspaces.length }, () => ({ output: [], success: true }));
|
|
481
|
+
installOutputCapture();
|
|
482
|
+
const start = performance.now();
|
|
483
|
+
await runWithConcurrency(
|
|
484
|
+
workspaces.map((ws, i) => ({ i, ws })),
|
|
485
|
+
concurrency,
|
|
486
|
+
async ({ i, ws }) => {
|
|
487
|
+
const output = [];
|
|
488
|
+
await outputStorage.run(output, async () => {
|
|
489
|
+
const success = await generateReadmeForWorkspace(ws.location, ws.name, template, defaultBody, typedoc, verbose, pmName);
|
|
490
|
+
results[i] = { output, success };
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
);
|
|
494
|
+
const failed = flushResults(results);
|
|
495
|
+
const ms = performance.now() - start;
|
|
496
|
+
console.log(chalk4.blue(`Generated ${workspaces.length} README(s) in ${ms.toFixed(0)}ms`));
|
|
497
|
+
return failed ? 1 : 0;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// src/lib/gitignoreTemplate.ts
|
|
501
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
502
|
+
import { createRequire as createRequire3 } from "module";
|
|
503
|
+
import PATH3 from "path";
|
|
504
|
+
var require4 = createRequire3(import.meta.url);
|
|
505
|
+
var packageRoot3 = PATH3.dirname(require4.resolve("@xylabs/ts-scripts-common/package.json"));
|
|
506
|
+
var templatesDir2 = PATH3.resolve(packageRoot3, "templates", "gitignore");
|
|
507
|
+
var gitignoreTemplate = () => readFileSync4(PATH3.resolve(templatesDir2, "template.gitignore"), "utf8");
|
|
508
|
+
|
|
509
|
+
// src/lib/latestVersions.ts
|
|
510
|
+
var latestVersions = {
|
|
511
|
+
node: "24.14.1",
|
|
512
|
+
nodeLtsCodename: "Krypton",
|
|
513
|
+
npm: "11.11.0",
|
|
514
|
+
pnpm: "10.33.0",
|
|
515
|
+
yarn: "4.13.0"
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// src/lib/loadConfig.ts
|
|
519
|
+
import chalk5 from "chalk";
|
|
520
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
521
|
+
import { TypeScriptLoader } from "cosmiconfig-typescript-loader";
|
|
522
|
+
import deepmerge from "deepmerge";
|
|
523
|
+
var config;
|
|
524
|
+
var rootConfigPath;
|
|
525
|
+
var workspaceConfigCache = /* @__PURE__ */ new Map();
|
|
526
|
+
var deprecationWarned = /* @__PURE__ */ new Set();
|
|
527
|
+
function createExplorer() {
|
|
528
|
+
return cosmiconfig("xy", { cache: true, loaders: { ".ts": TypeScriptLoader() } });
|
|
529
|
+
}
|
|
530
|
+
var loadConfig = async (params) => {
|
|
531
|
+
if (config === void 0) {
|
|
532
|
+
const cosmicConfigResult = await createExplorer().search();
|
|
533
|
+
config = cosmicConfigResult?.config ?? {};
|
|
534
|
+
rootConfigPath = cosmicConfigResult?.filepath;
|
|
535
|
+
const configFilePath = cosmicConfigResult?.filepath;
|
|
536
|
+
if (configFilePath !== void 0) {
|
|
537
|
+
console.log(chalk5.green(`Loaded config from ${configFilePath}`));
|
|
538
|
+
if (config.verbose) {
|
|
539
|
+
console.log(chalk5.gray(`${JSON.stringify(config, null, 2)}`));
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return deepmerge(config, params ?? {});
|
|
544
|
+
};
|
|
545
|
+
async function loadWorkspaceConfig(workspaceDir) {
|
|
546
|
+
const cached = workspaceConfigCache.get(workspaceDir);
|
|
547
|
+
if (cached !== void 0) return cached;
|
|
548
|
+
const result = await createExplorer().search(workspaceDir);
|
|
549
|
+
if (!result || result.filepath === rootConfigPath) {
|
|
550
|
+
workspaceConfigCache.set(workspaceDir, {});
|
|
551
|
+
return {};
|
|
552
|
+
}
|
|
553
|
+
const wsConfig = result.config ?? {};
|
|
554
|
+
workspaceConfigCache.set(workspaceDir, wsConfig);
|
|
555
|
+
return wsConfig;
|
|
556
|
+
}
|
|
557
|
+
var DEPRECATED_COMMAND_FIELDS = /* @__PURE__ */ new Set(["deplint", "publint"]);
|
|
558
|
+
function resolveCommandField(cfg, commandName, configPath) {
|
|
559
|
+
const commands = cfg.commands;
|
|
560
|
+
const fromCommands = commands?.[commandName];
|
|
561
|
+
const fromTopLevel = cfg[commandName];
|
|
562
|
+
if (fromCommands !== void 0 && typeof fromCommands === "object") {
|
|
563
|
+
return fromCommands;
|
|
564
|
+
}
|
|
565
|
+
if (fromTopLevel !== void 0 && typeof fromTopLevel === "object" && DEPRECATED_COMMAND_FIELDS.has(commandName)) {
|
|
566
|
+
const key = `${configPath ?? "unknown"}:${commandName}`;
|
|
567
|
+
if (!deprecationWarned.has(key)) {
|
|
568
|
+
deprecationWarned.add(key);
|
|
569
|
+
console.warn(chalk5.yellow(
|
|
570
|
+
`[xy] Deprecated: top-level "${commandName}" in ${configPath ?? "xy.config"} \u2014 move to "commands.${commandName}"`
|
|
571
|
+
));
|
|
572
|
+
}
|
|
573
|
+
return fromTopLevel;
|
|
574
|
+
}
|
|
575
|
+
return {};
|
|
576
|
+
}
|
|
577
|
+
async function loadWorkspaceCommandConfig(workspaceDir, commandName) {
|
|
578
|
+
const root = await loadConfig();
|
|
579
|
+
const rootCmd = resolveCommandField(root, commandName, rootConfigPath);
|
|
580
|
+
const wsConfig = await loadWorkspaceConfig(workspaceDir);
|
|
581
|
+
const wsConfigPath = workspaceConfigCache.has(workspaceDir) ? workspaceDir : void 0;
|
|
582
|
+
const wsCmd = resolveCommandField(wsConfig, commandName, wsConfigPath);
|
|
583
|
+
return deepmerge(rootCmd, wsCmd);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// src/lib/packageName.ts
|
|
587
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
588
|
+
import path from "path";
|
|
589
|
+
function packageName() {
|
|
590
|
+
if (process.env.npm_package_name) {
|
|
591
|
+
return process.env.npm_package_name;
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
const pkgPath = path.join(INIT_CWD(), "package.json");
|
|
595
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
596
|
+
return pkg.name;
|
|
597
|
+
} catch {
|
|
598
|
+
return void 0;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/lib/repoTemplates.ts
|
|
603
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
|
|
604
|
+
import { createRequire as createRequire4 } from "module";
|
|
605
|
+
import PATH4 from "path";
|
|
606
|
+
var require5 = createRequire4(import.meta.url);
|
|
607
|
+
var packageRoot4 = PATH4.dirname(require5.resolve("@xylabs/ts-scripts-common/package.json"));
|
|
608
|
+
var repoTemplatesDir = PATH4.resolve(packageRoot4, "templates", "repo");
|
|
609
|
+
function collectFiles(dir, prefix) {
|
|
610
|
+
const results = [];
|
|
611
|
+
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
612
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
613
|
+
if (entry.isDirectory()) {
|
|
614
|
+
results.push(...collectFiles(PATH4.resolve(dir, entry.name), rel));
|
|
615
|
+
} else {
|
|
616
|
+
results.push({
|
|
617
|
+
content: readFileSync6(PATH4.resolve(dir, entry.name), "utf8"),
|
|
618
|
+
relativePath: rel
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return results;
|
|
623
|
+
}
|
|
624
|
+
function loadRepoTemplateFiles(template, section) {
|
|
625
|
+
const dir = PATH4.resolve(repoTemplatesDir, template, section);
|
|
626
|
+
return collectFiles(dir, "");
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/lib/runInstall.ts
|
|
630
|
+
import { spawnSync } from "child_process";
|
|
631
|
+
import chalk6 from "chalk";
|
|
632
|
+
function runInstall(cwd) {
|
|
633
|
+
const pm = detectPackageManager();
|
|
634
|
+
console.log(chalk6.gray(`Running ${pm} install...`));
|
|
635
|
+
const result = spawnSync(pm, ["install"], {
|
|
636
|
+
cwd,
|
|
637
|
+
stdio: "inherit"
|
|
638
|
+
});
|
|
639
|
+
if (result.status !== 0) {
|
|
640
|
+
console.warn(chalk6.yellow(`${pm} install failed`));
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
console.log(chalk6.green("Dependencies installed"));
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// src/lib/runSteps.ts
|
|
648
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
649
|
+
import { existsSync as existsSync3 } from "fs";
|
|
650
|
+
import chalk7 from "chalk";
|
|
651
|
+
var runSteps = (name, steps, exitOnFail = true, messages) => {
|
|
652
|
+
return safeExit(() => {
|
|
653
|
+
const pkgName = packageName();
|
|
654
|
+
console.log(chalk7.green(`${name} [${pkgName}]`));
|
|
655
|
+
let totalStatus = 0;
|
|
656
|
+
for (const [i, [command, args, config2]] of steps.entries()) {
|
|
657
|
+
if (messages?.[i]) {
|
|
658
|
+
console.log(chalk7.gray(messages?.[i]));
|
|
659
|
+
}
|
|
660
|
+
const argList = Array.isArray(args) ? args : args.split(" ");
|
|
661
|
+
if (command === "node" && !existsSync3(argList[0])) {
|
|
662
|
+
throw new Error(`File not found [${argList[0]}]`);
|
|
663
|
+
}
|
|
664
|
+
const status = spawnSync2(command, Array.isArray(args) ? args : args.split(" "), {
|
|
665
|
+
...config2,
|
|
666
|
+
encoding: "utf8",
|
|
667
|
+
env: { FORCE_COLOR: "3", ...process.env },
|
|
668
|
+
shell: true,
|
|
669
|
+
stdio: "inherit"
|
|
670
|
+
}).status ?? 0;
|
|
671
|
+
checkResult(name, status, "error", exitOnFail);
|
|
672
|
+
totalStatus += status ?? 0;
|
|
673
|
+
}
|
|
674
|
+
return totalStatus;
|
|
675
|
+
}, !!exitOnFail);
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
// src/actions/claude-check.ts
|
|
679
|
+
import {
|
|
680
|
+
existsSync as existsSync4,
|
|
681
|
+
readdirSync as readdirSync3,
|
|
682
|
+
readFileSync as readFileSync7,
|
|
683
|
+
statSync as statSync2
|
|
684
|
+
} from "fs";
|
|
685
|
+
import PATH5 from "path";
|
|
686
|
+
import chalk8 from "chalk";
|
|
687
|
+
var checkCommands = (commandsDir) => {
|
|
688
|
+
const pm = detectPackageManager();
|
|
689
|
+
const rawTemplates = claudeCommandTemplates();
|
|
690
|
+
const templates = {};
|
|
691
|
+
for (const [name, content] of Object.entries(rawTemplates)) {
|
|
692
|
+
templates[name] = applyPackageManager(content, pm);
|
|
693
|
+
}
|
|
694
|
+
const missing = [];
|
|
695
|
+
const outdated = [];
|
|
696
|
+
for (const [filename2, content] of Object.entries(templates)) {
|
|
697
|
+
const targetPath = PATH5.resolve(commandsDir, filename2);
|
|
698
|
+
if (!existsSync4(targetPath)) {
|
|
699
|
+
missing.push(filename2);
|
|
700
|
+
} else if (readFileSync7(targetPath, "utf8") !== content) {
|
|
701
|
+
outdated.push(filename2);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
const templateNames = new Set(Object.keys(templates));
|
|
705
|
+
const stale = existsSync4(commandsDir) ? readdirSync3(commandsDir).filter((f) => f.startsWith(XYLABS_COMMANDS_PREFIX) && f.endsWith(".md") && !templateNames.has(f)) : [];
|
|
706
|
+
return {
|
|
707
|
+
missing,
|
|
708
|
+
outdated,
|
|
709
|
+
stale
|
|
710
|
+
};
|
|
711
|
+
};
|
|
712
|
+
var checkRules = (rulesDir) => {
|
|
713
|
+
const pm = detectPackageManager();
|
|
714
|
+
const rawTemplates = claudeMdRuleTemplates();
|
|
715
|
+
const templates = {};
|
|
716
|
+
for (const [name, content] of Object.entries(rawTemplates)) {
|
|
717
|
+
templates[name] = applyPackageManager(content, pm);
|
|
718
|
+
}
|
|
719
|
+
const missing = [];
|
|
720
|
+
const outdated = [];
|
|
721
|
+
for (const [filename2, content] of Object.entries(templates)) {
|
|
722
|
+
const targetPath = PATH5.resolve(rulesDir, filename2);
|
|
723
|
+
if (!existsSync4(targetPath)) {
|
|
724
|
+
missing.push(filename2);
|
|
725
|
+
} else if (readFileSync7(targetPath, "utf8") !== content) {
|
|
726
|
+
outdated.push(filename2);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
const templateNames = new Set(Object.keys(templates));
|
|
730
|
+
const stale = existsSync4(rulesDir) ? readdirSync3(rulesDir).filter((f) => f.startsWith(XYLABS_RULES_PREFIX) && f.endsWith(".md") && !templateNames.has(f)) : [];
|
|
731
|
+
return {
|
|
732
|
+
missing,
|
|
733
|
+
outdated,
|
|
734
|
+
stale
|
|
735
|
+
};
|
|
736
|
+
};
|
|
737
|
+
var checkSkills = (skillsDir) => {
|
|
738
|
+
const pm = detectPackageManager();
|
|
739
|
+
const rawTemplates = claudeSkillTemplates();
|
|
740
|
+
const missing = [];
|
|
741
|
+
const outdated = [];
|
|
742
|
+
for (const [skillName, files] of Object.entries(rawTemplates)) {
|
|
743
|
+
const skillDir = PATH5.resolve(skillsDir, skillName);
|
|
744
|
+
if (!existsSync4(skillDir)) {
|
|
745
|
+
missing.push(skillName);
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
for (const [filename2, rawContent] of Object.entries(files)) {
|
|
749
|
+
const content = applyPackageManager(rawContent, pm);
|
|
750
|
+
const targetPath = PATH5.resolve(skillDir, filename2);
|
|
751
|
+
if (!existsSync4(targetPath)) {
|
|
752
|
+
missing.push(`${skillName}/${filename2}`);
|
|
753
|
+
} else if (readFileSync7(targetPath, "utf8") !== content) {
|
|
754
|
+
outdated.push(`${skillName}/${filename2}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
const templateNames = new Set(Object.keys(rawTemplates));
|
|
759
|
+
const stale = existsSync4(skillsDir) ? readdirSync3(skillsDir).filter(
|
|
760
|
+
(f) => f.startsWith(XYLABS_SKILLS_PREFIX) && statSync2(PATH5.resolve(skillsDir, f)).isDirectory() && !templateNames.has(f)
|
|
761
|
+
) : [];
|
|
762
|
+
return {
|
|
763
|
+
missing,
|
|
764
|
+
outdated,
|
|
765
|
+
stale
|
|
766
|
+
};
|
|
767
|
+
};
|
|
768
|
+
var logSection = (label, result) => {
|
|
769
|
+
const issues = [...result.missing, ...result.outdated, ...result.stale];
|
|
770
|
+
if (issues.length === 0) {
|
|
771
|
+
console.log(chalk8.green(` \u2714 ${label}`));
|
|
772
|
+
return true;
|
|
773
|
+
}
|
|
774
|
+
console.log(chalk8.red(` \u2718 ${label}`));
|
|
775
|
+
for (const file of result.missing) {
|
|
776
|
+
console.log(chalk8.yellow(` missing: ${file}`));
|
|
777
|
+
}
|
|
778
|
+
for (const file of result.outdated) {
|
|
779
|
+
console.log(chalk8.yellow(` outdated: ${file}`));
|
|
780
|
+
}
|
|
781
|
+
for (const file of result.stale) {
|
|
782
|
+
console.log(chalk8.yellow(` stale: ${file}`));
|
|
783
|
+
}
|
|
784
|
+
return false;
|
|
785
|
+
};
|
|
786
|
+
function claudeCheck() {
|
|
787
|
+
const cwd = INIT_CWD();
|
|
788
|
+
const claudeDir = PATH5.resolve(cwd, ".claude");
|
|
789
|
+
console.log(chalk8.bold("Claude configuration check:"));
|
|
790
|
+
console.log();
|
|
791
|
+
const commandsResult = checkCommands(PATH5.resolve(claudeDir, "commands"));
|
|
792
|
+
const rulesResult = checkRules(PATH5.resolve(claudeDir, "rules"));
|
|
793
|
+
const skillsResult = checkSkills(PATH5.resolve(claudeDir, "skills"));
|
|
794
|
+
const commandsOk = logSection("commands", commandsResult);
|
|
795
|
+
const rulesOk = logSection("rules", rulesResult);
|
|
796
|
+
const skillsOk = logSection("skills", skillsResult);
|
|
797
|
+
console.log();
|
|
798
|
+
if (commandsOk && rulesOk && skillsOk) {
|
|
799
|
+
console.log(chalk8.green("All Claude configuration is up to date."));
|
|
800
|
+
} else {
|
|
801
|
+
console.log(chalk8.yellow("Run `xy claude init` to sync all configuration."));
|
|
802
|
+
}
|
|
803
|
+
return 0;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// src/actions/claude-clean.ts
|
|
807
|
+
import {
|
|
808
|
+
existsSync as existsSync5,
|
|
809
|
+
readdirSync as readdirSync4,
|
|
810
|
+
rmSync,
|
|
811
|
+
unlinkSync
|
|
812
|
+
} from "fs";
|
|
813
|
+
import PATH6 from "path";
|
|
814
|
+
import chalk9 from "chalk";
|
|
815
|
+
function removeFile(filePath, label) {
|
|
816
|
+
if (existsSync5(filePath)) {
|
|
817
|
+
unlinkSync(filePath);
|
|
818
|
+
console.log(chalk9.yellow(` Removed ${label}`));
|
|
819
|
+
return true;
|
|
820
|
+
}
|
|
821
|
+
return false;
|
|
822
|
+
}
|
|
823
|
+
function removeDir(dirPath, label) {
|
|
824
|
+
if (existsSync5(dirPath)) {
|
|
825
|
+
rmSync(dirPath, { recursive: true });
|
|
826
|
+
console.log(chalk9.yellow(` Removed ${label}`));
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
function claudeClean() {
|
|
832
|
+
console.log(chalk9.green("Clean Claude configuration"));
|
|
833
|
+
const cwd = INIT_CWD();
|
|
834
|
+
let removed = 0;
|
|
835
|
+
const rootFiles = ["CLAUDE.md", "CLAUDE.local.md"];
|
|
836
|
+
for (const file of rootFiles) {
|
|
837
|
+
if (removeFile(PATH6.resolve(cwd, file), file)) removed++;
|
|
838
|
+
}
|
|
839
|
+
if (removeDir(PATH6.resolve(cwd, ".claude"), ".claude/")) removed++;
|
|
840
|
+
const packagesDir = PATH6.resolve(cwd, "packages");
|
|
841
|
+
if (existsSync5(packagesDir)) {
|
|
842
|
+
const findClaudeFiles = (dir, prefix) => {
|
|
843
|
+
const entries = readdirSync4(dir, { withFileTypes: true });
|
|
844
|
+
for (const entry of entries) {
|
|
845
|
+
const fullPath = PATH6.resolve(dir, entry.name);
|
|
846
|
+
const label = `${prefix}${entry.name}`;
|
|
847
|
+
if (entry.isFile() && (entry.name === "CLAUDE.md" || entry.name === "CLAUDE.local.md")) {
|
|
848
|
+
if (removeFile(fullPath, label)) removed++;
|
|
849
|
+
} else if (entry.isDirectory() && entry.name === ".claude") {
|
|
850
|
+
if (removeDir(fullPath, `${label}/`)) removed++;
|
|
851
|
+
} else if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist") {
|
|
852
|
+
findClaudeFiles(fullPath, `${label}/`);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
findClaudeFiles(packagesDir, "packages/");
|
|
857
|
+
}
|
|
858
|
+
if (removed > 0) {
|
|
859
|
+
console.log(chalk9.green(` Removed ${removed} item(s)`));
|
|
860
|
+
} else {
|
|
861
|
+
console.log(chalk9.gray(" Nothing to clean"));
|
|
862
|
+
}
|
|
863
|
+
return 0;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// src/actions/claude-commands.ts
|
|
867
|
+
import {
|
|
868
|
+
existsSync as existsSync6,
|
|
869
|
+
mkdirSync,
|
|
870
|
+
readdirSync as readdirSync5,
|
|
871
|
+
readFileSync as readFileSync8,
|
|
872
|
+
unlinkSync as unlinkSync2,
|
|
873
|
+
writeFileSync as writeFileSync2
|
|
874
|
+
} from "fs";
|
|
875
|
+
import PATH7 from "path";
|
|
876
|
+
import chalk10 from "chalk";
|
|
877
|
+
var syncCommandFiles = (commandsDir) => {
|
|
878
|
+
const pm = detectPackageManager();
|
|
879
|
+
const rawTemplates = claudeCommandTemplates();
|
|
880
|
+
const templates = {};
|
|
881
|
+
for (const [name, content] of Object.entries(rawTemplates)) {
|
|
882
|
+
templates[name] = applyPackageManager(content, pm);
|
|
883
|
+
}
|
|
884
|
+
const templateNames = new Set(Object.keys(templates));
|
|
885
|
+
let updated = 0;
|
|
886
|
+
let created = 0;
|
|
887
|
+
for (const [filename2, content] of Object.entries(templates)) {
|
|
888
|
+
const targetPath = PATH7.resolve(commandsDir, filename2);
|
|
889
|
+
const existing = existsSync6(targetPath) ? readFileSync8(targetPath, "utf8") : void 0;
|
|
890
|
+
if (existing === content) continue;
|
|
891
|
+
writeFileSync2(targetPath, content, "utf8");
|
|
892
|
+
if (existing) {
|
|
893
|
+
updated++;
|
|
894
|
+
} else {
|
|
895
|
+
created++;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return {
|
|
899
|
+
created,
|
|
900
|
+
templateNames,
|
|
901
|
+
updated
|
|
902
|
+
};
|
|
903
|
+
};
|
|
904
|
+
var removeStaleCommands = (commandsDir, templateNames) => {
|
|
905
|
+
const existingCommands = readdirSync5(commandsDir).filter((f) => f.startsWith(XYLABS_COMMANDS_PREFIX) && f.endsWith(".md"));
|
|
906
|
+
let removed = 0;
|
|
907
|
+
for (const file of existingCommands) {
|
|
908
|
+
if (!templateNames.has(file)) {
|
|
909
|
+
unlinkSync2(PATH7.resolve(commandsDir, file));
|
|
910
|
+
removed++;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
return removed;
|
|
914
|
+
};
|
|
915
|
+
var removeLegacyCommands = (commandsDir) => {
|
|
916
|
+
const legacyFiles = readdirSync5(commandsDir).filter((f) => f.startsWith(LEGACY_COMMANDS_PREFIX) && f.endsWith(".md"));
|
|
917
|
+
for (const file of legacyFiles) {
|
|
918
|
+
unlinkSync2(PATH7.resolve(commandsDir, file));
|
|
919
|
+
}
|
|
920
|
+
return legacyFiles.length;
|
|
921
|
+
};
|
|
922
|
+
var logCommandsResult = (created, updated, removed) => {
|
|
923
|
+
if (created || updated || removed) {
|
|
924
|
+
const parts = [
|
|
925
|
+
created ? `${created} created` : "",
|
|
926
|
+
updated ? `${updated} updated` : "",
|
|
927
|
+
removed ? `${removed} removed` : ""
|
|
928
|
+
].filter(Boolean);
|
|
929
|
+
console.log(chalk10.green(`.claude/commands/${XYLABS_COMMANDS_PREFIX}*.md: ${parts.join(", ")}`));
|
|
930
|
+
} else {
|
|
931
|
+
console.log(chalk10.gray(`.claude/commands/${XYLABS_COMMANDS_PREFIX}*.md: already up to date`));
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
var claudeCommands = () => {
|
|
935
|
+
const cwd = INIT_CWD();
|
|
936
|
+
const commandsDir = PATH7.resolve(cwd, ".claude", "commands");
|
|
937
|
+
mkdirSync(commandsDir, { recursive: true });
|
|
938
|
+
const legacy = removeLegacyCommands(commandsDir);
|
|
939
|
+
const {
|
|
940
|
+
created,
|
|
941
|
+
templateNames,
|
|
942
|
+
updated
|
|
943
|
+
} = syncCommandFiles(commandsDir);
|
|
944
|
+
const removed = removeStaleCommands(commandsDir, templateNames);
|
|
945
|
+
logCommandsResult(created, updated, removed + legacy);
|
|
946
|
+
return 0;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
// src/actions/claude-rules.ts
|
|
950
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
951
|
+
import {
|
|
952
|
+
existsSync as existsSync7,
|
|
953
|
+
mkdirSync as mkdirSync2,
|
|
954
|
+
readdirSync as readdirSync6,
|
|
955
|
+
readFileSync as readFileSync9,
|
|
956
|
+
unlinkSync as unlinkSync3,
|
|
957
|
+
writeFileSync as writeFileSync3
|
|
958
|
+
} from "fs";
|
|
959
|
+
import PATH8 from "path";
|
|
960
|
+
import chalk11 from "chalk";
|
|
961
|
+
var syncRuleFiles = (rulesDir) => {
|
|
962
|
+
const pm = detectPackageManager();
|
|
963
|
+
const rawTemplates = claudeMdRuleTemplates();
|
|
964
|
+
const templates = {};
|
|
965
|
+
for (const [name, content] of Object.entries(rawTemplates)) {
|
|
966
|
+
templates[name] = applyPackageManager(content, pm);
|
|
967
|
+
}
|
|
968
|
+
const templateNames = new Set(Object.keys(templates));
|
|
969
|
+
let updated = 0;
|
|
970
|
+
let created = 0;
|
|
971
|
+
for (const [filename2, content] of Object.entries(templates)) {
|
|
972
|
+
const targetPath = PATH8.resolve(rulesDir, filename2);
|
|
973
|
+
const existing = existsSync7(targetPath) ? readFileSync9(targetPath, "utf8") : void 0;
|
|
974
|
+
if (existing === content) continue;
|
|
975
|
+
writeFileSync3(targetPath, content, "utf8");
|
|
976
|
+
if (existing) {
|
|
977
|
+
updated++;
|
|
978
|
+
} else {
|
|
979
|
+
created++;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return {
|
|
983
|
+
created,
|
|
984
|
+
templateNames,
|
|
985
|
+
updated
|
|
986
|
+
};
|
|
987
|
+
};
|
|
988
|
+
var removeStaleRules = (rulesDir, templateNames) => {
|
|
989
|
+
const existingRules = readdirSync6(rulesDir).filter((f) => f.startsWith(XYLABS_RULES_PREFIX) && f.endsWith(".md"));
|
|
990
|
+
let removed = 0;
|
|
991
|
+
for (const file of existingRules) {
|
|
992
|
+
if (!templateNames.has(file)) {
|
|
993
|
+
unlinkSync3(PATH8.resolve(rulesDir, file));
|
|
994
|
+
removed++;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return removed;
|
|
998
|
+
};
|
|
999
|
+
var logRulesResult = (created, updated, removed) => {
|
|
1000
|
+
if (created || updated || removed) {
|
|
1001
|
+
const parts = [
|
|
1002
|
+
created ? `${created} created` : "",
|
|
1003
|
+
updated ? `${updated} updated` : "",
|
|
1004
|
+
removed ? `${removed} removed` : ""
|
|
1005
|
+
].filter(Boolean);
|
|
1006
|
+
console.log(chalk11.green(`.claude/rules/${XYLABS_RULES_PREFIX}*.md: ${parts.join(", ")}`));
|
|
1007
|
+
} else {
|
|
1008
|
+
console.log(chalk11.gray(`.claude/rules/${XYLABS_RULES_PREFIX}*.md: already up to date`));
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
var ensureProjectClaudeMd = (cwd, force) => {
|
|
1012
|
+
const projectPath = PATH8.resolve(cwd, "CLAUDE.md");
|
|
1013
|
+
if (!existsSync7(projectPath) || force) {
|
|
1014
|
+
if (force && existsSync7(projectPath)) {
|
|
1015
|
+
console.log(chalk11.yellow("Regenerating CLAUDE.md"));
|
|
1016
|
+
}
|
|
1017
|
+
console.log(chalk11.green("Generating CLAUDE.md via claude /init..."));
|
|
1018
|
+
const result = spawnSync3("claude", ["-p", "/init", "--allowedTools", "Read", "Write", "Glob", "Grep"], {
|
|
1019
|
+
cwd,
|
|
1020
|
+
shell: true,
|
|
1021
|
+
stdio: "inherit"
|
|
1022
|
+
});
|
|
1023
|
+
if (result.status !== 0) {
|
|
1024
|
+
console.error(chalk11.red("claude /init failed \u2014 is Claude Code installed?"));
|
|
1025
|
+
return 1;
|
|
1026
|
+
}
|
|
1027
|
+
} else {
|
|
1028
|
+
console.log(chalk11.gray("CLAUDE.md already exists (skipped, use --force to regenerate)"));
|
|
1029
|
+
}
|
|
1030
|
+
return 0;
|
|
1031
|
+
};
|
|
1032
|
+
var ensureLocalClaudeMd = (cwd) => {
|
|
1033
|
+
const localPath = PATH8.resolve(cwd, "CLAUDE.local.md");
|
|
1034
|
+
if (existsSync7(localPath)) {
|
|
1035
|
+
console.log(chalk11.gray("CLAUDE.local.md already exists (skipped)"));
|
|
1036
|
+
} else {
|
|
1037
|
+
writeFileSync3(localPath, claudeMdLocalTemplate(), "utf8");
|
|
1038
|
+
console.log(chalk11.green("Generated CLAUDE.local.md"));
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
var claudeRules = ({ force } = {}) => {
|
|
1042
|
+
const cwd = INIT_CWD();
|
|
1043
|
+
const rulesDir = PATH8.resolve(cwd, ".claude", "rules");
|
|
1044
|
+
mkdirSync2(rulesDir, { recursive: true });
|
|
1045
|
+
const {
|
|
1046
|
+
created,
|
|
1047
|
+
templateNames,
|
|
1048
|
+
updated
|
|
1049
|
+
} = syncRuleFiles(rulesDir);
|
|
1050
|
+
const removed = removeStaleRules(rulesDir, templateNames);
|
|
1051
|
+
logRulesResult(created, updated, removed);
|
|
1052
|
+
const claudeMdResult = ensureProjectClaudeMd(cwd, force);
|
|
1053
|
+
ensureLocalClaudeMd(cwd);
|
|
1054
|
+
return claudeMdResult ?? 0;
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
// src/actions/claude-settings.ts
|
|
1058
|
+
import {
|
|
1059
|
+
existsSync as existsSync8,
|
|
1060
|
+
mkdirSync as mkdirSync3,
|
|
1061
|
+
writeFileSync as writeFileSync4
|
|
1062
|
+
} from "fs";
|
|
1063
|
+
import PATH9 from "path";
|
|
1064
|
+
import { createInterface as createInterface2 } from "readline";
|
|
1065
|
+
import chalk12 from "chalk";
|
|
1066
|
+
var DENY_LIST = [
|
|
1067
|
+
"Bash(git push --force *)",
|
|
1068
|
+
"Bash(git reset --hard *)",
|
|
1069
|
+
"Bash(rm -rf /*)"
|
|
1070
|
+
];
|
|
1071
|
+
var RESTRICTIVE_ALLOW = [
|
|
1072
|
+
"Bash(git *)",
|
|
1073
|
+
"Bash(yarn *)",
|
|
1074
|
+
"Bash(pnpm *)",
|
|
1075
|
+
"Bash(npx *)",
|
|
1076
|
+
"Bash(ls *)",
|
|
1077
|
+
"Bash(mkdir *)",
|
|
1078
|
+
"Bash(cp *)",
|
|
1079
|
+
"Bash(mv *)",
|
|
1080
|
+
"Bash(rm *)",
|
|
1081
|
+
"Bash(cat *)",
|
|
1082
|
+
"Bash(head *)",
|
|
1083
|
+
"Bash(tail *)",
|
|
1084
|
+
"Bash(echo *)",
|
|
1085
|
+
"Bash(pwd)",
|
|
1086
|
+
"Bash(which *)",
|
|
1087
|
+
"Bash(grep *)",
|
|
1088
|
+
"Bash(find *)",
|
|
1089
|
+
"Bash(wc *)",
|
|
1090
|
+
"Bash(npm view *)",
|
|
1091
|
+
"Bash(gh *)",
|
|
1092
|
+
"Read",
|
|
1093
|
+
"Edit",
|
|
1094
|
+
"Write",
|
|
1095
|
+
"Glob",
|
|
1096
|
+
"Grep",
|
|
1097
|
+
"Skill"
|
|
1098
|
+
];
|
|
1099
|
+
var PERMISSIVE_ALLOW = [
|
|
1100
|
+
...RESTRICTIVE_ALLOW,
|
|
1101
|
+
"Bash(node *)",
|
|
1102
|
+
"Bash(python3 *)",
|
|
1103
|
+
"Bash(claude *)",
|
|
1104
|
+
"Bash(sed *)",
|
|
1105
|
+
"Bash(xargs *)",
|
|
1106
|
+
"Bash(tee *)"
|
|
1107
|
+
];
|
|
1108
|
+
function buildSettings(level) {
|
|
1109
|
+
return {
|
|
1110
|
+
permissions: {
|
|
1111
|
+
allow: level === "restrictive" ? RESTRICTIVE_ALLOW : PERMISSIVE_ALLOW,
|
|
1112
|
+
deny: DENY_LIST
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
function askConfirmation2(question) {
|
|
1117
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
1118
|
+
return new Promise((resolve) => {
|
|
1119
|
+
rl.question(question, (answer) => {
|
|
1120
|
+
rl.close();
|
|
1121
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
1122
|
+
});
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
async function claudeSettings({ level = "permissive" } = {}) {
|
|
1126
|
+
const cwd = INIT_CWD();
|
|
1127
|
+
const claudeDir = PATH9.resolve(cwd, ".claude");
|
|
1128
|
+
const settingsPath = PATH9.resolve(claudeDir, "settings.local.json");
|
|
1129
|
+
mkdirSync3(claudeDir, { recursive: true });
|
|
1130
|
+
if (existsSync8(settingsPath)) {
|
|
1131
|
+
const confirmed = await askConfirmation2(
|
|
1132
|
+
chalk12.yellow(`${settingsPath} already exists. Replace it? (y/N) `)
|
|
1133
|
+
);
|
|
1134
|
+
if (!confirmed) {
|
|
1135
|
+
console.log(chalk12.gray("Skipped \u2014 existing settings.local.json preserved"));
|
|
1136
|
+
return 0;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
const settings = buildSettings(level);
|
|
1140
|
+
writeFileSync4(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
1141
|
+
`, "utf8");
|
|
1142
|
+
console.log(chalk12.green(`Generated .claude/settings.local.json (${level})`));
|
|
1143
|
+
return 0;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// src/actions/claude-skills.ts
|
|
1147
|
+
import {
|
|
1148
|
+
existsSync as existsSync9,
|
|
1149
|
+
mkdirSync as mkdirSync4,
|
|
1150
|
+
readdirSync as readdirSync7,
|
|
1151
|
+
readFileSync as readFileSync10,
|
|
1152
|
+
rmSync as rmSync2,
|
|
1153
|
+
statSync as statSync3,
|
|
1154
|
+
writeFileSync as writeFileSync5
|
|
1155
|
+
} from "fs";
|
|
1156
|
+
import PATH10 from "path";
|
|
1157
|
+
import chalk13 from "chalk";
|
|
1158
|
+
var syncSkillFiles = (skillsDir) => {
|
|
1159
|
+
const pm = detectPackageManager();
|
|
1160
|
+
const rawTemplates = claudeSkillTemplates();
|
|
1161
|
+
const templateNames = new Set(Object.keys(rawTemplates));
|
|
1162
|
+
let updated = 0;
|
|
1163
|
+
let created = 0;
|
|
1164
|
+
for (const [skillName, files] of Object.entries(rawTemplates)) {
|
|
1165
|
+
const skillDir = PATH10.resolve(skillsDir, skillName);
|
|
1166
|
+
mkdirSync4(skillDir, { recursive: true });
|
|
1167
|
+
for (const [filename2, rawContent] of Object.entries(files)) {
|
|
1168
|
+
const content = applyPackageManager(rawContent, pm);
|
|
1169
|
+
const targetPath = PATH10.resolve(skillDir, filename2);
|
|
1170
|
+
mkdirSync4(PATH10.dirname(targetPath), { recursive: true });
|
|
1171
|
+
const existing = existsSync9(targetPath) ? readFileSync10(targetPath, "utf8") : void 0;
|
|
1172
|
+
if (existing === content) continue;
|
|
1173
|
+
writeFileSync5(targetPath, content, "utf8");
|
|
1174
|
+
if (existing) {
|
|
1175
|
+
updated++;
|
|
1176
|
+
} else {
|
|
1177
|
+
created++;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
created,
|
|
1183
|
+
templateNames,
|
|
1184
|
+
updated
|
|
1185
|
+
};
|
|
1186
|
+
};
|
|
1187
|
+
var removeStaleSkills = (skillsDir, templateNames) => {
|
|
1188
|
+
const existingSkills = readdirSync7(skillsDir).filter(
|
|
1189
|
+
(f) => f.startsWith(XYLABS_SKILLS_PREFIX) && statSync3(PATH10.resolve(skillsDir, f)).isDirectory()
|
|
1190
|
+
);
|
|
1191
|
+
let removed = 0;
|
|
1192
|
+
for (const dir of existingSkills) {
|
|
1193
|
+
if (!templateNames.has(dir)) {
|
|
1194
|
+
rmSync2(PATH10.resolve(skillsDir, dir), { recursive: true });
|
|
1195
|
+
removed++;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return removed;
|
|
1199
|
+
};
|
|
1200
|
+
var logSkillsResult = (created, updated, removed) => {
|
|
1201
|
+
if (created || updated || removed) {
|
|
1202
|
+
const parts = [
|
|
1203
|
+
created ? `${created} created` : "",
|
|
1204
|
+
updated ? `${updated} updated` : "",
|
|
1205
|
+
removed ? `${removed} removed` : ""
|
|
1206
|
+
].filter(Boolean);
|
|
1207
|
+
console.log(chalk13.green(`.claude/skills/${XYLABS_SKILLS_PREFIX}*/: ${parts.join(", ")}`));
|
|
1208
|
+
} else {
|
|
1209
|
+
console.log(chalk13.gray(`.claude/skills/${XYLABS_SKILLS_PREFIX}*/: already up to date`));
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
var claudeSkills = () => {
|
|
1213
|
+
const cwd = INIT_CWD();
|
|
1214
|
+
const skillsDir = PATH10.resolve(cwd, ".claude", "skills");
|
|
1215
|
+
mkdirSync4(skillsDir, { recursive: true });
|
|
1216
|
+
const {
|
|
1217
|
+
created,
|
|
1218
|
+
templateNames,
|
|
1219
|
+
updated
|
|
1220
|
+
} = syncSkillFiles(skillsDir);
|
|
1221
|
+
const removed = removeStaleSkills(skillsDir, templateNames);
|
|
1222
|
+
logSkillsResult(created, updated, removed);
|
|
1223
|
+
return 0;
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
// src/actions/clean-docs.ts
|
|
1227
|
+
import path2 from "path";
|
|
1228
|
+
import chalk14 from "chalk";
|
|
1229
|
+
var cleanDocs = () => {
|
|
1230
|
+
const pkgName = packageName();
|
|
1231
|
+
console.log(chalk14.green(`Cleaning Docs [${pkgName}]`));
|
|
1232
|
+
for (const { location } of getPackageManager().listWorkspaces()) deleteGlob(path2.join(location, "docs"));
|
|
1233
|
+
return 0;
|
|
1234
|
+
};
|
|
1235
|
+
|
|
1236
|
+
// src/actions/dead.ts
|
|
1237
|
+
var dead = () => {
|
|
1238
|
+
return runSteps("Dead", [["ts-prune", ["-p", "tsconfig.json"]]]);
|
|
1239
|
+
};
|
|
1240
|
+
|
|
1241
|
+
// src/actions/package-lint-deps.ts
|
|
1242
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
|
|
1243
|
+
import PATH11 from "path";
|
|
1244
|
+
import chalk15 from "chalk";
|
|
1245
|
+
import semver from "semver";
|
|
1246
|
+
function readWorkspacePackageJson(cwd, location) {
|
|
1247
|
+
const pkgPath = PATH11.resolve(cwd, location, "package.json");
|
|
1248
|
+
try {
|
|
1249
|
+
return JSON.parse(readFileSync11(pkgPath, "utf8"));
|
|
1250
|
+
} catch {
|
|
1251
|
+
return void 0;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
function writeWorkspacePackageJson(cwd, location, pkg) {
|
|
1255
|
+
const pkgPath = PATH11.resolve(cwd, location, "package.json");
|
|
1256
|
+
writeFileSync6(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
1257
|
+
`, "utf8");
|
|
1258
|
+
}
|
|
1259
|
+
function buildWorkspaceVersionMap(cwd, workspaces) {
|
|
1260
|
+
const map = /* @__PURE__ */ new Map();
|
|
1261
|
+
for (const { location, name } of workspaces) {
|
|
1262
|
+
if (location === ".") continue;
|
|
1263
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1264
|
+
if (!pkg) continue;
|
|
1265
|
+
const version = pkg.version;
|
|
1266
|
+
if (version) map.set(name, version);
|
|
1267
|
+
}
|
|
1268
|
+
return map;
|
|
1269
|
+
}
|
|
1270
|
+
function expectedPeerRange(devDepVersion, targetVersion) {
|
|
1271
|
+
const parsed = semver.parse(targetVersion);
|
|
1272
|
+
if (!parsed) return `~${targetVersion}`;
|
|
1273
|
+
if (devDepVersion === "workspace:^") {
|
|
1274
|
+
return `^${parsed.major}`;
|
|
1275
|
+
}
|
|
1276
|
+
return `~${parsed.major}.${parsed.minor}`;
|
|
1277
|
+
}
|
|
1278
|
+
function checkVersionConsistency(cwd, rootPkg, workspaces) {
|
|
1279
|
+
const result = {
|
|
1280
|
+
errors: [],
|
|
1281
|
+
fixable: [],
|
|
1282
|
+
warnings: []
|
|
1283
|
+
};
|
|
1284
|
+
if (rootPkg.version !== void 0) {
|
|
1285
|
+
result.fixable.push('Root package.json should not have a "version" field in a monorepo');
|
|
1286
|
+
}
|
|
1287
|
+
const versions = /* @__PURE__ */ new Map();
|
|
1288
|
+
for (const { location, name } of workspaces) {
|
|
1289
|
+
if (location === ".") continue;
|
|
1290
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1291
|
+
if (!pkg) continue;
|
|
1292
|
+
const version = pkg.version;
|
|
1293
|
+
if (version) {
|
|
1294
|
+
versions.set(name, version);
|
|
1295
|
+
} else {
|
|
1296
|
+
result.errors.push(`${name} (${location}) is missing a "version" field`);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
const uniqueVersions = new Set(versions.values());
|
|
1300
|
+
if (uniqueVersions.size > 1) {
|
|
1301
|
+
const versionList = [...uniqueVersions].toSorted(semver.rcompare);
|
|
1302
|
+
for (const [name, version] of versions) {
|
|
1303
|
+
if (version !== versionList[0]) {
|
|
1304
|
+
result.fixable.push(`${name} has version ${version} (expected ${versionList[0]})`);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
return result;
|
|
1309
|
+
}
|
|
1310
|
+
function fixVersionConsistency(cwd, rootPkg, writeRootPackageJson2, workspaces) {
|
|
1311
|
+
if (rootPkg.version !== void 0) {
|
|
1312
|
+
delete rootPkg.version;
|
|
1313
|
+
writeRootPackageJson2(cwd, rootPkg);
|
|
1314
|
+
console.log(chalk15.green(' \u2714 Fixed: removed "version" from root package.json'));
|
|
1315
|
+
}
|
|
1316
|
+
const versions = [];
|
|
1317
|
+
for (const { location } of workspaces) {
|
|
1318
|
+
if (location === ".") continue;
|
|
1319
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1320
|
+
if (!pkg) continue;
|
|
1321
|
+
const version = pkg.version;
|
|
1322
|
+
if (version && semver.valid(version)) {
|
|
1323
|
+
versions.push(version);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
if (versions.length === 0) return;
|
|
1327
|
+
const highest = versions.toSorted(semver.rcompare)[0];
|
|
1328
|
+
for (const { location, name } of workspaces) {
|
|
1329
|
+
if (location === ".") continue;
|
|
1330
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1331
|
+
if (!pkg) continue;
|
|
1332
|
+
if (pkg.version !== highest) {
|
|
1333
|
+
pkg.version = highest;
|
|
1334
|
+
writeWorkspacePackageJson(cwd, location, pkg);
|
|
1335
|
+
console.log(chalk15.green(` \u2714 Fixed: set version to ${highest} in ${name} (${location})`));
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
function expectedDepVersion(targetVersion) {
|
|
1340
|
+
const parsed = semver.parse(targetVersion);
|
|
1341
|
+
if (!parsed) return `~${targetVersion}`;
|
|
1342
|
+
return `~${targetVersion}`;
|
|
1343
|
+
}
|
|
1344
|
+
function checkInternalDepVersions(cwd, workspaces) {
|
|
1345
|
+
const result = {
|
|
1346
|
+
errors: [],
|
|
1347
|
+
fixable: [],
|
|
1348
|
+
warnings: []
|
|
1349
|
+
};
|
|
1350
|
+
const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
|
|
1351
|
+
for (const { location, name } of workspaces) {
|
|
1352
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1353
|
+
if (!pkg) continue;
|
|
1354
|
+
for (const depField of ["dependencies", "devDependencies"]) {
|
|
1355
|
+
const deps = pkg[depField];
|
|
1356
|
+
if (!deps) continue;
|
|
1357
|
+
for (const [dep, version] of Object.entries(deps)) {
|
|
1358
|
+
const targetVersion = workspaceVersions.get(dep);
|
|
1359
|
+
if (!targetVersion) continue;
|
|
1360
|
+
const expected = expectedDepVersion(targetVersion);
|
|
1361
|
+
if (version.startsWith("workspace:")) {
|
|
1362
|
+
result.fixable.push(
|
|
1363
|
+
`${name} (${location}) ${depField}.${dep} is "${version}" \u2014 should be "${expected}" (not workspace: protocol)`
|
|
1364
|
+
);
|
|
1365
|
+
} else if (version !== expected) {
|
|
1366
|
+
result.fixable.push(
|
|
1367
|
+
`${name} (${location}) ${depField}.${dep} is "${version}" \u2014 should be "${expected}"`
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
return result;
|
|
1374
|
+
}
|
|
1375
|
+
function fixInternalDepVersions(cwd, workspaces) {
|
|
1376
|
+
const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
|
|
1377
|
+
for (const { location, name } of workspaces) {
|
|
1378
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1379
|
+
if (!pkg) continue;
|
|
1380
|
+
let modified = false;
|
|
1381
|
+
for (const depField of ["dependencies", "devDependencies"]) {
|
|
1382
|
+
const deps = pkg[depField];
|
|
1383
|
+
if (!deps) continue;
|
|
1384
|
+
for (const [dep, version] of Object.entries(deps)) {
|
|
1385
|
+
const targetVersion = workspaceVersions.get(dep);
|
|
1386
|
+
if (!targetVersion) continue;
|
|
1387
|
+
const expected = expectedDepVersion(targetVersion);
|
|
1388
|
+
if (version !== expected) {
|
|
1389
|
+
deps[dep] = expected;
|
|
1390
|
+
console.log(chalk15.green(` \u2714 Fixed: set ${depField}.${dep} to "${expected}" in ${name} (${location})`));
|
|
1391
|
+
modified = true;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
if (modified) {
|
|
1396
|
+
writeWorkspacePackageJson(cwd, location, pkg);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function checkWorkspaceProtocol(cwd, workspaces) {
|
|
1401
|
+
const result = {
|
|
1402
|
+
errors: [],
|
|
1403
|
+
fixable: [],
|
|
1404
|
+
warnings: []
|
|
1405
|
+
};
|
|
1406
|
+
const workspaceNames = new Set(workspaces.map((w) => w.name));
|
|
1407
|
+
for (const { location, name } of workspaces) {
|
|
1408
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1409
|
+
if (!pkg) continue;
|
|
1410
|
+
for (const depField of ["dependencies", "devDependencies"]) {
|
|
1411
|
+
const deps = pkg[depField];
|
|
1412
|
+
if (!deps) continue;
|
|
1413
|
+
for (const [dep, version] of Object.entries(deps)) {
|
|
1414
|
+
if (!workspaceNames.has(dep)) continue;
|
|
1415
|
+
if (!version.startsWith("workspace:")) {
|
|
1416
|
+
result.fixable.push(
|
|
1417
|
+
`${name} (${location}) ${depField}.${dep} is "${version}" \u2014 should use workspace: protocol`
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
return result;
|
|
1424
|
+
}
|
|
1425
|
+
function fixWorkspaceProtocol(cwd, workspaces) {
|
|
1426
|
+
const workspaceNames = new Set(workspaces.map((w) => w.name));
|
|
1427
|
+
for (const { location, name } of workspaces) {
|
|
1428
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1429
|
+
if (!pkg) continue;
|
|
1430
|
+
let modified = false;
|
|
1431
|
+
for (const depField of ["dependencies", "devDependencies"]) {
|
|
1432
|
+
const deps = pkg[depField];
|
|
1433
|
+
if (!deps) continue;
|
|
1434
|
+
for (const [dep, version] of Object.entries(deps)) {
|
|
1435
|
+
if (!workspaceNames.has(dep)) continue;
|
|
1436
|
+
if (!version.startsWith("workspace:")) {
|
|
1437
|
+
deps[dep] = "workspace:~";
|
|
1438
|
+
console.log(chalk15.green(` \u2714 Fixed: set ${depField}.${dep} to "workspace:~" in ${name} (${location})`));
|
|
1439
|
+
modified = true;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
if (modified) {
|
|
1444
|
+
writeWorkspacePackageJson(cwd, location, pkg);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
function checkInternalPeerVersions(cwd, workspaces) {
|
|
1449
|
+
const result = {
|
|
1450
|
+
errors: [],
|
|
1451
|
+
fixable: [],
|
|
1452
|
+
warnings: []
|
|
1453
|
+
};
|
|
1454
|
+
const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
|
|
1455
|
+
for (const { location, name } of workspaces) {
|
|
1456
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1457
|
+
if (!pkg) continue;
|
|
1458
|
+
const peerDeps = pkg.peerDependencies;
|
|
1459
|
+
if (!peerDeps) continue;
|
|
1460
|
+
const devDeps = pkg.devDependencies;
|
|
1461
|
+
for (const [dep, version] of Object.entries(peerDeps)) {
|
|
1462
|
+
const targetVersion = workspaceVersions.get(dep);
|
|
1463
|
+
if (!targetVersion) continue;
|
|
1464
|
+
if (version.startsWith("workspace:")) {
|
|
1465
|
+
const expected2 = expectedPeerRange(devDeps?.[dep], targetVersion);
|
|
1466
|
+
result.fixable.push(
|
|
1467
|
+
`${name} (${location}) peerDependencies.${dep} uses workspace: protocol \u2014 should be "${expected2}"`
|
|
1468
|
+
);
|
|
1469
|
+
continue;
|
|
1470
|
+
}
|
|
1471
|
+
const expected = expectedPeerRange(devDeps?.[dep], targetVersion);
|
|
1472
|
+
if (version !== expected && !semver.satisfies(targetVersion, version)) {
|
|
1473
|
+
result.fixable.push(
|
|
1474
|
+
`${name} (${location}) peerDependencies.${dep} is "${version}" \u2014 current version ${targetVersion} is not satisfied; expected "${expected}"`
|
|
1475
|
+
);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
return result;
|
|
1480
|
+
}
|
|
1481
|
+
function fixInternalPeerVersions(cwd, workspaces) {
|
|
1482
|
+
const workspaceVersions = buildWorkspaceVersionMap(cwd, workspaces);
|
|
1483
|
+
for (const { location, name } of workspaces) {
|
|
1484
|
+
const pkg = readWorkspacePackageJson(cwd, location);
|
|
1485
|
+
if (!pkg) continue;
|
|
1486
|
+
const peerDeps = pkg.peerDependencies;
|
|
1487
|
+
if (!peerDeps) continue;
|
|
1488
|
+
const devDeps = pkg.devDependencies;
|
|
1489
|
+
let modified = false;
|
|
1490
|
+
for (const [dep, version] of Object.entries(peerDeps)) {
|
|
1491
|
+
const targetVersion = workspaceVersions.get(dep);
|
|
1492
|
+
if (!targetVersion) continue;
|
|
1493
|
+
const expected = expectedPeerRange(devDeps?.[dep], targetVersion);
|
|
1494
|
+
if (version !== expected) {
|
|
1495
|
+
peerDeps[dep] = expected;
|
|
1496
|
+
console.log(chalk15.green(` \u2714 Fixed: set peerDependencies.${dep} to "${expected}" in ${name} (${location})`));
|
|
1497
|
+
modified = true;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
if (modified) {
|
|
1501
|
+
writeWorkspacePackageJson(cwd, location, pkg);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
// src/actions/gen-docs.ts
|
|
1507
|
+
var genDocs = ({
|
|
1508
|
+
jobs,
|
|
1509
|
+
pkg,
|
|
1510
|
+
incremental
|
|
1511
|
+
}) => {
|
|
1512
|
+
return pkg ? genDocsPackage({ pkg }) : genDocsAll({ incremental, jobs });
|
|
1513
|
+
};
|
|
1514
|
+
var genDocsPackage = ({ pkg }) => {
|
|
1515
|
+
const pm = getPackageManager();
|
|
1516
|
+
return runSteps(`GenDocs [${pkg}]`, [pm.runInWorkspace(pkg, "package-gen-docs")]);
|
|
1517
|
+
};
|
|
1518
|
+
var genDocsAll = ({ incremental, jobs }) => {
|
|
1519
|
+
const pm = getPackageManager();
|
|
1520
|
+
return runSteps(`GenDocs [All${incremental ? "-Incremental" : ""}]`, [
|
|
1521
|
+
pm.foreachWorkspace("package-gen-docs", [], { incremental, jobs })
|
|
1522
|
+
]);
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
// src/actions/gitignore.ts
|
|
1526
|
+
import { unlinkSync as unlinkSync4 } from "fs";
|
|
1527
|
+
import chalk16 from "chalk";
|
|
1528
|
+
var COMMENT_PREFIX = "#";
|
|
1529
|
+
var isComment = (line) => line.startsWith(COMMENT_PREFIX);
|
|
1530
|
+
var isNegation = (line) => line.startsWith("!");
|
|
1531
|
+
function parseTemplateSections(lines) {
|
|
1532
|
+
const sections = [];
|
|
1533
|
+
let current = [];
|
|
1534
|
+
for (const line of lines) {
|
|
1535
|
+
if (isComment(line)) {
|
|
1536
|
+
if (current.length > 0) {
|
|
1537
|
+
sections.push(current);
|
|
1538
|
+
}
|
|
1539
|
+
current = [line];
|
|
1540
|
+
} else {
|
|
1541
|
+
current.push(line);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
if (current.length > 0) {
|
|
1545
|
+
sections.push(current);
|
|
1546
|
+
}
|
|
1547
|
+
return sections;
|
|
1548
|
+
}
|
|
1549
|
+
function mergeWithTemplate(existing, templateContent) {
|
|
1550
|
+
const templateLines = templateContent.split("\n").filter((line) => line.trim().length > 0);
|
|
1551
|
+
const sections = parseTemplateSections(templateLines);
|
|
1552
|
+
const existingEntries = new Set(existing.filter((line) => !isComment(line)));
|
|
1553
|
+
const templateEntries = new Set(templateLines.filter((line) => !isComment(line)));
|
|
1554
|
+
const customEntries = [...existingEntries].filter((entry) => !templateEntries.has(entry));
|
|
1555
|
+
const result = [];
|
|
1556
|
+
for (const section of sections) {
|
|
1557
|
+
for (const line of section) {
|
|
1558
|
+
result.push(line);
|
|
1559
|
+
}
|
|
1560
|
+
result.push("");
|
|
1561
|
+
}
|
|
1562
|
+
if (customEntries.length > 0) {
|
|
1563
|
+
result.push("# Custom");
|
|
1564
|
+
const sorted = [...union(customEntries, [])].toSorted((a, b) => {
|
|
1565
|
+
if (isNegation(a) && !isNegation(b)) return 1;
|
|
1566
|
+
if (!isNegation(a) && isNegation(b)) return -1;
|
|
1567
|
+
return a.localeCompare(b);
|
|
1568
|
+
});
|
|
1569
|
+
for (const entry of sorted) {
|
|
1570
|
+
result.push(entry);
|
|
1571
|
+
}
|
|
1572
|
+
result.push("");
|
|
1573
|
+
}
|
|
1574
|
+
return result;
|
|
1575
|
+
}
|
|
1576
|
+
function removePackageGitignores(cwd) {
|
|
1577
|
+
let removed = 0;
|
|
1578
|
+
const workspaces = getPackageManager().listWorkspaces();
|
|
1579
|
+
for (const { location } of workspaces) {
|
|
1580
|
+
if (location === ".") continue;
|
|
1581
|
+
const filePath = `${cwd}/${location}/.gitignore`;
|
|
1582
|
+
try {
|
|
1583
|
+
unlinkSync4(filePath);
|
|
1584
|
+
console.log(chalk16.yellow(` Removed ${location}/.gitignore`));
|
|
1585
|
+
removed++;
|
|
1586
|
+
} catch {
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
return removed;
|
|
1590
|
+
}
|
|
1591
|
+
function gitignore() {
|
|
1592
|
+
console.log(chalk16.green("Generate .gitignore"));
|
|
1593
|
+
const cwd = INIT_CWD();
|
|
1594
|
+
const gitignorePath = `${cwd}/.gitignore`;
|
|
1595
|
+
try {
|
|
1596
|
+
const templateContent = gitignoreTemplate();
|
|
1597
|
+
const existing = readNonEmptyLines(gitignorePath);
|
|
1598
|
+
const merged = mergeWithTemplate(existing, templateContent);
|
|
1599
|
+
writeLines(gitignorePath, merged);
|
|
1600
|
+
console.log(chalk16.green(" Root .gitignore updated"));
|
|
1601
|
+
const removed = removePackageGitignores(cwd);
|
|
1602
|
+
if (removed > 0) {
|
|
1603
|
+
console.log(chalk16.green(` Removed ${removed} package .gitignore file(s)`));
|
|
1604
|
+
}
|
|
1605
|
+
return 0;
|
|
1606
|
+
} catch (ex) {
|
|
1607
|
+
const error = ex;
|
|
1608
|
+
console.error(chalk16.red(`Generate .gitignore failed: ${error.message}`));
|
|
1609
|
+
return 1;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// src/actions/gitlint.ts
|
|
1614
|
+
import chalk17 from "chalk";
|
|
1615
|
+
import ParseGitConfig from "parse-git-config";
|
|
1616
|
+
var gitlint = () => {
|
|
1617
|
+
console.log(`
|
|
1618
|
+
Gitlint Start [${process.cwd()}]
|
|
1619
|
+
`);
|
|
1620
|
+
let valid = 0;
|
|
1621
|
+
let warnings = 0;
|
|
1622
|
+
const errors = 0;
|
|
1623
|
+
const gitConfig = ParseGitConfig.sync();
|
|
1624
|
+
const warn = (message) => {
|
|
1625
|
+
console.warn(chalk17.yellow(`Warning: ${message}`));
|
|
1626
|
+
warnings++;
|
|
1627
|
+
};
|
|
1628
|
+
if (gitConfig.core.ignorecase) {
|
|
1629
|
+
warn("Please set core.ignorecase to FALSE in .git/config file [run yarn gitlint-fix]");
|
|
1630
|
+
} else {
|
|
1631
|
+
valid++;
|
|
1632
|
+
}
|
|
1633
|
+
if (gitConfig.core.autocrlf === false) {
|
|
1634
|
+
valid++;
|
|
1635
|
+
} else {
|
|
1636
|
+
warn("Please set core.autocrlf to FALSE in .git/config file [run yarn gitlint-fix]");
|
|
1637
|
+
}
|
|
1638
|
+
if (gitConfig.core.eol === "lf") {
|
|
1639
|
+
valid++;
|
|
1640
|
+
} else {
|
|
1641
|
+
warn('Please set core.eol to "lf" in .git/config file [run yarn gitlint-fix]');
|
|
1642
|
+
}
|
|
1643
|
+
const resultMessages = [];
|
|
1644
|
+
if (valid > 0) {
|
|
1645
|
+
resultMessages.push(chalk17.green(`Passed: ${valid}`));
|
|
1646
|
+
}
|
|
1647
|
+
if (warnings > 0) {
|
|
1648
|
+
resultMessages.push(chalk17.yellow(`Warnings: ${warnings}`));
|
|
1649
|
+
}
|
|
1650
|
+
if (errors > 0) {
|
|
1651
|
+
resultMessages.push(chalk17.red(` Errors: ${errors}`));
|
|
1652
|
+
}
|
|
1653
|
+
console.warn(`Gitlint Finish [ ${resultMessages.join(" | ")} ]
|
|
1654
|
+
`);
|
|
1655
|
+
return warnings + errors === 0 ? 0 : 1;
|
|
1656
|
+
};
|
|
1657
|
+
|
|
1658
|
+
// src/actions/gitlint-fix.ts
|
|
1659
|
+
import { execSync } from "child_process";
|
|
1660
|
+
import chalk18 from "chalk";
|
|
1661
|
+
import ParseGitConfig2 from "parse-git-config";
|
|
1662
|
+
var gitlintFix = () => {
|
|
1663
|
+
console.log(`
|
|
1664
|
+
Gitlint Fix Start [${process.cwd()}]
|
|
1665
|
+
`);
|
|
1666
|
+
const gitConfig = ParseGitConfig2.sync();
|
|
1667
|
+
if (gitConfig.core.ignorecase) {
|
|
1668
|
+
execSync("git config core.ignorecase false", { stdio: "inherit" });
|
|
1669
|
+
console.warn(chalk18.yellow("\nGitlint Fix: Updated core.ignorecase to be false\n"));
|
|
1670
|
+
}
|
|
1671
|
+
if (gitConfig.core.autocrlf !== false) {
|
|
1672
|
+
execSync("git config core.autocrlf false", { stdio: "inherit" });
|
|
1673
|
+
console.warn(chalk18.yellow("\nGitlint Fix: Updated core.autocrlf to be false\n"));
|
|
1674
|
+
}
|
|
1675
|
+
if (gitConfig.core.eol !== "lf") {
|
|
1676
|
+
execSync("git config core.eol lf", { stdio: "inherit" });
|
|
1677
|
+
console.warn(chalk18.yellow('\nGitlint Fix: Updated core.eol to be "lf"\n'));
|
|
1678
|
+
}
|
|
1679
|
+
return 1;
|
|
1680
|
+
};
|
|
1681
|
+
|
|
1682
|
+
// src/actions/license.ts
|
|
1683
|
+
import chalk19 from "chalk";
|
|
1684
|
+
import { init } from "license-checker";
|
|
1685
|
+
var license = async (pkg) => {
|
|
1686
|
+
const workspaces = getPackageManager().listWorkspaces();
|
|
1687
|
+
const workspaceList = workspaces.filter(({ name }) => {
|
|
1688
|
+
return pkg === void 0 || name === pkg;
|
|
1689
|
+
});
|
|
1690
|
+
const exclude = /* @__PURE__ */ new Set([
|
|
1691
|
+
"MIT",
|
|
1692
|
+
"MIT*",
|
|
1693
|
+
"ISC",
|
|
1694
|
+
"Apache-2.0",
|
|
1695
|
+
"BSD",
|
|
1696
|
+
"BSD*",
|
|
1697
|
+
"BSD-2-Clause",
|
|
1698
|
+
"BSD-3-Clause",
|
|
1699
|
+
"CC-BY-4.0",
|
|
1700
|
+
"Unlicense",
|
|
1701
|
+
"CC-BY-3.0",
|
|
1702
|
+
"CC0-1.0",
|
|
1703
|
+
"LGPL-3.0-only",
|
|
1704
|
+
"LGPL-3.0",
|
|
1705
|
+
"LGPL-3.0-or-later",
|
|
1706
|
+
"Python-2.0"
|
|
1707
|
+
]);
|
|
1708
|
+
console.log(chalk19.green("License Checker"));
|
|
1709
|
+
return (await Promise.all(
|
|
1710
|
+
workspaceList.map(({ location, name }) => {
|
|
1711
|
+
return new Promise((resolve) => {
|
|
1712
|
+
init({ production: true, start: location }, (error, packages) => {
|
|
1713
|
+
if (error) {
|
|
1714
|
+
console.error(chalk19.red(`License Checker [${name}] Error`));
|
|
1715
|
+
console.error(chalk19.gray(error));
|
|
1716
|
+
console.log("\n");
|
|
1717
|
+
resolve(1);
|
|
1718
|
+
} else {
|
|
1719
|
+
console.log(chalk19.green(`License Checker [${name}]`));
|
|
1720
|
+
let count = 0;
|
|
1721
|
+
for (const [name2, info] of Object.entries(packages)) {
|
|
1722
|
+
const licenses = Array.isArray(info.licenses) ? info.licenses : [info.licenses];
|
|
1723
|
+
for (const license2 of licenses) {
|
|
1724
|
+
if (license2) {
|
|
1725
|
+
const processedLicense = license2.startsWith("(") && license2.at(-1) === ")" ? license2.slice(1, -2) : license2;
|
|
1726
|
+
const orLicenses = processedLicense.split(" OR ");
|
|
1727
|
+
let orLicenseFound = false;
|
|
1728
|
+
for (const orLicense of orLicenses) {
|
|
1729
|
+
if (exclude.has(orLicense)) {
|
|
1730
|
+
orLicenseFound = true;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
if (!orLicenseFound) {
|
|
1734
|
+
count++;
|
|
1735
|
+
console.warn(chalk19.yellow(`${name2}: Package License not allowed [${license2}]`));
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
console.log("\n");
|
|
1741
|
+
resolve(count);
|
|
1742
|
+
}
|
|
1743
|
+
});
|
|
1744
|
+
});
|
|
1745
|
+
})
|
|
1746
|
+
)).reduce((prev, value) => prev || value, 0);
|
|
1747
|
+
};
|
|
1748
|
+
|
|
1749
|
+
// src/actions/lint-init.ts
|
|
1750
|
+
import {
|
|
1751
|
+
existsSync as existsSync10,
|
|
1752
|
+
readFileSync as readFileSync12,
|
|
1753
|
+
unlinkSync as unlinkSync5,
|
|
1754
|
+
writeFileSync as writeFileSync7
|
|
1755
|
+
} from "fs";
|
|
1756
|
+
import PATH12 from "path";
|
|
1757
|
+
import { createInterface as createInterface3 } from "readline";
|
|
1758
|
+
import chalk20 from "chalk";
|
|
1759
|
+
import { globSync } from "glob";
|
|
1760
|
+
function detectReactInMonorepo(cwd, verbose) {
|
|
1761
|
+
const packageJsonPaths = globSync("packages/**/package.json", {
|
|
1762
|
+
cwd,
|
|
1763
|
+
ignore: ["**/node_modules/**"]
|
|
1764
|
+
});
|
|
1765
|
+
for (const relPath of packageJsonPaths) {
|
|
1766
|
+
const fullPath = PATH12.resolve(cwd, relPath);
|
|
1767
|
+
try {
|
|
1768
|
+
const content = readFileSync12(fullPath, "utf8");
|
|
1769
|
+
const pkg = JSON.parse(content);
|
|
1770
|
+
const deps = pkg.dependencies;
|
|
1771
|
+
const peerDeps = pkg.peerDependencies;
|
|
1772
|
+
if (deps?.react || peerDeps?.react) {
|
|
1773
|
+
if (verbose) console.log(chalk20.gray(` React detected in ${relPath}`));
|
|
1774
|
+
return true;
|
|
1775
|
+
}
|
|
1776
|
+
} catch {
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
return false;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
// src/actions/lintlint.ts
|
|
1783
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
1784
|
+
import {
|
|
1785
|
+
existsSync as existsSync11,
|
|
1786
|
+
readFileSync as readFileSync13,
|
|
1787
|
+
writeFileSync as writeFileSync8
|
|
1788
|
+
} from "fs";
|
|
1789
|
+
import PATH13 from "path";
|
|
1790
|
+
import chalk21 from "chalk";
|
|
1791
|
+
import { findUp } from "find-up";
|
|
1792
|
+
function parseRuleValue(value) {
|
|
1793
|
+
if (typeof value === "string") {
|
|
1794
|
+
return { level: value };
|
|
1795
|
+
}
|
|
1796
|
+
if (typeof value === "number") {
|
|
1797
|
+
return { level: String(value) };
|
|
1798
|
+
}
|
|
1799
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
1800
|
+
return {
|
|
1801
|
+
level: String(value[0]),
|
|
1802
|
+
options: value.length > 1 ? value.slice(1) : void 0
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
return void 0;
|
|
1806
|
+
}
|
|
1807
|
+
function normalizeLevel(level) {
|
|
1808
|
+
if (level === "0" || level === "off") return "off";
|
|
1809
|
+
if (level === "1" || level === "warn") return "warn";
|
|
1810
|
+
if (level === "2" || level === "error") return "error";
|
|
1811
|
+
return level;
|
|
1812
|
+
}
|
|
1813
|
+
function rulesMatch(a, b) {
|
|
1814
|
+
if (normalizeLevel(a.level) !== normalizeLevel(b.level)) return false;
|
|
1815
|
+
return JSON.stringify(a.options) === JSON.stringify(b.options);
|
|
1816
|
+
}
|
|
1817
|
+
function formatRule(entry) {
|
|
1818
|
+
if (entry.options) {
|
|
1819
|
+
return JSON.stringify([entry.level, ...entry.options]);
|
|
1820
|
+
}
|
|
1821
|
+
return JSON.stringify([entry.level]);
|
|
1822
|
+
}
|
|
1823
|
+
function mergeRulesFromBlocks(blocks) {
|
|
1824
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1825
|
+
for (const block of blocks) {
|
|
1826
|
+
if (!block.rules) continue;
|
|
1827
|
+
for (const [name, value] of Object.entries(block.rules)) {
|
|
1828
|
+
const parsed = parseRuleValue(value);
|
|
1829
|
+
if (parsed) merged.set(name, parsed);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
return merged;
|
|
1833
|
+
}
|
|
1834
|
+
function detectSharedPackage(source) {
|
|
1835
|
+
if (source.includes("@xylabs/eslint-config-react-flat")) return "@xylabs/eslint-config-react-flat";
|
|
1836
|
+
if (source.includes("@xylabs/eslint-config-flat")) return "@xylabs/eslint-config-flat";
|
|
1837
|
+
return void 0;
|
|
1838
|
+
}
|
|
1839
|
+
function extractLocalRuleBlocks(source) {
|
|
1840
|
+
const blocks = [];
|
|
1841
|
+
const ruleBlockRegex = /\{\s*(?:files\s*:\s*\[.*?\]\s*,\s*)?rules\s*:\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/g;
|
|
1842
|
+
let match;
|
|
1843
|
+
while ((match = ruleBlockRegex.exec(source)) !== null) {
|
|
1844
|
+
blocks.push(match[1]);
|
|
1845
|
+
}
|
|
1846
|
+
return blocks;
|
|
1847
|
+
}
|
|
1848
|
+
function extractRulesFromSourceBlocks(blocks) {
|
|
1849
|
+
const rules = /* @__PURE__ */ new Map();
|
|
1850
|
+
for (const block of blocks) {
|
|
1851
|
+
const ruleRegex = /['"]([^'"]+)['"]\s*:\s*(\[[\s\S]*?\](?=\s*,|\s*$))/gm;
|
|
1852
|
+
let match;
|
|
1853
|
+
while ((match = ruleRegex.exec(block)) !== null) {
|
|
1854
|
+
rules.set(match[1], match[2]);
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
return rules;
|
|
1858
|
+
}
|
|
1859
|
+
function extractConfigBlocks(sharedModule) {
|
|
1860
|
+
const config2 = sharedModule.config ?? sharedModule.default;
|
|
1861
|
+
if (Array.isArray(config2)) return config2;
|
|
1862
|
+
return [];
|
|
1863
|
+
}
|
|
1864
|
+
async function resolveSharedConfig(configDir, sharedPkg) {
|
|
1865
|
+
try {
|
|
1866
|
+
const sharedModule = await import(sharedPkg);
|
|
1867
|
+
return extractConfigBlocks(sharedModule);
|
|
1868
|
+
} catch {
|
|
1869
|
+
const distPath = PATH13.resolve(configDir, "node_modules", sharedPkg, "dist", "node", "index.mjs");
|
|
1870
|
+
try {
|
|
1871
|
+
const sharedModule = await import(distPath);
|
|
1872
|
+
return extractConfigBlocks(sharedModule);
|
|
1873
|
+
} catch {
|
|
1874
|
+
const neutralPath = PATH13.resolve(configDir, "node_modules", sharedPkg, "dist", "neutral", "index.mjs");
|
|
1875
|
+
const sharedModule = await import(neutralPath);
|
|
1876
|
+
return extractConfigBlocks(sharedModule);
|
|
1877
|
+
}
|
|
1878
|
+
return [];
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
async function loadSharedRules(configDir, sharedPkg, verbose) {
|
|
1882
|
+
const sharedBlocks = await resolveSharedConfig(configDir, sharedPkg);
|
|
1883
|
+
const sharedRules = mergeRulesFromBlocks(sharedBlocks);
|
|
1884
|
+
if (verbose) {
|
|
1885
|
+
console.log(chalk21.gray(`Shared config defines ${sharedRules.size} rules`));
|
|
1886
|
+
}
|
|
1887
|
+
if (sharedRules.size === 0) {
|
|
1888
|
+
console.error(chalk21.red("Could not load rules from shared config. Is it installed and built?"));
|
|
1889
|
+
return void 0;
|
|
1890
|
+
}
|
|
1891
|
+
return sharedRules;
|
|
1892
|
+
}
|
|
1893
|
+
async function loadLocalRules(eslintConfigPath, source, verbose) {
|
|
1894
|
+
const localModule = await import(eslintConfigPath);
|
|
1895
|
+
const localConfig = localModule.default ?? localModule;
|
|
1896
|
+
const localBlocks = Array.isArray(localConfig) ? localConfig : [localConfig];
|
|
1897
|
+
const resolved = mergeRulesFromBlocks(localBlocks);
|
|
1898
|
+
const localRuleBlocks = extractLocalRuleBlocks(source);
|
|
1899
|
+
const explicit = extractRulesFromSourceBlocks(localRuleBlocks);
|
|
1900
|
+
if (verbose) {
|
|
1901
|
+
console.log(chalk21.gray(`Local config has ${explicit.size} explicit rule setting(s)`));
|
|
1902
|
+
}
|
|
1903
|
+
return { explicit, resolved };
|
|
1904
|
+
}
|
|
1905
|
+
function compareRules(explicitRuleNames, allResolvedRules, sharedRules) {
|
|
1906
|
+
const redundant = [];
|
|
1907
|
+
const overrides = [];
|
|
1908
|
+
const additions = [];
|
|
1909
|
+
for (const ruleName of explicitRuleNames.keys()) {
|
|
1910
|
+
const resolvedEntry = allResolvedRules.get(ruleName);
|
|
1911
|
+
const sharedEntry = sharedRules.get(ruleName);
|
|
1912
|
+
if (!resolvedEntry) continue;
|
|
1913
|
+
if (!sharedEntry) {
|
|
1914
|
+
additions.push({ local: resolvedEntry, rule: ruleName });
|
|
1915
|
+
} else if (rulesMatch(resolvedEntry, sharedEntry)) {
|
|
1916
|
+
redundant.push({
|
|
1917
|
+
local: resolvedEntry,
|
|
1918
|
+
rule: ruleName,
|
|
1919
|
+
shared: sharedEntry
|
|
1920
|
+
});
|
|
1921
|
+
} else {
|
|
1922
|
+
overrides.push({
|
|
1923
|
+
local: resolvedEntry,
|
|
1924
|
+
rule: ruleName,
|
|
1925
|
+
shared: sharedEntry
|
|
1926
|
+
});
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
return {
|
|
1930
|
+
additions,
|
|
1931
|
+
overrides,
|
|
1932
|
+
redundant
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
function reportResults({
|
|
1936
|
+
additions,
|
|
1937
|
+
overrides,
|
|
1938
|
+
redundant
|
|
1939
|
+
}, verbose) {
|
|
1940
|
+
if (redundant.length > 0) {
|
|
1941
|
+
console.log(chalk21.yellow(`
|
|
1942
|
+
${redundant.length} redundant rule(s) (same as shared config \u2014 can be removed):`));
|
|
1943
|
+
for (const { rule, local } of redundant) {
|
|
1944
|
+
console.log(chalk21.yellow(` ${rule}: ${formatRule(local)}`));
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
if (overrides.length > 0) {
|
|
1948
|
+
console.log(chalk21.cyan(`
|
|
1949
|
+
${overrides.length} rule override(s) (different from shared config):`));
|
|
1950
|
+
for (const {
|
|
1951
|
+
rule,
|
|
1952
|
+
local,
|
|
1953
|
+
shared
|
|
1954
|
+
} of overrides) {
|
|
1955
|
+
console.log(chalk21.cyan(` ${rule}:`));
|
|
1956
|
+
console.log(chalk21.gray(` shared: ${formatRule(shared)}`));
|
|
1957
|
+
console.log(chalk21.white(` local: ${formatRule(local)}`));
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
if (additions.length > 0 && verbose) {
|
|
1961
|
+
console.log(chalk21.gray(`
|
|
1962
|
+
${additions.length} local addition(s) (not in shared config):`));
|
|
1963
|
+
for (const { rule, local } of additions) {
|
|
1964
|
+
console.log(chalk21.gray(` ${rule}: ${formatRule(local)}`));
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
if (redundant.length === 0 && overrides.length === 0) {
|
|
1968
|
+
console.log(chalk21.green("No redundant or overridden rules found"));
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
function fixRedundantRules(eslintConfigPath, redundant) {
|
|
1972
|
+
let updated = readFileSync13(eslintConfigPath, "utf8");
|
|
1973
|
+
const original = updated;
|
|
1974
|
+
for (const { rule } of redundant) {
|
|
1975
|
+
const escaped = rule.replaceAll("/", String.raw`\/`);
|
|
1976
|
+
const pattern = new RegExp(String.raw`[ \t]*['"]${escaped}['"]\s*:\s*\[[^\]]*\],?[ \t]*\n?`, "g");
|
|
1977
|
+
updated = updated.replace(pattern, "");
|
|
1978
|
+
}
|
|
1979
|
+
updated = updated.replaceAll(/\{\s*rules\s*:\s*\{\s*\}\s*,?\s*\}\s*,?/g, "");
|
|
1980
|
+
updated = updated.replaceAll(/\n{3,}/g, "\n\n");
|
|
1981
|
+
if (updated !== original) {
|
|
1982
|
+
writeFileSync8(eslintConfigPath, updated, "utf8");
|
|
1983
|
+
console.log(chalk21.green(`
|
|
1984
|
+
Fixed: removed ${redundant.length} redundant rule(s)`));
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
function formatConfigFile(eslintConfigPath) {
|
|
1988
|
+
spawnSync4("eslint", ["--fix", eslintConfigPath], { stdio: "inherit" });
|
|
1989
|
+
}
|
|
1990
|
+
function fixConfigMismatch(eslintConfigPath, configDir, source, sharedPkg, expectedPkg) {
|
|
1991
|
+
const updated = source.replaceAll(sharedPkg, expectedPkg);
|
|
1992
|
+
writeFileSync8(eslintConfigPath, updated, "utf8");
|
|
1993
|
+
console.log(chalk21.green(`Fixed: replaced ${sharedPkg} with ${expectedPkg}`));
|
|
1994
|
+
const packageJsonPath = PATH13.resolve(configDir, "package.json");
|
|
1995
|
+
if (!existsSync11(packageJsonPath)) return;
|
|
1996
|
+
const content = readFileSync13(packageJsonPath, "utf8");
|
|
1997
|
+
const pkg = JSON.parse(content);
|
|
1998
|
+
const devDeps = pkg.devDependencies ?? {};
|
|
1999
|
+
const oldVersion = devDeps[sharedPkg];
|
|
2000
|
+
if (!oldVersion) return;
|
|
2001
|
+
delete devDeps[sharedPkg];
|
|
2002
|
+
devDeps[expectedPkg] = oldVersion;
|
|
2003
|
+
const sorted = Object.fromEntries(Object.entries(devDeps).toSorted(([a], [b]) => a.localeCompare(b)));
|
|
2004
|
+
pkg.devDependencies = sorted;
|
|
2005
|
+
writeFileSync8(packageJsonPath, `${JSON.stringify(pkg, null, 2)}
|
|
2006
|
+
`, "utf8");
|
|
2007
|
+
console.log(chalk21.green(`Updated package.json: ${sharedPkg} \u2192 ${expectedPkg}`));
|
|
2008
|
+
runInstall(configDir);
|
|
2009
|
+
}
|
|
2010
|
+
function checkConfigVariant(eslintConfigPath, configDir, source, sharedPkg, fix, verbose) {
|
|
2011
|
+
const hasReact = detectReactInMonorepo(configDir, verbose);
|
|
2012
|
+
const expectedPkg = hasReact ? "@xylabs/eslint-config-react-flat" : "@xylabs/eslint-config-flat";
|
|
2013
|
+
if (sharedPkg === expectedPkg) return false;
|
|
2014
|
+
console.log(chalk21.yellow(`
|
|
2015
|
+
Config mismatch: using ${sharedPkg} but ${hasReact ? "React packages detected" : "no React packages found"}`));
|
|
2016
|
+
console.log(chalk21.yellow(` Expected: ${expectedPkg}`));
|
|
2017
|
+
if (fix) {
|
|
2018
|
+
fixConfigMismatch(eslintConfigPath, configDir, source, sharedPkg, expectedPkg);
|
|
2019
|
+
}
|
|
2020
|
+
return true;
|
|
2021
|
+
}
|
|
2022
|
+
async function lintlint({ fix, verbose } = {}) {
|
|
2023
|
+
const eslintConfigPath = await findUp(["eslint.config.ts", "eslint.config.mjs"]);
|
|
2024
|
+
if (!eslintConfigPath) {
|
|
2025
|
+
console.error(chalk21.red("No eslint.config.ts found"));
|
|
2026
|
+
return 1;
|
|
2027
|
+
}
|
|
2028
|
+
const configDir = PATH13.dirname(eslintConfigPath);
|
|
2029
|
+
if (verbose) {
|
|
2030
|
+
console.log(chalk21.gray(`Found config: ${eslintConfigPath}`));
|
|
2031
|
+
}
|
|
2032
|
+
const source = readFileSync13(eslintConfigPath, "utf8");
|
|
2033
|
+
const sharedPkg = detectSharedPackage(source);
|
|
2034
|
+
if (!sharedPkg) {
|
|
2035
|
+
console.log(chalk21.yellow("No @xylabs/eslint-config-flat or @xylabs/eslint-config-react-flat imports found"));
|
|
2036
|
+
return 0;
|
|
2037
|
+
}
|
|
2038
|
+
if (verbose) {
|
|
2039
|
+
console.log(chalk21.gray(`Shared package: ${sharedPkg}`));
|
|
2040
|
+
}
|
|
2041
|
+
const hasMismatch = checkConfigVariant(eslintConfigPath, configDir, source, sharedPkg, !!fix, !!verbose);
|
|
2042
|
+
const currentSource = hasMismatch && fix ? readFileSync13(eslintConfigPath, "utf8") : source;
|
|
2043
|
+
const sharedRules = await loadSharedRules(configDir, sharedPkg, !!verbose);
|
|
2044
|
+
if (!sharedRules) return 1;
|
|
2045
|
+
const { explicit, resolved } = await loadLocalRules(eslintConfigPath, currentSource, !!verbose);
|
|
2046
|
+
const results = compareRules(explicit, resolved, sharedRules);
|
|
2047
|
+
reportResults(results, !!verbose);
|
|
2048
|
+
if (results.redundant.length > 0 && fix) {
|
|
2049
|
+
fixRedundantRules(eslintConfigPath, results.redundant);
|
|
2050
|
+
}
|
|
2051
|
+
const didFix = fix && (hasMismatch || results.redundant.length > 0);
|
|
2052
|
+
if (didFix) {
|
|
2053
|
+
formatConfigFile(eslintConfigPath);
|
|
2054
|
+
}
|
|
2055
|
+
const hasUnfixedMismatch = hasMismatch && !fix;
|
|
2056
|
+
const hasUnfixedRedundant = results.redundant.length > 0 && !fix;
|
|
2057
|
+
return hasUnfixedMismatch || hasUnfixedRedundant ? 1 : 0;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
// src/actions/npmignore-gen.ts
|
|
2061
|
+
var filename = ".npmignore";
|
|
2062
|
+
var npmignoreGen = (pkg) => generateIgnoreFiles(filename, pkg);
|
|
2063
|
+
|
|
2064
|
+
// src/actions/orphan.ts
|
|
2065
|
+
import fs2 from "fs";
|
|
2066
|
+
import path3 from "path";
|
|
2067
|
+
import chalk22 from "chalk";
|
|
2068
|
+
import { glob as glob2 } from "glob";
|
|
2069
|
+
function isAncestorOfWorkspace(dir, workspaceLocations) {
|
|
2070
|
+
const dirWithSep = dir.endsWith(path3.sep) ? dir : dir + path3.sep;
|
|
2071
|
+
for (const ws of workspaceLocations) {
|
|
2072
|
+
if (ws.startsWith(dirWithSep)) return true;
|
|
2073
|
+
}
|
|
2074
|
+
return false;
|
|
2075
|
+
}
|
|
2076
|
+
function findOrphans(cwd, verbose) {
|
|
2077
|
+
const pm = getPackageManager();
|
|
2078
|
+
const workspaces = pm.listWorkspaces();
|
|
2079
|
+
const workspaceLocations = new Set(
|
|
2080
|
+
workspaces.map((ws) => path3.resolve(cwd, ws.location))
|
|
2081
|
+
);
|
|
2082
|
+
const distDirs = glob2.sync("**/dist", {
|
|
2083
|
+
cwd,
|
|
2084
|
+
ignore: ["**/node_modules/**"]
|
|
2085
|
+
});
|
|
2086
|
+
const orphans = /* @__PURE__ */ new Set();
|
|
2087
|
+
for (const distDir of distDirs) {
|
|
2088
|
+
const parentRel = path3.dirname(distDir);
|
|
2089
|
+
const parentAbs = path3.resolve(cwd, parentRel);
|
|
2090
|
+
if (parentRel === ".") continue;
|
|
2091
|
+
if (workspaceLocations.has(parentAbs)) continue;
|
|
2092
|
+
if (fs2.existsSync(path3.join(parentAbs, "package.json"))) continue;
|
|
2093
|
+
if (verbose) {
|
|
2094
|
+
console.log(chalk22.gray(` Found orphan: ${parentRel}`));
|
|
2095
|
+
}
|
|
2096
|
+
let topOrphan = parentRel;
|
|
2097
|
+
let current = path3.dirname(parentRel);
|
|
2098
|
+
while (current !== ".") {
|
|
2099
|
+
const currentAbs = path3.resolve(cwd, current);
|
|
2100
|
+
if (workspaceLocations.has(currentAbs)) break;
|
|
2101
|
+
if (fs2.existsSync(path3.join(currentAbs, "package.json"))) break;
|
|
2102
|
+
if (isAncestorOfWorkspace(currentAbs, workspaceLocations)) break;
|
|
2103
|
+
topOrphan = current;
|
|
2104
|
+
current = path3.dirname(current);
|
|
2105
|
+
}
|
|
2106
|
+
orphans.add(topOrphan);
|
|
2107
|
+
}
|
|
2108
|
+
return [...orphans].toSorted();
|
|
2109
|
+
}
|
|
2110
|
+
function orphanList({ verbose } = {}) {
|
|
2111
|
+
const cwd = INIT_CWD();
|
|
2112
|
+
console.log(chalk22.green("Orphan List"));
|
|
2113
|
+
const orphans = findOrphans(cwd, verbose);
|
|
2114
|
+
if (orphans.length === 0) {
|
|
2115
|
+
console.log(chalk22.green(" No orphaned directories found"));
|
|
2116
|
+
return 0;
|
|
2117
|
+
}
|
|
2118
|
+
for (const orphan of orphans) {
|
|
2119
|
+
console.log(chalk22.yellow(` ${orphan}`));
|
|
2120
|
+
}
|
|
2121
|
+
console.log(chalk22.yellow(`
|
|
2122
|
+
Found ${orphans.length} orphaned director${orphans.length === 1 ? "y" : "ies"}`));
|
|
2123
|
+
return 1;
|
|
2124
|
+
}
|
|
2125
|
+
function orphanClean({ verbose } = {}) {
|
|
2126
|
+
const cwd = INIT_CWD();
|
|
2127
|
+
console.log(chalk22.green("Orphan Clean"));
|
|
2128
|
+
const orphans = findOrphans(cwd, verbose);
|
|
2129
|
+
if (orphans.length === 0) {
|
|
2130
|
+
console.log(chalk22.green(" No orphaned directories found"));
|
|
2131
|
+
return 0;
|
|
2132
|
+
}
|
|
2133
|
+
for (const orphan of orphans) {
|
|
2134
|
+
const absPath = path3.resolve(cwd, orphan);
|
|
2135
|
+
fs2.rmSync(absPath, { force: true, recursive: true });
|
|
2136
|
+
console.log(chalk22.yellow(` Removed ${orphan}`));
|
|
2137
|
+
}
|
|
2138
|
+
console.log(chalk22.green(`
|
|
2139
|
+
Cleaned ${orphans.length} orphaned director${orphans.length === 1 ? "y" : "ies"}`));
|
|
2140
|
+
return 0;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
// src/actions/package/compile/XyConfig.ts
|
|
2144
|
+
var ALL_PUBLINT_CHECKS = [
|
|
2145
|
+
"files",
|
|
2146
|
+
"importToDefault",
|
|
2147
|
+
"main",
|
|
2148
|
+
"module",
|
|
2149
|
+
"peerDeps",
|
|
2150
|
+
"publint",
|
|
2151
|
+
"resolutions",
|
|
2152
|
+
"rootSource",
|
|
2153
|
+
"rootTypes",
|
|
2154
|
+
"sideEffects",
|
|
2155
|
+
"source",
|
|
2156
|
+
"types"
|
|
2157
|
+
];
|
|
2158
|
+
var PUBLISH_ONLY_CHECKS = [
|
|
2159
|
+
"files",
|
|
2160
|
+
"importToDefault",
|
|
2161
|
+
"main",
|
|
2162
|
+
"module",
|
|
2163
|
+
"publint",
|
|
2164
|
+
"rootSource",
|
|
2165
|
+
"rootTypes",
|
|
2166
|
+
"sideEffects",
|
|
2167
|
+
"source",
|
|
2168
|
+
"types"
|
|
2169
|
+
];
|
|
2170
|
+
|
|
2171
|
+
// src/actions/package/publint.ts
|
|
2172
|
+
import { promises as fs3 } from "fs";
|
|
2173
|
+
import path4 from "path";
|
|
2174
|
+
import chalk23 from "chalk";
|
|
2175
|
+
import { glob as glob3 } from "glob";
|
|
2176
|
+
import sortPackageJson from "sort-package-json";
|
|
2177
|
+
var removeSourceFromExports = (exports) => {
|
|
2178
|
+
let removed = false;
|
|
2179
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
2180
|
+
if (key === "source") {
|
|
2181
|
+
delete exports[key];
|
|
2182
|
+
removed = true;
|
|
2183
|
+
} else if (typeof value === "object" && value !== null && removeSourceFromExports(value)) removed = true;
|
|
2184
|
+
}
|
|
2185
|
+
return removed;
|
|
2186
|
+
};
|
|
2187
|
+
var hasSourceInExports = (exports) => {
|
|
2188
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
2189
|
+
if (key === "source") return true;
|
|
2190
|
+
if (typeof value === "object" && value !== null && hasSourceInExports(value)) return true;
|
|
2191
|
+
}
|
|
2192
|
+
return false;
|
|
2193
|
+
};
|
|
2194
|
+
var hasImportKeyInExports = (exports) => {
|
|
2195
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
2196
|
+
if (key === "import" && typeof value === "string" && value.endsWith(".mjs")) return true;
|
|
2197
|
+
if (typeof value === "object" && value !== null && hasImportKeyInExports(value)) return true;
|
|
2198
|
+
}
|
|
2199
|
+
return false;
|
|
2200
|
+
};
|
|
2201
|
+
var replaceImportWithDefault = (exports) => {
|
|
2202
|
+
let modified = false;
|
|
2203
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
2204
|
+
if (key === "import" && typeof value === "string" && value.endsWith(".mjs")) {
|
|
2205
|
+
if (exports.default === void 0) {
|
|
2206
|
+
exports.default = value;
|
|
2207
|
+
}
|
|
2208
|
+
delete exports.import;
|
|
2209
|
+
if (exports.types === void 0) {
|
|
2210
|
+
exports.types = value.replace(/\.mjs$/, ".d.ts");
|
|
2211
|
+
}
|
|
2212
|
+
modified = true;
|
|
2213
|
+
} else if (typeof value === "object" && value !== null && replaceImportWithDefault(value)) modified = true;
|
|
2214
|
+
}
|
|
2215
|
+
return modified;
|
|
2216
|
+
};
|
|
2217
|
+
var hasTypesInExports = (exports) => {
|
|
2218
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
2219
|
+
if (key === "types") return true;
|
|
2220
|
+
if (typeof value === "object" && value !== null && hasTypesInExports(value)) return true;
|
|
2221
|
+
}
|
|
2222
|
+
return false;
|
|
2223
|
+
};
|
|
2224
|
+
function ensureExportsPath(value) {
|
|
2225
|
+
if (value.startsWith("./") || value.startsWith("../")) return value;
|
|
2226
|
+
return `./${value}`;
|
|
2227
|
+
}
|
|
2228
|
+
function emptyCustomResult() {
|
|
2229
|
+
return {
|
|
2230
|
+
errors: 0,
|
|
2231
|
+
modified: false,
|
|
2232
|
+
warnings: 0
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2235
|
+
function mergeResults(target, source) {
|
|
2236
|
+
target.errors += source.errors;
|
|
2237
|
+
target.warnings += source.warnings;
|
|
2238
|
+
target.modified = target.modified || source.modified;
|
|
2239
|
+
}
|
|
2240
|
+
function checkFiles(pkg, fix) {
|
|
2241
|
+
const result = emptyCustomResult();
|
|
2242
|
+
const files = pkg.files;
|
|
2243
|
+
if (files === void 0) {
|
|
2244
|
+
console.warn(chalk23.yellow('Publint [custom]: "files" field is missing'));
|
|
2245
|
+
result.warnings++;
|
|
2246
|
+
}
|
|
2247
|
+
if (Array.isArray(files) && !files.includes("README.md")) {
|
|
2248
|
+
files.push("README.md");
|
|
2249
|
+
console.warn(chalk23.yellow('Publint [custom]: added "README.md" to "files"'));
|
|
2250
|
+
result.modified = true;
|
|
2251
|
+
result.warnings++;
|
|
2252
|
+
}
|
|
2253
|
+
if (Array.isArray(files) && files.includes("src")) {
|
|
2254
|
+
if (fix) {
|
|
2255
|
+
pkg.files = files.filter((f) => f !== "src");
|
|
2256
|
+
console.warn(chalk23.yellow('Publint [custom]: removed "src" from "files"'));
|
|
2257
|
+
result.modified = true;
|
|
2258
|
+
} else {
|
|
2259
|
+
console.warn(chalk23.yellow('Publint [custom]: "src" should not be in "files" (use --fix to remove)'));
|
|
2260
|
+
}
|
|
2261
|
+
result.warnings++;
|
|
2262
|
+
}
|
|
2263
|
+
return result;
|
|
2264
|
+
}
|
|
2265
|
+
function checkExportsSource(pkg, fix) {
|
|
2266
|
+
const result = emptyCustomResult();
|
|
2267
|
+
const exports = pkg.exports;
|
|
2268
|
+
if (exports && typeof exports === "object" && hasSourceInExports(exports)) {
|
|
2269
|
+
if (fix) {
|
|
2270
|
+
removeSourceFromExports(exports);
|
|
2271
|
+
console.warn(chalk23.yellow('Publint [custom]: removed "source" entries from "exports"'));
|
|
2272
|
+
result.modified = true;
|
|
2273
|
+
} else {
|
|
2274
|
+
console.warn(chalk23.yellow('Publint [custom]: "source" entries should not be in "exports" (use --fix to remove)'));
|
|
2275
|
+
}
|
|
2276
|
+
result.warnings++;
|
|
2277
|
+
}
|
|
2278
|
+
return result;
|
|
2279
|
+
}
|
|
2280
|
+
function migrateFieldToExports(pkg, field, exportKey, fix) {
|
|
2281
|
+
const result = emptyCustomResult();
|
|
2282
|
+
if (pkg[field] === void 0) return result;
|
|
2283
|
+
const fieldValue = pkg[field];
|
|
2284
|
+
if (!fieldValue.endsWith(".js") && !fieldValue.endsWith(".mjs") && !fieldValue.endsWith(".cjs")) return result;
|
|
2285
|
+
if (fix) {
|
|
2286
|
+
const exportValue = ensureExportsPath(fieldValue);
|
|
2287
|
+
const exports = pkg.exports;
|
|
2288
|
+
if (exports && typeof exports === "object") {
|
|
2289
|
+
const dot = exports["."];
|
|
2290
|
+
if (dot && typeof dot === "object" && !dot[exportKey]) {
|
|
2291
|
+
dot[exportKey] = exportValue;
|
|
2292
|
+
console.warn(chalk23.yellow(`Publint [custom]: migrated "${field}" to "exports['.'].${exportKey}" (${fieldValue})`));
|
|
2293
|
+
}
|
|
2294
|
+
} else if (!pkg.exports) {
|
|
2295
|
+
pkg.exports = { ".": { [exportKey]: exportValue } };
|
|
2296
|
+
console.warn(chalk23.yellow(`Publint [custom]: migrated "${field}" to "exports" (.\u2192${fieldValue})`));
|
|
2297
|
+
}
|
|
2298
|
+
delete pkg[field];
|
|
2299
|
+
console.warn(chalk23.yellow(`Publint [custom]: removed deprecated "${field}" field`));
|
|
2300
|
+
result.modified = true;
|
|
2301
|
+
} else {
|
|
2302
|
+
console.warn(chalk23.yellow(`Publint [custom]: "${field}" field is deprecated, use "exports" instead (use --fix to remove)`));
|
|
2303
|
+
}
|
|
2304
|
+
result.warnings++;
|
|
2305
|
+
return result;
|
|
2306
|
+
}
|
|
2307
|
+
function checkSideEffects(pkg) {
|
|
2308
|
+
const result = emptyCustomResult();
|
|
2309
|
+
if (pkg.sideEffects !== false) {
|
|
2310
|
+
console.warn(chalk23.yellow('Publint [custom]: "sideEffects" field should be set to false'));
|
|
2311
|
+
result.warnings++;
|
|
2312
|
+
}
|
|
2313
|
+
return result;
|
|
2314
|
+
}
|
|
2315
|
+
function checkRootSource(pkg, fix) {
|
|
2316
|
+
const result = emptyCustomResult();
|
|
2317
|
+
for (const field of ["source", "src"]) {
|
|
2318
|
+
if (pkg[field] !== void 0) {
|
|
2319
|
+
if (fix) {
|
|
2320
|
+
delete pkg[field];
|
|
2321
|
+
console.warn(chalk23.yellow(`Publint [custom]: removed root-level "${field}" field`));
|
|
2322
|
+
result.modified = true;
|
|
2323
|
+
} else {
|
|
2324
|
+
console.warn(chalk23.yellow(`Publint [custom]: root-level "${field}" field should not be in package.json (use --fix to remove)`));
|
|
2325
|
+
}
|
|
2326
|
+
result.warnings++;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
return result;
|
|
2330
|
+
}
|
|
2331
|
+
function checkResolutions(pkg) {
|
|
2332
|
+
const result = emptyCustomResult();
|
|
2333
|
+
if (pkg.resolutions !== void 0) {
|
|
2334
|
+
console.warn(chalk23.yellow('Publint [custom]: "resolutions" in use'));
|
|
2335
|
+
console.warn(chalk23.gray(JSON.stringify(pkg.resolutions, null, 2)));
|
|
2336
|
+
result.warnings++;
|
|
2337
|
+
}
|
|
2338
|
+
return result;
|
|
2339
|
+
}
|
|
2340
|
+
function checkImportToDefault(pkg, fix) {
|
|
2341
|
+
const result = emptyCustomResult();
|
|
2342
|
+
const exports = pkg.exports;
|
|
2343
|
+
if (!exports || typeof exports !== "object") return result;
|
|
2344
|
+
if (!hasImportKeyInExports(exports)) return result;
|
|
2345
|
+
if (fix) {
|
|
2346
|
+
replaceImportWithDefault(exports);
|
|
2347
|
+
console.warn(chalk23.yellow('Publint [custom]: renamed "import" to "default" in "exports" and ensured "types" siblings'));
|
|
2348
|
+
result.modified = true;
|
|
2349
|
+
} else {
|
|
2350
|
+
console.warn(chalk23.yellow('Publint [custom]: "import" entries in "exports" should use "default" instead (use --fix to rename)'));
|
|
2351
|
+
}
|
|
2352
|
+
result.warnings++;
|
|
2353
|
+
return result;
|
|
2354
|
+
}
|
|
2355
|
+
function checkRootTypes(pkg, fix) {
|
|
2356
|
+
const result = emptyCustomResult();
|
|
2357
|
+
if (pkg.types === void 0) return result;
|
|
2358
|
+
const exports = pkg.exports;
|
|
2359
|
+
if (!exports || typeof exports !== "object" || !hasTypesInExports(exports)) return result;
|
|
2360
|
+
if (fix) {
|
|
2361
|
+
delete pkg.types;
|
|
2362
|
+
console.warn(chalk23.yellow('Publint [custom]: removed redundant root "types" field (already defined in "exports")'));
|
|
2363
|
+
result.modified = true;
|
|
2364
|
+
} else {
|
|
2365
|
+
console.warn(chalk23.yellow('Publint [custom]: root "types" field is redundant when "exports" defines types (use --fix to remove)'));
|
|
2366
|
+
}
|
|
2367
|
+
result.warnings++;
|
|
2368
|
+
return result;
|
|
2369
|
+
}
|
|
2370
|
+
function customPubLint(pkg, fix = false, exclude = /* @__PURE__ */ new Set()) {
|
|
2371
|
+
const result = emptyCustomResult();
|
|
2372
|
+
if (!exclude.has("files")) mergeResults(result, checkFiles(pkg, fix));
|
|
2373
|
+
if (!exclude.has("source")) mergeResults(result, checkExportsSource(pkg, fix));
|
|
2374
|
+
if (!exclude.has("rootSource")) mergeResults(result, checkRootSource(pkg, fix));
|
|
2375
|
+
if (!exclude.has("main")) mergeResults(result, migrateFieldToExports(pkg, "main", "default", fix));
|
|
2376
|
+
if (!exclude.has("types")) mergeResults(result, migrateFieldToExports(pkg, "types", "types", fix));
|
|
2377
|
+
if (!exclude.has("module")) mergeResults(result, migrateFieldToExports(pkg, "module", "default", fix));
|
|
2378
|
+
if (!exclude.has("importToDefault")) mergeResults(result, checkImportToDefault(pkg, fix));
|
|
2379
|
+
if (!exclude.has("rootTypes")) mergeResults(result, checkRootTypes(pkg, fix));
|
|
2380
|
+
if (!exclude.has("sideEffects")) mergeResults(result, checkSideEffects(pkg));
|
|
2381
|
+
if (!exclude.has("resolutions")) mergeResults(result, checkResolutions(pkg));
|
|
2382
|
+
return [result.errors, result.warnings, result.modified];
|
|
2383
|
+
}
|
|
2384
|
+
var ALWAYS_INCLUDED_PATTERNS = [
|
|
2385
|
+
"package.json",
|
|
2386
|
+
"README",
|
|
2387
|
+
"README.*",
|
|
2388
|
+
"LICENCE",
|
|
2389
|
+
"LICENCE.*",
|
|
2390
|
+
"LICENSE",
|
|
2391
|
+
"LICENSE.*",
|
|
2392
|
+
"CHANGELOG",
|
|
2393
|
+
"CHANGELOG.*"
|
|
2394
|
+
];
|
|
2395
|
+
async function resolvePackFiles(pkgDir, filesField) {
|
|
2396
|
+
const patterns = [...ALWAYS_INCLUDED_PATTERNS];
|
|
2397
|
+
if (filesField) {
|
|
2398
|
+
for (const pattern of filesField) {
|
|
2399
|
+
if (pattern.startsWith("!")) {
|
|
2400
|
+
patterns.push(pattern);
|
|
2401
|
+
} else {
|
|
2402
|
+
patterns.push(pattern, `${pattern}/**`);
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
const matched = await glob3(patterns, {
|
|
2407
|
+
cwd: pkgDir,
|
|
2408
|
+
nodir: true,
|
|
2409
|
+
dot: false
|
|
2410
|
+
});
|
|
2411
|
+
const files = await Promise.all(
|
|
2412
|
+
matched.map(async (rel) => {
|
|
2413
|
+
const abs = path4.join(pkgDir, rel);
|
|
2414
|
+
const data = await fs3.readFile(abs, "utf8").catch(() => "");
|
|
2415
|
+
return { name: path4.join(pkgDir, rel), data };
|
|
2416
|
+
})
|
|
2417
|
+
);
|
|
2418
|
+
return files;
|
|
2419
|
+
}
|
|
2420
|
+
async function runPublintLibrary(pkgDir, pkg, strict, pack) {
|
|
2421
|
+
const { publint: publint2 } = await import("publint");
|
|
2422
|
+
let packOption = false;
|
|
2423
|
+
if (pack) {
|
|
2424
|
+
const files = await resolvePackFiles(pkgDir, pkg.files);
|
|
2425
|
+
packOption = { files };
|
|
2426
|
+
}
|
|
2427
|
+
const { messages } = await publint2({
|
|
2428
|
+
level: "suggestion",
|
|
2429
|
+
pack: packOption,
|
|
2430
|
+
pkgDir,
|
|
2431
|
+
strict
|
|
2432
|
+
});
|
|
2433
|
+
const { formatMessage } = await import("publint/utils");
|
|
2434
|
+
for (const message of messages) {
|
|
2435
|
+
switch (message.type) {
|
|
2436
|
+
case "error": {
|
|
2437
|
+
console.error(chalk23.red(`[${message.code}] ${formatMessage(message, pkg)}`));
|
|
2438
|
+
break;
|
|
2439
|
+
}
|
|
2440
|
+
case "warning": {
|
|
2441
|
+
console.warn(chalk23.yellow(`[${message.code}] ${formatMessage(message, pkg)}`));
|
|
2442
|
+
break;
|
|
2443
|
+
}
|
|
2444
|
+
default: {
|
|
2445
|
+
console.log(chalk23.white(`[${message.code}] ${formatMessage(message, pkg)}`));
|
|
2446
|
+
break;
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
return {
|
|
2451
|
+
errors: messages.filter((message) => message.type === "error").length,
|
|
2452
|
+
total: messages.length
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2455
|
+
var packagePublint = async ({
|
|
2456
|
+
exclude = /* @__PURE__ */ new Set(),
|
|
2457
|
+
fix = false,
|
|
2458
|
+
pack = true,
|
|
2459
|
+
pkgDir: pkgDirParam,
|
|
2460
|
+
strict = true,
|
|
2461
|
+
verbose: _verbose = false
|
|
2462
|
+
} = {}) => {
|
|
2463
|
+
const pkgDir = pkgDirParam ?? INIT_CWD();
|
|
2464
|
+
const sortedPkg = sortPackageJson(await fs3.readFile(`${pkgDir}/package.json`, "utf8"));
|
|
2465
|
+
await fs3.writeFile(`${pkgDir}/package.json`, sortedPkg);
|
|
2466
|
+
const pkg = JSON.parse(await fs3.readFile(`${pkgDir}/package.json`, "utf8"));
|
|
2467
|
+
const effectiveExclude = pkg.private ? /* @__PURE__ */ new Set([...exclude, ...PUBLISH_ONLY_CHECKS]) : exclude;
|
|
2468
|
+
console.log(chalk23.green(`Publint: ${String(pkg.name)}${pkg.private ? chalk23.gray(" (private)") : ""}`));
|
|
2469
|
+
console.log(chalk23.gray(pkgDir));
|
|
2470
|
+
let libraryErrors = 0;
|
|
2471
|
+
if (!effectiveExclude.has("publint")) {
|
|
2472
|
+
const library = await runPublintLibrary(pkgDir, pkg, strict, pack);
|
|
2473
|
+
libraryErrors = library.errors;
|
|
2474
|
+
}
|
|
2475
|
+
const [errorCount, _warningCount, modified] = customPubLint(pkg, fix, effectiveExclude);
|
|
2476
|
+
if (modified) {
|
|
2477
|
+
const sorted = sortPackageJson(JSON.stringify(pkg, null, 2));
|
|
2478
|
+
await fs3.writeFile(`${pkgDir}/package.json`, sorted);
|
|
2479
|
+
}
|
|
2480
|
+
return libraryErrors + errorCount;
|
|
2481
|
+
};
|
|
2482
|
+
|
|
2483
|
+
// src/actions/package-lint.ts
|
|
2484
|
+
import {
|
|
2485
|
+
existsSync as existsSync12,
|
|
2486
|
+
readFileSync as readFileSync14,
|
|
2487
|
+
writeFileSync as writeFileSync9
|
|
2488
|
+
} from "fs";
|
|
2489
|
+
import PATH14 from "path";
|
|
2490
|
+
import chalk24 from "chalk";
|
|
2491
|
+
import picomatch from "picomatch";
|
|
2492
|
+
import semver2 from "semver";
|
|
2493
|
+
function emptyResult() {
|
|
2494
|
+
return {
|
|
2495
|
+
errors: [],
|
|
2496
|
+
fixable: [],
|
|
2497
|
+
warnings: []
|
|
2498
|
+
};
|
|
2499
|
+
}
|
|
2500
|
+
function readRootPackageJson(cwd) {
|
|
2501
|
+
const raw = readFileSync14(PATH14.resolve(cwd, "package.json"), "utf8");
|
|
2502
|
+
return JSON.parse(raw);
|
|
2503
|
+
}
|
|
2504
|
+
function writeRootPackageJson(cwd, pkg) {
|
|
2505
|
+
const path5 = PATH14.resolve(cwd, "package.json");
|
|
2506
|
+
writeFileSync9(path5, `${JSON.stringify(pkg, null, 2)}
|
|
2507
|
+
`, "utf8");
|
|
2508
|
+
}
|
|
2509
|
+
function readPnpmWorkspaceGlobs(cwd) {
|
|
2510
|
+
const wsPath = PATH14.resolve(cwd, "pnpm-workspace.yaml");
|
|
2511
|
+
if (!existsSync12(wsPath)) return void 0;
|
|
2512
|
+
const raw = readFileSync14(wsPath, "utf8");
|
|
2513
|
+
const globs = [];
|
|
2514
|
+
let inPackages = false;
|
|
2515
|
+
for (const line of raw.split("\n")) {
|
|
2516
|
+
if (/^packages\s*:/.test(line)) {
|
|
2517
|
+
inPackages = true;
|
|
2518
|
+
continue;
|
|
2519
|
+
}
|
|
2520
|
+
if (inPackages) {
|
|
2521
|
+
const match = /^\s+-\s+['"]?([^'"]+)['"]?\s*$/.exec(line);
|
|
2522
|
+
if (match) {
|
|
2523
|
+
globs.push(match[1]);
|
|
2524
|
+
} else if (/^\S/.test(line) && line.trim() !== "") {
|
|
2525
|
+
break;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
return globs.length > 0 ? globs : void 0;
|
|
2530
|
+
}
|
|
2531
|
+
function isMonorepo(pkg, cwd) {
|
|
2532
|
+
const workspaces = pkg.workspaces;
|
|
2533
|
+
if (Array.isArray(workspaces) && workspaces.length > 0) return true;
|
|
2534
|
+
return readPnpmWorkspaceGlobs(cwd) !== void 0;
|
|
2535
|
+
}
|
|
2536
|
+
function checkPackagesFolder(workspaces) {
|
|
2537
|
+
const result = emptyResult();
|
|
2538
|
+
for (const { location, name } of workspaces) {
|
|
2539
|
+
if (location === ".") continue;
|
|
2540
|
+
if (!location.startsWith("packages/") && !location.startsWith("packages\\")) {
|
|
2541
|
+
result.errors.push(`${name} (${location}) is not inside a packages/ folder`);
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
return result;
|
|
2545
|
+
}
|
|
2546
|
+
function checkRootPrivate(pkg) {
|
|
2547
|
+
const result = emptyResult();
|
|
2548
|
+
if (!pkg.private) {
|
|
2549
|
+
result.fixable.push("Root package.json must be private to prevent accidental publishing");
|
|
2550
|
+
}
|
|
2551
|
+
return result;
|
|
2552
|
+
}
|
|
2553
|
+
function fixRootPrivate(cwd, pkg) {
|
|
2554
|
+
pkg.private = true;
|
|
2555
|
+
writeRootPackageJson(cwd, pkg);
|
|
2556
|
+
console.log(chalk24.green(' \u2714 Fixed: set "private": true in root package.json'));
|
|
2557
|
+
}
|
|
2558
|
+
function checkNoPublishConfigOnPrivate(pkg) {
|
|
2559
|
+
const result = emptyResult();
|
|
2560
|
+
if (pkg.private && pkg.publishConfig) {
|
|
2561
|
+
result.fixable.push("Root package.json has publishConfig but is private \u2014 publishConfig is unnecessary");
|
|
2562
|
+
}
|
|
2563
|
+
return result;
|
|
2564
|
+
}
|
|
2565
|
+
function fixNoPublishConfigOnPrivate(cwd, pkg) {
|
|
2566
|
+
delete pkg.publishConfig;
|
|
2567
|
+
writeRootPackageJson(cwd, pkg);
|
|
2568
|
+
console.log(chalk24.green(" \u2714 Fixed: removed publishConfig from private root package.json"));
|
|
2569
|
+
}
|
|
2570
|
+
function checkNoPackageManagerInWorkspaces(cwd, workspaces) {
|
|
2571
|
+
const result = emptyResult();
|
|
2572
|
+
for (const { location, name } of workspaces) {
|
|
2573
|
+
if (location === ".") continue;
|
|
2574
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2575
|
+
try {
|
|
2576
|
+
const raw = readFileSync14(pkgPath, "utf8");
|
|
2577
|
+
const pkg = JSON.parse(raw);
|
|
2578
|
+
if (pkg.packageManager) {
|
|
2579
|
+
result.fixable.push(`${name} (${location}) has a packageManager field \u2014 only the root should define this`);
|
|
2580
|
+
}
|
|
2581
|
+
} catch {
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
return result;
|
|
2585
|
+
}
|
|
2586
|
+
function fixNoPackageManagerInWorkspaces(cwd, _pkg, workspaces) {
|
|
2587
|
+
for (const { location } of workspaces) {
|
|
2588
|
+
if (location === ".") continue;
|
|
2589
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2590
|
+
try {
|
|
2591
|
+
const raw = readFileSync14(pkgPath, "utf8");
|
|
2592
|
+
const pkg = JSON.parse(raw);
|
|
2593
|
+
if (pkg.packageManager) {
|
|
2594
|
+
delete pkg.packageManager;
|
|
2595
|
+
writeFileSync9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
2596
|
+
`, "utf8");
|
|
2597
|
+
console.log(chalk24.green(` \u2714 Fixed: removed packageManager from ${location}/package.json`));
|
|
2598
|
+
}
|
|
2599
|
+
} catch {
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
function checkWorkspacesFieldPlacement(cwd, pm, workspaces) {
|
|
2604
|
+
const result = emptyResult();
|
|
2605
|
+
for (const { location, name } of workspaces) {
|
|
2606
|
+
if (pm === "pnpm" ? true : location !== ".") {
|
|
2607
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2608
|
+
try {
|
|
2609
|
+
const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
|
|
2610
|
+
if (pkg.workspaces) {
|
|
2611
|
+
const label = location === "." ? "Root" : `${name} (${location})`;
|
|
2612
|
+
const reason = pm === "pnpm" ? "pnpm uses pnpm-workspace.yaml instead" : "only the root should define workspaces";
|
|
2613
|
+
result.fixable.push(`${label} has a workspaces field \u2014 ${reason}`);
|
|
2614
|
+
}
|
|
2615
|
+
} catch {
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
return result;
|
|
2620
|
+
}
|
|
2621
|
+
function fixWorkspacesFieldPlacement(cwd, pm, workspaces) {
|
|
2622
|
+
for (const { location } of workspaces) {
|
|
2623
|
+
if (pm === "pnpm" ? true : location !== ".") {
|
|
2624
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2625
|
+
try {
|
|
2626
|
+
const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
|
|
2627
|
+
if (pkg.workspaces) {
|
|
2628
|
+
delete pkg.workspaces;
|
|
2629
|
+
writeFileSync9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
2630
|
+
`, "utf8");
|
|
2631
|
+
const label = location === "." ? "root" : location;
|
|
2632
|
+
console.log(chalk24.green(` \u2714 Fixed: removed workspaces from ${label}/package.json`));
|
|
2633
|
+
}
|
|
2634
|
+
} catch {
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
function checkWorkspaceGlobCoverage(pkg, cwd, pm, workspaces) {
|
|
2640
|
+
const result = emptyResult();
|
|
2641
|
+
const globs = pm === "pnpm" ? readPnpmWorkspaceGlobs(cwd) ?? [] : Array.isArray(pkg.workspaces) ? pkg.workspaces : [];
|
|
2642
|
+
if (globs.length === 0) {
|
|
2643
|
+
const source = pm === "pnpm" ? "pnpm-workspace.yaml" : "root package.json workspaces";
|
|
2644
|
+
result.errors.push(`No workspace globs found in ${source}`);
|
|
2645
|
+
return result;
|
|
2646
|
+
}
|
|
2647
|
+
const matchers = globs.map((glob4) => picomatch(glob4));
|
|
2648
|
+
const isMatch = (location) => matchers.some((m) => m(location));
|
|
2649
|
+
for (const { location, name } of workspaces) {
|
|
2650
|
+
if (location === ".") continue;
|
|
2651
|
+
if (!isMatch(location)) {
|
|
2652
|
+
const source = pm === "pnpm" ? "pnpm-workspace.yaml" : "root package.json workspaces";
|
|
2653
|
+
result.errors.push(`${name} (${location}) is not matched by any glob in ${source}`);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
return result;
|
|
2657
|
+
}
|
|
2658
|
+
function logResults(label, result, fix) {
|
|
2659
|
+
let errors = 0;
|
|
2660
|
+
let fixed = 0;
|
|
2661
|
+
for (const error of result.errors) {
|
|
2662
|
+
console.log(chalk24.red(` \u2717 ${error}`));
|
|
2663
|
+
errors++;
|
|
2664
|
+
}
|
|
2665
|
+
for (const fixable of result.fixable) {
|
|
2666
|
+
if (fix) {
|
|
2667
|
+
fixed++;
|
|
2668
|
+
} else {
|
|
2669
|
+
console.log(chalk24.red(` \u2717 ${fixable} (fixable)`));
|
|
2670
|
+
errors++;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
for (const warning of result.warnings) {
|
|
2674
|
+
console.log(chalk24.yellow(` \u26A0 ${warning}`));
|
|
2675
|
+
}
|
|
2676
|
+
if (errors === 0 && fixed === 0 && result.warnings.length === 0) {
|
|
2677
|
+
console.log(chalk24.green(` \u2713 ${label}`));
|
|
2678
|
+
}
|
|
2679
|
+
return { errors, fixed };
|
|
2680
|
+
}
|
|
2681
|
+
function runChecks(entries, cwd, pkg, fix) {
|
|
2682
|
+
let totalErrors = 0;
|
|
2683
|
+
let totalFixed = 0;
|
|
2684
|
+
for (const entry of entries) {
|
|
2685
|
+
const result = entry.check();
|
|
2686
|
+
const log = logResults(entry.label, result, fix);
|
|
2687
|
+
if (fix && entry.fix && result.fixable.length > 0) {
|
|
2688
|
+
entry.fix(cwd, pkg);
|
|
2689
|
+
}
|
|
2690
|
+
totalErrors += log.errors;
|
|
2691
|
+
totalFixed += log.fixed;
|
|
2692
|
+
}
|
|
2693
|
+
return { errors: totalErrors, fixed: totalFixed };
|
|
2694
|
+
}
|
|
2695
|
+
function checkVoltaOnlyInRoot(cwd, workspaces) {
|
|
2696
|
+
const result = emptyResult();
|
|
2697
|
+
for (const { location, name } of workspaces) {
|
|
2698
|
+
if (location === ".") continue;
|
|
2699
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2700
|
+
try {
|
|
2701
|
+
const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
|
|
2702
|
+
if (pkg.volta) {
|
|
2703
|
+
result.fixable.push(`${name} (${location}) has a volta field \u2014 only the root should define this`);
|
|
2704
|
+
}
|
|
2705
|
+
} catch {
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
return result;
|
|
2709
|
+
}
|
|
2710
|
+
function fixVoltaOnlyInRoot(cwd, _pkg, workspaces) {
|
|
2711
|
+
for (const { location } of workspaces) {
|
|
2712
|
+
if (location === ".") continue;
|
|
2713
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2714
|
+
try {
|
|
2715
|
+
const raw = readFileSync14(pkgPath, "utf8");
|
|
2716
|
+
const pkg = JSON.parse(raw);
|
|
2717
|
+
if (pkg.volta) {
|
|
2718
|
+
delete pkg.volta;
|
|
2719
|
+
writeFileSync9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
2720
|
+
`, "utf8");
|
|
2721
|
+
console.log(chalk24.green(` \u2714 Fixed: removed volta from ${location}/package.json`));
|
|
2722
|
+
}
|
|
2723
|
+
} catch {
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
function isTerminalPackage(pkg) {
|
|
2728
|
+
return pkg.private === true;
|
|
2729
|
+
}
|
|
2730
|
+
function checkEnginesOnlyInNonTerminal(cwd, workspaces) {
|
|
2731
|
+
const result = emptyResult();
|
|
2732
|
+
const rootPkg = JSON.parse(readFileSync14(PATH14.resolve(cwd, "package.json"), "utf8"));
|
|
2733
|
+
if (rootPkg.engines) {
|
|
2734
|
+
result.fixable.push("Root package.json has engines \u2014 terminal packages should not declare engines (use volta instead)");
|
|
2735
|
+
}
|
|
2736
|
+
for (const { location, name } of workspaces) {
|
|
2737
|
+
if (location === ".") continue;
|
|
2738
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2739
|
+
try {
|
|
2740
|
+
const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
|
|
2741
|
+
if (isTerminalPackage(pkg) && pkg.engines) {
|
|
2742
|
+
result.fixable.push(`${name} (${location}) is terminal (private) but has engines \u2014 terminal packages should not declare engines`);
|
|
2743
|
+
}
|
|
2744
|
+
if (!isTerminalPackage(pkg) && !pkg.engines) {
|
|
2745
|
+
result.fixable.push(`${name} (${location}) is a library but has no engines field`);
|
|
2746
|
+
}
|
|
2747
|
+
} catch {
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
return result;
|
|
2751
|
+
}
|
|
2752
|
+
function fixEnginesOnlyInNonTerminal(cwd, _pkg, workspaces) {
|
|
2753
|
+
const rootPath = PATH14.resolve(cwd, "package.json");
|
|
2754
|
+
const rootRaw = readFileSync14(rootPath, "utf8");
|
|
2755
|
+
const rootPkg = JSON.parse(rootRaw);
|
|
2756
|
+
if (rootPkg.engines) {
|
|
2757
|
+
delete rootPkg.engines;
|
|
2758
|
+
writeFileSync9(rootPath, `${JSON.stringify(rootPkg, null, 2)}
|
|
2759
|
+
`, "utf8");
|
|
2760
|
+
console.log(chalk24.green(" \u2714 Fixed: removed engines from root package.json"));
|
|
2761
|
+
}
|
|
2762
|
+
const enginesTemplate = resolveEnginesTemplate(cwd, workspaces);
|
|
2763
|
+
for (const { location } of workspaces) {
|
|
2764
|
+
if (location === ".") continue;
|
|
2765
|
+
const pkgPath = PATH14.resolve(cwd, location, "package.json");
|
|
2766
|
+
try {
|
|
2767
|
+
const raw = readFileSync14(pkgPath, "utf8");
|
|
2768
|
+
const pkg = JSON.parse(raw);
|
|
2769
|
+
if (isTerminalPackage(pkg) && pkg.engines) {
|
|
2770
|
+
delete pkg.engines;
|
|
2771
|
+
writeFileSync9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
2772
|
+
`, "utf8");
|
|
2773
|
+
console.log(chalk24.green(` \u2714 Fixed: removed engines from ${location}/package.json`));
|
|
2774
|
+
}
|
|
2775
|
+
if (!isTerminalPackage(pkg) && !pkg.engines && enginesTemplate) {
|
|
2776
|
+
pkg.engines = enginesTemplate;
|
|
2777
|
+
writeFileSync9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
2778
|
+
`, "utf8");
|
|
2779
|
+
console.log(chalk24.green(` \u2714 Fixed: added engines to ${location}/package.json`));
|
|
2780
|
+
}
|
|
2781
|
+
} catch {
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
function resolveEnginesTemplate(cwd, workspaces) {
|
|
2786
|
+
for (const { location } of workspaces) {
|
|
2787
|
+
if (location === ".") continue;
|
|
2788
|
+
try {
|
|
2789
|
+
const pkg = JSON.parse(readFileSync14(PATH14.resolve(cwd, location, "package.json"), "utf8"));
|
|
2790
|
+
if (!isTerminalPackage(pkg) && pkg.engines) {
|
|
2791
|
+
return pkg.engines;
|
|
2792
|
+
}
|
|
2793
|
+
} catch {
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
return void 0;
|
|
2797
|
+
}
|
|
2798
|
+
function checkVersionsIncludeLts(cwd, workspaces) {
|
|
2799
|
+
const result = emptyResult();
|
|
2800
|
+
const toolVersions = {
|
|
2801
|
+
node: latestVersions.node,
|
|
2802
|
+
npm: latestVersions.npm,
|
|
2803
|
+
pnpm: latestVersions.pnpm,
|
|
2804
|
+
yarn: latestVersions.yarn
|
|
2805
|
+
};
|
|
2806
|
+
for (const { location, name } of workspaces) {
|
|
2807
|
+
const pkgPath = location === "." ? PATH14.resolve(cwd, "package.json") : PATH14.resolve(cwd, location, "package.json");
|
|
2808
|
+
try {
|
|
2809
|
+
const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
|
|
2810
|
+
const label = location === "." ? "root" : `${name} (${location})`;
|
|
2811
|
+
const engines = pkg.engines;
|
|
2812
|
+
if (engines) {
|
|
2813
|
+
for (const [tool, range] of Object.entries(engines)) {
|
|
2814
|
+
const latest = toolVersions[tool];
|
|
2815
|
+
if (latest && !semver2.satisfies(latest, range)) {
|
|
2816
|
+
result.errors.push(
|
|
2817
|
+
`${label} engines.${tool} "${range}" does not include latest ${tool === "node" ? "LTS " : ""}version ${latest}`
|
|
2818
|
+
);
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
const volta = pkg.volta;
|
|
2823
|
+
if (volta) {
|
|
2824
|
+
for (const [tool, pinnedVersion] of Object.entries(volta)) {
|
|
2825
|
+
const latest = toolVersions[tool];
|
|
2826
|
+
if (latest && semver2.lt(pinnedVersion, latest)) {
|
|
2827
|
+
result.warnings.push(
|
|
2828
|
+
`${label} volta.${tool} "${pinnedVersion}" is older than latest ${tool === "node" ? "LTS " : ""}version ${latest}`
|
|
2829
|
+
);
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
} catch {
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
return result;
|
|
2837
|
+
}
|
|
2838
|
+
function logSummary(errors, fixed) {
|
|
2839
|
+
if (fixed > 0) {
|
|
2840
|
+
console.log(chalk24.green(`
|
|
2841
|
+
Fixed ${fixed} issue(s)`));
|
|
2842
|
+
}
|
|
2843
|
+
if (errors > 0) {
|
|
2844
|
+
console.log(chalk24.red(`
|
|
2845
|
+
${errors} error(s) found`));
|
|
2846
|
+
} else if (fixed === 0) {
|
|
2847
|
+
console.log(chalk24.green("\n All checks passed"));
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
function packageLintMonorepo(fix = false) {
|
|
2851
|
+
const cwd = INIT_CWD();
|
|
2852
|
+
let pkg;
|
|
2853
|
+
try {
|
|
2854
|
+
pkg = readRootPackageJson(cwd);
|
|
2855
|
+
} catch {
|
|
2856
|
+
console.error(chalk24.red("Could not read package.json"));
|
|
2857
|
+
return 1;
|
|
2858
|
+
}
|
|
2859
|
+
if (!isMonorepo(pkg, cwd)) {
|
|
2860
|
+
console.log(chalk24.gray("Not a monorepo \u2014 skipping repo lint checks"));
|
|
2861
|
+
return 0;
|
|
2862
|
+
}
|
|
2863
|
+
console.log(chalk24.green("Repo Lint"));
|
|
2864
|
+
const pm = detectPackageManager();
|
|
2865
|
+
const workspaces = getPackageManager().listWorkspaces();
|
|
2866
|
+
const internalDepCheck = pm === "pnpm" ? {
|
|
2867
|
+
check: () => checkWorkspaceProtocol(cwd, workspaces),
|
|
2868
|
+
fix: () => fixWorkspaceProtocol(cwd, workspaces),
|
|
2869
|
+
label: "Internal deps/devDeps use workspace: protocol"
|
|
2870
|
+
} : {
|
|
2871
|
+
check: () => checkInternalDepVersions(cwd, workspaces),
|
|
2872
|
+
fix: () => fixInternalDepVersions(cwd, workspaces),
|
|
2873
|
+
label: "Internal deps/devDeps use correct version ranges"
|
|
2874
|
+
};
|
|
2875
|
+
const checks2 = [
|
|
2876
|
+
{
|
|
2877
|
+
check: () => checkRootPrivate(pkg),
|
|
2878
|
+
fix: fixRootPrivate,
|
|
2879
|
+
label: "Root package is private"
|
|
2880
|
+
},
|
|
2881
|
+
{
|
|
2882
|
+
check: () => checkNoPublishConfigOnPrivate(pkg),
|
|
2883
|
+
fix: fixNoPublishConfigOnPrivate,
|
|
2884
|
+
label: "No publishConfig on private root"
|
|
2885
|
+
},
|
|
2886
|
+
{ check: () => checkPackagesFolder(workspaces), label: "All packages are in packages/ folder" },
|
|
2887
|
+
{
|
|
2888
|
+
check: () => checkWorkspacesFieldPlacement(cwd, pm, workspaces),
|
|
2889
|
+
fix: () => fixWorkspacesFieldPlacement(cwd, pm, workspaces),
|
|
2890
|
+
label: pm === "pnpm" ? "No workspaces field in package.json (use pnpm-workspace.yaml)" : "Workspaces field only in root package.json"
|
|
2891
|
+
},
|
|
2892
|
+
{
|
|
2893
|
+
check: () => checkWorkspaceGlobCoverage(pkg, cwd, pm, workspaces),
|
|
2894
|
+
label: "Workspace globs cover all packages"
|
|
2895
|
+
},
|
|
2896
|
+
{
|
|
2897
|
+
check: () => checkNoPackageManagerInWorkspaces(cwd, workspaces),
|
|
2898
|
+
fix: () => fixNoPackageManagerInWorkspaces(cwd, pkg, workspaces),
|
|
2899
|
+
label: "No packageManager in workspace packages"
|
|
2900
|
+
},
|
|
2901
|
+
{
|
|
2902
|
+
check: () => checkVoltaOnlyInRoot(cwd, workspaces),
|
|
2903
|
+
fix: () => fixVoltaOnlyInRoot(cwd, pkg, workspaces),
|
|
2904
|
+
label: "Volta only in root package.json"
|
|
2905
|
+
},
|
|
2906
|
+
{
|
|
2907
|
+
check: () => checkEnginesOnlyInNonTerminal(cwd, workspaces),
|
|
2908
|
+
fix: () => fixEnginesOnlyInNonTerminal(cwd, pkg, workspaces),
|
|
2909
|
+
label: "Engines only in non-terminal (library) packages"
|
|
2910
|
+
},
|
|
2911
|
+
{
|
|
2912
|
+
check: () => checkVersionsIncludeLts(cwd, workspaces),
|
|
2913
|
+
label: "Engine/volta versions include latest LTS"
|
|
2914
|
+
},
|
|
2915
|
+
{
|
|
2916
|
+
check: () => checkVersionConsistency(cwd, pkg, workspaces),
|
|
2917
|
+
fix: () => fixVersionConsistency(cwd, pkg, writeRootPackageJson, workspaces),
|
|
2918
|
+
label: "Consistent versions across packages"
|
|
2919
|
+
},
|
|
2920
|
+
internalDepCheck,
|
|
2921
|
+
{
|
|
2922
|
+
check: () => checkInternalPeerVersions(cwd, workspaces),
|
|
2923
|
+
fix: () => fixInternalPeerVersions(cwd, workspaces),
|
|
2924
|
+
label: "Internal peerDeps use semver ranges (not workspace: protocol)"
|
|
2925
|
+
}
|
|
2926
|
+
];
|
|
2927
|
+
const { errors, fixed } = runChecks(checks2, cwd, pkg, fix);
|
|
2928
|
+
logSummary(errors, fixed);
|
|
2929
|
+
if (fix && fixed > 0) {
|
|
2930
|
+
runInstall();
|
|
2931
|
+
}
|
|
2932
|
+
return errors > 0 ? 1 : 0;
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
// src/actions/packman/clean.ts
|
|
2936
|
+
import {
|
|
2937
|
+
existsSync as existsSync18,
|
|
2938
|
+
rmSync as rmSync5,
|
|
2939
|
+
writeFileSync as writeFileSync14
|
|
2940
|
+
} from "fs";
|
|
2941
|
+
import PATH19 from "path";
|
|
2942
|
+
import chalk30 from "chalk";
|
|
2943
|
+
|
|
2944
|
+
// src/actions/packman/convert.ts
|
|
2945
|
+
import {
|
|
2946
|
+
existsSync as existsSync17,
|
|
2947
|
+
readdirSync as readdirSync8,
|
|
2948
|
+
readFileSync as readFileSync19,
|
|
2949
|
+
statSync as statSync4
|
|
2950
|
+
} from "fs";
|
|
2951
|
+
import PATH18 from "path";
|
|
2952
|
+
import chalk29 from "chalk";
|
|
2953
|
+
|
|
2954
|
+
// src/actions/packman/convertToPnpm.ts
|
|
2955
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
2956
|
+
import {
|
|
2957
|
+
existsSync as existsSync15,
|
|
2958
|
+
mkdirSync as mkdirSync5,
|
|
2959
|
+
readFileSync as readFileSync17,
|
|
2960
|
+
rmSync as rmSync3,
|
|
2961
|
+
writeFileSync as writeFileSync12
|
|
2962
|
+
} from "fs";
|
|
2963
|
+
import PATH16 from "path";
|
|
2964
|
+
import chalk27 from "chalk";
|
|
2965
|
+
|
|
2966
|
+
// src/actions/packman/rewriteScripts.ts
|
|
2967
|
+
function rewriteYarnToPnpm(script) {
|
|
2968
|
+
let result = script;
|
|
2969
|
+
result = result.replaceAll(/\byarn workspace (\S+) run /g, "pnpm --filter $1 run ");
|
|
2970
|
+
result = result.replaceAll(/\byarn workspace (\S+) (package-\S+)/g, "pnpm --filter $1 run $2");
|
|
2971
|
+
result = result.replaceAll(/\byarn workspaces foreach\s+(?:[^\s]*\s+)*run /g, "pnpm -r run ");
|
|
2972
|
+
result = result.replaceAll(/\byarn workspaces foreach --all version (\S+) --deferred/g, "pnpm -r exec npm version $1 --no-git-tag-version");
|
|
2973
|
+
result = result.replaceAll(/\byarn version apply --all/g, 'echo "versions applied"');
|
|
2974
|
+
result = result.replaceAll(/\byarn xy\b/g, "pnpm xy");
|
|
2975
|
+
result = result.replaceAll(/\byarn add\b/g, "pnpm add");
|
|
2976
|
+
result = result.replaceAll(/\byarn remove\b/g, "pnpm remove");
|
|
2977
|
+
result = result.replaceAll(/\byarn install\b/g, "pnpm install");
|
|
2978
|
+
result = result.replaceAll(/\byarn dedupe\b/g, "pnpm dedupe");
|
|
2979
|
+
result = result.replaceAll(/\byarn outdated\b/g, "pnpm outdated");
|
|
2980
|
+
result = result.replaceAll(/\byarn run\b/g, "pnpm run");
|
|
2981
|
+
result = result.replaceAll(/\byarn rimraf\b/g, "rimraf");
|
|
2982
|
+
result = result.replaceAll(/\byarn npm\b/g, "npm");
|
|
2983
|
+
result = result.replaceAll(/\byarn\b(?![@/.])/g, "pnpm");
|
|
2984
|
+
return result;
|
|
2985
|
+
}
|
|
2986
|
+
function rewritePnpmToYarn(script) {
|
|
2987
|
+
let result = script;
|
|
2988
|
+
result = result.replaceAll(/\bpnpm --filter (\S+) run /g, "yarn workspace $1 run ");
|
|
2989
|
+
result = result.replaceAll(/\bpnpm -r run /g, "yarn workspaces foreach -Apt run ");
|
|
2990
|
+
result = result.replaceAll(/\bpnpm -r exec npm version (\S+) --no-git-tag-version/g, "yarn workspaces foreach --all version $1 --deferred");
|
|
2991
|
+
result = result.replaceAll(/\bpnpm xy\b/g, "yarn xy");
|
|
2992
|
+
result = result.replaceAll(/\bpnpm add\b/g, "yarn add");
|
|
2993
|
+
result = result.replaceAll(/\bpnpm remove\b/g, "yarn remove");
|
|
2994
|
+
result = result.replaceAll(/\bpnpm install\b/g, "yarn install");
|
|
2995
|
+
result = result.replaceAll(/\bpnpm dedupe\b/g, "yarn dedupe");
|
|
2996
|
+
result = result.replaceAll(/\bpnpm outdated\b/g, "yarn outdated");
|
|
2997
|
+
result = result.replaceAll(/\bpnpm run\b/g, "yarn run");
|
|
2998
|
+
result = result.replaceAll(/\bpnpm\b(?![@/.])/g, "yarn");
|
|
2999
|
+
return result;
|
|
3000
|
+
}
|
|
3001
|
+
function rewriteScript(script, direction) {
|
|
3002
|
+
return direction === "yarn-to-pnpm" ? rewriteYarnToPnpm(script) : rewritePnpmToYarn(script);
|
|
3003
|
+
}
|
|
3004
|
+
function rewriteScriptsInPackageJson(pkg, direction) {
|
|
3005
|
+
const scripts = pkg.scripts;
|
|
3006
|
+
if (!scripts) return pkg;
|
|
3007
|
+
const rewritten = {};
|
|
3008
|
+
for (const [name, script] of Object.entries(scripts)) {
|
|
3009
|
+
rewritten[name] = rewriteScript(script, direction);
|
|
3010
|
+
}
|
|
3011
|
+
return { ...pkg, scripts: rewritten };
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
// src/actions/packman/rewriteSourceImports.ts
|
|
3015
|
+
import {
|
|
3016
|
+
existsSync as existsSync13,
|
|
3017
|
+
readFileSync as readFileSync15,
|
|
3018
|
+
writeFileSync as writeFileSync10
|
|
3019
|
+
} from "fs";
|
|
3020
|
+
import chalk25 from "chalk";
|
|
3021
|
+
import { globSync as globSync2 } from "glob";
|
|
3022
|
+
var IMPORT_SWAP_MAP = {
|
|
3023
|
+
"yarn-to-pnpm": [
|
|
3024
|
+
["@xylabs/ts-scripts-yarn3", "@xylabs/ts-scripts-pnpm"],
|
|
3025
|
+
["@xylabs/ts-scripts-react-yarn3", "@xylabs/ts-scripts-react-pnpm"]
|
|
3026
|
+
],
|
|
3027
|
+
"pnpm-to-yarn": [
|
|
3028
|
+
["@xylabs/ts-scripts-pnpm", "@xylabs/ts-scripts-yarn3"],
|
|
3029
|
+
["@xylabs/ts-scripts-react-pnpm", "@xylabs/ts-scripts-react-yarn3"]
|
|
3030
|
+
]
|
|
3031
|
+
};
|
|
3032
|
+
var SOURCE_GLOBS = [
|
|
3033
|
+
"**/*.ts",
|
|
3034
|
+
"**/*.tsx",
|
|
3035
|
+
"**/*.mts",
|
|
3036
|
+
"**/*.cts",
|
|
3037
|
+
"**/*.js",
|
|
3038
|
+
"**/*.mjs"
|
|
3039
|
+
];
|
|
3040
|
+
var IGNORE_PATTERNS = [
|
|
3041
|
+
"**/node_modules/**",
|
|
3042
|
+
"**/dist/**",
|
|
3043
|
+
"**/build/**",
|
|
3044
|
+
"**/.yarn/**"
|
|
3045
|
+
];
|
|
3046
|
+
function rewriteSourceImports(cwd, direction) {
|
|
3047
|
+
const swaps = IMPORT_SWAP_MAP[direction];
|
|
3048
|
+
const files = globSync2(SOURCE_GLOBS, {
|
|
3049
|
+
cwd,
|
|
3050
|
+
absolute: true,
|
|
3051
|
+
ignore: IGNORE_PATTERNS
|
|
3052
|
+
});
|
|
3053
|
+
let count = 0;
|
|
3054
|
+
for (const file of files) {
|
|
3055
|
+
if (!existsSync13(file)) continue;
|
|
3056
|
+
const original = readFileSync15(file, "utf8");
|
|
3057
|
+
let content = original;
|
|
3058
|
+
for (const [from, to] of swaps) {
|
|
3059
|
+
content = content.replaceAll(from, to);
|
|
3060
|
+
}
|
|
3061
|
+
if (content !== original) {
|
|
3062
|
+
writeFileSync10(file, content, "utf8");
|
|
3063
|
+
count++;
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
if (count > 0) {
|
|
3067
|
+
console.log(chalk25.green(` Rewrote ts-scripts imports in ${count} source file(s)`));
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
// src/actions/packman/swapTsScriptsDependency.ts
|
|
3072
|
+
import {
|
|
3073
|
+
existsSync as existsSync14,
|
|
3074
|
+
readFileSync as readFileSync16,
|
|
3075
|
+
writeFileSync as writeFileSync11
|
|
3076
|
+
} from "fs";
|
|
3077
|
+
import PATH15 from "path";
|
|
3078
|
+
import chalk26 from "chalk";
|
|
3079
|
+
var SWAP_MAP = {
|
|
3080
|
+
"yarn-to-pnpm": [
|
|
3081
|
+
["@xylabs/ts-scripts-yarn3", "@xylabs/ts-scripts-pnpm"]
|
|
3082
|
+
],
|
|
3083
|
+
"pnpm-to-yarn": [
|
|
3084
|
+
["@xylabs/ts-scripts-pnpm", "@xylabs/ts-scripts-yarn3"]
|
|
3085
|
+
]
|
|
3086
|
+
};
|
|
3087
|
+
function swapInPackageJson(pkgPath, direction) {
|
|
3088
|
+
if (!existsSync14(pkgPath)) return false;
|
|
3089
|
+
const raw = readFileSync16(pkgPath, "utf8");
|
|
3090
|
+
const pkg = JSON.parse(raw);
|
|
3091
|
+
let changed = false;
|
|
3092
|
+
for (const depField of ["dependencies", "devDependencies"]) {
|
|
3093
|
+
const deps = pkg[depField];
|
|
3094
|
+
if (!deps) continue;
|
|
3095
|
+
for (const [from, to] of SWAP_MAP[direction]) {
|
|
3096
|
+
if (deps[from]) {
|
|
3097
|
+
deps[to] = deps[from];
|
|
3098
|
+
delete deps[from];
|
|
3099
|
+
changed = true;
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
if (changed) {
|
|
3104
|
+
writeFileSync11(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
3105
|
+
}
|
|
3106
|
+
return changed;
|
|
3107
|
+
}
|
|
3108
|
+
function swapTsScriptsDependency(cwd, workspacePackageJsonPaths, direction) {
|
|
3109
|
+
let count = 0;
|
|
3110
|
+
if (swapInPackageJson(PATH15.join(cwd, "package.json"), direction)) {
|
|
3111
|
+
count++;
|
|
3112
|
+
}
|
|
3113
|
+
for (const pkgPath of workspacePackageJsonPaths) {
|
|
3114
|
+
const fullPath = PATH15.resolve(cwd, pkgPath, "package.json");
|
|
3115
|
+
if (swapInPackageJson(fullPath, direction)) {
|
|
3116
|
+
count++;
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
if (count > 0) {
|
|
3120
|
+
const target = direction === "yarn-to-pnpm" ? "@xylabs/ts-scripts-pnpm" : "@xylabs/ts-scripts-yarn3";
|
|
3121
|
+
console.log(chalk26.green(` Swapped ts-scripts dependency to ${target} in ${count} package(s)`));
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
// src/actions/packman/convertToPnpm.ts
|
|
3126
|
+
var PNPM_VERSION = "10.12.1";
|
|
3127
|
+
function createPnpmWorkspaceYaml(cwd, workspacePatterns) {
|
|
3128
|
+
const lines = ["packages:"];
|
|
3129
|
+
for (const pattern of workspacePatterns) {
|
|
3130
|
+
lines.push(` - '${pattern}'`);
|
|
3131
|
+
}
|
|
3132
|
+
writeFileSync12(PATH16.join(cwd, "pnpm-workspace.yaml"), lines.join("\n") + "\n", "utf8");
|
|
3133
|
+
console.log(chalk27.green(" Created pnpm-workspace.yaml"));
|
|
3134
|
+
}
|
|
3135
|
+
function readPnpmWorkspacePatterns(cwd) {
|
|
3136
|
+
const wsPath = PATH16.join(cwd, "pnpm-workspace.yaml");
|
|
3137
|
+
if (!existsSync15(wsPath)) return [];
|
|
3138
|
+
const content = readFileSync17(wsPath, "utf8");
|
|
3139
|
+
const patterns = [];
|
|
3140
|
+
const lines = content.split("\n");
|
|
3141
|
+
let inPackages = false;
|
|
3142
|
+
for (const line of lines) {
|
|
3143
|
+
if (line.trim() === "packages:") {
|
|
3144
|
+
inPackages = true;
|
|
3145
|
+
continue;
|
|
3146
|
+
}
|
|
3147
|
+
if (inPackages && /^\s+-\s+/.test(line)) {
|
|
3148
|
+
const pattern = line.replace(/^\s+-\s+/, "").replaceAll(/['"]/g, "").trim();
|
|
3149
|
+
if (pattern) patterns.push(pattern);
|
|
3150
|
+
} else if (inPackages && !/^\s/.test(line) && line.trim()) {
|
|
3151
|
+
inPackages = false;
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
return patterns;
|
|
3155
|
+
}
|
|
3156
|
+
function updateRootPackageJson(cwd) {
|
|
3157
|
+
const pkgPath = PATH16.join(cwd, "package.json");
|
|
3158
|
+
const pkg = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
3159
|
+
const workspacePatterns = pkg.workspaces ?? readPnpmWorkspacePatterns(cwd);
|
|
3160
|
+
delete pkg.workspaces;
|
|
3161
|
+
pkg.packageManager = `pnpm@${PNPM_VERSION}`;
|
|
3162
|
+
const updated = rewriteScriptsInPackageJson(pkg, "yarn-to-pnpm");
|
|
3163
|
+
writeFileSync12(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
3164
|
+
console.log(chalk27.green(" Updated root package.json"));
|
|
3165
|
+
return workspacePatterns;
|
|
3166
|
+
}
|
|
3167
|
+
function updateGitignore(cwd) {
|
|
3168
|
+
const gitignorePath = PATH16.join(cwd, ".gitignore");
|
|
3169
|
+
if (!existsSync15(gitignorePath)) return;
|
|
3170
|
+
let content = readFileSync17(gitignorePath, "utf8");
|
|
3171
|
+
const yarnLines = [
|
|
3172
|
+
".pnp.*",
|
|
3173
|
+
".pnp",
|
|
3174
|
+
".yarn/*",
|
|
3175
|
+
"!.yarn/patches",
|
|
3176
|
+
"!.yarn/plugins",
|
|
3177
|
+
"!.yarn/releases",
|
|
3178
|
+
"!.yarn/sdks",
|
|
3179
|
+
"!.yarn/versions"
|
|
3180
|
+
];
|
|
3181
|
+
for (const line of yarnLines) {
|
|
3182
|
+
content = content.replaceAll(new RegExp(String.raw`^${line.replaceAll(".", String.raw`\.`).replaceAll("*", String.raw`\*`).replaceAll("!", String.raw`\!`)}\s*$`, "gm"), "");
|
|
3183
|
+
}
|
|
3184
|
+
content = content.replaceAll(/\n{3,}/g, "\n\n");
|
|
3185
|
+
writeFileSync12(gitignorePath, content, "utf8");
|
|
3186
|
+
console.log(chalk27.green(" Updated .gitignore"));
|
|
3187
|
+
}
|
|
3188
|
+
function deleteYarnArtifacts(cwd) {
|
|
3189
|
+
const yarnLock = PATH16.join(cwd, "yarn.lock");
|
|
3190
|
+
const yarnrc = PATH16.join(cwd, ".yarnrc.yml");
|
|
3191
|
+
const yarnDir = PATH16.join(cwd, ".yarn");
|
|
3192
|
+
if (existsSync15(yarnLock)) {
|
|
3193
|
+
rmSync3(yarnLock);
|
|
3194
|
+
console.log(chalk27.gray(" Deleted yarn.lock"));
|
|
3195
|
+
}
|
|
3196
|
+
if (existsSync15(yarnrc)) {
|
|
3197
|
+
rmSync3(yarnrc);
|
|
3198
|
+
console.log(chalk27.gray(" Deleted .yarnrc.yml"));
|
|
3199
|
+
}
|
|
3200
|
+
if (existsSync15(yarnDir)) {
|
|
3201
|
+
rmSync3(yarnDir, { force: true, recursive: true });
|
|
3202
|
+
console.log(chalk27.gray(" Deleted .yarn/"));
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
function createNpmrc(cwd) {
|
|
3206
|
+
const npmrcPath = PATH16.join(cwd, ".npmrc");
|
|
3207
|
+
if (existsSync15(npmrcPath)) return;
|
|
3208
|
+
mkdirSync5(PATH16.dirname(npmrcPath), { recursive: true });
|
|
3209
|
+
writeFileSync12(npmrcPath, "", "utf8");
|
|
3210
|
+
console.log(chalk27.green(" Created .npmrc"));
|
|
3211
|
+
}
|
|
3212
|
+
function convertToPnpm(cwd, workspacePackageJsonPaths) {
|
|
3213
|
+
console.log(chalk27.blue("\nConverting to pnpm...\n"));
|
|
3214
|
+
const workspacePatterns = updateRootPackageJson(cwd);
|
|
3215
|
+
createPnpmWorkspaceYaml(cwd, workspacePatterns);
|
|
3216
|
+
for (const pkgPath of workspacePackageJsonPaths) {
|
|
3217
|
+
const fullPath = PATH16.resolve(cwd, pkgPath, "package.json");
|
|
3218
|
+
if (!existsSync15(fullPath)) continue;
|
|
3219
|
+
const pkg = JSON.parse(readFileSync17(fullPath, "utf8"));
|
|
3220
|
+
const updated = rewriteScriptsInPackageJson(pkg, "yarn-to-pnpm");
|
|
3221
|
+
if (JSON.stringify(pkg) !== JSON.stringify(updated)) {
|
|
3222
|
+
writeFileSync12(fullPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
console.log(chalk27.green(` Rewrote scripts in ${workspacePackageJsonPaths.length} workspace package(s)`));
|
|
3226
|
+
updateGitignore(cwd);
|
|
3227
|
+
createNpmrc(cwd);
|
|
3228
|
+
swapTsScriptsDependency(cwd, workspacePackageJsonPaths, "yarn-to-pnpm");
|
|
3229
|
+
rewriteSourceImports(cwd, "yarn-to-pnpm");
|
|
3230
|
+
deleteYarnArtifacts(cwd);
|
|
3231
|
+
console.log(chalk27.blue("\nRunning pnpm install..."));
|
|
3232
|
+
const install = spawnSync5("pnpm", ["install"], {
|
|
3233
|
+
cwd,
|
|
3234
|
+
encoding: "utf8",
|
|
3235
|
+
shell: true,
|
|
3236
|
+
stdio: "inherit"
|
|
3237
|
+
});
|
|
3238
|
+
if (install.status !== 0) {
|
|
3239
|
+
console.error(chalk27.red("pnpm install failed"));
|
|
3240
|
+
return 1;
|
|
3241
|
+
}
|
|
3242
|
+
console.log(chalk27.blue("\nConversion complete.\n"));
|
|
3243
|
+
return 0;
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
// src/actions/packman/convertToYarn.ts
|
|
3247
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
3248
|
+
import {
|
|
3249
|
+
existsSync as existsSync16,
|
|
3250
|
+
readFileSync as readFileSync18,
|
|
3251
|
+
rmSync as rmSync4,
|
|
3252
|
+
writeFileSync as writeFileSync13
|
|
3253
|
+
} from "fs";
|
|
3254
|
+
import PATH17 from "path";
|
|
3255
|
+
import chalk28 from "chalk";
|
|
3256
|
+
var YARN_VERSION = "4.13.0";
|
|
3257
|
+
var YARNRC_TEMPLATE = `compressionLevel: mixed
|
|
3258
|
+
|
|
3259
|
+
enableGlobalCache: true
|
|
3260
|
+
|
|
3261
|
+
enableInlineBuilds: true
|
|
3262
|
+
|
|
3263
|
+
nmHoistingLimits: none
|
|
3264
|
+
|
|
3265
|
+
nodeLinker: node-modules
|
|
3266
|
+
`;
|
|
3267
|
+
var YARN_GITIGNORE_ENTRIES = `
|
|
3268
|
+
.pnp.*
|
|
3269
|
+
.yarn/*
|
|
3270
|
+
!.yarn/patches
|
|
3271
|
+
!.yarn/plugins
|
|
3272
|
+
!.yarn/releases
|
|
3273
|
+
!.yarn/sdks
|
|
3274
|
+
!.yarn/versions
|
|
3275
|
+
`;
|
|
3276
|
+
function readPnpmWorkspacePatterns2(cwd) {
|
|
3277
|
+
const wsPath = PATH17.join(cwd, "pnpm-workspace.yaml");
|
|
3278
|
+
if (!existsSync16(wsPath)) return [];
|
|
3279
|
+
const content = readFileSync18(wsPath, "utf8");
|
|
3280
|
+
const patterns = [];
|
|
3281
|
+
const lines = content.split("\n");
|
|
3282
|
+
let inPackages = false;
|
|
3283
|
+
for (const line of lines) {
|
|
3284
|
+
if (line.trim() === "packages:") {
|
|
3285
|
+
inPackages = true;
|
|
3286
|
+
continue;
|
|
3287
|
+
}
|
|
3288
|
+
if (inPackages && /^\s+-\s+/.test(line)) {
|
|
3289
|
+
const pattern = line.replace(/^\s+-\s+/, "").replaceAll(/['"]/g, "").trim();
|
|
3290
|
+
if (pattern) patterns.push(pattern);
|
|
3291
|
+
} else if (inPackages && !/^\s/.test(line) && line.trim()) {
|
|
3292
|
+
inPackages = false;
|
|
3293
|
+
}
|
|
3294
|
+
}
|
|
3295
|
+
return patterns;
|
|
3296
|
+
}
|
|
3297
|
+
function updateRootPackageJson2(cwd, workspacePatterns) {
|
|
3298
|
+
const pkgPath = PATH17.join(cwd, "package.json");
|
|
3299
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
3300
|
+
pkg.workspaces = workspacePatterns;
|
|
3301
|
+
pkg.packageManager = `yarn@${YARN_VERSION}`;
|
|
3302
|
+
const updated = rewriteScriptsInPackageJson(pkg, "pnpm-to-yarn");
|
|
3303
|
+
writeFileSync13(pkgPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
3304
|
+
console.log(chalk28.green(" Updated root package.json"));
|
|
3305
|
+
}
|
|
3306
|
+
function updateGitignore2(cwd) {
|
|
3307
|
+
const gitignorePath = PATH17.join(cwd, ".gitignore");
|
|
3308
|
+
let content = existsSync16(gitignorePath) ? readFileSync18(gitignorePath, "utf8") : "";
|
|
3309
|
+
if (!content.includes(".yarn/*")) {
|
|
3310
|
+
content = content.trimEnd() + "\n" + YARN_GITIGNORE_ENTRIES;
|
|
3311
|
+
}
|
|
3312
|
+
writeFileSync13(gitignorePath, content, "utf8");
|
|
3313
|
+
console.log(chalk28.green(" Updated .gitignore"));
|
|
3314
|
+
}
|
|
3315
|
+
function deletePnpmArtifacts(cwd) {
|
|
3316
|
+
const lockfile = PATH17.join(cwd, "pnpm-lock.yaml");
|
|
3317
|
+
const workspaceYaml = PATH17.join(cwd, "pnpm-workspace.yaml");
|
|
3318
|
+
const npmrc = PATH17.join(cwd, ".npmrc");
|
|
3319
|
+
if (existsSync16(lockfile)) {
|
|
3320
|
+
rmSync4(lockfile);
|
|
3321
|
+
console.log(chalk28.gray(" Deleted pnpm-lock.yaml"));
|
|
3322
|
+
}
|
|
3323
|
+
if (existsSync16(workspaceYaml)) {
|
|
3324
|
+
rmSync4(workspaceYaml);
|
|
3325
|
+
console.log(chalk28.gray(" Deleted pnpm-workspace.yaml"));
|
|
3326
|
+
}
|
|
3327
|
+
if (existsSync16(npmrc)) {
|
|
3328
|
+
const content = readFileSync18(npmrc, "utf8");
|
|
3329
|
+
if (content.trim() === "" || content.includes("shamefully-hoist") || content.includes("node-linker")) {
|
|
3330
|
+
rmSync4(npmrc);
|
|
3331
|
+
console.log(chalk28.gray(" Deleted .npmrc"));
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
function createYarnrc(cwd) {
|
|
3336
|
+
const yarnrcPath = PATH17.join(cwd, ".yarnrc.yml");
|
|
3337
|
+
if (existsSync16(yarnrcPath)) return;
|
|
3338
|
+
writeFileSync13(yarnrcPath, YARNRC_TEMPLATE, "utf8");
|
|
3339
|
+
console.log(chalk28.green(" Created .yarnrc.yml"));
|
|
3340
|
+
}
|
|
3341
|
+
function readWorkspacePatternsFromPackageJson(cwd) {
|
|
3342
|
+
const pkgPath = PATH17.join(cwd, "package.json");
|
|
3343
|
+
if (!existsSync16(pkgPath)) return [];
|
|
3344
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
3345
|
+
return pkg.workspaces ?? [];
|
|
3346
|
+
}
|
|
3347
|
+
function convertToYarn(cwd, workspacePackageJsonPaths) {
|
|
3348
|
+
console.log(chalk28.blue("\nConverting to yarn...\n"));
|
|
3349
|
+
const workspacePatterns = readPnpmWorkspacePatterns2(cwd);
|
|
3350
|
+
if (workspacePatterns.length === 0) {
|
|
3351
|
+
const fromPkg = readWorkspacePatternsFromPackageJson(cwd);
|
|
3352
|
+
if (fromPkg.length > 0) {
|
|
3353
|
+
workspacePatterns.push(...fromPkg);
|
|
3354
|
+
} else {
|
|
3355
|
+
console.warn(chalk28.yellow(" No workspace patterns found"));
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
updateRootPackageJson2(cwd, workspacePatterns);
|
|
3359
|
+
for (const pkgPath of workspacePackageJsonPaths) {
|
|
3360
|
+
const fullPath = PATH17.resolve(cwd, pkgPath, "package.json");
|
|
3361
|
+
if (!existsSync16(fullPath)) continue;
|
|
3362
|
+
const pkg = JSON.parse(readFileSync18(fullPath, "utf8"));
|
|
3363
|
+
const updated = rewriteScriptsInPackageJson(pkg, "pnpm-to-yarn");
|
|
3364
|
+
if (JSON.stringify(pkg) !== JSON.stringify(updated)) {
|
|
3365
|
+
writeFileSync13(fullPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
console.log(chalk28.green(` Rewrote scripts in ${workspacePackageJsonPaths.length} workspace package(s)`));
|
|
3369
|
+
updateGitignore2(cwd);
|
|
3370
|
+
createYarnrc(cwd);
|
|
3371
|
+
swapTsScriptsDependency(cwd, workspacePackageJsonPaths, "pnpm-to-yarn");
|
|
3372
|
+
rewriteSourceImports(cwd, "pnpm-to-yarn");
|
|
3373
|
+
deletePnpmArtifacts(cwd);
|
|
3374
|
+
console.log(chalk28.blue("\nRunning yarn install..."));
|
|
3375
|
+
const install = spawnSync6("yarn", ["install"], {
|
|
3376
|
+
cwd,
|
|
3377
|
+
encoding: "utf8",
|
|
3378
|
+
shell: true,
|
|
3379
|
+
stdio: "inherit"
|
|
3380
|
+
});
|
|
3381
|
+
if (install.status !== 0) {
|
|
3382
|
+
console.error(chalk28.red("yarn install failed"));
|
|
3383
|
+
return 1;
|
|
3384
|
+
}
|
|
3385
|
+
console.log(chalk28.blue("\nConversion complete.\n"));
|
|
3386
|
+
return 0;
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3389
|
+
// src/actions/packman/convert.ts
|
|
3390
|
+
function detectCurrentPM(cwd) {
|
|
3391
|
+
if (existsSync17(PATH18.join(cwd, "pnpm-lock.yaml")) || existsSync17(PATH18.join(cwd, "pnpm-workspace.yaml"))) {
|
|
3392
|
+
return "pnpm";
|
|
3393
|
+
}
|
|
3394
|
+
if (existsSync17(PATH18.join(cwd, "yarn.lock")) || existsSync17(PATH18.join(cwd, ".yarnrc.yml"))) {
|
|
3395
|
+
return "yarn";
|
|
3396
|
+
}
|
|
3397
|
+
return "unknown";
|
|
3398
|
+
}
|
|
3399
|
+
function findWorkspacePackagePaths(cwd) {
|
|
3400
|
+
const pkgPath = PATH18.join(cwd, "package.json");
|
|
3401
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
3402
|
+
const patterns = pkg.workspaces ?? [];
|
|
3403
|
+
if (patterns.length === 0) {
|
|
3404
|
+
const wsPath = PATH18.join(cwd, "pnpm-workspace.yaml");
|
|
3405
|
+
if (existsSync17(wsPath)) {
|
|
3406
|
+
const content = readFileSync19(wsPath, "utf8");
|
|
3407
|
+
const lines = content.split("\n");
|
|
3408
|
+
let inPackages = false;
|
|
3409
|
+
for (const line of lines) {
|
|
3410
|
+
if (line.trim() === "packages:") {
|
|
3411
|
+
inPackages = true;
|
|
3412
|
+
continue;
|
|
3413
|
+
}
|
|
3414
|
+
if (inPackages && /^\s+-\s+/.test(line)) {
|
|
3415
|
+
const pattern = line.replace(/^\s+-\s+/, "").replaceAll(/['"]/g, "").trim();
|
|
3416
|
+
if (pattern) patterns.push(pattern);
|
|
3417
|
+
} else if (inPackages && !/^\s/.test(line) && line.trim()) {
|
|
3418
|
+
inPackages = false;
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
const dirs = [];
|
|
3424
|
+
for (const pattern of patterns) {
|
|
3425
|
+
const resolved = resolveWorkspaceGlob(cwd, pattern);
|
|
3426
|
+
dirs.push(...resolved);
|
|
3427
|
+
}
|
|
3428
|
+
return dirs;
|
|
3429
|
+
}
|
|
3430
|
+
function resolveWorkspaceGlob(cwd, pattern) {
|
|
3431
|
+
const parts = pattern.split("/");
|
|
3432
|
+
return walkGlob(cwd, parts, "");
|
|
3433
|
+
}
|
|
3434
|
+
function walkGlob(basePath, parts, currentPath) {
|
|
3435
|
+
if (parts.length === 0) {
|
|
3436
|
+
const fullPath = PATH18.join(basePath, currentPath);
|
|
3437
|
+
if (existsSync17(PATH18.join(fullPath, "package.json"))) {
|
|
3438
|
+
return [currentPath];
|
|
3439
|
+
}
|
|
3440
|
+
return [];
|
|
3441
|
+
}
|
|
3442
|
+
const [part, ...rest] = parts;
|
|
3443
|
+
const dirPath = PATH18.join(basePath, currentPath);
|
|
3444
|
+
if (!existsSync17(dirPath) || !statSync4(dirPath).isDirectory()) {
|
|
3445
|
+
return [];
|
|
3446
|
+
}
|
|
3447
|
+
if (part === "*" || part === "**") {
|
|
3448
|
+
const entries = readdirSync8(dirPath, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist");
|
|
3449
|
+
const results = [];
|
|
3450
|
+
if (part === "**") {
|
|
3451
|
+
results.push(...walkGlob(basePath, rest, currentPath));
|
|
3452
|
+
}
|
|
3453
|
+
for (const entry of entries) {
|
|
3454
|
+
const subPath2 = currentPath ? `${currentPath}/${entry.name}` : entry.name;
|
|
3455
|
+
if (part === "**") {
|
|
3456
|
+
results.push(
|
|
3457
|
+
...walkGlob(basePath, rest, subPath2),
|
|
3458
|
+
...walkGlob(basePath, parts, subPath2)
|
|
3459
|
+
);
|
|
3460
|
+
} else {
|
|
3461
|
+
results.push(...walkGlob(basePath, rest, subPath2));
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
return results;
|
|
3465
|
+
}
|
|
3466
|
+
const subPath = currentPath ? `${currentPath}/${part}` : part;
|
|
3467
|
+
return walkGlob(basePath, rest, subPath);
|
|
3468
|
+
}
|
|
3469
|
+
function convert({ target, verbose }) {
|
|
3470
|
+
const validTargets = ["pnpm", "yarn"];
|
|
3471
|
+
if (!validTargets.includes(target)) {
|
|
3472
|
+
console.error(chalk29.red(`Invalid target "${target}". Must be one of: ${validTargets.join(", ")}`));
|
|
3473
|
+
return 1;
|
|
3474
|
+
}
|
|
3475
|
+
const cwd = process.cwd();
|
|
3476
|
+
const currentPM = detectCurrentPM(cwd);
|
|
3477
|
+
if (verbose) {
|
|
3478
|
+
console.log(chalk29.gray(`Current package manager: ${currentPM}`));
|
|
3479
|
+
console.log(chalk29.gray(`Target package manager: ${target}`));
|
|
3480
|
+
}
|
|
3481
|
+
if (currentPM === target) {
|
|
3482
|
+
console.log(chalk29.yellow(`Already using ${target}. Re-applying conversion to fix any incomplete steps...`));
|
|
3483
|
+
}
|
|
3484
|
+
if (currentPM === "unknown") {
|
|
3485
|
+
console.error(chalk29.red("Could not detect current package manager. No yarn.lock or pnpm-lock.yaml found."));
|
|
3486
|
+
return 1;
|
|
3487
|
+
}
|
|
3488
|
+
const workspacePaths = findWorkspacePackagePaths(cwd);
|
|
3489
|
+
if (verbose) {
|
|
3490
|
+
console.log(chalk29.gray(`Found ${workspacePaths.length} workspace packages`));
|
|
3491
|
+
}
|
|
3492
|
+
const result = target === "pnpm" ? convertToPnpm(cwd, workspacePaths) : convertToYarn(cwd, workspacePaths);
|
|
3493
|
+
if (result !== 0) return result;
|
|
3494
|
+
console.log(chalk29.green("\nRunning repo lint --fix..."));
|
|
3495
|
+
packageLintMonorepo(true);
|
|
3496
|
+
return result;
|
|
3497
|
+
}
|
|
3498
|
+
|
|
3499
|
+
// src/actions/packman/clean.ts
|
|
3500
|
+
function removeNodeModules(dir, verbose) {
|
|
3501
|
+
const nmPath = PATH19.join(dir, "node_modules");
|
|
3502
|
+
if (existsSync18(nmPath)) {
|
|
3503
|
+
if (verbose) console.log(chalk30.gray(`Removing ${nmPath}`));
|
|
3504
|
+
rmSync5(nmPath, { force: true, recursive: true });
|
|
3505
|
+
return true;
|
|
3506
|
+
}
|
|
3507
|
+
return false;
|
|
3508
|
+
}
|
|
3509
|
+
function packmanClean({ verbose }) {
|
|
3510
|
+
const cwd = process.cwd();
|
|
3511
|
+
const pm = detectCurrentPM(cwd);
|
|
3512
|
+
if (pm === "unknown") {
|
|
3513
|
+
console.error(chalk30.red("Could not detect current package manager. No yarn.lock or pnpm-lock.yaml found."));
|
|
3514
|
+
return 1;
|
|
3515
|
+
}
|
|
3516
|
+
console.log(chalk30.blue(`Detected package manager: ${pm}`));
|
|
3517
|
+
let removedCount = 0;
|
|
3518
|
+
if (removeNodeModules(cwd, verbose)) removedCount++;
|
|
3519
|
+
const workspacePaths = findWorkspacePackagePaths(cwd);
|
|
3520
|
+
for (const wsPath of workspacePaths) {
|
|
3521
|
+
const fullPath = PATH19.join(cwd, wsPath);
|
|
3522
|
+
if (removeNodeModules(fullPath, verbose)) removedCount++;
|
|
3523
|
+
}
|
|
3524
|
+
console.log(chalk30.green(`Removed ${removedCount} node_modules folder${removedCount === 1 ? "" : "s"}`));
|
|
3525
|
+
if (pm === "yarn") {
|
|
3526
|
+
const lockPath = PATH19.join(cwd, "yarn.lock");
|
|
3527
|
+
if (existsSync18(lockPath)) {
|
|
3528
|
+
writeFileSync14(lockPath, "");
|
|
3529
|
+
console.log(chalk30.green("Truncated yarn.lock"));
|
|
3530
|
+
}
|
|
3531
|
+
} else if (pm === "pnpm") {
|
|
3532
|
+
const lockPath = PATH19.join(cwd, "pnpm-lock.yaml");
|
|
3533
|
+
if (existsSync18(lockPath)) {
|
|
3534
|
+
rmSync5(lockPath);
|
|
3535
|
+
console.log(chalk30.green("Deleted pnpm-lock.yaml"));
|
|
3536
|
+
}
|
|
3537
|
+
}
|
|
3538
|
+
console.log(chalk30.green("Ready for a clean install"));
|
|
3539
|
+
return 0;
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
// src/actions/packman/lint.ts
|
|
3543
|
+
import {
|
|
3544
|
+
existsSync as existsSync19,
|
|
3545
|
+
readFileSync as readFileSync20,
|
|
3546
|
+
writeFileSync as writeFileSync15
|
|
3547
|
+
} from "fs";
|
|
3548
|
+
import PATH20 from "path";
|
|
3549
|
+
import chalk31 from "chalk";
|
|
3550
|
+
function checkEnableScripts(cwd, verbose, silent) {
|
|
3551
|
+
const yarnrcPath = PATH20.join(cwd, ".yarnrc.yml");
|
|
3552
|
+
if (!existsSync19(yarnrcPath)) {
|
|
3553
|
+
if (verbose) console.log(chalk31.gray(" No .yarnrc.yml found, skipping enableScripts check"));
|
|
3554
|
+
return true;
|
|
3555
|
+
}
|
|
3556
|
+
const content = readFileSync20(yarnrcPath, "utf8");
|
|
3557
|
+
const lines = content.split("\n");
|
|
3558
|
+
for (const line of lines) {
|
|
3559
|
+
const trimmed = line.trim();
|
|
3560
|
+
if (/^enableScripts\s*:/.test(trimmed)) {
|
|
3561
|
+
const value = trimmed.replace(/^enableScripts\s*:\s*/, "").trim();
|
|
3562
|
+
if (value === "false") {
|
|
3563
|
+
if (verbose) console.log(chalk31.green(" enableScripts is correctly set to false"));
|
|
3564
|
+
return true;
|
|
3565
|
+
}
|
|
3566
|
+
if (!silent) console.log(chalk31.red(" enableScripts is set to", value, "(expected false)"));
|
|
3567
|
+
return false;
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
if (!silent) console.log(chalk31.red(" enableScripts is not set in .yarnrc.yml (expected false)"));
|
|
3571
|
+
return false;
|
|
3572
|
+
}
|
|
3573
|
+
function fixEnableScripts(cwd, verbose) {
|
|
3574
|
+
const yarnrcPath = PATH20.join(cwd, ".yarnrc.yml");
|
|
3575
|
+
if (!existsSync19(yarnrcPath)) {
|
|
3576
|
+
if (verbose) console.log(chalk31.gray(" No .yarnrc.yml found, skipping enableScripts fix"));
|
|
3577
|
+
return true;
|
|
3578
|
+
}
|
|
3579
|
+
const content = readFileSync20(yarnrcPath, "utf8");
|
|
3580
|
+
const lines = content.split("\n");
|
|
3581
|
+
let found = false;
|
|
3582
|
+
const newLines = lines.map((line) => {
|
|
3583
|
+
if (/^\s*enableScripts\s*:/.test(line)) {
|
|
3584
|
+
found = true;
|
|
3585
|
+
return "enableScripts: false";
|
|
3586
|
+
}
|
|
3587
|
+
return line;
|
|
3588
|
+
});
|
|
3589
|
+
if (!found) {
|
|
3590
|
+
let inserted = false;
|
|
3591
|
+
for (let i = 0; i < newLines.length; i++) {
|
|
3592
|
+
const trimmed = newLines[i].trim();
|
|
3593
|
+
if (trimmed && !trimmed.startsWith("#") && trimmed > "enableScripts:") {
|
|
3594
|
+
newLines.splice(i, 0, "enableScripts: false", "");
|
|
3595
|
+
inserted = true;
|
|
3596
|
+
break;
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
if (!inserted) {
|
|
3600
|
+
const lastLine = newLines.at(-1);
|
|
3601
|
+
if (lastLine === "") {
|
|
3602
|
+
newLines.splice(-1, 0, "enableScripts: false", "");
|
|
3603
|
+
} else {
|
|
3604
|
+
newLines.push("", "enableScripts: false");
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
writeFileSync15(yarnrcPath, newLines.join("\n"), "utf8");
|
|
3609
|
+
console.log(chalk31.green(" Fixed: enableScripts set to false"));
|
|
3610
|
+
return true;
|
|
3611
|
+
}
|
|
3612
|
+
var checks = [
|
|
3613
|
+
{
|
|
3614
|
+
name: "enableScripts should be false in .yarnrc.yml",
|
|
3615
|
+
check: checkEnableScripts,
|
|
3616
|
+
fix: fixEnableScripts
|
|
3617
|
+
}
|
|
3618
|
+
];
|
|
3619
|
+
function packmanLint({ fix, verbose } = {}) {
|
|
3620
|
+
const cwd = process.cwd();
|
|
3621
|
+
let failures = 0;
|
|
3622
|
+
for (const check of checks) {
|
|
3623
|
+
if (verbose) console.log(chalk31.gray(`Checking: ${check.name}`));
|
|
3624
|
+
const passed = check.check(cwd, verbose, fix);
|
|
3625
|
+
if (!passed) {
|
|
3626
|
+
if (fix) {
|
|
3627
|
+
const fixed = check.fix(cwd, verbose);
|
|
3628
|
+
if (!fixed) {
|
|
3629
|
+
failures++;
|
|
3630
|
+
}
|
|
3631
|
+
} else {
|
|
3632
|
+
failures++;
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
if (failures > 0) {
|
|
3637
|
+
console.log(chalk31.red(`
|
|
3638
|
+
packman lint: ${failures} check(s) failed`));
|
|
3639
|
+
if (!fix) {
|
|
3640
|
+
console.log(chalk31.yellow("Run with --fix to auto-fix issues"));
|
|
3641
|
+
}
|
|
3642
|
+
} else {
|
|
3643
|
+
console.log(chalk31.green("\npackman lint: all checks passed"));
|
|
3644
|
+
}
|
|
3645
|
+
return failures > 0 ? 1 : 0;
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
// src/actions/publint.ts
|
|
3649
|
+
import chalk32 from "chalk";
|
|
3650
|
+
function resolveExclude(publintConfig, cliExclude, cliInclude) {
|
|
3651
|
+
const hasExclude = (publintConfig.exclude?.length ?? 0) > 0 || (cliExclude?.length ?? 0) > 0;
|
|
3652
|
+
const hasInclude = (publintConfig.include?.length ?? 0) > 0 || (cliInclude?.length ?? 0) > 0;
|
|
3653
|
+
if (hasExclude && hasInclude) {
|
|
3654
|
+
console.error(chalk32.red("Publint: --include and --exclude cannot be used together"));
|
|
3655
|
+
return void 0;
|
|
3656
|
+
}
|
|
3657
|
+
if (hasInclude) {
|
|
3658
|
+
const include = /* @__PURE__ */ new Set([
|
|
3659
|
+
...publintConfig.include ?? [],
|
|
3660
|
+
...cliInclude ?? []
|
|
3661
|
+
]);
|
|
3662
|
+
return new Set(ALL_PUBLINT_CHECKS.filter((c) => !include.has(c)));
|
|
3663
|
+
}
|
|
3664
|
+
return /* @__PURE__ */ new Set([
|
|
3665
|
+
...publintConfig.exclude ?? [],
|
|
3666
|
+
...cliExclude ?? []
|
|
3667
|
+
]);
|
|
3668
|
+
}
|
|
3669
|
+
function normalizePublintConfig(value) {
|
|
3670
|
+
if (typeof value === "object") return value;
|
|
3671
|
+
return {};
|
|
3672
|
+
}
|
|
3673
|
+
var publint = async ({
|
|
3674
|
+
cliExclude,
|
|
3675
|
+
cliInclude,
|
|
3676
|
+
fix,
|
|
3677
|
+
jobs,
|
|
3678
|
+
pack,
|
|
3679
|
+
verbose,
|
|
3680
|
+
pkg
|
|
3681
|
+
}) => {
|
|
3682
|
+
return pkg === void 0 ? await publintAll({
|
|
3683
|
+
cliExclude,
|
|
3684
|
+
cliInclude,
|
|
3685
|
+
fix,
|
|
3686
|
+
jobs,
|
|
3687
|
+
pack,
|
|
3688
|
+
verbose
|
|
3689
|
+
}) : await publintSingle({
|
|
3690
|
+
cliExclude,
|
|
3691
|
+
cliInclude,
|
|
3692
|
+
fix,
|
|
3693
|
+
pack,
|
|
3694
|
+
pkg,
|
|
3695
|
+
verbose
|
|
3696
|
+
});
|
|
3697
|
+
};
|
|
3698
|
+
function logPublintSummary(packages, errors, ms) {
|
|
3699
|
+
const color = errors > 0 ? chalk32.red : chalk32.blue;
|
|
3700
|
+
console.log(color(`Checked ${packages} package(s) in ${ms.toFixed(0)}ms with ${errors} issue(s) found.`));
|
|
3701
|
+
}
|
|
3702
|
+
var publintSingle = async ({
|
|
3703
|
+
cliExclude,
|
|
3704
|
+
cliInclude,
|
|
3705
|
+
fix,
|
|
3706
|
+
pack,
|
|
3707
|
+
pkg,
|
|
3708
|
+
verbose
|
|
3709
|
+
}) => {
|
|
3710
|
+
const start = performance.now();
|
|
3711
|
+
const pm = getPackageManager();
|
|
3712
|
+
const workspace = pm.findWorkspace(pkg);
|
|
3713
|
+
if (!workspace) {
|
|
3714
|
+
console.error(chalk32.red(`Publint: workspace "${pkg}" not found`));
|
|
3715
|
+
return 1;
|
|
3716
|
+
}
|
|
3717
|
+
const wsPublintConfig = normalizePublintConfig(
|
|
3718
|
+
await loadWorkspaceCommandConfig(workspace.location, "publint")
|
|
3719
|
+
);
|
|
3720
|
+
const exclude = resolveExclude(wsPublintConfig, cliExclude, cliInclude);
|
|
3721
|
+
if (!exclude) return 1;
|
|
3722
|
+
const shouldPack = pack ?? wsPublintConfig.pack ?? true;
|
|
3723
|
+
const errors = await packagePublint({
|
|
3724
|
+
exclude,
|
|
3725
|
+
fix,
|
|
3726
|
+
pack: shouldPack,
|
|
3727
|
+
pkgDir: workspace.location,
|
|
3728
|
+
verbose
|
|
3729
|
+
});
|
|
3730
|
+
logPublintSummary(1, errors, performance.now() - start);
|
|
3731
|
+
return errors;
|
|
3732
|
+
};
|
|
3733
|
+
var publintAll = async ({
|
|
3734
|
+
cliExclude,
|
|
3735
|
+
cliInclude,
|
|
3736
|
+
fix,
|
|
3737
|
+
jobs,
|
|
3738
|
+
pack,
|
|
3739
|
+
verbose
|
|
3740
|
+
}) => {
|
|
3741
|
+
const start = performance.now();
|
|
3742
|
+
const pm = getPackageManager();
|
|
3743
|
+
const workspaces = pm.listWorkspaces();
|
|
3744
|
+
const concurrency = jobs;
|
|
3745
|
+
const results = Array.from({ length: workspaces.length }, () => ({ errors: 0, output: [] }));
|
|
3746
|
+
installOutputCapture();
|
|
3747
|
+
await runWithConcurrency(
|
|
3748
|
+
workspaces.map((ws, i) => ({ i, ws })),
|
|
3749
|
+
concurrency,
|
|
3750
|
+
async ({ i, ws }) => {
|
|
3751
|
+
const output = [];
|
|
3752
|
+
await outputStorage.run(output, async () => {
|
|
3753
|
+
try {
|
|
3754
|
+
const wsPublintConfig = normalizePublintConfig(
|
|
3755
|
+
await loadWorkspaceCommandConfig(ws.location, "publint")
|
|
3756
|
+
);
|
|
3757
|
+
const exclude = resolveExclude(wsPublintConfig, cliExclude, cliInclude) ?? /* @__PURE__ */ new Set();
|
|
3758
|
+
const shouldPack = pack ?? wsPublintConfig.pack ?? true;
|
|
3759
|
+
const errors = await packagePublint({
|
|
3760
|
+
exclude,
|
|
3761
|
+
fix,
|
|
3762
|
+
pack: shouldPack,
|
|
3763
|
+
pkgDir: ws.location,
|
|
3764
|
+
verbose
|
|
3765
|
+
});
|
|
3766
|
+
results[i] = { errors, output };
|
|
3767
|
+
} catch (ex) {
|
|
3768
|
+
output.push(chalk32.red(`Publint failed for ${ws.name}: ${ex.message}
|
|
3769
|
+
`));
|
|
3770
|
+
results[i] = { errors: 1, output };
|
|
3771
|
+
}
|
|
3772
|
+
});
|
|
3773
|
+
}
|
|
3774
|
+
);
|
|
3775
|
+
let totalErrors = 0;
|
|
3776
|
+
for (const { errors, output } of results) {
|
|
3777
|
+
for (const line of output) {
|
|
3778
|
+
process.stdout.write(line);
|
|
3779
|
+
}
|
|
3780
|
+
totalErrors += errors;
|
|
3781
|
+
}
|
|
3782
|
+
const allExclude = resolveExclude({}, cliExclude, cliInclude) ?? /* @__PURE__ */ new Set();
|
|
3783
|
+
if (!allExclude.has("peerDeps")) {
|
|
3784
|
+
const cwd = INIT_CWD();
|
|
3785
|
+
const peerResult = checkInternalPeerVersions(cwd, workspaces);
|
|
3786
|
+
if (peerResult.fixable.length > 0) {
|
|
3787
|
+
if (fix) {
|
|
3788
|
+
fixInternalPeerVersions(cwd, workspaces);
|
|
3789
|
+
runInstall();
|
|
3790
|
+
} else {
|
|
3791
|
+
for (const msg of peerResult.fixable) {
|
|
3792
|
+
console.log(chalk32.red(` \u2717 ${msg} (fixable)`));
|
|
3793
|
+
}
|
|
3794
|
+
totalErrors += peerResult.fixable.length;
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
totalErrors += peerResult.errors.length;
|
|
3798
|
+
}
|
|
3799
|
+
logPublintSummary(workspaces.length, totalErrors, performance.now() - start);
|
|
3800
|
+
return totalErrors;
|
|
3801
|
+
};
|
|
3802
|
+
|
|
3803
|
+
// src/actions/readme-gen.ts
|
|
3804
|
+
async function readmeGen({
|
|
3805
|
+
jobs,
|
|
3806
|
+
pkg,
|
|
3807
|
+
templatePath,
|
|
3808
|
+
typedoc,
|
|
3809
|
+
verbose
|
|
3810
|
+
}) {
|
|
3811
|
+
const config2 = await loadConfig();
|
|
3812
|
+
return await generateReadmeFiles({
|
|
3813
|
+
jobs,
|
|
3814
|
+
logoLinkUrl: config2.readme?.logoLinkUrl,
|
|
3815
|
+
logoUrl: config2.readme?.logoUrl,
|
|
3816
|
+
pkg,
|
|
3817
|
+
templatePath,
|
|
3818
|
+
typedoc,
|
|
3819
|
+
verbose
|
|
3820
|
+
});
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
// src/actions/readme-init.ts
|
|
3824
|
+
async function readmeInit({ templatePath }) {
|
|
3825
|
+
const config2 = await loadConfig();
|
|
3826
|
+
const template = applyLogoConfig(DEFAULT_README_TEMPLATE, config2.readme?.logoUrl, config2.readme?.logoLinkUrl);
|
|
3827
|
+
const resolvedTemplatePath = resolveTemplatePath(templatePath);
|
|
3828
|
+
await scaffoldTemplate(resolvedTemplatePath, template);
|
|
3829
|
+
return 0;
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
// src/actions/readme-lint.ts
|
|
3833
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
|
|
3834
|
+
import PATH21 from "path";
|
|
3835
|
+
import chalk33 from "chalk";
|
|
3836
|
+
function lintTemplate(cwd) {
|
|
3837
|
+
const result = { errors: [], warnings: [] };
|
|
3838
|
+
const templatePath = resolveTemplatePath();
|
|
3839
|
+
if (!existsSync20(templatePath)) {
|
|
3840
|
+
result.errors.push('Missing .xy/README.template.md (run "xy readme init" to create)');
|
|
3841
|
+
return result;
|
|
3842
|
+
}
|
|
3843
|
+
const template = readFileSync21(templatePath, "utf8");
|
|
3844
|
+
if (!template.includes("{{body}}")) {
|
|
3845
|
+
result.warnings.push(".xy/README.template.md does not contain a {{body}} placeholder");
|
|
3846
|
+
}
|
|
3847
|
+
if (!template.includes("{{description}}")) {
|
|
3848
|
+
result.warnings.push(".xy/README.template.md does not contain a {{description}} placeholder");
|
|
3849
|
+
}
|
|
3850
|
+
const bodyPath = PATH21.join(cwd, ".xy", "README.body.md");
|
|
3851
|
+
if (!existsSync20(bodyPath)) {
|
|
3852
|
+
result.errors.push('Missing .xy/README.body.md (run "xy readme init" to create)');
|
|
3853
|
+
}
|
|
3854
|
+
return result;
|
|
3855
|
+
}
|
|
3856
|
+
function lintLogoConfig(cwd, config2) {
|
|
3857
|
+
const result = { errors: [], warnings: [] };
|
|
3858
|
+
const templatePath = resolveTemplatePath();
|
|
3859
|
+
if (existsSync20(templatePath)) {
|
|
3860
|
+
const template = readFileSync21(templatePath, "utf8");
|
|
3861
|
+
const logoRef = /\[logo]: (.+)/.exec(template);
|
|
3862
|
+
if (logoRef?.[1].includes("example.com")) {
|
|
3863
|
+
result.warnings.push(".xy/README.template.md still has the example.com logo placeholder \u2014 update it or set readme.logoUrl in xy.config.ts");
|
|
3864
|
+
} else if (!logoRef && !config2.readme?.logoUrl) {
|
|
3865
|
+
result.warnings.push("No logo URL configured in xy.config.ts (readme.logoUrl) or template");
|
|
3866
|
+
}
|
|
3867
|
+
}
|
|
3868
|
+
if (!config2.readme?.logoUrl && !config2.readme?.logoLinkUrl) {
|
|
3869
|
+
result.warnings.push("No readme.logoUrl or readme.logoLinkUrl configured in xy.config.ts");
|
|
3870
|
+
}
|
|
3871
|
+
return result;
|
|
3872
|
+
}
|
|
3873
|
+
function lintPackages(cwd) {
|
|
3874
|
+
const result = { errors: [], warnings: [] };
|
|
3875
|
+
const pm = getPackageManager();
|
|
3876
|
+
const workspaces = pm.listWorkspaces();
|
|
3877
|
+
for (const { location, name } of workspaces) {
|
|
3878
|
+
if (location === ".") continue;
|
|
3879
|
+
const pkgPath = PATH21.join(cwd, location, "package.json");
|
|
3880
|
+
try {
|
|
3881
|
+
const pkg = JSON.parse(readFileSync21(pkgPath, "utf8"));
|
|
3882
|
+
if (pkg.private) continue;
|
|
3883
|
+
if (!pkg.description) {
|
|
3884
|
+
result.warnings.push(`${name} is missing a "description" in package.json`);
|
|
3885
|
+
}
|
|
3886
|
+
const readmePath = PATH21.join(cwd, location, "README.md");
|
|
3887
|
+
if (!existsSync20(readmePath)) {
|
|
3888
|
+
result.errors.push(`${name} is missing README.md`);
|
|
3889
|
+
}
|
|
3890
|
+
} catch {
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
return result;
|
|
3894
|
+
}
|
|
3895
|
+
function readmeLint({ config: config2, verbose }) {
|
|
3896
|
+
const cwd = INIT_CWD();
|
|
3897
|
+
console.log(chalk33.green("Readme Lint"));
|
|
3898
|
+
const checks2 = [
|
|
3899
|
+
lintTemplate(cwd),
|
|
3900
|
+
lintLogoConfig(cwd, config2),
|
|
3901
|
+
lintPackages(cwd)
|
|
3902
|
+
];
|
|
3903
|
+
let errorCount = 0;
|
|
3904
|
+
let warningCount = 0;
|
|
3905
|
+
for (const { errors, warnings } of checks2) {
|
|
3906
|
+
for (const error of errors) {
|
|
3907
|
+
console.log(chalk33.red(` \u2717 ${error}`));
|
|
3908
|
+
errorCount++;
|
|
3909
|
+
}
|
|
3910
|
+
for (const warning of warnings) {
|
|
3911
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
3912
|
+
warningCount++;
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
if (errorCount === 0 && warningCount === 0) {
|
|
3916
|
+
console.log(chalk33.green(" All checks passed"));
|
|
3917
|
+
} else {
|
|
3918
|
+
if (verbose) {
|
|
3919
|
+
console.log(chalk33.gray(` ${errorCount} error(s), ${warningCount} warning(s)`));
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
return errorCount > 0 ? 1 : 0;
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
// src/actions/repo-init.ts
|
|
3926
|
+
import { spawnSync as spawnSync7 } from "child_process";
|
|
3927
|
+
import {
|
|
3928
|
+
existsSync as existsSync21,
|
|
3929
|
+
mkdirSync as mkdirSync6,
|
|
3930
|
+
readdirSync as readdirSync9,
|
|
3931
|
+
readFileSync as readFileSync22,
|
|
3932
|
+
writeFileSync as writeFileSync16
|
|
3933
|
+
} from "fs";
|
|
3934
|
+
import { createRequire as createRequire5 } from "module";
|
|
3935
|
+
import PATH22 from "path";
|
|
3936
|
+
import { createInterface as createInterface4 } from "readline";
|
|
3937
|
+
import chalk34 from "chalk";
|
|
3938
|
+
function askQuestion(question) {
|
|
3939
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
3940
|
+
return new Promise((resolve) => {
|
|
3941
|
+
rl.question(question, (answer) => {
|
|
3942
|
+
rl.close();
|
|
3943
|
+
resolve(answer.trim());
|
|
3944
|
+
});
|
|
3945
|
+
});
|
|
3946
|
+
}
|
|
3947
|
+
function getConfigVersion() {
|
|
3948
|
+
const require6 = createRequire5(import.meta.url);
|
|
3949
|
+
const pkgPath = require6.resolve("@xylabs/ts-scripts-common/package.json");
|
|
3950
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
|
|
3951
|
+
return pkg.version.replace(/\.\d+$/, "");
|
|
3952
|
+
}
|
|
3953
|
+
function mapOutputPath(relativePath, variables) {
|
|
3954
|
+
let result = relativePath;
|
|
3955
|
+
if (result.endsWith(".tmpl")) {
|
|
3956
|
+
result = result.slice(0, -5);
|
|
3957
|
+
}
|
|
3958
|
+
if (result === "gitignore") {
|
|
3959
|
+
result = ".gitignore";
|
|
3960
|
+
}
|
|
3961
|
+
if (result.startsWith("github/")) {
|
|
3962
|
+
result = `.${result}`;
|
|
3963
|
+
}
|
|
3964
|
+
result = result.replaceAll("__packageName__", variables.packageName);
|
|
3965
|
+
return result;
|
|
3966
|
+
}
|
|
3967
|
+
function isPmSpecificFile(relativePath, pm) {
|
|
3968
|
+
if (relativePath === "pnpm-workspace.yaml" && pm === "yarn") return true;
|
|
3969
|
+
if (relativePath.includes("build-pnpm") && pm !== "pnpm") return true;
|
|
3970
|
+
if (relativePath.includes("build-yarn") && pm !== "yarn") return true;
|
|
3971
|
+
return false;
|
|
3972
|
+
}
|
|
3973
|
+
function mapBuildWorkflowName(outputPath) {
|
|
3974
|
+
return outputPath.replace(/build-(pnpm|yarn)\.yml/, "build.yml");
|
|
3975
|
+
}
|
|
3976
|
+
function buildVariables(params) {
|
|
3977
|
+
const {
|
|
3978
|
+
description,
|
|
3979
|
+
githubOrg,
|
|
3980
|
+
packageName: packageName2,
|
|
3981
|
+
pm,
|
|
3982
|
+
projectName,
|
|
3983
|
+
scope
|
|
3984
|
+
} = params;
|
|
3985
|
+
const identifierName = packageName2.replaceAll(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
3986
|
+
const pmPackage = pm === "pnpm" ? "@xylabs/ts-scripts-pnpm" : "@xylabs/ts-scripts-yarn3";
|
|
3987
|
+
return {
|
|
3988
|
+
configVersion: getConfigVersion(),
|
|
3989
|
+
description,
|
|
3990
|
+
githubOrg,
|
|
3991
|
+
identifierName,
|
|
3992
|
+
npmScope: scope,
|
|
3993
|
+
packageName: packageName2,
|
|
3994
|
+
pmName: pm,
|
|
3995
|
+
pmPackage,
|
|
3996
|
+
projectName
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
function ensureEmptyDir(projectDir, name) {
|
|
4000
|
+
if (existsSync21(projectDir)) {
|
|
4001
|
+
const entries = readdirSync9(projectDir);
|
|
4002
|
+
if (entries.length > 0) {
|
|
4003
|
+
console.error(chalk34.red(`Directory '${name}' already exists and is not empty`));
|
|
4004
|
+
return false;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
mkdirSync6(projectDir, { recursive: true });
|
|
4008
|
+
return true;
|
|
4009
|
+
}
|
|
4010
|
+
function scaffoldFiles(templateName, layer, outputDir, pm, variables, verbose) {
|
|
4011
|
+
const files = loadRepoTemplateFiles(templateName, layer);
|
|
4012
|
+
let count = 0;
|
|
4013
|
+
for (const file of files) {
|
|
4014
|
+
if (isPmSpecificFile(file.relativePath, pm)) continue;
|
|
4015
|
+
const content = fillTemplate(file.content, variables);
|
|
4016
|
+
let outputPath = mapOutputPath(file.relativePath, variables);
|
|
4017
|
+
if (!outputPath) continue;
|
|
4018
|
+
if (layer === "root") outputPath = mapBuildWorkflowName(outputPath);
|
|
4019
|
+
const fullPath = PATH22.resolve(outputDir, outputPath);
|
|
4020
|
+
mkdirSync6(PATH22.dirname(fullPath), { recursive: true });
|
|
4021
|
+
writeFileSync16(fullPath, content);
|
|
4022
|
+
count++;
|
|
4023
|
+
if (verbose) console.log(chalk34.gray(` ${layer === "root" ? outputPath : `packages/${variables.packageName}/${outputPath}`}`));
|
|
4024
|
+
}
|
|
4025
|
+
return count;
|
|
4026
|
+
}
|
|
4027
|
+
function initGitRepo(projectDir, verbose) {
|
|
4028
|
+
if (verbose) console.log(chalk34.gray("Initializing git repository..."));
|
|
4029
|
+
const result = spawnSync7("git", ["init", "-b", "main"], {
|
|
4030
|
+
cwd: projectDir,
|
|
4031
|
+
stdio: verbose ? "inherit" : "pipe"
|
|
4032
|
+
});
|
|
4033
|
+
if (result.status === 0) {
|
|
4034
|
+
console.log(chalk34.green("Initialized git repository"));
|
|
4035
|
+
} else {
|
|
4036
|
+
console.warn(chalk34.yellow("git init failed, skipping"));
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
function installDependencies(projectDir, pm) {
|
|
4040
|
+
console.log(chalk34.gray(`Running ${pm} install...`));
|
|
4041
|
+
const result = spawnSync7(pm, ["install"], {
|
|
4042
|
+
cwd: projectDir,
|
|
4043
|
+
stdio: "inherit"
|
|
4044
|
+
});
|
|
4045
|
+
if (result.status !== 0) {
|
|
4046
|
+
console.warn(chalk34.yellow(`${pm} install failed`));
|
|
4047
|
+
return false;
|
|
4048
|
+
}
|
|
4049
|
+
console.log(chalk34.green("Dependencies installed"));
|
|
4050
|
+
return true;
|
|
4051
|
+
}
|
|
4052
|
+
async function repoInit(params) {
|
|
4053
|
+
const {
|
|
4054
|
+
description,
|
|
4055
|
+
pm,
|
|
4056
|
+
scope,
|
|
4057
|
+
skipGit,
|
|
4058
|
+
skipInstall,
|
|
4059
|
+
template,
|
|
4060
|
+
verbose
|
|
4061
|
+
} = params;
|
|
4062
|
+
let name = params.name;
|
|
4063
|
+
if (!name) {
|
|
4064
|
+
name = await askQuestion(chalk34.cyan("Project name: "));
|
|
4065
|
+
if (!name) {
|
|
4066
|
+
console.error(chalk34.red("Project name is required"));
|
|
4067
|
+
return 1;
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
const projectName = PATH22.basename(name);
|
|
4071
|
+
const packageName2 = params.packageName ?? projectName;
|
|
4072
|
+
const githubOrg = params.githubOrg ?? scope.replace(/^@/, "");
|
|
4073
|
+
const variables = buildVariables({
|
|
4074
|
+
description,
|
|
4075
|
+
githubOrg,
|
|
4076
|
+
packageName: packageName2,
|
|
4077
|
+
pm,
|
|
4078
|
+
projectName,
|
|
4079
|
+
scope
|
|
4080
|
+
});
|
|
4081
|
+
if (verbose) {
|
|
4082
|
+
console.log(chalk34.gray("Template variables:"));
|
|
4083
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
4084
|
+
console.log(chalk34.gray(` ${key}: ${value}`));
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
const projectDir = PATH22.resolve(process.cwd(), name);
|
|
4088
|
+
if (!ensureEmptyDir(projectDir, name)) return 1;
|
|
4089
|
+
const rootCount = scaffoldFiles(template, "root", projectDir, pm, variables, verbose);
|
|
4090
|
+
const pkgDir = PATH22.resolve(projectDir, "packages", packageName2);
|
|
4091
|
+
const pkgCount = scaffoldFiles(template, "package", pkgDir, pm, variables, verbose);
|
|
4092
|
+
console.log(chalk34.green(`Scaffolded ${rootCount + pkgCount} files into ${name}/`));
|
|
4093
|
+
if (!skipGit) initGitRepo(projectDir, verbose);
|
|
4094
|
+
if (!skipInstall && !installDependencies(projectDir, pm)) return 1;
|
|
4095
|
+
console.log("");
|
|
4096
|
+
console.log(chalk34.cyan(`Project ${name} created successfully!`));
|
|
4097
|
+
console.log("");
|
|
4098
|
+
console.log(chalk34.gray("Next steps:"));
|
|
4099
|
+
console.log(chalk34.gray(` cd ${name}`));
|
|
4100
|
+
if (skipInstall) console.log(chalk34.gray(` ${pm} install`));
|
|
4101
|
+
console.log(chalk34.gray(` ${pm} xy build`));
|
|
4102
|
+
return 0;
|
|
4103
|
+
}
|
|
4104
|
+
|
|
4105
|
+
// src/actions/retest.ts
|
|
4106
|
+
var retest = ({ target } = {}) => {
|
|
4107
|
+
const pm = getPackageManager();
|
|
4108
|
+
if (target && pm.findWorkspace(target)) {
|
|
4109
|
+
return runSteps(`Re-Test [${target}]`, [
|
|
4110
|
+
pm.runInWorkspace(target, "vitest", ["--clearCache"]),
|
|
4111
|
+
pm.runInWorkspace(target, "vitest", ["."])
|
|
4112
|
+
]);
|
|
4113
|
+
}
|
|
4114
|
+
const path5 = target ?? ".";
|
|
4115
|
+
return runSteps("Re-Test", [
|
|
4116
|
+
["vitest", ["--clearCache"]],
|
|
4117
|
+
["vitest", [path5]]
|
|
4118
|
+
]);
|
|
4119
|
+
};
|
|
4120
|
+
|
|
4121
|
+
// src/actions/test.ts
|
|
4122
|
+
var test = ({ target } = {}) => {
|
|
4123
|
+
const pm = getPackageManager();
|
|
4124
|
+
if (target && pm.findWorkspace(target)) {
|
|
4125
|
+
return runSteps(`Test [${target}]`, [pm.runInWorkspace(target, "vitest", ["."])]);
|
|
4126
|
+
}
|
|
4127
|
+
const path5 = target ?? ".";
|
|
4128
|
+
return runSteps("Test", [["vitest", [path5]]]);
|
|
4129
|
+
};
|
|
4130
|
+
|
|
4131
|
+
// src/xy/common/checkCommand.ts
|
|
4132
|
+
var checkCommand = {
|
|
4133
|
+
command: "check",
|
|
4134
|
+
describe: "Check - Run gitlint, publint, repo lint, lintlint, and readme lint",
|
|
4135
|
+
builder: (yargs) => {
|
|
4136
|
+
return yargs.option("fix", {
|
|
4137
|
+
default: false,
|
|
4138
|
+
description: "Auto-fix fixable issues",
|
|
4139
|
+
type: "boolean"
|
|
4140
|
+
});
|
|
4141
|
+
},
|
|
4142
|
+
handler: async (argv) => {
|
|
4143
|
+
const verbose = !!argv.verbose;
|
|
4144
|
+
const fix = !!argv.fix;
|
|
4145
|
+
const jobs = argv.jobs;
|
|
4146
|
+
let errors = 0;
|
|
4147
|
+
if (verbose) console.log("Check");
|
|
4148
|
+
console.log(chalk35.blue("\n\u2014 gitlint \u2014"));
|
|
4149
|
+
errors += fix ? gitlintFix() : gitlint();
|
|
4150
|
+
console.log(chalk35.blue("\n\u2014 publint \u2014"));
|
|
4151
|
+
errors += await publint({
|
|
4152
|
+
fix,
|
|
4153
|
+
jobs,
|
|
4154
|
+
verbose
|
|
4155
|
+
});
|
|
4156
|
+
console.log(chalk35.blue("\n\u2014 repo lint \u2014"));
|
|
4157
|
+
errors += packageLintMonorepo(fix);
|
|
4158
|
+
console.log(chalk35.blue("\n\u2014 lintlint \u2014"));
|
|
4159
|
+
errors += await lintlint({ fix, verbose });
|
|
4160
|
+
console.log(chalk35.blue("\n\u2014 readme lint \u2014"));
|
|
4161
|
+
const config2 = await loadConfig();
|
|
4162
|
+
errors += readmeLint({ config: config2, verbose });
|
|
4163
|
+
if (errors > 0) {
|
|
4164
|
+
console.log(chalk35.red(`${errors} issue(s) found`));
|
|
4165
|
+
} else {
|
|
4166
|
+
console.log(chalk35.green("All checks passed"));
|
|
4167
|
+
}
|
|
4168
|
+
process.exitCode = errors > 0 ? 1 : 0;
|
|
4169
|
+
}
|
|
4170
|
+
};
|
|
4171
|
+
|
|
4172
|
+
// src/xy/common/claude/checkCommand.ts
|
|
4173
|
+
var checkCommand2 = {
|
|
4174
|
+
command: "check",
|
|
4175
|
+
describe: "Check if Claude configuration is up to date with templates",
|
|
4176
|
+
handler: (argv) => {
|
|
4177
|
+
if (argv.verbose) console.log("Claude Check");
|
|
4178
|
+
process.exitCode = claudeCheck();
|
|
4179
|
+
}
|
|
4180
|
+
};
|
|
4181
|
+
|
|
4182
|
+
// src/xy/common/claude/cleanCommand.ts
|
|
4183
|
+
var cleanCommand = {
|
|
4184
|
+
command: "clean",
|
|
4185
|
+
describe: "Remove all Claude configuration files from the repo",
|
|
4186
|
+
handler: (argv) => {
|
|
4187
|
+
if (argv.verbose) console.log("Claude Clean");
|
|
4188
|
+
process.exitCode = claudeClean();
|
|
4189
|
+
}
|
|
4190
|
+
};
|
|
4191
|
+
|
|
4192
|
+
// src/xy/common/claude/commandsCommand.ts
|
|
4193
|
+
var commandsCommand = {
|
|
4194
|
+
command: "commands",
|
|
4195
|
+
describe: "Sync XY Labs standard Claude slash commands to .claude/commands/",
|
|
4196
|
+
handler: (argv) => {
|
|
4197
|
+
if (argv.verbose) console.log("Claude Commands");
|
|
4198
|
+
process.exitCode = claudeCommands();
|
|
4199
|
+
}
|
|
4200
|
+
};
|
|
4201
|
+
|
|
4202
|
+
// src/xy/common/claude/initCommand.ts
|
|
4203
|
+
var initCommand = {
|
|
4204
|
+
builder: (yargs) => {
|
|
4205
|
+
return yargs.option("force", {
|
|
4206
|
+
alias: "f",
|
|
4207
|
+
default: false,
|
|
4208
|
+
description: "Overwrite existing CLAUDE.md",
|
|
4209
|
+
type: "boolean"
|
|
4210
|
+
}).option("level", {
|
|
4211
|
+
choices: ["restrictive", "permissive"],
|
|
4212
|
+
default: "permissive",
|
|
4213
|
+
description: "Permission level for settings (restrictive omits node, python3, claude, sed, xargs, tee)",
|
|
4214
|
+
type: "string"
|
|
4215
|
+
});
|
|
4216
|
+
},
|
|
4217
|
+
command: "init",
|
|
4218
|
+
describe: "Initialize all Claude configuration (commands, rules, skills, settings)",
|
|
4219
|
+
handler: async (argv) => {
|
|
4220
|
+
if (argv.verbose) console.log("Claude Init");
|
|
4221
|
+
const commandsResult = claudeCommands();
|
|
4222
|
+
const rulesResult = claudeRules({ force: argv.force });
|
|
4223
|
+
const skillsResult = claudeSkills();
|
|
4224
|
+
const settingsResult = await claudeSettings({ level: argv.level });
|
|
4225
|
+
process.exitCode = commandsResult || rulesResult || skillsResult || settingsResult;
|
|
4226
|
+
}
|
|
4227
|
+
};
|
|
4228
|
+
|
|
4229
|
+
// src/xy/common/claude/rulesCommand.ts
|
|
4230
|
+
var rulesCommand = {
|
|
4231
|
+
builder: (yargs) => {
|
|
4232
|
+
return yargs.option("force", {
|
|
4233
|
+
alias: "f",
|
|
4234
|
+
default: false,
|
|
4235
|
+
description: "Overwrite existing CLAUDE.md",
|
|
4236
|
+
type: "boolean"
|
|
4237
|
+
});
|
|
4238
|
+
},
|
|
4239
|
+
command: "rules",
|
|
4240
|
+
describe: "Sync XY Labs standard Claude rules to .claude/rules/",
|
|
4241
|
+
handler: (argv) => {
|
|
4242
|
+
if (argv.verbose) console.log("Claude Rules");
|
|
4243
|
+
process.exitCode = claudeRules({ force: argv.force });
|
|
4244
|
+
}
|
|
4245
|
+
};
|
|
4246
|
+
|
|
4247
|
+
// src/xy/common/claude/settingsCommand.ts
|
|
4248
|
+
var settingsCommand = {
|
|
4249
|
+
builder: (yargs) => {
|
|
4250
|
+
return yargs.option("level", {
|
|
4251
|
+
choices: ["restrictive", "permissive"],
|
|
4252
|
+
default: "permissive",
|
|
4253
|
+
description: "Permission level (restrictive omits node, python3, claude, sed, xargs, tee)",
|
|
4254
|
+
type: "string"
|
|
4255
|
+
});
|
|
4256
|
+
},
|
|
4257
|
+
command: "settings",
|
|
4258
|
+
describe: "Initialize .claude/settings.local.json with XY Labs defaults",
|
|
4259
|
+
handler: async (argv) => {
|
|
4260
|
+
if (argv.verbose) console.log("Claude Settings");
|
|
4261
|
+
process.exitCode = await claudeSettings({ level: argv.level });
|
|
4262
|
+
}
|
|
4263
|
+
};
|
|
4264
|
+
|
|
4265
|
+
// src/xy/common/claude/skillsCommand.ts
|
|
4266
|
+
var skillsCommand = {
|
|
4267
|
+
builder: (yargs) => yargs,
|
|
4268
|
+
command: "skills",
|
|
4269
|
+
describe: "Sync XY Labs standard Claude skills to .claude/skills/",
|
|
4270
|
+
handler: (argv) => {
|
|
4271
|
+
if (argv.verbose) console.log("Claude Skills");
|
|
4272
|
+
process.exitCode = claudeSkills();
|
|
4273
|
+
}
|
|
4274
|
+
};
|
|
4275
|
+
|
|
4276
|
+
// src/xy/common/claude/index.ts
|
|
4277
|
+
var claudeCommand = {
|
|
4278
|
+
builder: (yargs) => {
|
|
4279
|
+
return yargs.command(checkCommand2).command(cleanCommand).command(commandsCommand).command(initCommand).command(rulesCommand).command(settingsCommand).command(skillsCommand).demandCommand(1, "Please specify a claude subcommand").strictCommands();
|
|
4280
|
+
},
|
|
4281
|
+
command: "claude",
|
|
4282
|
+
describe: "Claude - Claude Code configuration utilities",
|
|
4283
|
+
handler: () => {
|
|
4284
|
+
}
|
|
4285
|
+
};
|
|
4286
|
+
|
|
4287
|
+
// src/xy/common/cleanDocsCommand.ts
|
|
4288
|
+
var cleanDocsCommand = {
|
|
4289
|
+
command: "clean-docs",
|
|
4290
|
+
describe: "CleanDocs - Clean TypeDocs",
|
|
4291
|
+
handler: (argv) => {
|
|
4292
|
+
if (argv.verbose) console.log("Cleaning TypeDocs: all");
|
|
4293
|
+
process.exitCode = cleanDocs();
|
|
4294
|
+
}
|
|
4295
|
+
};
|
|
4296
|
+
|
|
4297
|
+
// src/xy/param.ts
|
|
4298
|
+
var packagePositionalParam = (yargs) => {
|
|
4299
|
+
return yargs.positional("package", { describe: "Specific package to target", type: "string" });
|
|
4300
|
+
};
|
|
4301
|
+
|
|
4302
|
+
// src/xy/common/deadCommand.ts
|
|
4303
|
+
var deadCommand = {
|
|
4304
|
+
builder: (yargs) => {
|
|
4305
|
+
return packagePositionalParam(yargs);
|
|
4306
|
+
},
|
|
4307
|
+
command: "dead [package]",
|
|
4308
|
+
describe: "Dead - Check for dead code",
|
|
4309
|
+
handler: (argv) => {
|
|
4310
|
+
if (argv.verbose) console.log("Dead");
|
|
4311
|
+
process.exitCode = dead();
|
|
4312
|
+
}
|
|
4313
|
+
};
|
|
4314
|
+
|
|
4315
|
+
// src/xy/common/genDocsCommand.ts
|
|
4316
|
+
var genDocsCommand = {
|
|
4317
|
+
builder: (yargs) => {
|
|
4318
|
+
return packagePositionalParam(yargs);
|
|
4319
|
+
},
|
|
4320
|
+
command: "gen-docs [package]",
|
|
4321
|
+
describe: "GenDocs - Generate TypeDocs",
|
|
4322
|
+
handler: (argv) => {
|
|
4323
|
+
if (argv.verbose) console.log(`Generating TypeDocs: ${argv.package ?? "all"}`);
|
|
4324
|
+
process.exitCode = genDocs({
|
|
4325
|
+
incremental: !!argv.incremental,
|
|
4326
|
+
jobs: argv.jobs,
|
|
4327
|
+
pkg: argv.package
|
|
4328
|
+
});
|
|
4329
|
+
}
|
|
4330
|
+
};
|
|
4331
|
+
|
|
4332
|
+
// src/xy/common/gitignoreCommand.ts
|
|
4333
|
+
var gitignoreCommand = {
|
|
4334
|
+
command: "gitignore",
|
|
4335
|
+
describe: "GitIgnore - Generate root .gitignore and remove package .gitignore files",
|
|
4336
|
+
handler: (argv) => {
|
|
4337
|
+
if (argv.verbose) console.log("GitIgnore");
|
|
4338
|
+
process.exitCode = gitignore();
|
|
4339
|
+
}
|
|
4340
|
+
};
|
|
4341
|
+
|
|
4342
|
+
// src/xy/common/gitlintCommand.ts
|
|
4343
|
+
var gitlintCommand = {
|
|
4344
|
+
builder: (yargs) => {
|
|
4345
|
+
return yargs.option("fix", {
|
|
4346
|
+
default: false,
|
|
4347
|
+
description: "Auto-fix git config issues",
|
|
4348
|
+
type: "boolean"
|
|
4349
|
+
});
|
|
4350
|
+
},
|
|
4351
|
+
command: "gitlint",
|
|
4352
|
+
describe: "Gitlint - Lint your git config",
|
|
4353
|
+
handler: (argv) => {
|
|
4354
|
+
if (argv.verbose) console.log("Gitlint");
|
|
4355
|
+
process.exitCode = argv.fix ? gitlintFix() : gitlint();
|
|
4356
|
+
}
|
|
4357
|
+
};
|
|
4358
|
+
|
|
4359
|
+
// src/xy/common/licenseCommand.ts
|
|
4360
|
+
var licenseCommand = {
|
|
4361
|
+
builder: (yargs) => {
|
|
4362
|
+
return packagePositionalParam(yargs);
|
|
4363
|
+
},
|
|
4364
|
+
command: "license [package]",
|
|
4365
|
+
describe: "License - Check licenses of dependencies",
|
|
4366
|
+
handler: async (argv) => {
|
|
4367
|
+
if (argv.verbose) console.log(`License: ${argv.package ?? "all"}`);
|
|
4368
|
+
process.exitCode = await license();
|
|
4369
|
+
}
|
|
4370
|
+
};
|
|
4371
|
+
|
|
4372
|
+
// src/xy/common/npmignoreGenCommand.ts
|
|
4373
|
+
var npmignoreGenCommand = {
|
|
4374
|
+
command: "npmignore-gen",
|
|
4375
|
+
describe: "NpmIgnore Gen - Generate .npmignore files",
|
|
4376
|
+
handler: (argv) => {
|
|
4377
|
+
if (argv.verbose) console.log("NpmIgnore Gen");
|
|
4378
|
+
process.exitCode = npmignoreGen();
|
|
4379
|
+
}
|
|
4380
|
+
};
|
|
4381
|
+
|
|
4382
|
+
// src/xy/common/orphan/cleanCommand.ts
|
|
4383
|
+
var cleanCommand2 = {
|
|
4384
|
+
command: "clean",
|
|
4385
|
+
describe: "Remove orphaned directories containing only build artifacts",
|
|
4386
|
+
handler: (argv) => {
|
|
4387
|
+
if (argv.verbose) console.log("Orphan Clean");
|
|
4388
|
+
process.exitCode = orphanClean({ verbose: argv.verbose });
|
|
4389
|
+
}
|
|
4390
|
+
};
|
|
4391
|
+
|
|
4392
|
+
// src/xy/common/orphan/listCommand.ts
|
|
4393
|
+
var listCommand = {
|
|
4394
|
+
command: "list",
|
|
4395
|
+
describe: "List orphaned directories containing only build artifacts",
|
|
4396
|
+
handler: (argv) => {
|
|
4397
|
+
if (argv.verbose) console.log("Orphan List");
|
|
4398
|
+
process.exitCode = orphanList({ verbose: argv.verbose });
|
|
4399
|
+
}
|
|
4400
|
+
};
|
|
4401
|
+
|
|
4402
|
+
// src/xy/common/orphan/index.ts
|
|
4403
|
+
var orphanCommand = {
|
|
4404
|
+
builder: (yargs) => {
|
|
4405
|
+
return yargs.command(listCommand).command(cleanCommand2).demandCommand(1, "Please specify an orphan subcommand").strictCommands();
|
|
4406
|
+
},
|
|
4407
|
+
command: "orphan",
|
|
4408
|
+
describe: "Orphan - Detect and clean orphaned build artifacts",
|
|
4409
|
+
handler: () => {
|
|
4410
|
+
}
|
|
4411
|
+
};
|
|
4412
|
+
|
|
4413
|
+
// src/xy/common/packmanCommand.ts
|
|
4414
|
+
var convertCommand = {
|
|
4415
|
+
command: "convert <target>",
|
|
4416
|
+
describe: "Convert repo to a different package manager (pnpm or yarn)",
|
|
4417
|
+
builder: (yargs) => {
|
|
4418
|
+
return yargs.positional("target", {
|
|
4419
|
+
choices: ["pnpm", "yarn"],
|
|
4420
|
+
describe: "Target package manager",
|
|
4421
|
+
type: "string"
|
|
4422
|
+
});
|
|
4423
|
+
},
|
|
4424
|
+
handler: (argv) => {
|
|
4425
|
+
process.exitCode = convert({
|
|
4426
|
+
target: argv.target,
|
|
4427
|
+
verbose: !!argv.verbose
|
|
4428
|
+
});
|
|
4429
|
+
}
|
|
4430
|
+
};
|
|
4431
|
+
var cleanCommand3 = {
|
|
4432
|
+
command: "clean",
|
|
4433
|
+
describe: "Remove node_modules and lock files for a clean install",
|
|
4434
|
+
handler: (argv) => {
|
|
4435
|
+
process.exitCode = packmanClean({ verbose: !!argv.verbose });
|
|
4436
|
+
}
|
|
4437
|
+
};
|
|
4438
|
+
var lintCommand = {
|
|
4439
|
+
command: "lint",
|
|
4440
|
+
describe: "Check package manager configuration settings",
|
|
4441
|
+
builder: (yargs) => {
|
|
4442
|
+
return yargs.option("fix", {
|
|
4443
|
+
alias: "f",
|
|
4444
|
+
default: false,
|
|
4445
|
+
description: "Auto-fix configuration issues",
|
|
4446
|
+
type: "boolean"
|
|
4447
|
+
});
|
|
4448
|
+
},
|
|
4449
|
+
handler: (argv) => {
|
|
4450
|
+
process.exitCode = packmanLint({
|
|
4451
|
+
fix: !!argv.fix,
|
|
4452
|
+
verbose: !!argv.verbose
|
|
4453
|
+
});
|
|
4454
|
+
}
|
|
4455
|
+
};
|
|
4456
|
+
var packmanCommand = {
|
|
4457
|
+
builder: (yargs) => {
|
|
4458
|
+
return yargs.command(cleanCommand3).command(convertCommand).command(lintCommand).demandCommand(1, "Please specify a packman subcommand").strictCommands();
|
|
4459
|
+
},
|
|
4460
|
+
command: "packman",
|
|
4461
|
+
describe: "Package Manager - Configuration and conversion utilities",
|
|
4462
|
+
handler: () => {
|
|
4463
|
+
}
|
|
4464
|
+
};
|
|
4465
|
+
|
|
4466
|
+
// src/xy/common/readme/genCommand.ts
|
|
4467
|
+
var genCommand = {
|
|
4468
|
+
builder: (yargs) => {
|
|
4469
|
+
return packagePositionalParam(yargs).option("template", {
|
|
4470
|
+
alias: "t",
|
|
4471
|
+
description: "Path to README.template.md",
|
|
4472
|
+
type: "string"
|
|
4473
|
+
}).option("notypedoc", {
|
|
4474
|
+
default: false,
|
|
4475
|
+
description: "Disable TypeDoc reference sections",
|
|
4476
|
+
type: "boolean"
|
|
4477
|
+
});
|
|
4478
|
+
},
|
|
4479
|
+
aliases: ["$0"],
|
|
4480
|
+
command: "gen [package]",
|
|
4481
|
+
describe: "Generate README.md files from template",
|
|
4482
|
+
handler: async (argv) => {
|
|
4483
|
+
if (argv.verbose) console.log("Readme Gen");
|
|
4484
|
+
process.exitCode = await readmeGen({
|
|
4485
|
+
jobs: argv.jobs,
|
|
4486
|
+
pkg: argv.package,
|
|
4487
|
+
templatePath: argv.template,
|
|
4488
|
+
typedoc: !argv.notypedoc,
|
|
4489
|
+
verbose: !!argv.verbose
|
|
4490
|
+
});
|
|
4491
|
+
}
|
|
4492
|
+
};
|
|
4493
|
+
|
|
4494
|
+
// src/xy/common/readme/initCommand.ts
|
|
4495
|
+
var initCommand2 = {
|
|
4496
|
+
builder: (yargs) => {
|
|
4497
|
+
return yargs.option("template", {
|
|
4498
|
+
alias: "t",
|
|
4499
|
+
description: "Path to README.template.md",
|
|
4500
|
+
type: "string"
|
|
4501
|
+
});
|
|
4502
|
+
},
|
|
4503
|
+
command: "init",
|
|
4504
|
+
describe: "Initialize README template and logo files",
|
|
4505
|
+
handler: async (argv) => {
|
|
4506
|
+
if (argv.verbose) console.log("Readme Init");
|
|
4507
|
+
process.exitCode = await readmeInit({
|
|
4508
|
+
templatePath: argv.template,
|
|
4509
|
+
verbose: !!argv.verbose
|
|
4510
|
+
});
|
|
4511
|
+
}
|
|
4512
|
+
};
|
|
4513
|
+
|
|
4514
|
+
// src/xy/common/readme/lintCommand.ts
|
|
4515
|
+
var lintCommand2 = {
|
|
4516
|
+
command: "lint",
|
|
4517
|
+
describe: "Check for missing readme templates, body files, logos, and descriptions",
|
|
4518
|
+
handler: async (argv) => {
|
|
4519
|
+
const config2 = await loadConfig();
|
|
4520
|
+
process.exitCode = readmeLint({ config: config2, verbose: !!argv.verbose });
|
|
4521
|
+
}
|
|
4522
|
+
};
|
|
4523
|
+
|
|
4524
|
+
// src/xy/common/readme/index.ts
|
|
4525
|
+
var readmeCommand = {
|
|
4526
|
+
builder: (yargs) => {
|
|
4527
|
+
return yargs.command(genCommand).command(initCommand2).command(lintCommand2).demandCommand(1, "Please specify a readme subcommand").strictCommands();
|
|
4528
|
+
},
|
|
4529
|
+
command: "readme",
|
|
4530
|
+
describe: "Readme - README file utilities",
|
|
4531
|
+
handler: () => {
|
|
4532
|
+
}
|
|
4533
|
+
};
|
|
4534
|
+
|
|
4535
|
+
// src/xy/common/repo/initCommand.ts
|
|
4536
|
+
var initCommand3 = {
|
|
4537
|
+
command: "init <template> [name]",
|
|
4538
|
+
describe: "Scaffold a new monorepo from a template",
|
|
4539
|
+
builder: (yargs) => {
|
|
4540
|
+
return yargs.positional("template", {
|
|
4541
|
+
choices: ["cli"],
|
|
4542
|
+
describe: "Template to use",
|
|
4543
|
+
type: "string"
|
|
4544
|
+
}).positional("name", {
|
|
4545
|
+
describe: "Project name (also used as directory name)",
|
|
4546
|
+
type: "string"
|
|
4547
|
+
}).option("scope", {
|
|
4548
|
+
default: "@xylabs",
|
|
4549
|
+
describe: "npm scope for packages",
|
|
4550
|
+
type: "string"
|
|
4551
|
+
}).option("package", {
|
|
4552
|
+
describe: "Package name within the monorepo (defaults to project name)",
|
|
4553
|
+
type: "string"
|
|
4554
|
+
}).option("description", {
|
|
4555
|
+
default: "",
|
|
4556
|
+
describe: "Project description",
|
|
4557
|
+
type: "string"
|
|
4558
|
+
}).option("github-org", {
|
|
4559
|
+
describe: "GitHub organization (derived from scope if not set)",
|
|
4560
|
+
type: "string"
|
|
4561
|
+
}).option("pm", {
|
|
4562
|
+
choices: ["pnpm", "yarn"],
|
|
4563
|
+
default: "pnpm",
|
|
4564
|
+
describe: "Package manager to configure",
|
|
4565
|
+
type: "string"
|
|
4566
|
+
}).option("skip-install", {
|
|
4567
|
+
default: false,
|
|
4568
|
+
describe: "Skip dependency installation after scaffolding",
|
|
4569
|
+
type: "boolean"
|
|
4570
|
+
}).option("skip-git", {
|
|
4571
|
+
default: false,
|
|
4572
|
+
describe: "Skip git init after scaffolding",
|
|
4573
|
+
type: "boolean"
|
|
4574
|
+
});
|
|
4575
|
+
},
|
|
4576
|
+
handler: async (argv) => {
|
|
4577
|
+
if (argv.verbose) console.log("Repo Init");
|
|
4578
|
+
process.exitCode = await repoInit({
|
|
4579
|
+
description: argv.description,
|
|
4580
|
+
githubOrg: argv["github-org"],
|
|
4581
|
+
name: argv.name,
|
|
4582
|
+
packageName: argv.package,
|
|
4583
|
+
pm: argv.pm,
|
|
4584
|
+
scope: argv.scope,
|
|
4585
|
+
skipGit: !!argv.skipGit,
|
|
4586
|
+
skipInstall: !!argv.skipInstall,
|
|
4587
|
+
template: argv.template,
|
|
4588
|
+
verbose: !!argv.verbose
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
4591
|
+
};
|
|
4592
|
+
|
|
4593
|
+
// src/xy/common/repo/lintCommand.ts
|
|
4594
|
+
var lintCommand3 = {
|
|
4595
|
+
command: "lint",
|
|
4596
|
+
describe: "Check monorepo package structure",
|
|
4597
|
+
builder: (yargs) => {
|
|
4598
|
+
return yargs.option("fix", {
|
|
4599
|
+
default: false,
|
|
4600
|
+
description: "Auto-fix fixable issues",
|
|
4601
|
+
type: "boolean"
|
|
4602
|
+
});
|
|
4603
|
+
},
|
|
4604
|
+
handler: (argv) => {
|
|
4605
|
+
if (argv.verbose) console.log("Repo Lint");
|
|
4606
|
+
process.exitCode = packageLintMonorepo(!!argv.fix);
|
|
4607
|
+
}
|
|
4608
|
+
};
|
|
4609
|
+
|
|
4610
|
+
// src/xy/common/repo/index.ts
|
|
4611
|
+
var repoCommand = {
|
|
4612
|
+
builder: (yargs) => {
|
|
4613
|
+
return yargs.command(initCommand3).command(lintCommand3).demandCommand(1, "Please specify a repo subcommand").strictCommands();
|
|
4614
|
+
},
|
|
4615
|
+
command: "repo",
|
|
4616
|
+
describe: "Repo - Repository structure utilities",
|
|
4617
|
+
handler: () => {
|
|
4618
|
+
}
|
|
4619
|
+
};
|
|
4620
|
+
|
|
4621
|
+
// src/xy/common/retestCommand.ts
|
|
4622
|
+
var retestCommand = {
|
|
4623
|
+
command: "retest [target]",
|
|
4624
|
+
describe: "Re-Test - Run Vitest Tests with cleaned cache",
|
|
4625
|
+
builder: (yargs) => {
|
|
4626
|
+
return yargs.positional("target", { describe: "Package name or file/folder path to test" });
|
|
4627
|
+
},
|
|
4628
|
+
handler: (argv) => {
|
|
4629
|
+
if (argv.verbose) console.log(`Re-Testing: ${argv.target ?? "all"}`);
|
|
4630
|
+
process.exitCode = retest({ target: argv.target });
|
|
4631
|
+
}
|
|
4632
|
+
};
|
|
4633
|
+
|
|
4634
|
+
// src/xy/common/testCommand.ts
|
|
4635
|
+
var testCommand = {
|
|
4636
|
+
command: "test [target]",
|
|
4637
|
+
describe: "Test - Run Vitest Tests",
|
|
4638
|
+
builder: (yargs) => {
|
|
4639
|
+
return yargs.positional("target", { describe: "Package name or file/folder path to test" });
|
|
4640
|
+
},
|
|
4641
|
+
handler: (argv) => {
|
|
4642
|
+
if (argv.verbose) console.log(`Testing: ${argv.target ?? "all"}`);
|
|
4643
|
+
process.exitCode = test({ target: argv.target });
|
|
4644
|
+
}
|
|
4645
|
+
};
|
|
4646
|
+
|
|
4647
|
+
// src/xy/common/index.ts
|
|
4648
|
+
var xyCommonCommands = (args) => {
|
|
4649
|
+
return args.command(checkCommand).command(claudeCommand).command(licenseCommand).command(deadCommand).command(genDocsCommand).command(cleanDocsCommand).command(gitlintCommand).command(gitignoreCommand).command(npmignoreGenCommand).command(orphanCommand).command(packmanCommand).command(readmeCommand).command(repoCommand).command(retestCommand).command(testCommand);
|
|
4650
|
+
};
|
|
4651
|
+
export {
|
|
4652
|
+
xyCommonCommands
|
|
4653
|
+
};
|
|
4654
|
+
//# sourceMappingURL=index.mjs.map
|