This commit is contained in:
Johannes Loher 2022-02-14 20:22:17 +01:00
commit e5a8eb701c
25 changed files with 21090 additions and 0 deletions

9
.editorconfig Normal file
View file

@ -0,0 +1,9 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true

1
.eslintignore Normal file
View file

@ -0,0 +1 @@
dist

29
.eslintrc.cjs Normal file
View file

@ -0,0 +1,29 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
env: {
browser: true,
},
extends: ['plugin:@typescript-eslint/recommended', 'plugin:jest/recommended', 'plugin:prettier/recommended'],
plugins: ['@typescript-eslint', 'jest'],
rules: {
// Specify any specific ESLint rules.
},
overrides: [
{
files: ['./*.cjs'],
rules: {
'@typescript-eslint/no-var-requires': 'off',
},
},
],
};

28
.gitignore vendored Normal file
View file

@ -0,0 +1,28 @@
# IDE
.idea/
.vs/
# Node Modules
node_modules/
npm-debug.log
# yarn2
.yarn/*
!.yarn/patches
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
# Local configuration
foundryconfig.json
# Distribution files
dist
# ESLint
.eslintcache
# Junit results
junit.xml

118
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,118 @@
image: node:lts
variables:
PACKAGE_NAME: foundry-factory-demo-gitlab
PACKAGE_TYPE: module
PACKAGE_REGISTRY_URL: $CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/$PACKAGE_NAME
stages:
- build
- prepare-release
- release
- publish
cache: &global_cache
paths:
- .npm
lint:
stage: build
before_script:
- npm ci --cache .npm --prefer-offline
script:
- npm run lint
cache:
<<: *global_cache
test:
stage: build
before_script:
- npm ci --cache .npm --prefer-offline
script:
- npm run test:ci
cache:
<<: *global_cache
artifacts:
when: always
reports:
junit:
- junit.xml
typecheck:
stage: build
before_script:
- npm ci --cache .npm --prefer-offline
script:
- npm run typecheck
cache:
<<: *global_cache
build:
stage: build
before_script:
- apt --yes update
- apt --yes install jq
- npm ci --cache .npm --prefer-offline
script: |
jq '.version = $version | .url = $url | .manifest = $manifest | .download = $download' \
--arg version "${CI_COMMIT_TAG:1}" \
--arg url "$CI_PROJECT_URL" \
--arg manifest "$PACKAGE_REGISTRY_URL/latest/$PACKAGE_TYPE.json" \
--arg download "$CI_PROJECT_URL/-/releases/$CI_COMMIT_TAG/downloads/$PACKAGE_TYPE.zip" \
src/$PACKAGE_TYPE.json > src/tmp.$$.json
mv src/tmp.$$.json src/$PACKAGE_TYPE.json
npm run build
cache:
<<: *global_cache
artifacts:
paths:
- dist
expire_in: 1 week
publish-artifacts:
stage: prepare-release
image: alpine:latest
before_script:
- apk update
- apk add zip curl
script: |
cd dist
zip -r ../$PACKAGE_TYPE.zip .
cd ..
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $PACKAGE_TYPE.zip "$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/$PACKAGE_TYPE.zip"
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file dist/$PACKAGE_TYPE.json "$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/$PACKAGE_TYPE.json"
rules:
- if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/'
release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script:
- echo 'release job'
rules:
- if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/'
release:
name: ${CI_COMMIT_TAG:1}
tag_name: $CI_COMMIT_TAG
description: '**Installation:** To manually install this release, please use the following manifest URL: $CI_PROJECT_URL/-/releases/$CI_COMMIT_TAG/downloads/$PACKAGE_TYPE.json'
assets:
links:
- name: '$PACKAGE_TYPE.zip'
url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/$PACKAGE_TYPE.zip'
filepath: /$PACKAGE_TYPE.zip
link_type: package
- name: '$PACKAGE_TYPE.json'
url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/$PACKAGE_TYPE.json'
filepath: /$PACKAGE_TYPE.json
link_type: other
publish-latest-manifest:
stage: publish
image: alpine:latest
before_script:
- apk update
- apk add zip curl
script: |
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file dist/$PACKAGE_TYPE.json "$PACKAGE_REGISTRY_URL/latest/$PACKAGE_TYPE.json"
rules:
- if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/'

4
.husky/pre-commit Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

1
.nvmrc Normal file
View file

@ -0,0 +1 @@
lts/*

2
.prettierignore Normal file
View file

@ -0,0 +1,2 @@
dist
package-lock.json

7
.prettierrc.cjs Normal file
View file

@ -0,0 +1,7 @@
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 2,
};

100
README.md Normal file
View file

@ -0,0 +1,100 @@
# foundry-factory-demo-gitlab
Please add your description here.
## Installation
Please add your installation instructions here.
## Development
### Prerequisites
In order to build this module, recent versions of `node` and `npm` are
required. Most likely, using `yarn` also works, but only `npm` is officially
supported. We recommend using the latest lts version of `node`. If you use `nvm`
to manage your `node` versions, you can simply run
```
nvm install
```
in the project's root directory.
You also need to install the project's dependencies. To do so, run
```
npm install
```
### Building
You can build the project by running
```
npm run build
```
Alternatively, you can run
```
npm run build:watch
```
to watch for changes and automatically build as necessary.
### Linking the built project to Foundry VTT
In order to provide a fluent development experience, it is recommended to link
the built module to your local Foundry VTT installation's data folder. In
order to do so, first add a file called `foundryconfig.json` to the project root
with the following content:
```
{
"dataPath": "/absolute/path/to/your/FoundryVTT"
}
```
(if you are using Windows, make sure to use `\` as a path separator instead of
`/`)
Then run
```
npm run link-project
```
On Windows, creating symlinks requires administrator privileges, so unfortunately
you need to run the above command in an administrator terminal for it to work.
### Running the tests
You can run the tests with the following command:
```
npm test
```
### Creating a release
In order to create a versioned release, simply create / push a new tag that follows the pattern
`v<number>.<number>.<number>`. This triggers a pipeline run that automatically builds the package and creates a release
that has a `module.zip` / `system.zip` and a `module.json` / `system.json` attached to it. These files are set up so
that they work in the same way as in the [League Basic JS Module Template], so you can follow the instructions given
there to list the release on the Foundry VTT package admin page.
If you want to provide release notes, you can then edit the created release to add a description.
## Licensing
This project is being developed under the terms of the
[LIMITED LICENSE AGREEMENT FOR MODULE DEVELOPMENT] for Foundry Virtual Tabletop.
Please add your licensing information here. Add your chosen license as
`LICENSE` file to the project root and mention it here. If you don't know which
license to choose, take a look at [Choose an open source license].
[League Basic JS Module Template]: https://github.com/League-of-Foundry-Developers/FoundryVTT-Module-Template
[LIMITED LICENSE AGREEMENT FOR MODULE DEVELOPMENT]: https://foundryvtt.com/article/license/
[Choose an open source license]: https://choosealicense.com/

156
gulpfile.js Normal file
View file

@ -0,0 +1,156 @@
import fs from 'fs-extra';
import gulp from 'gulp';
import sass from 'gulp-dart-sass';
import sourcemaps from 'gulp-sourcemaps';
import path from 'node:path';
import buffer from 'vinyl-buffer';
import source from 'vinyl-source-stream';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import rollupStream from '@rollup/stream';
import rollupConfig from './rollup.config.js';
/********************/
/* CONFIGURATION */
/********************/
const name = 'foundry-factory-demo-gitlab';
const sourceDirectory = './src';
const distDirectory = './dist';
const stylesDirectory = `${sourceDirectory}/styles`;
const stylesExtension = 'scss';
const sourceFileExtension = 'ts';
const staticFiles = ['assets', 'fonts', 'lang', 'packs', 'templates', 'module.json'];
/********************/
/* BUILD */
/********************/
let cache;
/**
* Build the distributable JavaScript code
*/
function buildCode() {
return rollupStream({ ...rollupConfig(), cache })
.on('bundle', (bundle) => {
cache = bundle;
})
.pipe(source(`${name}.js`))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(`${distDirectory}/module`));
}
/**
* Build style sheets
*/
function buildStyles() {
return gulp
.src(`${stylesDirectory}/${name}.${stylesExtension}`)
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(`${distDirectory}/styles`));
}
/**
* Copy static files
*/
async function copyFiles() {
for (const file of staticFiles) {
if (fs.existsSync(`${sourceDirectory}/${file}`)) {
await fs.copy(`${sourceDirectory}/${file}`, `${distDirectory}/${file}`);
}
}
}
/**
* Watch for changes for each build step
*/
export function watch() {
gulp.watch(`${sourceDirectory}/**/*.${sourceFileExtension}`, { ignoreInitial: false }, buildCode);
gulp.watch(`${stylesDirectory}/**/*.${stylesExtension}`, { ignoreInitial: false }, buildStyles);
gulp.watch(
staticFiles.map((file) => `${sourceDirectory}/${file}`),
{ ignoreInitial: false },
copyFiles,
);
}
export const build = gulp.series(clean, gulp.parallel(buildCode, buildStyles, copyFiles));
/********************/
/* CLEAN */
/********************/
/**
* Remove built files from `dist` folder while ignoring source files
*/
export async function clean() {
const files = [...staticFiles, 'module'];
if (fs.existsSync(`${stylesDirectory}/${name}.${stylesExtension}`)) {
files.push('styles');
}
console.log(' ', 'Files to clean:');
console.log(' ', files.join('\n '));
for (const filePath of files) {
await fs.remove(`${distDirectory}/${filePath}`);
}
}
/********************/
/* LINK */
/********************/
/**
* Get the data path of Foundry VTT based on what is configured in `foundryconfig.json`
*/
function getDataPath() {
const config = fs.readJSONSync('foundryconfig.json');
if (config?.dataPath) {
if (!fs.existsSync(path.resolve(config.dataPath))) {
throw new Error('User Data path invalid, no Data directory found');
}
return path.resolve(config.dataPath);
} else {
throw new Error('No User Data path defined in foundryconfig.json');
}
}
/**
* Link build to User Data folder
*/
export async function link() {
let destinationDirectory;
if (fs.existsSync(path.resolve(sourceDirectory, 'module.json'))) {
destinationDirectory = 'modules';
} else {
throw new Error('Could not find module.json');
}
const linkDirectory = path.resolve(getDataPath(), 'Data', destinationDirectory, name);
const argv = yargs(hideBin(process.argv)).option('clean', {
alias: 'c',
type: 'boolean',
default: false,
}).argv;
const clean = argv.c;
if (clean) {
console.log(`Removing build in ${linkDirectory}.`);
await fs.remove(linkDirectory);
} else if (!fs.existsSync(linkDirectory)) {
console.log(`Linking dist to ${linkDirectory}.`);
await fs.ensureDir(path.resolve(linkDirectory, '..'));
await fs.symlink(path.resolve(distDirectory), linkDirectory);
}
}

