fix: deployment issues with typescript and dist
This commit is contained in:
10
package.json
10
package.json
@@ -110,14 +110,10 @@
|
||||
"url": "https://github.com/eyaltoledano/claude-task-master/issues"
|
||||
},
|
||||
"files": [
|
||||
"scripts/**",
|
||||
"assets/**",
|
||||
".cursor/**",
|
||||
"dist/**",
|
||||
"README-task-master.md",
|
||||
"index.js",
|
||||
"bin/**",
|
||||
"mcp-server/**",
|
||||
"src/**"
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"overrides": {
|
||||
"node-fetch": "^2.6.12",
|
||||
|
||||
@@ -32,6 +32,9 @@ import {
|
||||
} from '../src/utils/rule-transformer.js';
|
||||
import { updateConfigMaxTokens } from './modules/update-config-tokens.js';
|
||||
|
||||
// Import asset resolver
|
||||
import { assetExists, readAsset } from '../src/utils/asset-resolver.js';
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import {
|
||||
EXAMPLE_PRD_FILE,
|
||||
@@ -222,32 +225,14 @@ function createInitialStateFile(targetDir) {
|
||||
// Function to copy a file from the package to the target directory
|
||||
function copyTemplateFile(templateName, targetPath, replacements = {}) {
|
||||
// Get the file content from the appropriate source directory
|
||||
let sourcePath;
|
||||
|
||||
// Map template names to their actual source paths
|
||||
switch (templateName) {
|
||||
// case 'scripts_README.md':
|
||||
// sourcePath = path.join(__dirname, '..', 'assets', 'scripts_README.md');
|
||||
// break;
|
||||
// case 'README-task-master.md':
|
||||
// sourcePath = path.join(__dirname, '..', 'README-task-master.md');
|
||||
// break;
|
||||
default:
|
||||
// For other files like env.example, gitignore, etc. that don't have direct equivalents
|
||||
sourcePath = path.join(__dirname, '..', 'assets', templateName);
|
||||
}
|
||||
|
||||
// Check if the source file exists
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
// Fall back to templates directory for files that might not have been moved yet
|
||||
sourcePath = path.join(__dirname, '..', 'assets', templateName);
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
log('error', `Source file not found: ${sourcePath}`);
|
||||
// Check if the asset exists
|
||||
if (!assetExists(templateName)) {
|
||||
log('error', `Source file not found: ${templateName}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let content = fs.readFileSync(sourcePath, 'utf8');
|
||||
// Read the asset content using the resolver
|
||||
let content = readAsset(templateName, 'utf8');
|
||||
|
||||
// Replace placeholders with actual values
|
||||
Object.entries(replacements).forEach(([key, value]) => {
|
||||
|
||||
84
src/utils/asset-resolver.js
Normal file
84
src/utils/asset-resolver.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Asset Resolver Module
|
||||
* Handles resolving paths to asset files in the package
|
||||
*
|
||||
* The public/assets folder is copied to dist/assets during build via tsup's publicDir,
|
||||
* so we can reliably find it relative to the bundled files.
|
||||
*/
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
/**
|
||||
* Get the assets directory path
|
||||
* When bundled, assets are in dist/assets
|
||||
* When in development, assets are in public/assets
|
||||
* @returns {string} Path to the assets directory
|
||||
*/
|
||||
export function getAssetsDir() {
|
||||
// Check multiple possible locations
|
||||
const possiblePaths = [
|
||||
// When running from dist (bundled) - assets are in dist/assets
|
||||
path.join(__dirname, 'assets'),
|
||||
path.join(__dirname, '..', 'assets'),
|
||||
// When running from source in development - now in public/assets
|
||||
path.join(__dirname, '..', '..', 'public', 'assets'),
|
||||
// When installed as npm package - assets at package root
|
||||
path.join(process.cwd(), 'assets'),
|
||||
// For npx usage - check node_modules
|
||||
path.join(process.cwd(), 'node_modules', 'task-master-ai', 'dist', 'assets'),
|
||||
path.join(process.cwd(), 'node_modules', 'task-master-ai', 'assets')
|
||||
];
|
||||
|
||||
// Find the first existing assets directory
|
||||
for (const assetPath of possiblePaths) {
|
||||
if (fs.existsSync(assetPath)) {
|
||||
// Verify it's actually the assets directory by checking for known files
|
||||
const testFile = path.join(assetPath, 'rules', 'taskmaster.mdc');
|
||||
if (fs.existsSync(testFile)) {
|
||||
return assetPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no assets directory found, throw an error
|
||||
throw new Error('Assets directory not found. This is likely a packaging issue.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to a specific asset file
|
||||
* @param {string} relativePath - Path relative to assets directory
|
||||
* @returns {string} Full path to the asset file
|
||||
*/
|
||||
export function getAssetPath(relativePath) {
|
||||
const assetsDir = getAssetsDir();
|
||||
return path.join(assetsDir, relativePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an asset file exists
|
||||
* @param {string} relativePath - Path relative to assets directory
|
||||
* @returns {boolean} True if the asset exists
|
||||
*/
|
||||
export function assetExists(relativePath) {
|
||||
try {
|
||||
const assetPath = getAssetPath(relativePath);
|
||||
return fs.existsSync(assetPath);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an asset file
|
||||
* @param {string} relativePath - Path relative to assets directory
|
||||
* @param {string} encoding - File encoding (default: 'utf8')
|
||||
* @returns {string|Buffer} File contents
|
||||
*/
|
||||
export function readAsset(relativePath, encoding = 'utf8') {
|
||||
const assetPath = getAssetPath(relativePath);
|
||||
return fs.readFileSync(assetPath, encoding);
|
||||
}
|
||||
@@ -7,9 +7,11 @@
|
||||
*/
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { log } from '../../scripts/modules/utils.js';
|
||||
|
||||
// Import asset resolver
|
||||
import { assetExists, readAsset, getAssetsDir } from './asset-resolver.js';
|
||||
|
||||
// Import the shared MCP configuration helper
|
||||
import {
|
||||
setupMCPConfiguration,
|
||||
@@ -199,11 +201,7 @@ export function convertRuleToProfileRule(sourcePath, targetPath, profile) {
|
||||
* Convert all Cursor rules to profile rules for a specific profile
|
||||
*/
|
||||
export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const sourceDir = path.join(__dirname, '..', '..', 'assets', 'rules');
|
||||
const targetDir = path.join(projectRoot, profile.rulesDir);
|
||||
const assetsDir = path.join(__dirname, '..', '..', 'assets');
|
||||
|
||||
let success = 0;
|
||||
let failed = 0;
|
||||
@@ -211,6 +209,7 @@ export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
// 1. Call onAddRulesProfile first (for pre-processing like copying assets)
|
||||
if (typeof profile.onAddRulesProfile === 'function') {
|
||||
try {
|
||||
const assetsDir = getAssetsDir();
|
||||
profile.onAddRulesProfile(projectRoot, assetsDir);
|
||||
log(
|
||||
'debug',
|
||||
@@ -238,14 +237,11 @@ export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
const isAssetFile = !sourceFile.startsWith('rules/');
|
||||
|
||||
try {
|
||||
// Use explicit path from fileMap - assets/ is the base directory
|
||||
const sourcePath = path.join(assetsDir, sourceFile);
|
||||
|
||||
// Check if source file exists
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
// Check if source file exists using asset resolver
|
||||
if (!assetExists(sourceFile)) {
|
||||
log(
|
||||
'warn',
|
||||
`[Rule Transformer] Source file not found: ${sourcePath}, skipping`
|
||||
`[Rule Transformer] Source file not found: ${sourceFile}, skipping`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -259,8 +255,8 @@ export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
fs.mkdirSync(targetFileDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Read source content
|
||||
let content = fs.readFileSync(sourcePath, 'utf8');
|
||||
// Read source content using asset resolver
|
||||
let content = readAsset(sourceFile, 'utf8');
|
||||
|
||||
// Apply transformations (only if this is a rule file, not an asset file)
|
||||
if (!isAssetFile) {
|
||||
@@ -308,6 +304,7 @@ export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
// 4. Call post-conversion hook (for finalization)
|
||||
if (typeof profile.onPostConvertRulesProfile === 'function') {
|
||||
try {
|
||||
const assetsDir = getAssetsDir();
|
||||
profile.onPostConvertRulesProfile(projectRoot, assetsDir);
|
||||
log(
|
||||
'debug',
|
||||
@@ -386,11 +383,46 @@ export function removeProfileRules(projectRoot, profile) {
|
||||
);
|
||||
|
||||
// Get all files in the rules directory
|
||||
const allFiles = fs.readdirSync(targetDir, { recursive: true });
|
||||
// For root-level directories, we need to be careful to avoid circular symlinks
|
||||
let allFiles = [];
|
||||
if (targetDir === projectRoot || profile.rulesDir === '.') {
|
||||
// For root directory, manually read without recursion into problematic directories
|
||||
const items = fs.readdirSync(targetDir);
|
||||
for (const item of items) {
|
||||
// Skip directories that can cause issues or are irrelevant
|
||||
if (item === 'node_modules' || item === '.git' || item === 'dist') {
|
||||
continue;
|
||||
}
|
||||
const itemPath = path.join(targetDir, item);
|
||||
try {
|
||||
const stats = fs.lstatSync(itemPath);
|
||||
if (stats.isFile()) {
|
||||
allFiles.push(item);
|
||||
} else if (stats.isDirectory() && !stats.isSymbolicLink()) {
|
||||
// Only recurse into safe directories
|
||||
const subFiles = fs.readdirSync(itemPath, { recursive: true });
|
||||
subFiles.forEach(subFile => {
|
||||
allFiles.push(path.join(item, subFile.toString()));
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// Silently skip files we can't access
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For non-root directories, use normal recursive read
|
||||
allFiles = fs.readdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
const allFilePaths = allFiles
|
||||
.filter((file) => {
|
||||
const fullPath = path.join(targetDir, file);
|
||||
return fs.statSync(fullPath).isFile();
|
||||
try {
|
||||
const stats = fs.statSync(fullPath);
|
||||
return stats.isFile();
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.map((file) => file.toString()); // Ensure it's a string
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ export default defineConfig({
|
||||
clean: true,
|
||||
bundle: true, // Bundle everything into one file
|
||||
outDir: 'dist',
|
||||
publicDir: 'public',
|
||||
// Handle TypeScript imports transparently
|
||||
loader: {
|
||||
'.js': 'jsx',
|
||||
|
||||
Reference in New Issue
Block a user