safeword 0.15.7 → 0.15.8
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/{check-JQMMRAOP.js → check-DQVIVY3V.js} +8 -5
- package/dist/check-DQVIVY3V.js.map +1 -0
- package/dist/{chunk-SPPPGWFT.js → chunk-4C3ASNAV.js} +2 -3
- package/dist/chunk-4C3ASNAV.js.map +1 -0
- package/dist/chunk-57C2XQBO.js +152 -0
- package/dist/chunk-57C2XQBO.js.map +1 -0
- package/dist/chunk-7OYOED6T.js +955 -0
- package/dist/chunk-7OYOED6T.js.map +1 -0
- package/dist/{chunk-WSFYO2MK.js → chunk-C2I6E7CC.js} +243 -173
- package/dist/chunk-C2I6E7CC.js.map +1 -0
- package/dist/{chunk-HSY47672.js → chunk-JLOQFDEL.js} +6 -3
- package/dist/chunk-JLOQFDEL.js.map +1 -0
- package/dist/{chunk-ESL7ZI5O.js → chunk-OFRKIGME.js} +3 -3
- package/dist/cli.js +8 -8
- package/dist/cli.js.map +1 -1
- package/dist/{diff-C3OHG2JB.js → diff-NZGZ6CPR.js} +7 -4
- package/dist/{diff-C3OHG2JB.js.map → diff-NZGZ6CPR.js.map} +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -1
- package/dist/presets/typescript/index.d.ts +283 -0
- package/dist/presets/typescript/index.js +36 -0
- package/dist/{reset-P3WI3BKA.js → reset-6I2IEPBY.js} +4 -3
- package/dist/{reset-P3WI3BKA.js.map → reset-6I2IEPBY.js.map} +1 -1
- package/dist/setup-M3TBEMDZ.js +304 -0
- package/dist/setup-M3TBEMDZ.js.map +1 -0
- package/dist/{sync-config-W3ZVCKQV.js → sync-config-SJ2HBZM6.js} +3 -3
- package/dist/sync-config-SJ2HBZM6.js.map +1 -0
- package/dist/{upgrade-RX5FE5GL.js → upgrade-QOVSU2M2.js} +7 -8
- package/dist/upgrade-QOVSU2M2.js.map +1 -0
- package/package.json +5 -1
- package/templates/AGENTS.md +0 -2
- package/templates/SAFEWORD.md +3 -3
- package/templates/guides/cli-reference.md +1 -1
- package/templates/guides/learning-extraction.md +48 -84
- package/templates/skills/safeword-bdd-orchestrating/SKILL.md +2 -2
- package/dist/check-JQMMRAOP.js.map +0 -1
- package/dist/chunk-HSY47672.js.map +0 -1
- package/dist/chunk-SPPPGWFT.js.map +0 -1
- package/dist/chunk-WSFYO2MK.js.map +0 -1
- package/dist/setup-LEDGIKSR.js +0 -245
- package/dist/setup-LEDGIKSR.js.map +0 -1
- package/dist/upgrade-RX5FE5GL.js.map +0 -1
- package/templates/hooks/post-tool-guide-check.ts +0 -59
- package/templates/knip.json +0 -3
- /package/dist/{chunk-ESL7ZI5O.js.map → chunk-OFRKIGME.js.map} +0 -0
- /package/dist/{sync-config-W3ZVCKQV.js.map → presets/typescript/index.js.map} +0 -0
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-FJYRWU2V.js";
|
|
4
4
|
import {
|
|
5
5
|
getMissingPacks
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OFRKIGME.js";
|
|
7
7
|
import {
|
|
8
8
|
SAFEWORD_SCHEMA,
|
|
9
9
|
createProjectContext,
|
|
10
10
|
reconcile
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-C2I6E7CC.js";
|
|
12
|
+
import "./chunk-57C2XQBO.js";
|
|
12
13
|
import {
|
|
13
14
|
VERSION
|
|
14
15
|
} from "./chunk-ORQHKDT2.js";
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
readFileSafe,
|
|
22
23
|
success,
|
|
23
24
|
warn
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-4C3ASNAV.js";
|
|
25
26
|
|
|
26
27
|
// src/commands/check.ts
|
|
27
28
|
import nodePath from "path";
|
|
@@ -84,7 +85,9 @@ async function checkHealth(cwd) {
|
|
|
84
85
|
const versionPath = nodePath.join(safewordDirectory, "version");
|
|
85
86
|
const projectVersion = readFileSafe(versionPath)?.trim() ?? void 0;
|
|
86
87
|
const ctx = createProjectContext(cwd);
|
|
87
|
-
const result = await reconcile(SAFEWORD_SCHEMA, "upgrade", ctx, {
|
|
88
|
+
const result = await reconcile(SAFEWORD_SCHEMA, "upgrade", ctx, {
|
|
89
|
+
dryRun: true
|
|
90
|
+
});
|
|
88
91
|
const actionsWithPath = result.actions.filter(
|
|
89
92
|
(a) => a.type !== "chmod" && a.type !== "json-merge" && a.type !== "json-unmerge"
|
|
90
93
|
);
|
|
@@ -186,4 +189,4 @@ async function check(options) {
|
|
|
186
189
|
export {
|
|
187
190
|
check
|
|
188
191
|
};
|
|
189
|
-
//# sourceMappingURL=check-
|
|
192
|
+
//# sourceMappingURL=check-DQVIVY3V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/check.ts"],"sourcesContent":["/**\n * Check command - Verify project health and configuration\n *\n * Uses reconcile() with dryRun to detect missing files and configuration issues.\n */\n\nimport nodePath from 'node:path';\n\nimport { getMissingPacks } from '../packs/registry.js';\nimport { reconcile } from '../reconcile.js';\nimport { SAFEWORD_SCHEMA } from '../schema.js';\nimport { createProjectContext } from '../utils/context.js';\nimport { exists, readFileSafe } from '../utils/fs.js';\nimport { header, info, keyValue, listItem, success, warn } from '../utils/output.js';\nimport { isNewerVersion } from '../utils/version.js';\nimport { VERSION } from '../version.js';\n\ninterface CheckOptions {\n offline?: boolean;\n}\n\n/**\n * Check for missing files from write actions\n * @param cwd\n * @param actions\n */\nfunction findMissingFiles(cwd: string, actions: { type: string; path: string }[]): string[] {\n const issues: string[] = [];\n for (const action of actions) {\n if (action.type === 'write' && !exists(nodePath.join(cwd, action.path))) {\n issues.push(`Missing: ${action.path}`);\n }\n }\n return issues;\n}\n\n/**\n * Check for missing text patch markers\n * @param cwd\n * @param actions\n */\nfunction findMissingPatches(\n cwd: string,\n actions: { type: string; path: string; definition?: { marker: string } }[],\n): string[] {\n const issues: string[] = [];\n for (const action of actions) {\n if (action.type !== 'text-patch') continue;\n\n const fullPath = nodePath.join(cwd, action.path);\n if (exists(fullPath)) {\n const content = readFileSafe(fullPath) ?? '';\n if (action.definition && !content.includes(action.definition.marker)) {\n issues.push(`${action.path} missing safeword link`);\n }\n } else {\n issues.push(`${action.path} file missing`);\n }\n }\n return issues;\n}\n\ninterface HealthStatus {\n configured: boolean;\n projectVersion: string | undefined;\n cliVersion: string;\n updateAvailable: boolean;\n latestVersion: string | undefined;\n issues: string[];\n missingPackages: string[];\n missingPacks: string[];\n}\n\n/**\n * Check for latest version from npm (with timeout)\n * @param timeout\n */\nasync function checkLatestVersion(timeout = 3000): Promise<string | undefined> {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeout);\n\n const response = await fetch('https://registry.npmjs.org/safeword/latest', {\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) return undefined;\n\n const data = (await response.json()) as { version?: string };\n return data.version ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Check project configuration health using reconcile dryRun\n * @param cwd\n */\nasync function checkHealth(cwd: string): Promise<HealthStatus> {\n const safewordDirectory = nodePath.join(cwd, '.safeword');\n\n // Check if configured\n if (!exists(safewordDirectory)) {\n return {\n configured: false,\n projectVersion: undefined,\n cliVersion: VERSION,\n updateAvailable: false,\n latestVersion: undefined,\n issues: [],\n missingPackages: [],\n missingPacks: [],\n };\n }\n\n // Read project version\n const versionPath = nodePath.join(safewordDirectory, 'version');\n const projectVersion = readFileSafe(versionPath)?.trim() ?? undefined;\n\n // Use reconcile with dryRun to detect issues\n const ctx = createProjectContext(cwd);\n const result = await reconcile(SAFEWORD_SCHEMA, 'upgrade', ctx, {\n dryRun: true,\n });\n\n // Collect issues from write actions and text patches\n // Filter out chmod (paths[] instead of path) and json-merge/unmerge (incompatible definition)\n const actionsWithPath = result.actions.filter(\n (\n a,\n ): a is Exclude<\n (typeof result.actions)[number],\n { type: 'chmod' } | { type: 'json-merge' } | { type: 'json-unmerge' }\n > => a.type !== 'chmod' && a.type !== 'json-merge' && a.type !== 'json-unmerge',\n );\n const issues: string[] = [\n ...findMissingFiles(cwd, actionsWithPath),\n ...findMissingPatches(cwd, actionsWithPath),\n ];\n\n // Check for missing .claude/settings.json\n if (!exists(nodePath.join(cwd, '.claude', 'settings.json'))) {\n issues.push('Missing: .claude/settings.json');\n }\n\n // Check for missing language packs\n const missingPacks = getMissingPacks(cwd);\n\n return {\n configured: true,\n projectVersion,\n cliVersion: VERSION,\n updateAvailable: false,\n latestVersion: undefined,\n issues,\n missingPackages: result.packagesToInstall,\n missingPacks,\n };\n}\n\n/**\n * Check for CLI updates and report status\n * @param health\n */\nasync function reportUpdateStatus(health: HealthStatus): Promise<void> {\n info('\\nChecking for updates...');\n const latestVersion = await checkLatestVersion();\n\n if (!latestVersion) {\n warn(\"Couldn't check for updates (offline?)\");\n return;\n }\n\n health.latestVersion = latestVersion;\n health.updateAvailable = isNewerVersion(health.cliVersion, latestVersion);\n\n if (health.updateAvailable) {\n warn(`Update available: v${latestVersion}`);\n info('Run `bunx safeword@latest upgrade` to upgrade');\n } else {\n success('CLI is up to date');\n }\n}\n\n/**\n * Compare project version vs CLI version and report\n * @param health\n */\nfunction reportVersionMismatch(health: HealthStatus): void {\n if (!health.projectVersion) return;\n\n if (isNewerVersion(health.cliVersion, health.projectVersion)) {\n warn(`Project config (v${health.projectVersion}) is newer than CLI (v${health.cliVersion})`);\n info('Consider upgrading the CLI');\n } else if (isNewerVersion(health.projectVersion, health.cliVersion)) {\n info(`\\nUpgrade available for project config`);\n info(\n `Run \\`safeword upgrade\\` to update from v${health.projectVersion} to v${health.cliVersion}`,\n );\n }\n}\n\n/**\n * Report issues or success\n * @param health\n * @returns true if there are issues requiring attention\n */\nfunction reportHealthSummary(health: HealthStatus): boolean {\n // Check missing packs first (highest priority - explains missing files)\n if (health.missingPacks.length > 0) {\n header('Missing Language Packs');\n for (const pack of health.missingPacks) {\n listItem(`${pack} pack not installed`);\n }\n info('\\nRun `safeword upgrade` to install missing packs');\n return true;\n }\n\n if (health.missingPackages.length > 0) {\n header('Missing Packages');\n for (const pkg of health.missingPackages) listItem(pkg);\n info('\\nRun `safeword upgrade` to install missing packages');\n return true;\n }\n\n if (health.issues.length > 0) {\n header('Issues Found');\n for (const issue of health.issues) {\n warn(issue);\n }\n info('\\nRun `safeword upgrade` to repair configuration');\n return true;\n }\n\n success('\\nConfiguration is healthy');\n return false;\n}\n\n/**\n *\n * @param options\n */\nexport async function check(options: CheckOptions): Promise<void> {\n const cwd = process.cwd();\n\n header('Safeword Health Check');\n\n const health = await checkHealth(cwd);\n\n // Not configured\n if (!health.configured) {\n info('Not configured. Run `safeword setup` to initialize.');\n return;\n }\n\n // Show versions\n keyValue('Safeword CLI', `v${health.cliVersion}`);\n keyValue('Project config', health.projectVersion ? `v${health.projectVersion}` : 'unknown');\n\n // Check for updates (unless offline)\n if (options.offline) {\n info('\\nSkipped update check (offline mode)');\n } else {\n await reportUpdateStatus(health);\n }\n\n reportVersionMismatch(health);\n const hasIssues = reportHealthSummary(health);\n\n if (hasIssues) {\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
writeFileSync
|
|
11
11
|
} from "fs";
|
|
12
12
|
import nodePath from "path";
|
|
13
|
-
|
|
14
|
-
var __dirname = nodePath.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
var __dirname = import.meta.dirname;
|
|
15
14
|
function getTemplatesDirectory() {
|
|
16
15
|
const knownTemplateFile = "SAFEWORD.md";
|
|
17
16
|
const candidates = [
|
|
@@ -129,4 +128,4 @@ export {
|
|
|
129
128
|
listItem,
|
|
130
129
|
keyValue
|
|
131
130
|
};
|
|
132
|
-
//# sourceMappingURL=chunk-
|
|
131
|
+
//# sourceMappingURL=chunk-4C3ASNAV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/fs.ts","../src/utils/output.ts"],"sourcesContent":["/**\n * File system utilities for CLI operations\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmdirSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport nodePath from 'node:path';\n\n// Get the directory of this module (for locating templates)\nconst __dirname = import.meta.dirname;\n\n/**\n * Get path to bundled templates directory.\n * Works in both development (src/) and production (dist/) contexts.\n *\n * Note: We check for SAFEWORD.md to distinguish from src/templates/ which\n * contains TypeScript source files (config.ts, content.ts).\n *\n * Path resolution (bundled with tsup):\n * - From dist/chunk-*.js: __dirname = packages/cli/dist/ → ../templates\n */\nexport function getTemplatesDirectory(): string {\n const knownTemplateFile = 'SAFEWORD.md';\n\n // Try different relative paths - the bundled code ends up in dist/ directly (flat)\n // while source is in src/utils/\n const candidates = [\n nodePath.join(__dirname, '..', 'templates'), // From dist/ (flat bundled)\n nodePath.join(__dirname, '..', '..', 'templates'), // From src/utils/ or dist/utils/\n nodePath.join(__dirname, 'templates'), // Direct sibling (unlikely but safe)\n ];\n\n for (const candidate of candidates) {\n if (existsSync(nodePath.join(candidate, knownTemplateFile))) {\n return candidate;\n }\n }\n\n throw new Error('Templates directory not found');\n}\n\n/**\n * Check if a path exists\n * @param path\n */\nexport function exists(path: string): boolean {\n return existsSync(path);\n}\n\n/**\n * Create directory recursively\n * @param path\n */\nexport function ensureDirectory(path: string): void {\n if (!existsSync(path)) {\n mkdirSync(path, { recursive: true });\n }\n}\n\n/**\n * Read file as string\n * @param path\n */\nexport function readFile(path: string): string {\n return readFileSync(path, 'utf8');\n}\n\n/**\n * Read file as string, return null if not exists\n * @param path\n */\nexport function readFileSafe(path: string): string | undefined {\n if (!existsSync(path)) return undefined;\n return readFileSync(path, 'utf8');\n}\n\n/**\n * Write file, creating parent directories if needed\n * @param path\n * @param content\n */\nexport function writeFile(path: string, content: string): void {\n ensureDirectory(nodePath.dirname(path));\n writeFileSync(path, content);\n}\n\n/**\n * Remove file or directory recursively\n * @param path\n */\nexport function remove(path: string): void {\n if (existsSync(path)) {\n rmSync(path, { recursive: true, force: true });\n }\n}\n\n/**\n * Remove directory only if empty, returns true if removed\n * @param path\n */\nexport function removeIfEmpty(path: string): boolean {\n if (!existsSync(path)) return false;\n try {\n rmdirSync(path); // Non-recursive, throws if not empty\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Make all shell scripts in a directory executable\n * @param dirPath\n */\nexport function makeScriptsExecutable(dirPath: string): void {\n if (!existsSync(dirPath)) return;\n for (const file of readdirSync(dirPath)) {\n if (file.endsWith('.sh')) {\n chmodSync(nodePath.join(dirPath, file), 0o755);\n }\n }\n}\n\n/**\n * Read JSON file\n * @param path\n */\nexport function readJson(path: string): unknown {\n const content = readFileSafe(path);\n if (!content) return undefined;\n try {\n return JSON.parse(content) as unknown;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Write JSON file with formatting\n * @param path\n * @param data\n */\nexport function writeJson(path: string, data: unknown): void {\n writeFile(path, `${JSON.stringify(data, undefined, 2)}\\n`);\n}\n","/**\n * Console output utilities for consistent CLI messaging\n */\n\n/**\n * Print info message\n * @param message\n */\nexport function info(message: string): void {\n console.log(message);\n}\n\n/**\n * Print success message\n * @param message\n */\nexport function success(message: string): void {\n console.log(`✓ ${message}`);\n}\n\n/**\n * Print warning message\n * @param message\n */\nexport function warn(message: string): void {\n console.warn(`⚠ ${message}`);\n}\n\n/**\n * Print error message to stderr\n * @param message\n */\nexport function error(message: string): void {\n console.error(`✗ ${message}`);\n}\n\n/**\n * Print a section header\n * @param title\n */\nexport function header(title: string): void {\n console.log(`\\n${title}`);\n console.log('─'.repeat(title.length));\n}\n\n/**\n * Print a list item\n * @param item\n * @param indent\n */\nexport function listItem(item: string, indent = 2): void {\n console.log(`${' '.repeat(indent)}• ${item}`);\n}\n\n/**\n * Print key-value pair\n * @param key\n * @param value\n */\nexport function keyValue(key: string, value: string): void {\n console.log(` ${key}: ${value}`);\n}\n"],"mappings":";AAIA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAO,cAAc;AAGrB,IAAM,YAAY,YAAY;AAYvB,SAAS,wBAAgC;AAC9C,QAAM,oBAAoB;AAI1B,QAAM,aAAa;AAAA,IACjB,SAAS,KAAK,WAAW,MAAM,WAAW;AAAA;AAAA,IAC1C,SAAS,KAAK,WAAW,MAAM,MAAM,WAAW;AAAA;AAAA,IAChD,SAAS,KAAK,WAAW,WAAW;AAAA;AAAA,EACtC;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI,WAAW,SAAS,KAAK,WAAW,iBAAiB,CAAC,GAAG;AAC3D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,+BAA+B;AACjD;AAMO,SAAS,OAAO,MAAuB;AAC5C,SAAO,WAAW,IAAI;AACxB;AAMO,SAAS,gBAAgB,MAAoB;AAClD,MAAI,CAAC,WAAW,IAAI,GAAG;AACrB,cAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,EACrC;AACF;AAMO,SAAS,SAAS,MAAsB;AAC7C,SAAO,aAAa,MAAM,MAAM;AAClC;AAMO,SAAS,aAAa,MAAkC;AAC7D,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,SAAO,aAAa,MAAM,MAAM;AAClC;AAOO,SAAS,UAAU,MAAc,SAAuB;AAC7D,kBAAgB,SAAS,QAAQ,IAAI,CAAC;AACtC,gBAAc,MAAM,OAAO;AAC7B;AAMO,SAAS,OAAO,MAAoB;AACzC,MAAI,WAAW,IAAI,GAAG;AACpB,WAAO,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAC/C;AACF;AAMO,SAAS,cAAc,MAAuB;AACnD,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,cAAU,IAAI;AACd,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,sBAAsB,SAAuB;AAC3D,MAAI,CAAC,WAAW,OAAO,EAAG;AAC1B,aAAW,QAAQ,YAAY,OAAO,GAAG;AACvC,QAAI,KAAK,SAAS,KAAK,GAAG;AACxB,gBAAU,SAAS,KAAK,SAAS,IAAI,GAAG,GAAK;AAAA,IAC/C;AAAA,EACF;AACF;AAMO,SAAS,SAAS,MAAuB;AAC9C,QAAM,UAAU,aAAa,IAAI;AACjC,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,UAAU,MAAc,MAAqB;AAC3D,YAAU,MAAM,GAAG,KAAK,UAAU,MAAM,QAAW,CAAC,CAAC;AAAA,CAAI;AAC3D;;;AChJO,SAAS,KAAK,SAAuB;AAC1C,UAAQ,IAAI,OAAO;AACrB;AAMO,SAAS,QAAQ,SAAuB;AAC7C,UAAQ,IAAI,UAAK,OAAO,EAAE;AAC5B;AAMO,SAAS,KAAK,SAAuB;AAC1C,UAAQ,KAAK,UAAK,OAAO,EAAE;AAC7B;AAMO,SAAS,MAAM,SAAuB;AAC3C,UAAQ,MAAM,UAAK,OAAO,EAAE;AAC9B;AAMO,SAAS,OAAO,OAAqB;AAC1C,UAAQ,IAAI;AAAA,EAAK,KAAK,EAAE;AACxB,UAAQ,IAAI,SAAI,OAAO,MAAM,MAAM,CAAC;AACtC;AAOO,SAAS,SAAS,MAAc,SAAS,GAAS;AACvD,UAAQ,IAAI,GAAG,IAAI,OAAO,MAAM,CAAC,UAAK,IAAI,EAAE;AAC9C;AAOO,SAAS,SAAS,KAAa,OAAqB;AACzD,UAAQ,IAAI,KAAK,GAAG,KAAK,KAAK,EAAE;AAClC;","names":[]}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// src/presets/typescript/detect.ts
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
var TANSTACK_QUERY_PACKAGES = [
|
|
5
|
+
"@tanstack/react-query",
|
|
6
|
+
"@tanstack/vue-query",
|
|
7
|
+
"@tanstack/solid-query",
|
|
8
|
+
"@tanstack/svelte-query",
|
|
9
|
+
"@tanstack/angular-query-experimental"
|
|
10
|
+
];
|
|
11
|
+
var TAILWIND_PACKAGES = ["tailwindcss", "@tailwindcss/vite", "@tailwindcss/postcss"];
|
|
12
|
+
var PLAYWRIGHT_PACKAGES = ["@playwright/test", "playwright"];
|
|
13
|
+
var FORMATTER_CONFIG_FILES = [
|
|
14
|
+
// Biome
|
|
15
|
+
"biome.json",
|
|
16
|
+
"biome.jsonc",
|
|
17
|
+
// dprint
|
|
18
|
+
"dprint.json",
|
|
19
|
+
".dprint.json",
|
|
20
|
+
"dprint.jsonc",
|
|
21
|
+
".dprint.jsonc",
|
|
22
|
+
// Rome (legacy, now Biome)
|
|
23
|
+
"rome.json",
|
|
24
|
+
// Prettier - all supported config formats
|
|
25
|
+
// See: https://prettier.io/docs/en/configuration.html
|
|
26
|
+
".prettierrc",
|
|
27
|
+
".prettierrc.json",
|
|
28
|
+
".prettierrc.json5",
|
|
29
|
+
".prettierrc.yaml",
|
|
30
|
+
".prettierrc.yml",
|
|
31
|
+
".prettierrc.toml",
|
|
32
|
+
".prettierrc.js",
|
|
33
|
+
".prettierrc.cjs",
|
|
34
|
+
".prettierrc.mjs",
|
|
35
|
+
".prettierrc.ts",
|
|
36
|
+
".prettierrc.cts",
|
|
37
|
+
".prettierrc.mts",
|
|
38
|
+
"prettier.config.js",
|
|
39
|
+
"prettier.config.cjs",
|
|
40
|
+
"prettier.config.mjs",
|
|
41
|
+
"prettier.config.ts",
|
|
42
|
+
"prettier.config.cts",
|
|
43
|
+
"prettier.config.mts"
|
|
44
|
+
];
|
|
45
|
+
function readPackageDeps(pkgPath) {
|
|
46
|
+
try {
|
|
47
|
+
if (!existsSync(pkgPath)) return {};
|
|
48
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
49
|
+
return { ...pkg.dependencies, ...pkg.devDependencies };
|
|
50
|
+
} catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function getWorkspacePatternsFromPackage(rootPackagePath) {
|
|
55
|
+
try {
|
|
56
|
+
const rootPackage = JSON.parse(readFileSync(rootPackagePath, "utf8"));
|
|
57
|
+
if (Array.isArray(rootPackage.workspaces)) {
|
|
58
|
+
return rootPackage.workspaces;
|
|
59
|
+
}
|
|
60
|
+
if (rootPackage.workspaces?.packages) {
|
|
61
|
+
return rootPackage.workspaces.packages;
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
function scanWorkspaceDirectory(rootDirectory, pattern) {
|
|
68
|
+
if (!pattern.endsWith("/*")) return {};
|
|
69
|
+
const baseDirectory = path.join(rootDirectory, pattern.slice(0, -2));
|
|
70
|
+
if (!existsSync(baseDirectory)) return {};
|
|
71
|
+
const allDeps = {};
|
|
72
|
+
try {
|
|
73
|
+
const entries = readdirSync(baseDirectory, { withFileTypes: true });
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
if (entry.isDirectory()) {
|
|
76
|
+
Object.assign(
|
|
77
|
+
allDeps,
|
|
78
|
+
readPackageDeps(path.join(baseDirectory, entry.name, "package.json"))
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
84
|
+
return allDeps;
|
|
85
|
+
}
|
|
86
|
+
function collectAllDeps(rootDirectory) {
|
|
87
|
+
const rootPackagePath = path.join(rootDirectory, "package.json");
|
|
88
|
+
const allDeps = readPackageDeps(rootPackagePath);
|
|
89
|
+
const workspacePatterns = getWorkspacePatternsFromPackage(rootPackagePath);
|
|
90
|
+
const commonPatterns = ["apps/*", "packages/*"];
|
|
91
|
+
const patterns = [.../* @__PURE__ */ new Set([...workspacePatterns, ...commonPatterns])];
|
|
92
|
+
for (const pattern of patterns) {
|
|
93
|
+
Object.assign(allDeps, scanWorkspaceDirectory(rootDirectory, pattern));
|
|
94
|
+
}
|
|
95
|
+
return allDeps;
|
|
96
|
+
}
|
|
97
|
+
function hasTailwind(deps) {
|
|
98
|
+
return TAILWIND_PACKAGES.some((pkg) => pkg in deps);
|
|
99
|
+
}
|
|
100
|
+
function hasTanstackQuery(deps) {
|
|
101
|
+
return TANSTACK_QUERY_PACKAGES.some((pkg) => pkg in deps);
|
|
102
|
+
}
|
|
103
|
+
function hasVitest(deps) {
|
|
104
|
+
return "vitest" in deps;
|
|
105
|
+
}
|
|
106
|
+
function hasPlaywright(deps) {
|
|
107
|
+
return PLAYWRIGHT_PACKAGES.some((pkg) => pkg in deps);
|
|
108
|
+
}
|
|
109
|
+
function detectFramework(deps) {
|
|
110
|
+
if ("next" in deps) return "next";
|
|
111
|
+
if ("react" in deps) return "react";
|
|
112
|
+
if ("astro" in deps) return "astro";
|
|
113
|
+
if ("typescript" in deps || "typescript-eslint" in deps) return "typescript";
|
|
114
|
+
return "javascript";
|
|
115
|
+
}
|
|
116
|
+
function getIgnores(deps) {
|
|
117
|
+
const ignores = ["**/node_modules/", "**/dist/", "**/build/", "**/coverage/"];
|
|
118
|
+
if ("next" in deps) ignores.push("**/.next/");
|
|
119
|
+
if ("astro" in deps) ignores.push("**/.astro/");
|
|
120
|
+
return ignores;
|
|
121
|
+
}
|
|
122
|
+
function hasExistingLinter(scripts) {
|
|
123
|
+
return "lint" in scripts;
|
|
124
|
+
}
|
|
125
|
+
function hasExistingFormatter(cwd, scripts) {
|
|
126
|
+
if ("format" in scripts) return true;
|
|
127
|
+
return FORMATTER_CONFIG_FILES.some((file) => existsSync(path.join(cwd, file)));
|
|
128
|
+
}
|
|
129
|
+
var detect = {
|
|
130
|
+
// Package lists
|
|
131
|
+
TAILWIND_PACKAGES,
|
|
132
|
+
TANSTACK_QUERY_PACKAGES,
|
|
133
|
+
PLAYWRIGHT_PACKAGES,
|
|
134
|
+
FORMATTER_CONFIG_FILES,
|
|
135
|
+
// Core utilities
|
|
136
|
+
collectAllDeps,
|
|
137
|
+
detectFramework,
|
|
138
|
+
getIgnores,
|
|
139
|
+
// Feature detection
|
|
140
|
+
hasTailwind,
|
|
141
|
+
hasTanstackQuery,
|
|
142
|
+
hasVitest,
|
|
143
|
+
hasPlaywright,
|
|
144
|
+
// Existing tooling detection
|
|
145
|
+
hasExistingLinter,
|
|
146
|
+
hasExistingFormatter
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export {
|
|
150
|
+
detect
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=chunk-57C2XQBO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presets/typescript/detect.ts"],"sourcesContent":["/**\n * Framework detection utilities for safeword ESLint preset\n *\n * Single source of truth for package detection. Used by:\n * - Generated eslint.config.mjs at lint time\n * - CLI's project-detector at init time\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * TanStack Query package names across all supported frameworks.\n */\nconst TANSTACK_QUERY_PACKAGES = [\n '@tanstack/react-query',\n '@tanstack/vue-query',\n '@tanstack/solid-query',\n '@tanstack/svelte-query',\n '@tanstack/angular-query-experimental',\n] as const;\n\n/**\n * Tailwind CSS package names (v3 and v4 installation methods).\n */\nconst TAILWIND_PACKAGES = ['tailwindcss', '@tailwindcss/vite', '@tailwindcss/postcss'] as const;\n\n/**\n * Playwright test package names.\n */\nconst PLAYWRIGHT_PACKAGES = ['@playwright/test', 'playwright'] as const;\n\n/**\n * Known formatter config files.\n * If any exist, user likely has their own formatter setup.\n */\nconst FORMATTER_CONFIG_FILES = [\n // Biome\n 'biome.json',\n 'biome.jsonc',\n // dprint\n 'dprint.json',\n '.dprint.json',\n 'dprint.jsonc',\n '.dprint.jsonc',\n // Rome (legacy, now Biome)\n 'rome.json',\n // Prettier - all supported config formats\n // See: https://prettier.io/docs/en/configuration.html\n '.prettierrc',\n '.prettierrc.json',\n '.prettierrc.json5',\n '.prettierrc.yaml',\n '.prettierrc.yml',\n '.prettierrc.toml',\n '.prettierrc.js',\n '.prettierrc.cjs',\n '.prettierrc.mjs',\n '.prettierrc.ts',\n '.prettierrc.cts',\n '.prettierrc.mts',\n 'prettier.config.js',\n 'prettier.config.cjs',\n 'prettier.config.mjs',\n 'prettier.config.ts',\n 'prettier.config.cts',\n 'prettier.config.mts',\n] as const;\n\ntype DepsRecord = Record<string, string | undefined>;\ntype ScriptsRecord = Record<string, string | undefined>;\n\n/**\n * Read dependencies from a package.json file.\n */\nfunction readPackageDeps(pkgPath: string): DepsRecord {\n try {\n if (!existsSync(pkgPath)) return {};\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));\n return { ...pkg.dependencies, ...pkg.devDependencies };\n } catch {\n return {};\n }\n}\n\n/**\n * Get workspace patterns from root package.json.\n */\nfunction getWorkspacePatternsFromPackage(rootPackagePath: string): string[] {\n try {\n const rootPackage = JSON.parse(readFileSync(rootPackagePath, 'utf8'));\n if (Array.isArray(rootPackage.workspaces)) {\n return rootPackage.workspaces;\n }\n if (rootPackage.workspaces?.packages) {\n return rootPackage.workspaces.packages;\n }\n } catch {\n // No workspaces defined\n }\n return [];\n}\n\n/**\n * Scan a workspace directory for package.json files.\n */\nfunction scanWorkspaceDirectory(rootDirectory: string, pattern: string): DepsRecord {\n if (!pattern.endsWith('/*')) return {};\n\n const baseDirectory = path.join(rootDirectory, pattern.slice(0, -2));\n if (!existsSync(baseDirectory)) return {};\n\n const allDeps: DepsRecord = {};\n try {\n const entries = readdirSync(baseDirectory, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n Object.assign(\n allDeps,\n readPackageDeps(path.join(baseDirectory, entry.name, 'package.json')),\n );\n }\n }\n } catch {\n // Ignore read errors\n }\n return allDeps;\n}\n\n/**\n * Collect all dependencies from root and workspace package.json files.\n * Supports npm/yarn workspaces and common monorepo patterns.\n */\nfunction collectAllDeps(rootDirectory: string): DepsRecord {\n const rootPackagePath = path.join(rootDirectory, 'package.json');\n const allDeps = readPackageDeps(rootPackagePath);\n\n // Get patterns from workspaces config + common monorepo directories\n const workspacePatterns = getWorkspacePatternsFromPackage(rootPackagePath);\n const commonPatterns = ['apps/*', 'packages/*'];\n const patterns = [...new Set([...workspacePatterns, ...commonPatterns])];\n\n // Scan each workspace pattern\n for (const pattern of patterns) {\n Object.assign(allDeps, scanWorkspaceDirectory(rootDirectory, pattern));\n }\n\n return allDeps;\n}\n\n/**\n * Check if Tailwind CSS is installed.\n */\nfunction hasTailwind(deps: DepsRecord): boolean {\n return TAILWIND_PACKAGES.some(pkg => pkg in deps);\n}\n\n/**\n * Check if TanStack Query is installed.\n */\nfunction hasTanstackQuery(deps: DepsRecord): boolean {\n return TANSTACK_QUERY_PACKAGES.some(pkg => pkg in deps);\n}\n\n/**\n * Check if Vitest is installed.\n */\nfunction hasVitest(deps: DepsRecord): boolean {\n return 'vitest' in deps;\n}\n\n/**\n * Check if Playwright is installed.\n */\nfunction hasPlaywright(deps: DepsRecord): boolean {\n return PLAYWRIGHT_PACKAGES.some(pkg => pkg in deps);\n}\n\n/**\n * Detect base framework for config selection.\n * Returns the most specific framework detected.\n */\nfunction detectFramework(\n deps: DepsRecord,\n): 'next' | 'react' | 'astro' | 'typescript' | 'javascript' {\n if ('next' in deps) return 'next';\n if ('react' in deps) return 'react';\n if ('astro' in deps) return 'astro';\n if ('typescript' in deps || 'typescript-eslint' in deps) return 'typescript';\n return 'javascript';\n}\n\n/**\n * Get dynamic ignores based on detected frameworks.\n */\nfunction getIgnores(deps: DepsRecord): string[] {\n const ignores = ['**/node_modules/', '**/dist/', '**/build/', '**/coverage/'];\n if ('next' in deps) ignores.push('**/.next/');\n if ('astro' in deps) ignores.push('**/.astro/');\n return ignores;\n}\n\n/**\n * Check if project has an existing linter setup.\n * True if package.json has a \"lint\" script.\n */\nfunction hasExistingLinter(scripts: ScriptsRecord): boolean {\n return 'lint' in scripts;\n}\n\n/**\n * Check if project has an existing formatter setup.\n * True if package.json has a \"format\" script OR any formatter config file exists.\n */\nfunction hasExistingFormatter(cwd: string, scripts: ScriptsRecord): boolean {\n // Check for format script\n if ('format' in scripts) return true;\n\n // Check for formatter config files\n return FORMATTER_CONFIG_FILES.some(file => existsSync(path.join(cwd, file)));\n}\n\n/**\n * All detection utilities bundled together.\n */\nexport const detect = {\n // Package lists\n TAILWIND_PACKAGES,\n TANSTACK_QUERY_PACKAGES,\n PLAYWRIGHT_PACKAGES,\n FORMATTER_CONFIG_FILES,\n\n // Core utilities\n collectAllDeps,\n detectFramework,\n getIgnores,\n\n // Feature detection\n hasTailwind,\n hasTanstackQuery,\n hasVitest,\n hasPlaywright,\n\n // Existing tooling detection\n hasExistingLinter,\n hasExistingFormatter,\n};\n"],"mappings":"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","names":[]}
|