9
jest.config.js Normal file
View file

@ -0,0 +1,9 @@
export default {
preset: 'ts-jest',
testEnvironment: 'node',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/test/tsconfig.test.json',
},
},
};

20420
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

68
package.json Normal file
View file

@ -0,0 +1,68 @@
{
"private": true,
"name": "foundry-factory-demo-gitlab",
"description": "",
"license": "",
"homepage": "",
"repository": {
"type": "git",
"url": ""
},
"bugs": {
"url": ""
},
"contributors": [
{
"name": "",
"email": ""
}
],
"type": "module",
"scripts": {
"build": "gulp build",
"build:watch": "gulp watch",
"link-project": "gulp link",
"clean": "gulp clean",
"clean:link": "gulp link --clean",
"typecheck": "tsc --noEmit",
"lint": "eslint --ext .ts,.js,.cjs .",
"lint:fix": "eslint --ext .ts,.js,.cjs --fix .",
"format": "prettier --write \"./**/*.(ts|js|cjs|json|yml|scss)\"",
"test": "jest",
"test:watch": "jest --watch",
"test:ci": "jest --ci --reporters=default --reporters=jest-junit",
"postinstall": "husky install"
},
"devDependencies": {
"@league-of-foundry-developers/foundry-vtt-types": "^9.249.2",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-typescript": "^8.3.0",
"@rollup/stream": "^2.0.0",
"@types/jest": "^27.4.0",
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jest": "^26.1.0",
"eslint-plugin-prettier": "^4.0.0",
"fs-extra": "^10.0.0",
"gulp": "^4.0.2",
"gulp-dart-sass": "^1.0.2",
"gulp-sourcemaps": "^3.0.0",
"husky": "^7.0.4",
"jest": "^27.5.1",
"jest-junit": "^13.0.0",
"lint-staged": "^12.3.4",
"prettier": "^2.5.1",
"rollup": "^2.67.2",
"ts-jest": "^27.1.3",
"typescript": "^4.5.5",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0",
"yargs": "^17.3.1"
},
"lint-staged": {
"*.(ts|js|cjs)": "eslint --fix",
"*.(json|yml|scss)": "prettier --write"
}
}

