mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-06-06 04:44:16 +02:00
Fancier dev setup
This commit is contained in:
parent
a4428fd5be
commit
ba738244ab
7 changed files with 107 additions and 73 deletions
|
|
@ -1,2 +1,2 @@
|
|||
FOUNDRY_MAIN_PATH=/path/to/foundry/resources/app/main.js
|
||||
FOUNDRY_DATA_PATH=/path/to/foundry/data
|
||||
FOUNDRY_DATA_PATH=/path/to/foundry/
|
||||
12
README.md
12
README.md
|
|
@ -38,11 +38,13 @@ You can find the documentation here: https://github.com/Foundryborne/daggerheart
|
|||
|
||||
3. **Configure your Foundry paths:**
|
||||
|
||||
```bash
|
||||
npm run setup:dev -- --foundry-path="/path/to/foundry/main.js" --data-path="/path/to/data"
|
||||
```
|
||||
Copy `.env.example` to `.env` and set up the foundry path and data path. The foundry path must point to main.js, and the data path must point the folder containing the Data folder itself (but not the `Data` folder itself).
|
||||
|
||||
4. **Start developing:**
|
||||
4. **Setup symlinks:**
|
||||
|
||||
In a shell with elevated privilages, run `npm run createSymlink`. It will add a foundry folder for types, and add a symlink to the daggerheart folder into your foundry data.
|
||||
|
||||
5. **Start developing:**
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
|
@ -51,7 +53,7 @@ You can find the documentation here: https://github.com/Foundryborne/daggerheart
|
|||
|
||||
- `npm start` - Start development with file watching and Foundry launching
|
||||
- `npm run build` - One-time build
|
||||
- `npm run setup:dev -- --foundry-path="<path>" --data-path="<path>"` - Configure development environment
|
||||
- `npm run createSymlink` - Setup types and output symlinks
|
||||
|
||||
### Notes
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
"pullYMLtoLDB": "node ./tools/pullYMLtoLDB.mjs",
|
||||
"pullYMLtoLDBBuild": "node ./tools/pullYMLtoLDB.mjs --build",
|
||||
"createSymlink": "node ./tools/create-symlink.mjs",
|
||||
"setup:dev": "node ./tools/dev-setup.mjs",
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"prepare": "husky"
|
||||
|
|
|
|||
|
|
@ -1,47 +1,70 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import readline from 'readline';
|
||||
import { isContainedPath, readEnvFile } from './util.mjs';
|
||||
|
||||
console.log('Creates a foundry symlink in the base folder for type purposes\n');
|
||||
const projectRoot = path.resolve(import.meta.dirname, '../')
|
||||
const { foundryRoot, dataPath } = readEnvFile();
|
||||
|
||||
const askQuestion = question => {
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
async function createFoundrySymlink() {
|
||||
// If foundry already exists, exit and inform the user. This operation can't complete correctly otherwise.
|
||||
// If the folder is empty, its fine. It may have failed due to perms
|
||||
const foundryDestPath = path.join(projectRoot, 'foundry');
|
||||
if (fs.existsSync(foundryDestPath) && fs.readdirSync(foundryDestPath).length) {
|
||||
console.log('"foundry" folder already exists in this project');
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise(resolve =>
|
||||
rl.question(question, answer => {
|
||||
rl.close();
|
||||
resolve(answer);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const installPath = await askQuestion('Enter your Foundry install path: ');
|
||||
|
||||
// Determine if it's an Electron install (nested structure)
|
||||
const nested = fs.existsSync(path.join(installPath, 'resources', 'app'));
|
||||
const fileRoot = nested ? path.join(installPath, 'resources', 'app') : installPath;
|
||||
|
||||
try {
|
||||
await fs.promises.mkdir('foundry');
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
}
|
||||
|
||||
// JavaScript files
|
||||
for (const p of ['client', 'common', 'tsconfig.json']) {
|
||||
console.log('Creating "foundry" symlinks for types');
|
||||
try {
|
||||
await fs.promises.symlink(path.join(fileRoot, p), path.join('foundry', p));
|
||||
await fs.promises.mkdir(foundryDestPath);
|
||||
console.log('Root foundry folder created');
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
}
|
||||
|
||||
// JavaScript files
|
||||
for (const p of ['client', 'common', 'tsconfig.json']) {
|
||||
try {
|
||||
await fs.promises.symlink(path.join(foundryRoot, p), path.join(foundryDestPath, p));
|
||||
console.log(`${p} folder created`);
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Language files
|
||||
try {
|
||||
await fs.promises.symlink(path.join(foundryRoot, 'public', 'lang'), path.join(foundryDestPath, 'lang'));
|
||||
console.log(`lang folder created`);
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
console.log(`lang folder already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
// Language files
|
||||
try {
|
||||
await fs.promises.symlink(path.join(fileRoot, 'public', 'lang'), path.join('foundry', 'lang'));
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
async function createDaggerheartSymlink() {
|
||||
if (isContainedPath(dataPath, projectRoot)) {
|
||||
console.log('The Daggerheart project repo is in foundry data, so a symlink won\'t be created');
|
||||
return;
|
||||
}
|
||||
|
||||
const destination = path.join(dataPath, 'Data', 'systems', 'daggerheart');
|
||||
if (fs.existsSync(destination)) {
|
||||
console.log('A Daggerheart folder already exists in Foundry data');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Creating Daggerheart symlink in the foundry systems folder')
|
||||
try {
|
||||
await fs.promises.symlink(projectRoot, destination);
|
||||
console.log('Daggerheart system folder symlink created');
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
console.log(`Daggerheart system folder already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
await createFoundrySymlink();
|
||||
console.log();
|
||||
await createDaggerheartSymlink();
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
import fs from 'fs';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const foundryPath = args.find(arg => arg.startsWith('--foundry-path='))?.split('=')[1];
|
||||
const dataPath = args.find(arg => arg.startsWith('--data-path='))?.split('=')[1];
|
||||
|
||||
if (!foundryPath || !dataPath) {
|
||||
console.log('Usage: npm run setup:dev -- --foundry-path="/path/to/foundry/main.js" --data-path="/path/to/data"');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const envContent = `FOUNDRY_MAIN_PATH=${foundryPath}
|
||||
FOUNDRY_DATA_PATH=${dataPath}
|
||||
`;
|
||||
|
||||
fs.writeFileSync('.env', envContent);
|
||||
console.log(`✅ Development environment configured: ${foundryPath}, ${dataPath}`);
|
||||
|
|
@ -1,21 +1,10 @@
|
|||
#!/usr/bin/env node
|
||||
import { spawn } from 'child_process';
|
||||
import { readEnvFile } from './util.mjs';
|
||||
import fs from 'fs';
|
||||
|
||||
// Load .env file if it exists
|
||||
if (fs.existsSync('.env')) {
|
||||
const envFile = fs.readFileSync('.env', 'utf8');
|
||||
envFile.split('\n').forEach(line => {
|
||||
const [key, value] = line.split('=');
|
||||
if (key && value) {
|
||||
process.env[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set defaults if not in environment
|
||||
const foundryPath = process.env.FOUNDRY_MAIN_PATH || '../../../../FoundryDev/main.js';
|
||||
const dataPath = process.env.FOUNDRY_DATA_PATH || '../../../';
|
||||
// Load .env file params
|
||||
const { foundryPath, dataPath } = readEnvFile();
|
||||
|
||||
// Run the original command with proper environment
|
||||
const args = ['rollup -c --watch', `node "\"${foundryPath}\"" --dataPath="${dataPath}" --noupnp`, 'gulp'];
|
||||
|
|
|
|||
39
tools/util.mjs
Normal file
39
tools/util.mjs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
export function readEnvFile() {
|
||||
if (!fs.existsSync('.env')) {
|
||||
console.error('No configured .env file. Copy .env.example to .env and configure it.');
|
||||
process.exit();
|
||||
}
|
||||
|
||||
const envFile = fs.readFileSync('.env', 'utf8');
|
||||
envFile.split('\n').forEach(line => {
|
||||
const [key, value] = line.split('=');
|
||||
if (key && value) {
|
||||
process.env[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
// Determine foundry path, handling if its an electron install (nested structure)
|
||||
const foundryPath = path.normalize(process.env.FOUNDRY_MAIN_PATH);
|
||||
const dataPath = path.normalize(process.env.FOUNDRY_DATA_PATH);
|
||||
if (!foundryPath.endsWith(path.join('app', 'main.js'))) {
|
||||
console.error('Configured FOUNDRY_MAIN_PATH is invalid, it must end with app/main.js');
|
||||
process.exit();
|
||||
}
|
||||
if (/Data(\/|\\)?$/.test(dataPath) || !fs.existsSync(path.join(dataPath, 'Data'))) {
|
||||
console.error('Configured FOUNDRY_DATA_PATH is incorrect. This must be a folder that contains "Data"');
|
||||
}
|
||||
|
||||
return {
|
||||
foundryPath,
|
||||
foundryRoot: path.dirname(foundryPath),
|
||||
dataPath
|
||||
};
|
||||
}
|
||||
|
||||
export function isContainedPath(parent, child) {
|
||||
const relative = path.relative(parent, child);
|
||||
return relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue