feat: config reloading
This commit is contained in:
parent
c552a64ee5
commit
47aed47b5e
400
package-lock.json
generated
400
package-lock.json
generated
|
@ -2021,6 +2021,18 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dependents/detective-less": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@dependents/detective-less/-/detective-less-4.1.0.tgz",
|
||||
"integrity": "sha512-KrkT6qO5NxqNfy68sBl6CTSoJ4SNDIS5iQArkibhlbGU4LaDukZ3q2HIkh8aUKDio6o4itU4xDR7t82Y2eP1Bg==",
|
||||
"dependencies": {
|
||||
"gonzales-pe": "^4.3.0",
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
|
@ -4225,6 +4237,87 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "5.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
|
||||
"integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
|
||||
"integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.62.0",
|
||||
"@typescript-eslint/visitor-keys": "5.62.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.7",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
|
||||
"integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.62.0",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/structured-clone": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||
|
@ -5037,6 +5130,14 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-module-types": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-5.0.0.tgz",
|
||||
"integrity": "sha512-JvqziE0Wc0rXQfma0HZC/aY7URXHFuZV84fJRtP8u+lhp0JYCNd5wJzVXP45t0PH0Mej3ynlzvdyITYIu0G4LQ==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-types-flow": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
|
||||
|
@ -7135,6 +7236,105 @@
|
|||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/detective-amd": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-5.0.2.tgz",
|
||||
"integrity": "sha512-XFd/VEQ76HSpym80zxM68ieB77unNuoMwopU2TFT/ErUk5n4KvUTwW4beafAVUugrjV48l4BmmR0rh2MglBaiA==",
|
||||
"dependencies": {
|
||||
"ast-module-types": "^5.0.0",
|
||||
"escodegen": "^2.0.0",
|
||||
"get-amd-module-type": "^5.0.1",
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"detective-amd": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-cjs": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-5.0.1.tgz",
|
||||
"integrity": "sha512-6nTvAZtpomyz/2pmEmGX1sXNjaqgMplhQkskq2MLrar0ZAIkHMrDhLXkRiK2mvbu9wSWr0V5/IfiTrZqAQMrmQ==",
|
||||
"dependencies": {
|
||||
"ast-module-types": "^5.0.0",
|
||||
"node-source-walk": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-es6": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-4.0.1.tgz",
|
||||
"integrity": "sha512-k3Z5tB4LQ8UVHkuMrFOlvb3GgFWdJ9NqAa2YLUU/jTaWJIm+JJnEh4PsMc+6dfT223Y8ACKOaC0qcj7diIhBKw==",
|
||||
"dependencies": {
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-postcss": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-6.1.3.tgz",
|
||||
"integrity": "sha512-7BRVvE5pPEvk2ukUWNQ+H2XOq43xENWbH0LcdCE14mwgTBEAMoAx+Fc1rdp76SmyZ4Sp48HlV7VedUnP6GA1Tw==",
|
||||
"dependencies": {
|
||||
"is-url": "^1.2.4",
|
||||
"postcss": "^8.4.23",
|
||||
"postcss-values-parser": "^6.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-sass": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-5.0.3.tgz",
|
||||
"integrity": "sha512-YsYT2WuA8YIafp2RVF5CEfGhhyIVdPzlwQgxSjK+TUm3JoHP+Tcorbk3SfG0cNZ7D7+cYWa0ZBcvOaR0O8+LlA==",
|
||||
"dependencies": {
|
||||
"gonzales-pe": "^4.3.0",
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-scss": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-4.0.3.tgz",
|
||||
"integrity": "sha512-VYI6cHcD0fLokwqqPFFtDQhhSnlFWvU614J42eY6G0s8c+MBhi9QAWycLwIOGxlmD8I/XvGSOUV1kIDhJ70ZPg==",
|
||||
"dependencies": {
|
||||
"gonzales-pe": "^4.3.0",
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-stylus": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-4.0.0.tgz",
|
||||
"integrity": "sha512-TfPotjhszKLgFBzBhTOxNHDsutIxx9GTWjrL5Wh7Qx/ydxKhwUrlSFeLIn+ZaHPF+h0siVBkAQSuy6CADyTxgQ==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/detective-typescript": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-11.1.0.tgz",
|
||||
"integrity": "sha512-Mq8egjnW2NSCkzEb/Az15/JnBI/Ryyl6Po0Y+0mABTFvOS6DAyUGRZqz1nyhu4QJmWWe0zaGs/ITIBeWkvCkGw==",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "^5.59.5",
|
||||
"ast-module-types": "^5.0.0",
|
||||
"node-source-walk": "^6.0.1",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.14.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||
|
@ -7839,6 +8039,26 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/escodegen": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
|
||||
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
|
||||
"dependencies": {
|
||||
"esprima": "^4.0.1",
|
||||
"estraverse": "^5.2.0",
|
||||
"esutils": "^2.0.2"
|
||||
},
|
||||
"bin": {
|
||||
"escodegen": "bin/escodegen.js",
|
||||
"esgenerate": "bin/esgenerate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.56.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
|
||||
|
@ -8445,7 +8665,6 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
|
@ -9454,6 +9673,18 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-amd-module-type": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-5.0.1.tgz",
|
||||
"integrity": "sha512-jb65zDeHyDjFR1loOVk0HQGM5WNwoGB8aLWy3LKCieMKol0/ProHkhO2X1JxojuN10vbz1qNn09MJ7tNp7qMzw==",
|
||||
"dependencies": {
|
||||
"ast-module-types": "^5.0.0",
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
|
@ -9882,6 +10113,20 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/gonzales-pe": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz",
|
||||
"integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5"
|
||||
},
|
||||
"bin": {
|
||||
"gonzales": "bin/gonzales.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
|
@ -11518,6 +11763,22 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-url": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
|
||||
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
|
||||
},
|
||||
"node_modules/is-url-superb": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz",
|
||||
"integrity": "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-weakmap": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
|
||||
|
@ -11574,7 +11835,6 @@
|
|||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
|
||||
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
|
@ -11652,6 +11912,11 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/javascript-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg=="
|
||||
},
|
||||
"node_modules/jest-diff": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
|
||||
|
@ -13295,6 +13560,21 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/module-definition": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/module-definition/-/module-definition-5.0.1.tgz",
|
||||
"integrity": "sha512-kvw3B4G19IXk+BOXnYq/D/VeO9qfHaapMeuS7w7sNUqmGaA6hywdFHMi+VWeR9wUScXM7XjoryTffCZ5B0/8IA==",
|
||||
"dependencies": {
|
||||
"ast-module-types": "^5.0.0",
|
||||
"node-source-walk": "^6.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"module-definition": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
|
@ -13527,6 +13807,17 @@
|
|||
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-source-walk": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-6.0.2.tgz",
|
||||
"integrity": "sha512-jn9vOIK/nfqoFCcpK89/VCVaLg1IHE6UVfDOzvqmANaJ/rWCTEdH8RZ1V278nv2jr36BJdyQXIAavBLXpzdlag==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.21.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/nopt": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz",
|
||||
|
@ -15691,6 +15982,22 @@
|
|||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/postcss-values-parser": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz",
|
||||
"integrity": "sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==",
|
||||
"dependencies": {
|
||||
"color-name": "^1.1.4",
|
||||
"is-url-superb": "^4.0.0",
|
||||
"quote-unquote": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.2.9"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss/node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
|
@ -15735,6 +16042,39 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/precinct": {
|
||||
"version": "11.0.5",
|
||||
"resolved": "https://registry.npmjs.org/precinct/-/precinct-11.0.5.tgz",
|
||||
"integrity": "sha512-oHSWLC8cL/0znFhvln26D14KfCQFFn4KOLSw6hmLhd+LQ2SKt9Ljm89but76Pc7flM9Ty1TnXyrA2u16MfRV3w==",
|
||||
"dependencies": {
|
||||
"@dependents/detective-less": "^4.1.0",
|
||||
"commander": "^10.0.1",
|
||||
"detective-amd": "^5.0.2",
|
||||
"detective-cjs": "^5.0.1",
|
||||
"detective-es6": "^4.0.1",
|
||||
"detective-postcss": "^6.1.3",
|
||||
"detective-sass": "^5.0.3",
|
||||
"detective-scss": "^4.0.3",
|
||||
"detective-stylus": "^4.0.0",
|
||||
"detective-typescript": "^11.1.0",
|
||||
"module-definition": "^5.0.1",
|
||||
"node-source-walk": "^6.0.2"
|
||||
},
|
||||
"bin": {
|
||||
"precinct": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.14.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/precinct/node_modules/commander": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
|
@ -15971,6 +16311,11 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/quote-unquote": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/quote-unquote/-/quote-unquote-1.0.0.tgz",
|
||||
"integrity": "sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg=="
|
||||
},
|
||||
"node_modules/random-bytes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||
|
@ -19614,6 +19959,25 @@
|
|||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tsutils": {
|
||||
"version": "3.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
|
||||
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
|
||||
"dependencies": {
|
||||
"tslib": "^1.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
||||
}
|
||||
},
|
||||
"node_modules/tsutils/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/tuf-js": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz",
|
||||
|
@ -20643,8 +21007,6 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
|
||||
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^3.1.1"
|
||||
},
|
||||
|
@ -20992,6 +21354,27 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/yaml-loader": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.8.0.tgz",
|
||||
"integrity": "sha512-LjeKnTzVBKWiQBeE2L9ssl6WprqaUIxCSNs5tle8PaDydgu3wVFXTbMfsvF2MSErpy9TDVa092n4q6adYwJaWg==",
|
||||
"dependencies": {
|
||||
"javascript-stringify": "^2.0.1",
|
||||
"loader-utils": "^2.0.0",
|
||||
"yaml": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.13"
|
||||
}
|
||||
},
|
||||
"node_modules/yaml-loader/node_modules/yaml": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
|
||||
"integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
|
@ -21109,6 +21492,7 @@
|
|||
"babel-merge": "^3.0.0",
|
||||
"chai": "4.2.0",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"commander": "11.1.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"enhanced-resolve": "^5.9.2",
|
||||
|
@ -21126,12 +21510,14 @@
|
|||
"graceful-fs": "^4.2.11",
|
||||
"js-yaml": "4.1.0",
|
||||
"mocha": "^10.2.0",
|
||||
"precinct": "^11.0.5",
|
||||
"rimraf": "^5.0.5",
|
||||
"source-map-loader": "4.0.1",
|
||||
"source-map-support": "0.5.19",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
"yaml-loader": "^0.8.0"
|
||||
},
|
||||
"bin": {
|
||||
"flecks": "build/cli.js"
|
||||
|
@ -21166,7 +21552,8 @@
|
|||
"lodash.get": "^4.4.2",
|
||||
"set-value": "^4.1.0",
|
||||
"source-map-support": "0.5.19",
|
||||
"supports-color": "9.2.1"
|
||||
"supports-color": "9.2.1",
|
||||
"which": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
|
@ -21388,7 +21775,6 @@
|
|||
"dependencies": {
|
||||
"@flecks/core": "^3.2.1",
|
||||
"babel-merge": "^3.0.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"debug": "^4.3.3",
|
||||
"mocha": "^10.2.0"
|
||||
},
|
||||
|
|
|
@ -197,7 +197,15 @@ module.exports = class Build extends Flecks {
|
|||
return this.resolver.resolve(join(fleck, 'build', config));
|
||||
}
|
||||
|
||||
async runtimeCompiler(runtime, config) {
|
||||
async runtimeCompiler(runtime, config, env, argv) {
|
||||
if ('production' !== argv.mode) {
|
||||
config.module.rules.push(
|
||||
{
|
||||
test: /\.ya?ml$/,
|
||||
use: 'yaml-loader',
|
||||
},
|
||||
);
|
||||
}
|
||||
// Compile?
|
||||
const compiled = this.roots.filter(([path, request]) => path !== request);
|
||||
if (compiled.length > 0) {
|
||||
|
|
|
@ -4,7 +4,11 @@ const {
|
|||
readFile,
|
||||
writeFile,
|
||||
} = require('fs/promises');
|
||||
const {join} = require('path');
|
||||
const {
|
||||
dirname,
|
||||
join,
|
||||
resolve,
|
||||
} = require('path');
|
||||
|
||||
const {parseAsync} = require('@babel/core');
|
||||
const {default: generate} = require('@babel/generator');
|
||||
|
@ -22,7 +26,10 @@ const {
|
|||
lockFile,
|
||||
spawnWith,
|
||||
} = require('@flecks/core/src/server');
|
||||
const chokidar = require('chokidar');
|
||||
const {glob} = require('glob');
|
||||
const {load: loadYml} = require('js-yaml');
|
||||
const {paperwork} = require('precinct');
|
||||
const {rimraf} = require('rimraf');
|
||||
|
||||
const addPathsToYml = require('./add-paths-to-yml');
|
||||
|
@ -57,6 +64,39 @@ function stringLiteralSinglequote(value) {
|
|||
};
|
||||
}
|
||||
|
||||
const dependencies = {};
|
||||
|
||||
async function gatherDependencies(request, resolver) {
|
||||
const resolved = await resolver.resolve(request);
|
||||
if (!resolved || dependencies[resolved]) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const localDeps = paperwork(resolved);
|
||||
dependencies[resolved] = true;
|
||||
await Promise.all(
|
||||
localDeps.map(
|
||||
async (dependency) => {
|
||||
const resolvedDependency = await resolver.resolve(
|
||||
resolve(dirname(resolved), dependency),
|
||||
);
|
||||
return resolvedDependency && gatherDependencies(resolvedDependency, resolver);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
catch (error) {}
|
||||
}
|
||||
|
||||
async function rootsDependencies(roots, resolver) {
|
||||
return Promise.all(
|
||||
roots.map(([request]) => (
|
||||
gatherDependencies(join(request, 'build', 'flecks.bootstrap.js'), resolver)
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
exports.commands = (program, flecks) => {
|
||||
const commands = {
|
||||
add: {
|
||||
|
@ -176,7 +216,12 @@ exports.commands = (program, flecks) => {
|
|||
production,
|
||||
watch,
|
||||
} = opts;
|
||||
debug('Building...', opts);
|
||||
if (watch) {
|
||||
debug('Watching...', opts);
|
||||
}
|
||||
else {
|
||||
debug('Building...', opts);
|
||||
}
|
||||
const webpackConfig = await flecks.resolveBuildConfig('fleckspack.config.js');
|
||||
const cmd = [
|
||||
await binaryPath('webpack'),
|
||||
|
@ -184,16 +229,70 @@ exports.commands = (program, flecks) => {
|
|||
'--config', webpackConfig,
|
||||
'--mode', (production && !hot) ? 'production' : 'development',
|
||||
];
|
||||
return spawnWith(
|
||||
cmd,
|
||||
{
|
||||
env: {
|
||||
FLECKS_CORE_IS_PRODUCTION: production,
|
||||
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
|
||||
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
|
||||
let webpack;
|
||||
const spawnWebpack = () => {
|
||||
webpack = spawnWith(
|
||||
cmd,
|
||||
{
|
||||
env: {
|
||||
FLECKS_BUILD_IS_PRODUCTION: production,
|
||||
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
|
||||
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
|
||||
},
|
||||
useFork: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
);
|
||||
webpack.on('message', (message) => {
|
||||
if ('restart' === message) {
|
||||
webpack.kill();
|
||||
spawnWebpack();
|
||||
}
|
||||
});
|
||||
};
|
||||
spawnWebpack();
|
||||
if (watch) {
|
||||
await rootsDependencies(flecks.roots, flecks.resolver);
|
||||
const watched = Object.keys(dependencies);
|
||||
watched.push(
|
||||
...await Promise.all(
|
||||
flecks.roots.map(([, request]) => flecks.resolver.resolve(join(request, 'package.json'))),
|
||||
),
|
||||
);
|
||||
watched.push(join(FLECKS_CORE_ROOT, 'build/flecks.yml'));
|
||||
const watcher = chokidar.watch(watched, {
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: 50,
|
||||
pollInterval: 5,
|
||||
},
|
||||
});
|
||||
await new Promise((resolve, reject) => {
|
||||
watcher.on('error', reject);
|
||||
watcher.on('ready', resolve);
|
||||
});
|
||||
const configPath = join(FLECKS_CORE_ROOT, 'build', 'flecks.yml');
|
||||
const initialConfig = loadYml(await readFile(configPath));
|
||||
watcher.on('all', async (event, path) => {
|
||||
let respawn = false;
|
||||
if (configPath === path) {
|
||||
const config = loadYml(await readFile(configPath));
|
||||
if (
|
||||
JSON.stringify(Object.keys(initialConfig).sort())
|
||||
!== JSON.stringify(Object.keys(config).sort())
|
||||
) {
|
||||
debug('Config keys changed');
|
||||
respawn = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
respawn = true;
|
||||
}
|
||||
if (respawn) {
|
||||
debug('Respawning...');
|
||||
webpack.kill();
|
||||
spawnWebpack();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"babel-merge": "^3.0.0",
|
||||
"chai": "4.2.0",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"commander": "11.1.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"enhanced-resolve": "^5.9.2",
|
||||
|
@ -51,11 +52,13 @@
|
|||
"graceful-fs": "^4.2.11",
|
||||
"js-yaml": "4.1.0",
|
||||
"mocha": "^10.2.0",
|
||||
"precinct": "^11.0.5",
|
||||
"rimraf": "^5.0.5",
|
||||
"source-map-loader": "4.0.1",
|
||||
"source-map-support": "0.5.19",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
"yaml-loader": "^0.8.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,21 @@ export const hooks = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked when `flecks.yml` is hot reloaded. Throw to abort hot reload and restart application.
|
||||
* Must be synchronous.
|
||||
*
|
||||
* @param {string} fleck The fleck whose config changed.
|
||||
* @param {Object} config The new config.
|
||||
*/
|
||||
'@flecks/core.reload': (fleck, config, flecks) => {
|
||||
if ('i-care-about' === fleck) {
|
||||
if (flecks.get(`${fleck}.volatile`) !== config.volatile) {
|
||||
throw new Error('Changes too volatile');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the application is starting.
|
||||
* @invoke SequentialAsync
|
||||
|
|
|
@ -74,13 +74,13 @@ class Flecks {
|
|||
* @param {object} runtime.flecks fleck modules.
|
||||
*/
|
||||
constructor({
|
||||
bootstrappedConfig = {},
|
||||
config = {},
|
||||
flecks = {},
|
||||
} = {}) {
|
||||
const emptyConfigForAllFlecks = Object.fromEntries(
|
||||
Object.keys(flecks).map((path) => [path, {}]),
|
||||
);
|
||||
this.config = {...emptyConfigForAllFlecks, ...config};
|
||||
this.bootstrappedConfig = JSON.parse(JSON.stringify(bootstrappedConfig));
|
||||
this.originalConfig = JSON.parse(JSON.stringify(config));
|
||||
this.config = {};
|
||||
const entries = Object.entries(flecks);
|
||||
this.constructor.debugSilly('paths: %O', entries.map(([fleck]) => fleck));
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
|
@ -100,8 +100,9 @@ class Flecks {
|
|||
*/
|
||||
configureFleckDefaults(fleck) {
|
||||
this.config[fleck] = {
|
||||
...this.bootstrappedConfig[fleck] || {},
|
||||
...this.invokeFleck('@flecks/core.config', fleck),
|
||||
...this.config[fleck],
|
||||
...this.originalConfig[fleck],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -111,7 +112,7 @@ class Flecks {
|
|||
* @protected
|
||||
*/
|
||||
configureFlecksDefaults() {
|
||||
const flecks = this.flecksImplementing('@flecks/core.config');
|
||||
const flecks = Object.keys(this.flecks);
|
||||
for (let i = 0; i < flecks.length; i++) {
|
||||
this.configureFleckDefaults(flecks[i]);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
"lodash.get": "^4.4.2",
|
||||
"set-value": "^4.1.0",
|
||||
"source-map-support": "0.5.19",
|
||||
"supports-color": "9.2.1"
|
||||
"supports-color": "9.2.1",
|
||||
"which": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
/* eslint-disable global-require */
|
||||
|
||||
const {join} = require('path');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
module.exports = {
|
||||
Class: require('../build/class'),
|
||||
compose: require('../build/compose'),
|
||||
|
@ -7,6 +13,27 @@ module.exports = {
|
|||
EventEmitter: require('../build/event-emitter'),
|
||||
...require('../build/flecks'),
|
||||
hooks: {
|
||||
'@flecks/core.hmr': (path, config, flecks) => {
|
||||
if (path !== join(FLECKS_CORE_ROOT, 'build', 'flecks.yml')) {
|
||||
return;
|
||||
}
|
||||
Object.entries(flecks.constructor.dealiasedConfig(config))
|
||||
.forEach(([fleck, value]) => {
|
||||
if (JSON.stringify(flecks.originalConfig[fleck]) !== JSON.stringify(value)) {
|
||||
const fleckList = flecks.flecksImplementing('@flecks/core.reload');
|
||||
for (let i = 0; i < fleckList.length; ++i) {
|
||||
try {
|
||||
flecks.invokeFleck('@flecks/core.reload', fleckList[i], fleck, value);
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`'${fleck}' aborted reload: ${error.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
flecks.originalConfig[fleck] = value;
|
||||
flecks.configureFleckDefaults(fleck);
|
||||
}
|
||||
});
|
||||
},
|
||||
'@flecks/web.config': async (req, flecks) => ({
|
||||
id: flecks.get('@flecks/core.id'),
|
||||
}),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const {exec, spawn} = require('child_process');
|
||||
const {exec, fork, spawn} = require('child_process');
|
||||
|
||||
const D = require('../../build/debug');
|
||||
|
||||
|
@ -28,14 +28,15 @@ exports.processCode = (child) => new Promise((resolve, reject) => {
|
|||
const children = [];
|
||||
|
||||
exports.spawnWith = (cmd, opts = {}) => {
|
||||
debug("spawning: '%s'", cmd.join(' '));
|
||||
debugSilly('with options: %O', opts);
|
||||
const child = spawn(cmd[0], cmd.slice(1), {
|
||||
const {useFork, ...rest} = opts;
|
||||
debug("%sing: '%s'", useFork ? 'fork' : 'spawn', cmd.join(' '));
|
||||
debugSilly('with options: %O', rest);
|
||||
const child = (useFork ? fork : spawn)(cmd[0], cmd.slice(1), {
|
||||
stdio: 'inherit',
|
||||
...opts,
|
||||
...rest,
|
||||
env: {
|
||||
...process.env,
|
||||
...opts.env,
|
||||
...rest.env,
|
||||
},
|
||||
});
|
||||
children.push(child);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
"dependencies": {
|
||||
"@flecks/core": "^3.2.1",
|
||||
"babel-merge": "^3.0.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"debug": "^4.3.3",
|
||||
"mocha": "^10.2.0"
|
||||
},
|
||||
|
|
|
@ -3,10 +3,10 @@ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'
|
|||
const plugins = [];
|
||||
|
||||
const {
|
||||
FLECKS_CORE_IS_PRODUCTION,
|
||||
FLECKS_BUILD_IS_PRODUCTION,
|
||||
} = process.env;
|
||||
|
||||
if ('true' !== FLECKS_CORE_IS_PRODUCTION) {
|
||||
if ('true' !== FLECKS_BUILD_IS_PRODUCTION) {
|
||||
plugins.push('react-refresh/babel');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
const {externals} = require('@flecks/build/src/server');
|
||||
|
||||
const D = require('@flecks/core/build/debug');
|
||||
|
||||
const debug = D('@flecks/server/build/runtime');
|
||||
const {join} = require('path');
|
||||
|
||||
const {version} = require('../package.json');
|
||||
|
||||
module.exports = async (config, env, argv, flecks) => {
|
||||
const runtimePath = await flecks.resolver.resolve('@flecks/server/runtime');
|
||||
async function runtimeModule(compilation, flecks) {
|
||||
const {compiler} = compilation;
|
||||
// Inject flecks configuration.
|
||||
const paths = Object.keys(flecks.flecks);
|
||||
const resolvedPaths = (await Promise.all(
|
||||
|
@ -15,8 +11,18 @@ module.exports = async (config, env, argv, flecks) => {
|
|||
))
|
||||
.filter(([, resolved]) => resolved)
|
||||
.map(([path]) => path);
|
||||
const ymlPath = join(flecks.root, 'build', 'flecks.yml');
|
||||
const runtime = {
|
||||
config: JSON.stringify(flecks.config),
|
||||
/* eslint-disable indent */
|
||||
bootstrappedConfig: JSON.stringify(flecks.invoke('@flecks/core.config')),
|
||||
config: (`
|
||||
dealiasedConfig(${
|
||||
'production' === compiler.options.mode
|
||||
? JSON.stringify(flecks.originalConfig)
|
||||
: `require('${ymlPath}').default`
|
||||
})
|
||||
`),
|
||||
/* eslint-enable indent */
|
||||
loadFlecks: [
|
||||
'async () => (',
|
||||
' Object.fromEntries(',
|
||||
|
@ -48,11 +54,23 @@ module.exports = async (config, env, argv, flecks) => {
|
|||
.map(([key, value]) => `"${key}": ${value}`).join(', ')
|
||||
}}`;
|
||||
const source = [
|
||||
`const {dealiasedConfig} = {${flecks.constructor.dealiasedConfig.toString()}};`,
|
||||
"process.env.FLECKS_CORE_BUILD_TARGET = 'server';",
|
||||
`module.exports = (async () => (${runtimeString}))();`,
|
||||
];
|
||||
// HMR.
|
||||
source.push('if (module.hot) {');
|
||||
source.push(` module.hot.accept('${ymlPath}', async () => {`);
|
||||
source.push(` const M = require('${ymlPath}').default;`);
|
||||
source.push(' try {');
|
||||
source.push(` global.flecks.invokeSequential('@flecks/core.hmr', '${ymlPath}', M);`);
|
||||
source.push(' }');
|
||||
source.push(' catch (error) {');
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
source.push(' console.error(`flecks.reload() failed: ${error.message}`);');
|
||||
source.push(' module.hot.invalidate();');
|
||||
source.push(' }');
|
||||
source.push(' });');
|
||||
// Keep HMR junk out of our output path.
|
||||
source.push(' const {glob} = require("glob");');
|
||||
source.push(' const {join} = require("path");');
|
||||
|
@ -61,7 +79,7 @@ module.exports = async (config, env, argv, flecks) => {
|
|||
source.push(' module.hot.addStatusHandler(async (status) => {');
|
||||
source.push(' if ("idle" === status) {');
|
||||
source.push(' const disposing = await glob(');
|
||||
source.push(` join('${config.output.path}', \`*\${previousHash}.hot-update.*\`),`);
|
||||
source.push(` join('${compiler.options.output.path}', \`*\${previousHash}.hot-update.*\`),`);
|
||||
source.push(' );');
|
||||
source.push(' await Promise.all(disposing.map((filename) => unlink(filename)));');
|
||||
source.push(' previousHash = __webpack_hash__;');
|
||||
|
@ -83,43 +101,8 @@ module.exports = async (config, env, argv, flecks) => {
|
|||
source.push(' });');
|
||||
});
|
||||
source.push('}');
|
||||
// Create runtime.
|
||||
config.module.rules.push(
|
||||
{
|
||||
test: runtimePath,
|
||||
use: [
|
||||
{
|
||||
loader: runtimePath,
|
||||
options: {
|
||||
source: source.join('\n'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
const allowlist = [
|
||||
'@flecks/server/entry',
|
||||
'@flecks/server/runtime',
|
||||
/^@babel\/runtime\/helpers\/esm/,
|
||||
];
|
||||
config.resolve.alias['@flecks/server/runtime$'] = runtimePath;
|
||||
Object.entries(flecks.resolver.aliases).forEach(([path, request]) => {
|
||||
debug('server runtime de-externalized %s, alias: %s', path, request);
|
||||
allowlist.push(new RegExp(`^${path}`));
|
||||
});
|
||||
// Stubs.
|
||||
flecks.stubs.forEach((stub) => {
|
||||
config.resolve.alias[stub] = false;
|
||||
});
|
||||
await flecks.runtimeCompiler('server', config, env, argv);
|
||||
// Rewrite to signals for HMR.
|
||||
if ('production' !== argv.mode) {
|
||||
allowlist.push(/^webpack\/hot\/signal/);
|
||||
}
|
||||
// Externalize the rest.
|
||||
config.externals = await externals({
|
||||
additionalModuleDirs: flecks.resolver.modules,
|
||||
allowlist,
|
||||
importType: 'commonjs',
|
||||
});
|
||||
};
|
||||
// Create asset.
|
||||
return source.join('\n');
|
||||
}
|
||||
|
||||
exports.runtimeModule = runtimeModule;
|
||||
|
|
|
@ -3,10 +3,15 @@ const {delimiter, join} = require('path');
|
|||
const {
|
||||
banner,
|
||||
defaultConfig,
|
||||
externals,
|
||||
webpack,
|
||||
} = require('@flecks/build/src/server');
|
||||
|
||||
const runtime = require('./runtime');
|
||||
const D = require('@flecks/core/build/debug');
|
||||
|
||||
const debug = D('@flecks/server/build');
|
||||
|
||||
const {runtimeModule} = require('./runtime');
|
||||
const startServer = require('./start');
|
||||
|
||||
const {
|
||||
|
@ -66,7 +71,53 @@ module.exports = async (env, argv, flecks) => {
|
|||
}),
|
||||
);
|
||||
}
|
||||
// Build the server runtime.
|
||||
await runtime(config, env, argv, flecks);
|
||||
// Create runtime.
|
||||
const runtimePath = await flecks.resolver.resolve('@flecks/server/runtime');
|
||||
config.module.rules.push(
|
||||
{
|
||||
test: runtimePath,
|
||||
use: [
|
||||
{
|
||||
loader: runtimePath,
|
||||
options: {
|
||||
source: await runtimeModule(
|
||||
{
|
||||
compiler: {
|
||||
options: {
|
||||
mode: argv.mode, output: {path: config.output.path},
|
||||
},
|
||||
},
|
||||
},
|
||||
flecks,
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
const allowlist = [
|
||||
'@flecks/server/entry',
|
||||
'@flecks/server/runtime',
|
||||
/^@babel\/runtime\/helpers\/esm/,
|
||||
];
|
||||
Object.entries(flecks.resolver.aliases).forEach(([path, request]) => {
|
||||
debug('server runtime de-externalized %s, alias: %s', path, request);
|
||||
allowlist.push(new RegExp(`^${path}`));
|
||||
});
|
||||
// Stubs.
|
||||
flecks.stubs.forEach((stub) => {
|
||||
config.resolve.alias[stub] = false;
|
||||
});
|
||||
await flecks.runtimeCompiler('server', config, env, argv);
|
||||
// Rewrite to signals for HMR.
|
||||
if ('production' !== argv.mode) {
|
||||
allowlist.push(/^webpack\/hot\/signal/);
|
||||
}
|
||||
// Externalize the rest.
|
||||
config.externals = await externals({
|
||||
additionalModuleDirs: flecks.resolver.modules,
|
||||
allowlist,
|
||||
importType: 'commonjs',
|
||||
});
|
||||
return config;
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ class StartServerPlugin {
|
|||
['exit', 'SIGINT', 'SIGTERM']
|
||||
.forEach((event) => {
|
||||
process.on(event, () => {
|
||||
this.worker.kill('exit' === event ? 'SIGKILL' : event);
|
||||
this.worker?.kill('exit' === event ? 'SIGKILL' : event);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class StartServerPlugin {
|
|||
if (this.worker.exitedAfterDisconnect) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[HMR] Restarting application...');
|
||||
this.worker = cluster.fork(env);
|
||||
process.send('restart');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import {join} from 'path';
|
|||
import {D, Flecks} from '@flecks/core';
|
||||
|
||||
(async () => {
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const runtime = await import('@flecks/server/runtime');
|
||||
const {loadFlecks, version} = runtime;
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -33,7 +32,7 @@ import {D, Flecks} from '@flecks/core';
|
|||
})();
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept('./runtime', () => {
|
||||
module.hot.accept('@flecks/server/runtime', () => {
|
||||
if (cluster.isWorker) {
|
||||
cluster.worker.disconnect();
|
||||
const error = new Error('Restart requested!');
|
||||
|
|
|
@ -3,10 +3,10 @@ import {join} from 'path';
|
|||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {createApplicationAt, build} from './build/build';
|
||||
import {createApplication, build} from './build/build';
|
||||
|
||||
it('builds for development', async () => {
|
||||
const path = await createApplicationAt('development');
|
||||
const path = await createApplication();
|
||||
await build(path, {args: ['-d']});
|
||||
let artifact;
|
||||
try {
|
||||
|
|
|
@ -3,10 +3,10 @@ import {join} from 'path';
|
|||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {createApplicationAt, build} from './build/build';
|
||||
import {createApplication, build} from './build/build';
|
||||
|
||||
it('builds for production', async () => {
|
||||
const path = await createApplicationAt('production');
|
||||
const path = await createApplication();
|
||||
await build(path);
|
||||
let artifact;
|
||||
try {
|
||||
|
|
|
@ -4,6 +4,7 @@ import {join} from 'path';
|
|||
import {rimraf} from '@flecks/build/server';
|
||||
import {binaryPath, processCode, spawnWith} from '@flecks/core/server';
|
||||
|
||||
import id from './id';
|
||||
import {listen} from './listen';
|
||||
|
||||
const {
|
||||
|
@ -13,12 +14,18 @@ const {
|
|||
export const applications = join(FLECKS_CORE_ROOT, 'node_modules', '.cache', '@flecks', 'server');
|
||||
export const template = join(FLECKS_CORE_ROOT, 'test', 'server', 'template');
|
||||
|
||||
export async function createApplicationAt(path) {
|
||||
await rimraf(join(applications, path));
|
||||
await mkdir(join(applications, path), {recursive: true});
|
||||
const qualified = join(applications, path, process.pid.toString());
|
||||
await cp(template, qualified, {recursive: true});
|
||||
return qualified;
|
||||
export async function createApplication() {
|
||||
const path = join(applications, await id());
|
||||
await rimraf(path);
|
||||
await mkdir(path, {recursive: true});
|
||||
await cp(template, path, {recursive: true});
|
||||
// sheeeeesh
|
||||
process.prependListener('message', async (message) => {
|
||||
if ('__workerpool-terminate__' === message) {
|
||||
rimraf.sync(path);
|
||||
}
|
||||
});
|
||||
return path;
|
||||
}
|
||||
|
||||
export async function buildChild(path, {args = [], opts = {}} = {}) {
|
||||
|
@ -27,7 +34,7 @@ export async function buildChild(path, {args = [], opts = {}} = {}) {
|
|||
{
|
||||
...opts,
|
||||
env: {
|
||||
FLECKS_ENV__flecks_server__stats: '{"all": false}',
|
||||
FLECKS_ENV__flecks_server__stats: '{"preset": "none"}',
|
||||
FLECKS_ENV__flecks_server__start: 0,
|
||||
FLECKS_CORE_ROOT: path,
|
||||
...opts.env,
|
||||
|
@ -41,7 +48,7 @@ export async function build(path, {args = [], opts = {}} = {}) {
|
|||
}
|
||||
|
||||
export async function serverActions(path, actions) {
|
||||
const {connected, listening, path: socketPath} = await listen();
|
||||
const {listening, path: socketPath, socketServer} = await listen();
|
||||
await listening;
|
||||
const server = spawnWith(
|
||||
['node', join(path, 'dist', 'server')],
|
||||
|
@ -53,7 +60,7 @@ export async function serverActions(path, actions) {
|
|||
);
|
||||
const [code, results] = await Promise.all([
|
||||
processCode(server),
|
||||
connected.then(async (socket) => {
|
||||
socketServer.waitForSocket().then(async (socket) => {
|
||||
const results = [];
|
||||
await actions.reduce(
|
||||
(p, action) => (
|
||||
|
|
|
@ -52,17 +52,26 @@ export async function listen() {
|
|||
await mkdir(dirname(path), {recursive: true});
|
||||
const server = createServer();
|
||||
server.listen(path);
|
||||
return {
|
||||
connected: new Promise((resolve, reject) => {
|
||||
server.waitForSocket = () => (
|
||||
new Promise((resolve, reject) => {
|
||||
server.on('error', reject);
|
||||
server.on('connection', (socket) => {
|
||||
resolve(new SocketWrapper(socket));
|
||||
});
|
||||
}),
|
||||
})
|
||||
);
|
||||
return {
|
||||
listening: new Promise((resolve, reject) => {
|
||||
server.on('error', reject);
|
||||
server.on('listening', resolve);
|
||||
}),
|
||||
path,
|
||||
socketServer: server,
|
||||
};
|
||||
}
|
||||
|
||||
export async function socketListener() {
|
||||
const {listening, path: socketPath, socketServer} = await listen();
|
||||
await listening;
|
||||
return {socketServer, socketPath};
|
||||
}
|
||||
|
|
65
packages/server/test/server/config-fail.js
Normal file
65
packages/server/test/server/config-fail.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
import {writeFile} from 'fs/promises';
|
||||
import {join} from 'path';
|
||||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {build, createApplication} from './build/build';
|
||||
import {socketListener} from './build/listen';
|
||||
|
||||
it('updates config', async () => {
|
||||
const path = await createApplication();
|
||||
const {socketPath, socketServer} = await socketListener();
|
||||
build(
|
||||
path,
|
||||
{
|
||||
args: ['-h'],
|
||||
opts: {
|
||||
env: {
|
||||
FLECKS_ENV__flecks_server__start: true,
|
||||
FLECKS_SERVER_TEST_SOCKET: socketPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
const socket = await socketServer.waitForSocket();
|
||||
expect((await socket.send({type: 'config.get', payload: 'comm.foo'})).payload)
|
||||
.to.equal('bar');
|
||||
await writeFile(
|
||||
join(path, 'build', 'flecks.yml'),
|
||||
`
|
||||
'@flecks/build': {}
|
||||
'@flecks/core': {}
|
||||
'@flecks/server': {}
|
||||
'comm:./comm': {foo: 'baz'}
|
||||
`,
|
||||
);
|
||||
await socket.waitForHmr();
|
||||
expect((await socket.send({type: 'config.get', payload: 'comm.foo'})).payload)
|
||||
.to.equal('baz');
|
||||
let restarted;
|
||||
const whatHappened = Promise.race([
|
||||
socket.waitForHmr()
|
||||
.then(() => {
|
||||
restarted = false;
|
||||
})
|
||||
.catch(() => {}),
|
||||
new Promise((resolve) => {
|
||||
socket.socket.on('close', () => {
|
||||
restarted = true;
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
]);
|
||||
await writeFile(
|
||||
join(path, 'build', 'flecks.yml'),
|
||||
`
|
||||
'@flecks/build': {}
|
||||
'@flecks/core': {}
|
||||
'@flecks/server': {}
|
||||
'comm:./comm': {foo: 'fail'}
|
||||
`,
|
||||
);
|
||||
await whatHappened;
|
||||
expect(restarted)
|
||||
.to.be.true;
|
||||
});
|
59
packages/server/test/server/config-restart.js
Normal file
59
packages/server/test/server/config-restart.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
import {writeFile} from 'fs/promises';
|
||||
import {join} from 'path';
|
||||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {buildChild, createApplication} from './build/build';
|
||||
import {socketListener} from './build/listen';
|
||||
|
||||
it('restarts when config keys change', async () => {
|
||||
const path = await createApplication();
|
||||
const {socketPath, socketServer} = await socketListener();
|
||||
await buildChild(
|
||||
path,
|
||||
{
|
||||
args: ['-w'],
|
||||
opts: {
|
||||
env: {
|
||||
FLECKS_ENV__flecks_server__start: true,
|
||||
FLECKS_SERVER_TEST_SOCKET: socketPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
const socket = await socketServer.waitForSocket();
|
||||
let restarted;
|
||||
const whatHappened = Promise.race([
|
||||
socket.waitForHmr()
|
||||
.then(() => {
|
||||
restarted = false;
|
||||
})
|
||||
.catch(() => {}),
|
||||
new Promise((resolve) => {
|
||||
socket.socket.on('close', () => {
|
||||
restarted = true;
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
]);
|
||||
await writeFile(
|
||||
join(path, 'build', 'flecks.yml'),
|
||||
`
|
||||
'@flecks/build': {}
|
||||
'@flecks/core': {}
|
||||
'@flecks/repl': {}
|
||||
'@flecks/server': {}
|
||||
'comm:./comm': {}
|
||||
`,
|
||||
);
|
||||
await whatHappened;
|
||||
expect(restarted)
|
||||
.to.be.true;
|
||||
let config;
|
||||
await socketServer.waitForSocket()
|
||||
.then(async (socket) => {
|
||||
({payload: config} = await socket.send({type: 'config.get', payload: '@flecks/repl/server'}));
|
||||
});
|
||||
expect(config)
|
||||
.to.not.be.undefined;
|
||||
});
|
40
packages/server/test/server/config-update.js
Normal file
40
packages/server/test/server/config-update.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import {writeFile} from 'fs/promises';
|
||||
import {join} from 'path';
|
||||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {build, createApplication} from './build/build';
|
||||
import {socketListener} from './build/listen';
|
||||
|
||||
it('updates config', async () => {
|
||||
const path = await createApplication();
|
||||
const {socketPath, socketServer} = await socketListener();
|
||||
build(
|
||||
path,
|
||||
{
|
||||
args: ['-h'],
|
||||
opts: {
|
||||
env: {
|
||||
FLECKS_ENV__flecks_server__start: true,
|
||||
FLECKS_SERVER_TEST_SOCKET: socketPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
const socket = await socketServer.waitForSocket();
|
||||
expect((await socket.send({type: 'config.get', payload: '@flecks/core.id'})).payload)
|
||||
.to.equal('flecks');
|
||||
await writeFile(
|
||||
join(path, 'build', 'flecks.yml'),
|
||||
`
|
||||
'@flecks/build': {}
|
||||
'@flecks/core': {id: 'testing'}
|
||||
'@flecks/server': {}
|
||||
'comm:./comm': {}
|
||||
`,
|
||||
);
|
||||
await socket.waitForHmr();
|
||||
expect((await socket.send({type: 'config.get', payload: '@flecks/core.id'})).payload)
|
||||
.to.equal('testing');
|
||||
await socket.send({type: 'exit'});
|
||||
});
|
|
@ -1,9 +1,9 @@
|
|||
import {expect} from 'chai';
|
||||
|
||||
import {build, createApplicationAt, serverActions} from './build/build';
|
||||
import {build, createApplication, serverActions} from './build/build';
|
||||
|
||||
it('propagates bootstrap config', async () => {
|
||||
const path = await createApplicationAt('runtime-config-bootstrap');
|
||||
const path = await createApplication();
|
||||
await build(path, {args: ['-d']});
|
||||
const {results: [{payload: id}]} = await serverActions(path, [
|
||||
{type: 'config.get', payload: '@flecks/core.id'},
|
||||
|
|
|
@ -3,10 +3,10 @@ import {join} from 'path';
|
|||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {build, createApplicationAt, serverActions} from './build/build';
|
||||
import {build, createApplication, serverActions} from './build/build';
|
||||
|
||||
it('propagates bootstrap config', async () => {
|
||||
const path = await createApplicationAt('runtime-config-override');
|
||||
const path = await createApplication();
|
||||
await writeFile(
|
||||
join(path, 'build', 'flecks.yml'),
|
||||
`
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {expect} from 'chai';
|
||||
|
||||
import {build, createApplicationAt, serverActions} from './build/build';
|
||||
import {build, createApplication, serverActions} from './build/build';
|
||||
|
||||
it('propagates runtime config', async () => {
|
||||
const path = await createApplicationAt('runtime-config-runtime');
|
||||
const path = await createApplication();
|
||||
await build(path, {args: ['-d']});
|
||||
const {results: [{payload: foo}]} = await serverActions(path, [
|
||||
{type: 'config.get', payload: 'comm.foo'},
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {expect} from 'chai';
|
||||
|
||||
import {build, createApplicationAt, serverActions} from './build/build';
|
||||
import {build, createApplication, serverActions} from './build/build';
|
||||
|
||||
it('connects', async () => {
|
||||
const path = await createApplicationAt('runtime-connect');
|
||||
const path = await createApplication();
|
||||
await build(path, {args: ['-d']});
|
||||
const {code} = await serverActions(path, [
|
||||
{type: 'exit', payload: 42},
|
||||
|
|
43
packages/server/test/server/source-restart.js
Normal file
43
packages/server/test/server/source-restart.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
import {writeFile} from 'fs/promises';
|
||||
import {join} from 'path';
|
||||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import {buildChild, createApplication} from './build/build';
|
||||
import {socketListener} from './build/listen';
|
||||
|
||||
it('restarts when root sources change', async () => {
|
||||
const path = await createApplication();
|
||||
const {socketPath, socketServer} = await socketListener();
|
||||
await buildChild(
|
||||
path,
|
||||
{
|
||||
args: ['-w'],
|
||||
opts: {
|
||||
env: {
|
||||
FLECKS_ENV__flecks_server__start: true,
|
||||
FLECKS_SERVER_TEST_SOCKET: socketPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
const socket = await socketServer.waitForSocket();
|
||||
let restarted;
|
||||
const whatHappened = Promise.race([
|
||||
socket.waitForHmr()
|
||||
.then(() => {
|
||||
restarted = false;
|
||||
})
|
||||
.catch(() => {}),
|
||||
new Promise((resolve) => {
|
||||
socket.socket.on('close', () => {
|
||||
restarted = true;
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
]);
|
||||
await writeFile(join(path, 'comm', 'package.json'), '{}');
|
||||
await whatHappened;
|
||||
expect(restarted)
|
||||
.to.be.true;
|
||||
});
|
|
@ -6,6 +6,11 @@ const {
|
|||
} = process.env;
|
||||
|
||||
export const hooks = {
|
||||
'@flecks/core.reload': (fleck, config) => {
|
||||
if ('comm' === fleck && 'fail' === config.foo) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
'@flecks/core.hmr': async (path, M, flecks) => {
|
||||
if (!flecks.socket) {
|
||||
return;
|
||||
|
|
|
@ -52,6 +52,7 @@ module.exports = async (config, env, argv, flecks) => {
|
|||
.map(([path]) => path);
|
||||
const source = [
|
||||
'module.exports = (update) => (async () => ({',
|
||||
` bootstrappedConfig: ${JSON.stringify(buildFlecks.invoke('@flecks/core.config'))},`,
|
||||
" config: window[Symbol.for('@flecks/web.config')],",
|
||||
' flecks: Object.fromEntries(await Promise.all([',
|
||||
...resolvedPaths
|
||||
|
|
Loading…
Reference in New Issue
Block a user