12
rollup.config.js Normal file
View file

@ -0,0 +1,12 @@
import typescript from '@rollup/plugin-typescript';
import { nodeResolve } from '@rollup/plugin-node-resolve';
export default () => ({
input: 'src/module/foundry-factory-demo-gitlab.ts',
output: {
dir: 'dist/module',
format: 'es',
sourcemap: true,
},
plugins: [nodeResolve(), typescript()],
});

1
src/lang/en.json Normal file
View file

@ -0,0 +1 @@
{}

38
src/module.json Normal file
View file

@ -0,0 +1,38 @@
{
"name": "foundry-factory-demo-gitlab",
"title": "foundry-factory-demo-gitlab",
"description": "",
"version": "This is auto replaced",
"author": "<your name>",
"authors": [
{
"name": "<your name>",
"email": "<optionally your e-mail address>",
"discord": "<optionally your discord username>"
}
],
"minimumCoreVersion": "9",
"compatibleCoreVersion": "9",
"scripts": [],
"esmodules": ["module/foundry-factory-demo-gitlab.js"],
"styles": ["styles/foundry-factory-demo-gitlab.css"],
"packs": [],
"dependencies": [],
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
],
"socket": false,
"url": "This is auto replaced",
"manifest": "This is auto replaced",
"download": "This is auto replaced",
"license": "",
"readme": "",
"bugs": "",
"changelog": "",
"system": [],
"library": false
}

