@fmsim/builder 0.0.49

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/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
+ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
+
8
+ <!-- ## [Unreleased] -->
package/README.md ADDED
File without changes
@@ -0,0 +1,43 @@
1
+ /*
2
+ * 모든 클라이언트 모듈의 entries 파일들에 오버라이드를 적용해서 최종에 entries 파일로 병합될 파일리스트를 선정하는 기능.
3
+ */
4
+
5
+ const path = require('path')
6
+ const glob = require('glob')
7
+
8
+ module.exports = function () {
9
+ const { orderedModuleNames, appRootPath } = require('@things-factory/env')
10
+
11
+ const AppPackage = require(path.resolve(appRootPath, 'package.json'))
12
+
13
+ var appname = AppPackage.name
14
+
15
+ var reversedModuleNames = [...orderedModuleNames, appname].reverse()
16
+ var entryFiles = {}
17
+
18
+ /* 최상위 모듈부터 복사한다. 하위 모듈에서는 중복 여부에 따라 복사여부를 결정한다. */
19
+ reversedModuleNames.forEach(m => {
20
+ var modulePackage = appname === m ? AppPackage : require(`${m}/package.json`)
21
+ var browserPath = modulePackage.browser
22
+
23
+ if (!browserPath) {
24
+ return
25
+ }
26
+
27
+ var modulePath = appname === m ? appRootPath : path.dirname(require.resolve(`${m}/package.json`))
28
+ modulePath = path.dirname(path.join(modulePath, browserPath))
29
+
30
+ var files = glob.sync(`${path.join(modulePath, 'entries', '**', '*.js')}`)
31
+ var idx = path.join(modulePath, 'entries').length
32
+
33
+ files.forEach(filepath => {
34
+ let filename = filepath.substring(idx + 1, filepath.length - 3)
35
+
36
+ if (!entryFiles[filename]) {
37
+ entryFiles[filename] = [filepath]
38
+ }
39
+ })
40
+ })
41
+
42
+ return entryFiles
43
+ }
@@ -0,0 +1,15 @@
1
+ FROM nginx
2
+
3
+ # 기본 설정 파일을 지우고, 새로운 파일로 대체합니다.
4
+ RUN rm -rf /etc/nginx/conf.d/default.conf
5
+
6
+ COPY ./app.conf /etc/nginx/conf.d/app.conf
7
+ COPY ./nginx.conf /etc/nginx/nginx.conf
8
+
9
+ VOLUME ["/data", "/etc/nginx", "/var/log/nginx"]
10
+
11
+ WORKDIR /etc/nginx
12
+
13
+ CMD ["nginx"]
14
+
15
+ EXPOSE 80
@@ -0,0 +1,19 @@
1
+ server {
2
+ listen 80;
3
+ listen [::]:80;
4
+
5
+ server_name "";
6
+
7
+ access_log off;
8
+
9
+ location / {
10
+ proxy_pass http://app:3000;
11
+ proxy_set_header Host $host:$server_port;
12
+ proxy_set_header X-Forwarded-Host $server_name;
13
+ proxy_set_header X-Real-IP $remote_addr;
14
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
15
+ proxy_set_header Upgrade $http_upgrade;
16
+ proxy_set_header Connection "upgrade";
17
+ proxy_http_version 1.1;
18
+ }
19
+ }
@@ -0,0 +1,47 @@
1
+ #nginx.conf
2
+ daemon off;
3
+ user www-data;
4
+ worker_processes 2;
5
+
6
+ error_log /var/log/nginx/error.log warn;
7
+ pid /var/run/nginx.pid;
8
+
9
+ events {
10
+ worker_connections 1024;
11
+ use epoll;
12
+ accept_mutex off;
13
+ }
14
+
15
+ http {
16
+ include /etc/nginx/mime.types;
17
+ proxy_set_header X-Real-IP $remote_addr;
18
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
19
+
20
+ default_type application/octet-stream;
21
+
22
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
23
+ '$status $body_bytes_sent "$http_referer" '
24
+ '"$http_user_agent" "$http_x_forwarded_for"';
25
+
26
+ access_log /var/log/nginx/access.log main;
27
+
28
+ sendfile on;
29
+ #tcp_nopush on;
30
+
31
+ keepalive_timeout 65;
32
+
33
+ client_max_body_size 300m;
34
+ client_body_buffer_size 128k;
35
+
36
+ gzip on;
37
+ gzip_http_version 1.0;
38
+ gzip_comp_level 6;
39
+ gzip_min_length 0;
40
+ gzip_buffers 16 8k;
41
+ gzip_proxied any;
42
+ gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json;
43
+ gzip_disable "MSIE [1-6]\.";
44
+ gzip_vary on;
45
+
46
+ include /etc/nginx/conf.d/*.conf;
47
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env bash
2
+
3
+ VERSION=latest
4
+
5
+ if [ $# -eq 0 ] ; then
6
+ echo "Default Version latest"
7
+ else
8
+ VERSION=$1
9
+ fi
10
+
11
+ echo "VERSION : ${VERSION}"
12
+
13
+ docker image build -t hatiolab/operato-nginx:${VERSION} -f Dockerfile --platform ${PLATFORM} .
@@ -0,0 +1,47 @@
1
+ # Use an official node image
2
+ FROM node:18.12
3
+
4
+ ARG DEBIAN_FRONTEND=noninteractive
5
+
6
+ # Install the required packages
7
+
8
+ RUN echo "deb http://ftp.de.debian.org/debian stable main" > /etc/apt/sources.list
9
+
10
+ RUN apt-get update
11
+
12
+ RUN apt-get install -y --no-install-recommends apt-utils
13
+ RUN apt-get install -y chromium
14
+ RUN apt-get install -y libcups2-dev
15
+ RUN apt-get install -y libavahi-compat-libdnssd-dev
16
+ RUN apt-get install -y gconf-service libasound2 libatk1.0-0 libcairo2 libcups2 libfontconfig1 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libxss1 fonts-liberation libnss3 lsb-release xdg-utils libaio1
17
+
18
+ RUN apt update
19
+ RUN apt-get install -y ghostscript
20
+ RUN apt-get install -y curl
21
+ RUN apt-get install -y git
22
+
23
+ # install chrome
24
+ RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
25
+ RUN dpkg -i google-chrome-stable_current_amd64.deb; apt-get -fy install
26
+ RUN rm google-chrome-stable_current_amd64.deb
27
+
28
+
29
+
30
+ # make oracle path
31
+ RUN mkdir -p /opt/oracle
32
+ WORKDIR /opt/oracle
33
+
34
+ # download newest oracle cilent for connect to Oracle Database
35
+ RUN wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip && \
36
+ unzip instantclient-basiclite-linuxx64.zip && \
37
+ rm -f instantclient-basiclite-linuxx64.zip && \
38
+ cd /opt/oracle/instantclient* && \
39
+ rm -f *jdbc* *occi* *mysql* *mql1* *ipc1* *jar uidrvci genezi adrci && \
40
+ echo /opt/oracle/instantclient* > /etc/ld.so.conf.d/oracle-instantclient.conf &&\
41
+ ldconfig
42
+
43
+ # fix the font issue of headless control
44
+ RUN apt-get update && apt-get install -y fonts-unfonts-core
45
+
46
+ RUN apt-get clean \
47
+ && rm -rf /var/lib/apt/lists/*
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+
3
+ IMAGE_LASTEST=latest
4
+ PLATFORM=linux/amd64
5
+ VERSION=18
6
+
7
+ if [ $# -eq 0 ] ; then
8
+ echo "Default Version ${VERSION}"
9
+ echo "Default Platform ${PLATFORM}"
10
+ else
11
+ VERSION=$1
12
+ IMAGE_LASTEST=$2
13
+ PLATFORM=$3
14
+ fi
15
+
16
+ docker image build -t hatiolab/operato-env:${VERSION} -t hatiolab/operato-env:${IMAGE_LASTEST} -f Dockerfile --platform ${PLATFORM} .
17
+
18
+ docker image push hatiolab/operato-env:${VERSION} && docker image push hatiolab/operato-env:${IMAGE_LASTEST}
package/index.js ADDED
File without changes
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@fmsim/builder",
3
+ "version": "0.0.49",
4
+ "description": "Layout View 어플리케이션 빌드를 위해 구성된 모듈입니다.",
5
+ "main": "index.js",
6
+ "author": "Hearty Oh <heartyoh@hatiolab.com>",
7
+ "license": "MIT",
8
+ "publishConfig": {
9
+ "access": "public",
10
+ "@things-factory:registry": "https://registry.npmjs.org"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/hatiolab/fmsim.git",
15
+ "directory": "packages/integrator"
16
+ },
17
+ "dependencies": {
18
+ "@babel/cli": "^7.18.10",
19
+ "@babel/core": "^7.18.13",
20
+ "@babel/eslint-parser": "^7.18.9",
21
+ "@babel/plugin-proposal-decorators": "^7.18.10",
22
+ "@babel/preset-env": "^7.18.10",
23
+ "@babel/preset-react": "^7.18.6",
24
+ "@babel/preset-typescript": "^7.18.6",
25
+ "@babel/register": "^7.18.9",
26
+ "@types/jest": "^29.2.1",
27
+ "@types/lodash": "^4.14.139",
28
+ "@types/node": "^18.11.18",
29
+ "@types/react": "^18.0.26",
30
+ "@types/react-dom": "^18.0.11",
31
+ "babel-jest": "^29.2.2",
32
+ "babel-loader": "^9.1.2",
33
+ "concurrently": "^8.0.1",
34
+ "copy-webpack-plugin": "^11.0.0",
35
+ "copyfiles": "^2.4.1",
36
+ "cross-fetch": "^3.0.4",
37
+ "css-loader": "^6.7.3",
38
+ "docdash": "^2.0.1",
39
+ "documentation": "^14.0.0",
40
+ "element-closest": "^3.0.2",
41
+ "eslint": "^8.39.0",
42
+ "faker": "^6.6.6",
43
+ "file-loader": "^6.2.0",
44
+ "fs-extra": "^11.1.1",
45
+ "full-icu": "^1.3.0",
46
+ "get-port": "^6.1.2",
47
+ "graphql": "^16.5.0",
48
+ "html-webpack-plugin": "^5.5.0",
49
+ "intl-pluralrules": "^2.0.0",
50
+ "jest": "^29.2.2",
51
+ "lerna": "^6.6.1",
52
+ "less": "^4.1.3",
53
+ "less-loader": "^11.1.0",
54
+ "mini-css-extract-plugin": "^2.5.2",
55
+ "node-polyfill-webpack-plugin": "^2.0.1",
56
+ "plop": "^3.1.1",
57
+ "postcss-loader": "^7.3.0",
58
+ "prettier": "^2.5.1",
59
+ "raw-loader": "^4.0.2",
60
+ "replace-in-file-webpack-plugin": "^1.0.6",
61
+ "rimraf": "^5.0.0",
62
+ "saddle-up": "^0.5.1",
63
+ "sass-loader": "^13.2.2",
64
+ "terser": "^5.1.0",
65
+ "text-loader": "^0.0.1",
66
+ "ts-jest": "^29.1.0",
67
+ "ts-node": "^10.9.1",
68
+ "tsconfig-paths": "^4.1.0",
69
+ "typescript": "^5.0.4",
70
+ "webpack": "^5.65.0",
71
+ "webpack-cli": "^5.0.1",
72
+ "webpack-dev-server": "^4.11.0",
73
+ "workbox-webpack-plugin": "^6.5.4"
74
+ },
75
+ "gitHead": "59b7cd248a3b0e637d4e124a28829441c4b258b2"
76
+ }
@@ -0,0 +1,56 @@
1
+ const debug = require('debug')('things-factory:builder:things-factory-module-loader')
2
+
3
+ const path = require('path')
4
+ const { orderedModuleNames } = require('@things-factory/env')
5
+
6
+ const appRootPath = path.resolve('.')
7
+ const selfModulePackage = require(path.resolve(appRootPath, 'package.json'))
8
+ const selfModuleName = selfModulePackage.name
9
+
10
+ function pkgLoader(moduleName) {
11
+ try {
12
+ if (selfModuleName == moduleName) {
13
+ return selfModulePackage
14
+ } else {
15
+ return require(moduleName)
16
+ }
17
+ } catch (e) {
18
+ console.error('load error', e)
19
+ }
20
+ }
21
+
22
+ module.exports = function (content) {
23
+ debug('Module Configuration Begin')
24
+
25
+ const moduleConfigMap = orderedModuleNames.reduce((sum, name) => {
26
+ const pkg = pkgLoader(name + '/package.json')
27
+ const thingsFactoryConfig = pkg.thingsFactoryConfig ?? 'things-factory.config.js'
28
+ const config = `${name}/${thingsFactoryConfig}`
29
+
30
+ sum[name] = { pkg, config }
31
+ return sum
32
+ }, {})
33
+
34
+ var result = `
35
+ export var modules = [];
36
+
37
+ ${orderedModuleNames
38
+ .filter(name => moduleConfigMap[name])
39
+ .map((module, idx) => {
40
+ return `
41
+ import v${idx} from "${moduleConfigMap[module].config}"
42
+ modules.push({
43
+ ...v${idx},
44
+ name: "${moduleConfigMap[module].pkg.name}",
45
+ version: "${moduleConfigMap[module].pkg.version}",
46
+ license: "${moduleConfigMap[module].pkg.license}"
47
+ })
48
+ `
49
+ })
50
+ .join('')}
51
+ `
52
+
53
+ debug('Module Configuration End.')
54
+
55
+ return result
56
+ }
@@ -0,0 +1,18 @@
1
+ const debug = require('debug')('things-factory:builder:things-scene-config-webpack-loader')
2
+
3
+ const { sceneModuleNames } = require('@things-factory/env')
4
+
5
+ module.exports = function (content) {
6
+ const script =
7
+ 'var metas = []\n' +
8
+ sceneModuleNames
9
+ .map((name, idx) => {
10
+ return `import v${idx} from "${name}/things-scene.config.js"\nmetas[${idx}] = v${idx}`
11
+ })
12
+ .join('\n') +
13
+ '\nexport default metas\n'
14
+
15
+ debug('Things Scene Components for Modeller\n', script)
16
+
17
+ return script
18
+ }
@@ -0,0 +1,12 @@
1
+ const debug = require('debug')('things-factory:builder:things-scene-webpack-loader')
2
+
3
+ const { sceneModuleNames } = require('@things-factory/env')
4
+
5
+ module.exports = function (content) {
6
+
7
+ const script = sceneModuleNames.map(component => `import '${component}'\n`).join('')
8
+
9
+ debug('Things Scene Components', '\n' + script)
10
+
11
+ return script
12
+ }
@@ -0,0 +1,112 @@
1
+ /*
2
+ * 모든 모듈의 특정 폴더(특히, assets)를 모듈 디펜던시 순서에 따라 오버라이드 및 병합한다.
3
+ */
4
+
5
+ const path = require('path')
6
+ const fs = require('fs-extra')
7
+ const glob = require('glob')
8
+ const loaderUtils = require('loader-utils')
9
+ const debug = require('debug')('things-factory:builder:folder-override-plugin')
10
+
11
+ const { orderedModuleNames, sceneModuleNames, appRootPath } = require('@things-factory/env')
12
+
13
+ const AppPackage = require(path.resolve(appRootPath, 'package.json'))
14
+
15
+ class FolderOverridePlugin {
16
+ constructor(options = {}) {
17
+ this.options = options
18
+ this.writtenFrom = {}
19
+ this.writtenTo = {}
20
+ }
21
+
22
+ apply(compiler) {
23
+ var contexts = []
24
+
25
+ compiler.hooks.thisCompilation.tap({ name: 'FolderOverridePlugin' }, compilation => {
26
+ /* contexts 초기화 */
27
+ contexts = []
28
+ var { target: targetDir } = this.options
29
+
30
+ var appname = AppPackage.name
31
+ var modules = [...orderedModuleNames, ...sceneModuleNames].filter(modulename => modulename !== appname)
32
+ modules.push(appname)
33
+ var reversedModuleNames = modules.reverse()
34
+
35
+ /* 최상위 모듈부터 복사한다. 하위 모듈에서는 중복 여부에 따라 복사여부를 결정한다. */
36
+ reversedModuleNames.forEach(m => {
37
+ if (appname == m) {
38
+ var modulePath = appRootPath
39
+ } else {
40
+ var modulePath = path.dirname(require.resolve(`${m}/package.json`))
41
+ }
42
+
43
+ var sourcePath = path.resolve(modulePath, targetDir)
44
+ contexts.push(sourcePath)
45
+
46
+ var files = glob.sync(`${sourcePath}/**/*`)
47
+
48
+ files.forEach(filepath => {
49
+ let relativePath = path.relative(modulePath, filepath)
50
+
51
+ this.write(compilation, filepath, relativePath)
52
+ })
53
+ })
54
+ })
55
+
56
+ compiler.hooks.afterEmit.tap({ name: 'FolderOverridePlugin' }, compilation => {
57
+ // Add context dependencies if they're not already tracked
58
+ contexts.forEach(context => {
59
+ if (!compilation.contextDependencies.has(context)) {
60
+ compilation.contextDependencies.add(context)
61
+ }
62
+ })
63
+ })
64
+ }
65
+
66
+ write(compilation, filepath, relativePath) {
67
+ var stat = fs.statSync(filepath)
68
+ if (stat.isDirectory()) {
69
+ return
70
+ }
71
+
72
+ var content = fs.readFileSync(filepath)
73
+ const hash = loaderUtils.getHashDigest(content)
74
+ const webpackTo = loaderUtils.interpolateName(
75
+ {
76
+ resourcePath: filepath
77
+ },
78
+ relativePath,
79
+ {
80
+ content
81
+ }
82
+ )
83
+
84
+ if (this.writtenTo[webpackTo] && this.writtenTo[webpackTo] !== filepath) {
85
+ return
86
+ }
87
+
88
+ if (this.writtenFrom[filepath] && this.writtenFrom[filepath][hash]) {
89
+ // debug(`skipping '${filepath}', because it hasn't changed`)
90
+ return
91
+ }
92
+
93
+ // debug(`writing '${webpackTo}' from '${filepath}'`)
94
+ this.writtenTo[webpackTo] = filepath
95
+ this.writtenFrom[filepath] = {
96
+ [hash]: true
97
+ }
98
+
99
+ this.writtenFrom[filepath].webpackTo = webpackTo
100
+
101
+ compilation.assets[webpackTo] = {
102
+ size() {
103
+ return stat.size
104
+ },
105
+ source() {
106
+ return content
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ module.exports = FolderOverridePlugin
@@ -0,0 +1,100 @@
1
+ /*
2
+ * 모든 모듈의 translations에 정의된 locale 리소스들을 모두 모아서 하나의 translations로 병합한다.
3
+ */
4
+
5
+ const fs = require('fs-extra')
6
+ const path = require('path')
7
+ const glob = require('glob')
8
+ const debug = require('debug')('things-factory:builder:i18n-bundler-plugin')
9
+
10
+ const { orderedModuleNames, sceneModuleNames, appRootPath } = require('@things-factory/env')
11
+
12
+ const AppPackage = require(path.resolve(appRootPath, 'package.json'))
13
+
14
+ function merge(target, source) {
15
+ for (let key of Object.keys(source)) {
16
+ if (source[key] instanceof Object) Object.assign(source[key], merge(target[key], source[key]))
17
+ }
18
+
19
+ Object.assign(target || {}, source)
20
+ return target
21
+ }
22
+
23
+ class I18nBundlerPlugin {
24
+ constructor(options = {}) {
25
+ this.options = options
26
+ }
27
+
28
+ apply(compiler) {
29
+ var contexts = []
30
+ var files = []
31
+
32
+ compiler.hooks.thisCompilation.tap({ name: 'I18nBundlerPlugin' }, compilation => {
33
+ /* dependencies 초기화 */
34
+ contexts = []
35
+ files = []
36
+
37
+ var appname = AppPackage.name
38
+ var modules = [...orderedModuleNames, ...sceneModuleNames].filter(modulename => modulename !== appname)
39
+ modules.push(appname)
40
+
41
+ var translationsDir = this.options.output || 'translations'
42
+
43
+ var translations = modules.reduce((summary, m) => {
44
+ if (appname == m) {
45
+ var modulePath = appRootPath
46
+ } else {
47
+ var modulePath = path.dirname(require.resolve(`${m}/package.json`))
48
+ }
49
+ var translationsPath = path.resolve(modulePath, translationsDir)
50
+ contexts.push(translationsPath)
51
+
52
+ files = glob.sync(`${translationsPath}/*.json`)
53
+
54
+ return files.reduce((summary, file) => {
55
+ try {
56
+ var contents = fs.readFileSync(file)
57
+ var json = JSON.parse(contents)
58
+
59
+ var filename = file.replace(/^.*[\\\/]/, '')
60
+ var locale = filename.substring(0, filename.length - 5)
61
+
62
+ summary[locale] = merge(summary[locale] || {}, json)
63
+ } catch (e) {
64
+ console.error(e)
65
+ } finally {
66
+ return summary
67
+ }
68
+ }, summary)
69
+ }, {})
70
+
71
+ /* 각 locale 별로 file을 저장한다. */
72
+ for (let locale in translations) {
73
+ let localePath = path.join(translationsDir, `${locale}.json`)
74
+ let content = JSON.stringify(translations[locale], null, 2)
75
+
76
+ // debug(`Restoring locale '${locale}' resource into '${localePath}'`)
77
+
78
+ compilation.assets[localePath] = {
79
+ source: function () {
80
+ return content
81
+ },
82
+ size: function () {
83
+ return content.length
84
+ }
85
+ }
86
+ }
87
+ })
88
+
89
+ compiler.hooks.afterEmit.tap({ name: 'I18nBundlerPlugin' }, compilation => {
90
+ // Add context dependencies if they're not already tracked
91
+ contexts.forEach(context => {
92
+ if (!compilation.contextDependencies.has(context)) {
93
+ compilation.contextDependencies.add(context)
94
+ }
95
+ })
96
+ })
97
+ }
98
+ }
99
+
100
+ module.exports = I18nBundlerPlugin
@@ -0,0 +1,56 @@
1
+ /*
2
+ * 모든 모듈의 theme 파일들에 오버라이드를 적용해서 최종에 theme css파일로 병합될 파일리스트를 선정하여, webpack의 inputOption에 추가한다.
3
+ */
4
+
5
+ const path = require('path')
6
+ const glob = require('glob')
7
+
8
+ const { orderedModuleNames, appRootPath } = require('@things-factory/env')
9
+
10
+ const AppPackage = require(`${appRootPath}/package.json`)
11
+
12
+ class ThemeOverridePlugin {
13
+ constructor(options = {}) {
14
+ this.options = options
15
+ this.writtenFrom = {}
16
+ this.writtenTo = {}
17
+ }
18
+
19
+ apply(compiler) {
20
+ compiler.hooks.entryOption.tap({ name: 'ThemeOverridePlugin' }, (context, entry) => {
21
+ var appname = AppPackage.name
22
+
23
+ var { chunk = 'theme', themeFolder = path.join('client', 'themes') } = this.options
24
+
25
+ var reversedModuleNames = [...orderedModuleNames, appname].reverse()
26
+ var themeFiles = {}
27
+
28
+ /* 최상위 모듈부터 복사한다. 하위 모듈에서는 중복 여부에 따라 복사여부를 결정한다. */
29
+ reversedModuleNames.forEach(m => {
30
+ if (appname == m) {
31
+ var modulePath = appRootPath
32
+ } else {
33
+ var modulePath = path.dirname(require.resolve(`${m}/package.json`))
34
+ }
35
+
36
+ var sourcePath = path.join(modulePath, themeFolder)
37
+
38
+ var files = glob.sync(path.join(sourcePath, '*.?(sass|scss|css)'))
39
+
40
+ files.forEach(filepath => {
41
+ let filename = path.basename(filepath)
42
+
43
+ if (!themeFiles[filename]) {
44
+ themeFiles[filename] = filepath
45
+ }
46
+ })
47
+ })
48
+
49
+ entry[chunk] = {
50
+ import: Object.values(themeFiles)
51
+ }
52
+ })
53
+ }
54
+ }
55
+
56
+ module.exports = ThemeOverridePlugin
@@ -0,0 +1,268 @@
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const webpack = require('webpack')
4
+ const HTMLWebpackPlugin = require('html-webpack-plugin')
5
+ const CopyWebpackPlugin = require('copy-webpack-plugin')
6
+ const I18nBundlerPlugin = require('./webpack-plugins/i18n-bundler-plugin')
7
+ const FolderOverridePlugin = require('./webpack-plugins/folder-override-plugin')
8
+ const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
9
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
10
+ const ThemeOverridePlugin = require('./webpack-plugins/theme-override-plugin')
11
+ const EntryBuilder = require('./controller/entries-builder')
12
+
13
+ const glob = require('glob')
14
+ const debug = require('debug')('things-factory:builder:webpack.config.dev')
15
+
16
+ const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
17
+
18
+ const { appRootPath } = require('@things-factory/env')
19
+ const AppPackage = require(path.resolve(appRootPath, 'package.json'))
20
+
21
+ const OUTPUT_PATH = path.resolve(appRootPath, 'dist-app')
22
+
23
+ debug('Output Path: ', OUTPUT_PATH)
24
+
25
+ const module_resolve = require('resolve')
26
+
27
+ try {
28
+ let pathName = module_resolve.sync('@things-factory/shell', {
29
+ basedir: process.cwd()
30
+ })
31
+ var ShellModulePath = path.resolve(pathName, '../..')
32
+ var NodeModulePath = path.resolve(pathName, '../../../..')
33
+ var NodeModuleParentPath = path.resolve(NodeModulePath, '..')
34
+ } catch (e) {
35
+ throw new Error('@things-factory/shell module not found.', e)
36
+ }
37
+
38
+ try {
39
+ var BuilderModulePath = path.resolve(
40
+ module_resolve.sync('@things-factory/builder', {
41
+ basedir: process.cwd()
42
+ }),
43
+ '..'
44
+ )
45
+ } catch (e) {
46
+ throw new Error('@things-factory/builder module not found.', e)
47
+ }
48
+
49
+ debug('FactoryShell Module Path', ShellModulePath)
50
+ debug('External Module Path', NodeModulePath)
51
+ debug('External Module Parent Path', NodeModuleParentPath)
52
+ debug('Builder Module Path', BuilderModulePath)
53
+
54
+ const ShellPackage = require(path.resolve(ShellModulePath, 'package.json'))
55
+
56
+ /* check if application root has _index.html for override template */
57
+ try {
58
+ if (fs.existsSync(path.resolve(appRootPath, '_index.html'))) {
59
+ var TemplatePath = path.resolve(appRootPath, '_index.html')
60
+ } else {
61
+ var TemplatePath = path.resolve(ShellModulePath, '_index.html')
62
+ }
63
+ } catch (e) {
64
+ var TemplatePath = path.resolve(ShellModulePath, '_index.html')
65
+ }
66
+
67
+ let entries = Object.assign({}, EntryBuilder(), {
68
+ main: [
69
+ path.resolve(ShellModulePath, 'client', 'index.js'),
70
+ '@hatiolab/webpack-hot-client/client?path=/__webpack_hmr&timeout=20000&reload=true'
71
+ ],
72
+ 'headless-scene-components': [path.resolve(ShellModulePath, '.', 'client', 'scene', 'scene-components.js')],
73
+ 'scene-viewer': [path.resolve(ShellModulePath, '.', 'client', 'scene', 'scene-viewer.js')]
74
+ })
75
+
76
+ module.exports = {
77
+ mode: 'development',
78
+ entry: entries,
79
+ resolve: {
80
+ aliasFields: ['browser'],
81
+ alias: {
82
+ [AppPackage.name]:
83
+ AppPackage.name == '@hatiolab/things-scene' ? path.resolve(appRootPath, 'src', 'index.js') : appRootPath
84
+ },
85
+ extensions: ['.ts', '.js', '.jsx', '.tsx', '.json'],
86
+ modules: [NodeModulePath]
87
+ },
88
+ resolveLoader: {
89
+ modules: [path.resolve(BuilderModulePath, 'web-loaders'), NodeModulePath]
90
+ },
91
+ externals:
92
+ AppPackage.name == '@hatiolab/things-scene'
93
+ ? {}
94
+ : {
95
+ '@hatiolab/things-scene': 'scene'
96
+ },
97
+ output: {
98
+ path: OUTPUT_PATH,
99
+ filename: 'fmsim/[name].js',
100
+ chunkFilename: 'fmsim/[name].js',
101
+ publicPath: '/'
102
+ },
103
+ module: {
104
+ rules: [
105
+ {
106
+ test: /\.(ts|js)x?$/,
107
+ use: [
108
+ {
109
+ loader: 'babel-loader',
110
+ options: {
111
+ rootMode: 'upward',
112
+ cacheDirectory: true
113
+ }
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ test: /\.mjs$/,
119
+ type: 'javascript/auto'
120
+ },
121
+ {
122
+ test: /\.(gif|jpe?g|png|svg)$/,
123
+ type: 'asset/resource',
124
+ generator: {
125
+ filename: 'fmsim/[hash][ext][query]'
126
+ }
127
+ },
128
+ {
129
+ test: /\.(sa|sc|c)ss$/,
130
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
131
+ },
132
+ {
133
+ test: /\.less$/,
134
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
135
+ },
136
+ {
137
+ test: /\.bpmn$/,
138
+ use: 'raw-loader'
139
+ },
140
+ {
141
+ test: /module-importer.import$/,
142
+ use: {
143
+ loader: 'things-factory-module-loader',
144
+ options: {
145
+ module_path: NodeModulePath
146
+ }
147
+ }
148
+ },
149
+ {
150
+ test: /things-scene-components.import$/,
151
+ use: [
152
+ {
153
+ loader: 'babel-loader',
154
+ options: {
155
+ rootMode: 'upward',
156
+ cacheDirectory: true
157
+ }
158
+ },
159
+ {
160
+ loader: 'things-scene-webpack-loader',
161
+ options: {
162
+ module_path: NodeModulePath
163
+ }
164
+ }
165
+ ]
166
+ },
167
+ {
168
+ test: /things-scene-components-with-tools.import$/,
169
+ use: [
170
+ {
171
+ loader: 'babel-loader',
172
+ options: {
173
+ rootMode: 'upward',
174
+ cacheDirectory: true
175
+ }
176
+ },
177
+ {
178
+ loader: 'things-scene-config-webpack-loader',
179
+ options: {
180
+ module_path: NodeModulePath
181
+ }
182
+ }
183
+ ]
184
+ }
185
+ ]
186
+ },
187
+ plugins: [
188
+ new ThemeOverridePlugin({
189
+ chunk: 'theme',
190
+ themeFolder: path.join('client', 'themes')
191
+ }),
192
+ new HTMLWebpackPlugin({
193
+ template: TemplatePath,
194
+ /*
195
+ Allows to control how chunks should be sorted before they are included to the HTML.
196
+ Allowed values are 'none' | 'auto' | 'dependency' | 'manual' | {Function}
197
+ */
198
+ chunksSortMode: 'none',
199
+ chunks: ['main', 'theme']
200
+ }),
201
+ new MiniCssExtractPlugin({
202
+ filename: '[name].css',
203
+ chunkFilename: '[name].[hash].css',
204
+ ignoreOrder: false
205
+ }),
206
+ new CopyWebpackPlugin({
207
+ patterns: [
208
+ {
209
+ from: 'node_modules/@material-design-icons/font/*',
210
+ to: OUTPUT_PATH,
211
+ context: NodeModuleParentPath
212
+ },
213
+ {
214
+ from: 'node_modules/@fontsource/roboto/**/*',
215
+ to: OUTPUT_PATH,
216
+ context: NodeModuleParentPath
217
+ },
218
+ {
219
+ from: 'node_modules/@webcomponents/webcomponentsjs/*',
220
+ to: OUTPUT_PATH,
221
+ context: NodeModuleParentPath
222
+ },
223
+ {
224
+ from: 'node_modules/web-animations-js/web-animations-next.min.js*',
225
+ to: OUTPUT_PATH,
226
+ context: NodeModuleParentPath
227
+ },
228
+ {
229
+ from: 'node_modules/@hatiolab/things-scene/*.js*',
230
+ to: OUTPUT_PATH,
231
+ noErrorOnMissing: true,
232
+ context: NodeModuleParentPath
233
+ }
234
+ ]
235
+ }),
236
+ new FolderOverridePlugin({
237
+ target: 'views'
238
+ }),
239
+ new FolderOverridePlugin({
240
+ target: 'assets'
241
+ }),
242
+ new FolderOverridePlugin({
243
+ target: 'helps'
244
+ }),
245
+ new I18nBundlerPlugin({
246
+ output: 'translations'
247
+ }),
248
+ new WorkboxWebpackPlugin.InjectManifest({
249
+ swSrc: path.resolve(ShellModulePath, 'client/serviceworker/sw-src.js'),
250
+ swDest: 'service-worker.js',
251
+ maximumFileSizeToCacheInBytes: 50000000,
252
+ exclude: [/^helps\//, /headless/, /openapi/] // exclude help files, headless files
253
+ }),
254
+ new webpack.DefinePlugin({
255
+ 'process.env': {
256
+ 'NODE-ENV': JSON.stringify('development'),
257
+ 'SHELL-VERSION': JSON.stringify(ShellPackage.version),
258
+ 'SHELL-LICENSE': JSON.stringify(ShellPackage.license),
259
+ 'APP-VERSION': JSON.stringify(AppPackage.version),
260
+ 'APP-LICENSE': JSON.stringify(AppPackage.license),
261
+ 'APP-NAME': JSON.stringify(AppPackage.name),
262
+ 'APP-DESCRIPTION': JSON.stringify(AppPackage.description),
263
+ 'APP-TAGLINE': JSON.stringify(AppPackage.tagline)
264
+ }
265
+ })
266
+ ],
267
+ devtool: 'eval-cheap-module-source-map'
268
+ }
@@ -0,0 +1,265 @@
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const webpack = require('webpack')
4
+ const CopyWebpackPlugin = require('copy-webpack-plugin')
5
+ const HTMLWebpackPlugin = require('html-webpack-plugin')
6
+ const I18nBundlerPlugin = require('./webpack-plugins/i18n-bundler-plugin')
7
+ const FolderOverridePlugin = require('./webpack-plugins/folder-override-plugin')
8
+ const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
9
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
10
+ const ThemeOverridePlugin = require('./webpack-plugins/theme-override-plugin')
11
+ const EntryBuilder = require('./controller/entries-builder')
12
+
13
+ const glob = require('glob')
14
+ const debug = require('debug')('things-factory:builder:webpack.config')
15
+
16
+ const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
17
+
18
+ const { appRootPath } = require('@things-factory/env')
19
+ const AppPackage = require(path.resolve(appRootPath, 'package.json'))
20
+
21
+ const OUTPUT_PATH = path.resolve(appRootPath, 'dist-app')
22
+
23
+ debug('Output Path: ', OUTPUT_PATH)
24
+
25
+ const module_resolve = require('resolve')
26
+
27
+ try {
28
+ let pathName = module_resolve.sync('@things-factory/shell', {
29
+ basedir: process.cwd()
30
+ })
31
+ var ShellModulePath = path.resolve(pathName, '../..')
32
+ var NodeModulePath = path.resolve(pathName, '../../../..')
33
+ var NodeModuleParentPath = path.resolve(NodeModulePath, '..')
34
+ } catch (e) {
35
+ throw new Error('@things-factory/shell module not found.', e)
36
+ }
37
+
38
+ try {
39
+ var BuilderModulePath = path.resolve(
40
+ module_resolve.sync('@things-factory/builder', {
41
+ basedir: process.cwd()
42
+ }),
43
+ '..'
44
+ )
45
+ } catch (e) {
46
+ throw new Error('@things-factory/builder module not found.', e)
47
+ }
48
+
49
+ debug('FactoryShell Module Path', ShellModulePath)
50
+ debug('External Module Path', NodeModulePath)
51
+ debug('External Module Parent Path', NodeModuleParentPath)
52
+ debug('Builder Module Path', BuilderModulePath)
53
+
54
+ const ShellPackage = require(path.resolve(ShellModulePath, 'package.json'))
55
+
56
+ /* check if application root has _index.html for override template */
57
+ try {
58
+ if (fs.existsSync(path.resolve(appRootPath, '_index.html'))) {
59
+ var TemplatePath = path.resolve(appRootPath, '_index.html')
60
+ } else {
61
+ var TemplatePath = path.resolve(ShellModulePath, '_index.html')
62
+ }
63
+ } catch (e) {
64
+ var TemplatePath = path.resolve(ShellModulePath, '_index.html')
65
+ }
66
+
67
+ debug('Index.html TemplatePath', TemplatePath)
68
+
69
+ let entries = Object.assign({}, EntryBuilder(), {
70
+ main: path.resolve(ShellModulePath, 'client', 'index.js'),
71
+ 'headless-scene-components': [path.resolve(ShellModulePath, '.', 'client', 'scene', 'scene-components.js')],
72
+ 'scene-viewer': [path.resolve(ShellModulePath, '.', 'client', 'scene', 'scene-viewer.js')]
73
+ })
74
+
75
+ module.exports = {
76
+ mode: 'production',
77
+ entry: entries,
78
+ resolve: {
79
+ aliasFields: ['browser'],
80
+ alias: {
81
+ [AppPackage.name]:
82
+ AppPackage.name == '@hatiolab/things-scene' ? path.resolve(appRootPath, 'src', 'index.js') : appRootPath
83
+ },
84
+ extensions: ['.ts', '.js', '.jsx', '.tsx', '.json'],
85
+ modules: [NodeModulePath]
86
+ },
87
+ resolveLoader: {
88
+ modules: [path.resolve(BuilderModulePath, 'web-loaders'), NodeModulePath]
89
+ },
90
+ externals:
91
+ AppPackage.name == '@hatiolab/things-scene'
92
+ ? {}
93
+ : {
94
+ '@hatiolab/things-scene': 'scene'
95
+ },
96
+ output: {
97
+ path: OUTPUT_PATH,
98
+ filename: 'fmsim/[name].js',
99
+ chunkFilename: 'fmsim/[name].js',
100
+ publicPath: '/'
101
+ },
102
+ module: {
103
+ rules: [
104
+ {
105
+ test: /\.(ts|js)x?$/,
106
+ use: [
107
+ {
108
+ loader: 'babel-loader',
109
+ options: {
110
+ rootMode: 'upward',
111
+ cacheDirectory: true
112
+ }
113
+ }
114
+ ]
115
+ },
116
+ {
117
+ test: /\.mjs$/,
118
+ type: 'javascript/auto'
119
+ },
120
+ {
121
+ test: /\.(gif|jpe?g|png|svg)$/,
122
+ type: 'asset/resource',
123
+ generator: {
124
+ filename: 'fmsim/[hash][ext][query]'
125
+ }
126
+ },
127
+ {
128
+ test: /\.(sa|sc|c)ss$/,
129
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
130
+ },
131
+ {
132
+ test: /\.less$/,
133
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
134
+ },
135
+ {
136
+ test: /module-importer.import$/,
137
+ use: {
138
+ loader: 'things-factory-module-loader',
139
+ options: {
140
+ module_path: NodeModulePath
141
+ }
142
+ }
143
+ },
144
+ {
145
+ test: /things-scene-components.import$/,
146
+ use: [
147
+ {
148
+ loader: 'babel-loader',
149
+ options: {
150
+ rootMode: 'upward',
151
+ cacheDirectory: true
152
+ }
153
+ },
154
+ {
155
+ loader: 'things-scene-webpack-loader',
156
+ options: {
157
+ module_path: NodeModulePath
158
+ }
159
+ }
160
+ ]
161
+ },
162
+ {
163
+ test: /things-scene-components-with-tools.import$/,
164
+ use: [
165
+ {
166
+ loader: 'babel-loader',
167
+ options: {
168
+ rootMode: 'upward',
169
+ cacheDirectory: true
170
+ }
171
+ },
172
+ {
173
+ loader: 'things-scene-config-webpack-loader',
174
+ options: {
175
+ module_path: NodeModulePath
176
+ }
177
+ }
178
+ ]
179
+ }
180
+ ]
181
+ },
182
+ plugins: [
183
+ new ThemeOverridePlugin({
184
+ chunk: 'theme',
185
+ themeFolder: path.join('client', 'themes')
186
+ }),
187
+ new HTMLWebpackPlugin({
188
+ template: TemplatePath,
189
+ /*
190
+ Allows to control how chunks should be sorted before they are included to the HTML.
191
+ Allowed values are 'none' | 'auto' | 'dependency' | 'manual' | {Function}
192
+ */
193
+ chunksSortMode: 'none',
194
+ chunks: ['main', 'theme']
195
+ }),
196
+ new MiniCssExtractPlugin({
197
+ // Options similar to the same options in webpackOptions.output
198
+ // all options are optional
199
+ filename: 'fmsim/[name].css',
200
+ chunkFilename: 'fmsim/[name].[hash].css',
201
+ ignoreOrder: false // Enable to remove warnings about conflicting order
202
+ }),
203
+ new CopyWebpackPlugin({
204
+ patterns: [
205
+ {
206
+ from: 'node_modules/@material-design-icons/font/*',
207
+ to: OUTPUT_PATH + '/fmsim',
208
+ context: NodeModuleParentPath
209
+ },
210
+ {
211
+ from: 'node_modules/@fontsource/roboto/**/*',
212
+ to: OUTPUT_PATH + '/fmsim',
213
+ context: NodeModuleParentPath
214
+ },
215
+ {
216
+ from: 'node_modules/@webcomponents/webcomponentsjs/*',
217
+ to: OUTPUT_PATH + '/fmsim',
218
+ context: NodeModuleParentPath
219
+ },
220
+ {
221
+ from: 'node_modules/web-animations-js/web-animations-next.min.js*',
222
+ to: OUTPUT_PATH + '/fmsim',
223
+ context: NodeModuleParentPath
224
+ },
225
+ {
226
+ from: 'node_modules/@hatiolab/things-scene/*.js*',
227
+ to: OUTPUT_PATH + '/fmsim',
228
+ noErrorOnMissing: true,
229
+ context: NodeModuleParentPath
230
+ }
231
+ ]
232
+ }),
233
+ new FolderOverridePlugin({
234
+ target: 'views'
235
+ }),
236
+ new FolderOverridePlugin({
237
+ target: 'assets'
238
+ }),
239
+ new FolderOverridePlugin({
240
+ target: 'helps'
241
+ }),
242
+ new I18nBundlerPlugin({
243
+ output: 'translations'
244
+ }),
245
+ new WorkboxWebpackPlugin.InjectManifest({
246
+ swSrc: path.resolve(ShellModulePath, 'client/serviceworker/sw-src.js'),
247
+ swDest: 'service-worker.js',
248
+ maximumFileSizeToCacheInBytes: 50000000,
249
+ exclude: [/^helps\//, /headless/, /openapi/] // exclude help files, headless files
250
+ }),
251
+ new webpack.DefinePlugin({
252
+ 'process.env': {
253
+ 'NODE-ENV': JSON.stringify('production'),
254
+ 'SHELL-VERSION': JSON.stringify(ShellPackage.version),
255
+ 'SHELL-LICENSE': JSON.stringify(ShellPackage.license),
256
+ 'APP-VERSION': JSON.stringify(AppPackage.version),
257
+ 'APP-LICENSE': JSON.stringify(AppPackage.license),
258
+ 'APP-NAME': JSON.stringify(AppPackage.name),
259
+ 'APP-DESCRIPTION': JSON.stringify(AppPackage.description),
260
+ 'APP-TAGLINE': JSON.stringify(AppPackage.tagline)
261
+ }
262
+ }),
263
+ new NodePolyfillPlugin()
264
+ ]
265
+ }