Converted the javascript to typescript #4

Closed
p4535992 wants to merge 1 commits from develop into develop
22 changed files with 8113 additions and 1 deletions
Showing only changes of commit 3b7b0e5a39 - Show all commits

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
gulpfile.js

24
.eslintrc Normal file
View File

@@ -0,0 +1,24 @@
{
"env": {
"jquery": true,
"browser": true,
"es2020": true
},
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"extends": ["plugin:@typescript-eslint/recommended"],
"rules": {
"no-underscore-dangle": "off",
"import/extensions": "on",
"class-methods-use-this": [
"error",
{
"exceptMethods": ["getData", "_updateObject"]
}
]
}
}

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules
/dist

View File

@@ -3,6 +3,22 @@
# Smart Doors # Smart Doors
Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors (and also tells you which of the doors). Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors (and also tells you which of the doors).
## Installation
It's always easiest to install modules from the in game add-on browser.
To install this module manually:
1. Inside the Foundry "Configuration and Setup" screen, click "Add-on Modules"
2. Click "Install Module"
3. In the "Manifest URL" field, paste the following url:
`https://raw.githubusercontent.com/manuelVo/foundryvtt-smart-doors/master/src/module.json`
4. Click 'Install' and wait for installation to complete
5. Don't forget to enable the module in game using the "Manage Module" button
### libWrapper
This module uses the [libWrapper](https://github.com/ruipin/fvtt-lib-wrapper) library for wrapping core methods. It is a hard dependency and it is recommended for the best experience and compatibility with other modules.
## Feature overview ## Feature overview
### Consistent Door Control Size ### Consistent Door Control Size
@@ -52,3 +68,14 @@ Once a Synchronization Group is set up for multiple doors, simply open/close/loc
- Doors that can only be seen from one side when closed - Doors that can only be seen from one side when closed
- Only allow doors to be opened of the character is near - Only allow doors to be opened of the character is near
- Doors that can only be opened from one side - Doors that can only be opened from one side
## Issues
Any issues, bugs, or feature requests are always welcome to be reported directly to the [Issue Tracker](https://github.com/manuelVo/foundryvtt-smart-doors/issues ), or using the [Bug Reporter Module](https://foundryvtt.com/packages/bug-reporter/).
## Acknowledgements
Bootstrapped with League of Extraordinary FoundryVTT Developers [foundry-vtt-types](https://github.com/League-of-Foundry-Developers/foundry-vtt-types).
Mad props to the 'League of Extraordinary FoundryVTT Developers' community which helped me figure out a lot.

5
foundryconfig.json Normal file
View File

@@ -0,0 +1,5 @@
{
"dataPath": "D:/FoundryVTT",
"repository": "",
"rawURL": ""
}

528
gulpfile.js Normal file
View File

@@ -0,0 +1,528 @@
const gulp = require('gulp');
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const archiver = require('archiver');
const stringify = require('json-stringify-pretty-compact');
const typescript = require('typescript');
const ts = require('gulp-typescript');
const less = require('gulp-less');
const sass = require('gulp-sass');
const git = require('gulp-git');
const argv = require('yargs').argv;
sass.compiler = require('sass');
function getConfig() {
const configPath = path.resolve(process.cwd(), 'foundryconfig.json');
let config;
if (fs.existsSync(configPath)) {
config = fs.readJSONSync(configPath);
return config;
} else {
return;
}
}
function getManifest() {
const json = {};
if (fs.existsSync('src')) {
json.root = 'src';
} else {
json.root = 'dist';
}
const modulePath = path.join(json.root, 'module.json');
const systemPath = path.join(json.root, 'system.json');
if (fs.existsSync(modulePath)) {
json.file = fs.readJSONSync(modulePath);
json.name = 'module.json';
} else if (fs.existsSync(systemPath)) {
json.file = fs.readJSONSync(systemPath);
json.name = 'system.json';
} else {
return;
}
return json;
}
/**
* TypeScript transformers
* @returns {typescript.TransformerFactory<typescript.SourceFile>}
*/
function createTransformer() {
/**
* @param {typescript.Node} node
*/
function shouldMutateModuleSpecifier(node) {
if (
!typescript.isImportDeclaration(node) &&
!typescript.isExportDeclaration(node)
)
return false;
if (node.moduleSpecifier === undefined) return false;
if (!typescript.isStringLiteral(node.moduleSpecifier)) return false;
if (
!node.moduleSpecifier.text.startsWith('./') &&
!node.moduleSpecifier.text.startsWith('../')
)
return false;
if (path.extname(node.moduleSpecifier.text) !== '') return false;
return true;
}
/**
* Transforms import/export declarations to append `.js` extension
* @param {typescript.TransformationContext} context
*/
function importTransformer(context) {
return (node) => {
/**
* @param {typescript.Node} node
*/
function visitor(node) {
if (shouldMutateModuleSpecifier(node)) {
if (typescript.isImportDeclaration(node)) {
const newModuleSpecifier = typescript.createLiteral(
`${node.moduleSpecifier.text}.js`
);
return typescript.updateImportDeclaration(
node,
node.decorators,
node.modifiers,
node.importClause,
newModuleSpecifier
);
} else if (typescript.isExportDeclaration(node)) {
const newModuleSpecifier = typescript.createLiteral(
`${node.moduleSpecifier.text}.js`
);
return typescript.updateExportDeclaration(
node,
node.decorators,
node.modifiers,
node.exportClause,
newModuleSpecifier
);
}
}
return typescript.visitEachChild(node, visitor, context);
}
return typescript.visitNode(node, visitor);
};
}
return importTransformer;
}
const tsConfig = ts.createProject('tsconfig.json', {
getCustomTransformers: (_program) => ({
after: [createTransformer()],
}),
});
/********************/
/* BUILD */
/********************/
/**
* Build TypeScript
*/
function buildTS() {
return gulp.src('src/**/*.ts').pipe(tsConfig()).pipe(gulp.dest('dist'));
}
/**
* Build JavaScript
*/
function buildJS() {
return gulp.src('src/**/*.js').pipe(gulp.dest('dist'));
}
/**
* Build JavaScript
*/
function buildMJS() {
return gulp.src('src/**/*.mjs').pipe(gulp.dest('dist'));
}
/**
* Build JavaScript
*/
function buildCSS() {
return gulp.src('src/**/*.css').pipe(gulp.dest('dist'));
}
/**
* Build Less
*/
function buildLess() {
return gulp.src('src/**/*.less').pipe(less()).pipe(gulp.dest('dist'));
}
/**
* Build SASS
*/
function buildSASS() {
return gulp
.src('src/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('dist'));
}
/**
* Copy static files
*/
async function copyFiles() {
const statics = [
'lang',
'fonts',
'assets',
'templates',
'module.json',
'system.json',
'template.json'
];
try {
for (const file of statics) {
if (fs.existsSync(path.join('src', file))) {
await fs.copy(path.join('src', file), path.join('dist', file));
}
}
return Promise.resolve();
} catch (err) {
Promise.reject(err);
}
}
/**
* Watch for changes for each build step
*/
function buildWatch() {
gulp.watch('src/**/*.ts', { ignoreInitial: false }, buildTS);
gulp.watch('src/**/*.less', { ignoreInitial: false }, buildLess);
gulp.watch('src/**/*.scss', { ignoreInitial: false }, buildSASS);
gulp.watch('src/**/*.js', { ignoreInitial: false }, buildJS);
gulp.watch('src/**/*.mjs', { ignoreInitial: false }, buildMJS);
gulp.watch('src/**/*.css', { ignoreInitial: false }, buildCSS);
gulp.watch(
['src/fonts', 'src/lang', 'src/templates', 'src/*.json'],
{ ignoreInitial: false },
copyFiles
);
}
/********************/
/* CLEAN */
/********************/
/**
* Remove built files from `dist` folder
* while ignoring source files
*/
async function clean() {
const name = path.basename(path.resolve('.'));
const files = [];
// If the project uses TypeScript
if (fs.existsSync(path.join('src', `${name}.ts`))) {
files.push(
'lang',
'templates',
'assets',
'module',
`${name}.js`,
'module.json',
'system.json',
'template.json'
);
}
// If the project uses Less or SASS
if (
fs.existsSync(path.join('src', `${name}.less`)) ||
fs.existsSync(path.join('src', `${name}.scss`))
) {
files.push('fonts', `${name}.css`);
}
console.log(' ', chalk.yellow('Files to clean:'));
console.log(' ', chalk.blueBright(files.join('\n ')));
// Attempt to remove the files
try {
for (const filePath of files) {
await fs.remove(path.join('dist', filePath));
}
return Promise.resolve();
} catch (err) {
Promise.reject(err);
}
}
/********************/
/* LINK */
/********************/
/**
* Link build to User Data folder
*/
async function linkUserData() {
const name = path.basename(path.resolve('.'));
const config = fs.readJSONSync('foundryconfig.json');
let destDir;
try {
if (
fs.existsSync(path.resolve('.', 'dist', 'module.json')) ||
fs.existsSync(path.resolve('.', 'src', 'module.json'))
) {
destDir = 'modules';
} else if (
fs.existsSync(path.resolve('.', 'dist', 'system.json')) ||
fs.existsSync(path.resolve('.', 'src', 'system.json'))
) {
destDir = 'systems';
} else {
throw Error(
`Could not find ${chalk.blueBright(
'module.json'
)} or ${chalk.blueBright('system.json')}`
);
}
let linkDir;
if (config.dataPath) {
if (!fs.existsSync(path.join(config.dataPath, 'Data')))
throw Error('User Data path invalid, no Data directory found');
linkDir = path.join(config.dataPath, 'Data', destDir, name);
} else {
throw Error('No User Data path defined in foundryconfig.json');
}
if (argv.clean || argv.c) {
console.log(
chalk.yellow(`Removing build in ${chalk.blueBright(linkDir)}`)
);
await fs.remove(linkDir);
} else if (!fs.existsSync(linkDir)) {
console.log(
chalk.green(`Copying build to ${chalk.blueBright(linkDir)}`)
);
await fs.symlink(path.resolve('./dist'), linkDir);
}
return Promise.resolve();
} catch (err) {
Promise.reject(err);
}
}
/*********************/
/* PACKAGE */
/*********************/
/**
* Package build
*/
async function packageBuild() {
const manifest = getManifest();
return new Promise((resolve, reject) => {
try {
// Remove the package dir without doing anything else
if (argv.clean || argv.c) {
console.log(chalk.yellow('Removing all packaged files'));
fs.removeSync('package');
return;
}
// Ensure there is a directory to hold all the packaged versions
fs.ensureDirSync('package');
// Initialize the zip file
const zipName = `${manifest.file.name}-v${manifest.file.version}.zip`;
const zipFile = fs.createWriteStream(path.join('package', zipName));
const zip = archiver('zip', { zlib: { level: 9 } });
zipFile.on('close', () => {
console.log(chalk.green(zip.pointer() + ' total bytes'));
console.log(
chalk.green(`Zip file ${zipName} has been written`)
);
return resolve();
});
zip.on('error', (err) => {
throw err;
});
zip.pipe(zipFile);
// Add the directory with the final code
zip.directory('dist/', manifest.file.name);
zip.finalize();
} catch (err) {
return reject(err);
}
});
}
/*********************/
/* PACKAGE */
/*********************/
/**
* Update version and URLs in the manifest JSON
*/
function updateManifest(cb) {
const packageJson = fs.readJSONSync('package.json');
const config = getConfig(),
manifest = getManifest(),
rawURL = config.rawURL,
repoURL = config.repository,
manifestRoot = manifest.root;
if (!config) cb(Error(chalk.red('foundryconfig.json not found')));
if (!manifest) cb(Error(chalk.red('Manifest JSON not found')));
if (!rawURL || !repoURL)
cb(
Error(
chalk.red(
'Repository URLs not configured in foundryconfig.json'
)
)
);
try {
const version = argv.update || argv.u;
/* Update version */
const versionMatch = /^(\d{1,}).(\d{1,}).(\d{1,})$/;
const currentVersion = manifest.file.version;
let targetVersion = '';
if (!version) {
cb(Error('Missing version number'));
}
if (versionMatch.test(version)) {
targetVersion = version;
} else {
targetVersion = currentVersion.replace(
versionMatch,
(substring, major, minor, patch) => {
console.log(
substring,
Number(major) + 1,
Number(minor) + 1,
Number(patch) + 1
);
if (version === 'major') {
return `${Number(major) + 1}.0.0`;
} else if (version === 'minor') {
return `${major}.${Number(minor) + 1}.0`;
} else if (version === 'patch') {
return `${major}.${minor}.${Number(patch) + 1}`;
} else {
return '';
}
}
);
}
if (targetVersion === '') {
return cb(Error(chalk.red('Error: Incorrect version arguments.')));
}
if (targetVersion === currentVersion) {
return cb(
Error(
chalk.red(
'Error: Target version is identical to current version.'
)
)
);
}
console.log(`Updating version number to '${targetVersion}'`);
packageJson.version = targetVersion;
manifest.file.version = targetVersion;
/* Update URLs */
const result = `${rawURL}/v${manifest.file.version}/package/${manifest.file.name}-v${manifest.file.version}.zip`;
manifest.file.url = repoURL;
manifest.file.manifest = `${rawURL}/master/${manifestRoot}/${manifest.name}`;
manifest.file.download = result;
const prettyProjectJson = stringify(manifest.file, {
maxLength: 35,
indent: '\t',
});
fs.writeJSONSync('package.json', packageJson, { spaces: '\t' });
fs.writeFileSync(
path.join(manifest.root, manifest.name),
prettyProjectJson,
'utf8'
);
return cb();
} catch (err) {
cb(err);
}
}
function gitAdd() {
return gulp.src('package').pipe(git.add({ args: '--no-all' }));
}
function gitCommit() {
return gulp.src('./*').pipe(
git.commit(`v${getManifest().file.version}`, {
args: '-a',
disableAppendPaths: true,
})
);
}
function gitTag() {
const manifest = getManifest();
return git.tag(
`v${manifest.file.version}`,
`Updated to ${manifest.file.version}`,
(err) => {
if (err) throw err;
}
);
}
const execGit = gulp.series(gitAdd, gitCommit, gitTag);
const execBuild = gulp.parallel(buildTS, buildJS, buildMJS, buildCSS, buildLess, buildSASS, copyFiles);
exports.build = gulp.series(clean, execBuild);
exports.watch = buildWatch;
exports.clean = clean;
exports.link = linkUserData;
exports.package = packageBuild;
exports.update = updateManifest;
exports.publish = gulp.series(
clean,
updateManifest,
execBuild,
packageBuild,
execGit
);

View File

@@ -3,6 +3,8 @@
"title": "Smart Doors", "title": "Smart Doors",
"description": "Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors.", "description": "Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors.",
"version": "1.2.5", "version": "1.2.5",
"type": "module",
"socket": true,
"minimumCoreVersion" : "0.7.7", "minimumCoreVersion" : "0.7.7",
"compatibleCoreVersion" : "0.7.9", "compatibleCoreVersion" : "0.7.9",
"authors": [ "authors": [
@@ -27,5 +29,7 @@
"download": "https://github.com/manuelVo/foundryvtt-smart-doors/archive/v1.2.5.zip", "download": "https://github.com/manuelVo/foundryvtt-smart-doors/archive/v1.2.5.zip",
"readme": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/README.md", "readme": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/README.md",
"changelog": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/CHANGELOG.md", "changelog": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/CHANGELOG.md",
"bugs": "https://github.com/manuelVo/foundryvtt-smart-doors/issues" "bugs": "https://github.com/manuelVo/foundryvtt-smart-doors/issues",
"allowBugReporter": true
} }

7464
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

43
package.json Normal file
View File

@@ -0,0 +1,43 @@
{
"private": true,
"name": "smart-doors",
"version": "1.2.5",
"description": "Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors.",
"repository": {
"type": "git",
"url": "git@github-manuelVo:manuelVo/foundryvtt-smart-doors.git"
},
"author": "manuelVo",
"license": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"package": "gulp package",
"build": "gulp build && gulp link",
"build:watch": "gulp watch",
"clean": "gulp clean && gulp link --clean",
"update": "npm install --save-dev @league-of-foundry-developers/foundry-vtt-types@fvtt-0.7.9"
},
"devDependencies": {
"@league-of-foundry-developers/foundry-vtt-types": "^0.7.9-6",
"archiver": "^5.2.0",
"chalk": "^4.1.0",
"fs-extra": "^9.0.1",
"gulp": "^4.0.2",
"gulp-git": "^2.10.1",
"gulp-less": "^4.0.1",
"gulp-sass": "^4.1.0",
"gulp-typescript": "^6.0.0-alpha.1",
"json-stringify-pretty-compact": "^2.0.0",
"sass": "^1.26.10",
"typescript": "^4.2.4",
"yargs": "^15.4.1"
},
"dependencies": {
"eslint": "^7.14.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0"
}
}

14
tsconfig.json Normal file
View File

@@ -0,0 +1,14 @@
{
"compilerOptions": {
"moduleResolution": "node",
"noEmit": false,
"strict": false,
"target": "es2020",
"lib": [
"DOM",
"ES6",
"ES2020"
],
"types": ["@league-of-foundry-developers/foundry-vtt-types"]
}
}