View file

@ -0,0 +1,43 @@
/**
* This is your TypeScript entry file for Foundry VTT.
* Register custom settings, sheets, and constants using the Foundry API.
* Change this heading to be more descriptive to your module, or remove it.
* Author: [your name]
* Content License: [copyright and-or license] If using an existing system
* you may want to put a (link to a) license or copyright
* notice here (e.g. the OGL).
* Software License: [your license] Put your desired license here, which
* determines how others may use and modify your module.
*/
// Import TypeScript modules
import { registerSettings } from './settings';
import { preloadTemplates } from './preloadTemplates';
// Initialize module
Hooks.once('init', async () => {
console.log('foundry-factory-demo-gitlab | Initializing foundry-factory-demo-gitlab');
// Assign custom classes and constants here
// Register custom module settings
registerSettings();
// Preload Handlebars templates
await preloadTemplates();
// Register custom sheets (if any)
});
// Setup module
Hooks.once('setup', async () => {
// Do anything after initialization but before
// ready
});
// When ready
Hooks.once('ready', async () => {
// Do anything once the module is ready
});
// Add any additional hooks if necessary

View file

@ -0,0 +1,7 @@
export async function preloadTemplates(): Promise<Handlebars.TemplateDelegate[]> {
const templatePaths: string[] = [
// Add paths to "modules/foundry-factory-demo-gitlab/templates"
];
return loadTemplates(templatePaths);
}

3
src/module/settings.ts Normal file
View file

@ -0,0 +1,3 @@
export function registerSettings(): void {
// Register any custom module settings here
}

View file

@ -0,0 +1,4 @@
/* ---------------------------- */
/* Sass */
/* This is your Sass entry file */
/* ---------------------------- */

7
test/example.test.ts Normal file
View file

@ -0,0 +1,7 @@
describe('An example test', () => {
it('will always succeed', () => {
expect(true).toBeTruthy();
});
});
// Add real tests here.

7
test/tsconfig.test.json Normal file
View file

@ -0,0 +1,7 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": ["@league-of-foundry-developers/foundry-vtt-types", "jest"]
},
"include": ["../src", "./"]
}

4
tsconfig.eslint.json Normal file
View file

@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["src", "test", "*.js", "*.cjs"]
}

12
tsconfig.json Normal file
View file

@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES2020",
"lib": ["DOM", "ES2020"],
"types": ["@league-of-foundry-developers/foundry-vtt-types"],
"esModuleInterop": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"strict": true
},
"include": ["src"]
}