From 91242b238bd3c95764f4784c955a6fffbbe0901e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?chencheng=20=28=E4=BA=91=E8=B0=A6=29?= Date: Tue, 5 Nov 2024 15:05:50 +0800 Subject: [PATCH] feat: config (#9) --- .gitignore | 4 - README.md | 7 ++ examples/normal/.tnfrc.ts | 1 + package.json | 4 +- pnpm-lock.yaml | 197 ++++++++++++++++++++++++++++++++++---- src/build.ts | 25 +++-- src/cli.ts | 66 +++++++------ src/config.ts | 67 +++++++++++++ src/constants.ts | 3 +- src/dev.ts | 33 +++---- 10 files changed, 326 insertions(+), 81 deletions(-) create mode 100644 examples/normal/.tnfrc.ts create mode 100644 src/config.ts diff --git a/.gitignore b/.gitignore index 48c4b4f..33fe186 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,3 @@ /examples/*/src/.tnf /examples/*/dist /examples/*/node_modules -# Playwright -/test-results/ -/playwright-report/ -/playwright/.cache/ diff --git a/README.md b/README.md index 827bc30..fe3564f 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,13 @@ $ npx serve dist - `@umijs/tnf/router`: The router module, reexported from `@tanstack/react-router`. +## Config + +Config is loaded from `.tnfrc.ts` by default. + +- `externals: Record`: An object that maps package names to their corresponding paths. +- `devServer: { port?: number; host?: string; https?: { hosts?: string[] }; ip?: string }`: The development server configuration. + ## LICENSE [MIT](LICENSE) diff --git a/examples/normal/.tnfrc.ts b/examples/normal/.tnfrc.ts new file mode 100644 index 0000000..ff8b4c5 --- /dev/null +++ b/examples/normal/.tnfrc.ts @@ -0,0 +1 @@ +export default {}; diff --git a/package.json b/package.json index 076cd59..c04aea9 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/spdy": "^3.4.9", "@types/yargs-parser": "^21.0.3", "@umijs/mako": "^0.9.3", + "c12": "^2.0.1", "chokidar": "^4.0.1", "compression": "^1.7.5", "connect-history-api-fallback": "^2.0.0", @@ -51,7 +52,8 @@ "react": "19.0.0-rc-02c0e824-20241028", "react-dom": "19.0.0-rc-02c0e824-20241028", "spdy": "^4.0.2", - "yargs-parser": "^21.1.1" + "yargs-parser": "^21.1.1", + "zod": "^3.23.8" }, "devDependencies": { "@playwright/test": "^1.42.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb76d09..4ff302d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,6 +50,9 @@ importers: '@umijs/mako': specifier: ^0.9.3 version: 0.9.3 + c12: + specifier: ^2.0.1 + version: 2.0.1 chokidar: specifier: ^4.0.1 version: 4.0.1 @@ -92,6 +95,9 @@ importers: yargs-parser: specifier: ^21.1.1 version: 21.1.1 + zod: + specifier: ^3.23.8 + version: 3.23.8 devDependencies: '@playwright/test': specifier: ^1.42.1 @@ -2689,7 +2695,6 @@ packages: resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} engines: {node: '>=0.4.0'} hasBin: true - dev: true /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} @@ -3034,6 +3039,28 @@ packages: engines: {node: '>= 0.8'} dev: false + /c12@2.0.1: + resolution: {integrity: sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==} + peerDependencies: + magicast: ^0.3.5 + peerDependenciesMeta: + magicast: + optional: true + dependencies: + chokidar: 4.0.1 + confbox: 0.1.8 + defu: 6.1.4 + dotenv: 16.4.5 + giget: 1.2.3 + jiti: 2.4.0 + mlly: 1.7.2 + ohash: 1.1.4 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + pkg-types: 1.2.1 + rc9: 2.1.2 + dev: false + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -3132,6 +3159,11 @@ packages: readdirp: 4.0.2 dev: false + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + /chrome-trace-event@1.0.4: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} @@ -3148,6 +3180,12 @@ packages: inherits: 2.0.4 safe-buffer: 5.2.1 + /citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + dependencies: + consola: 3.2.3 + dev: false + /cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -3237,11 +3275,20 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + dev: false + /connect-history-api-fallback@2.0.0: resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} engines: {node: '>=0.8'} dev: false + /consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: false + /console-browserify@1.2.0: resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} @@ -3347,7 +3394,6 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true /crypto-browserify@3.12.1: resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} @@ -3558,6 +3604,10 @@ packages: object-keys: 1.1.1 dev: true + /defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + dev: false + /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -3569,6 +3619,10 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 + /destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + dev: false + /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -3621,6 +3675,11 @@ packages: domhandler: 4.3.1 dev: true + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false + /duplexify@4.1.3: resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} dependencies: @@ -4042,7 +4101,6 @@ packages: onetime: 6.0.0 signal-exit: 4.1.0 strip-final-newline: 3.0.0 - dev: true /express-http-proxy@2.1.1: resolution: {integrity: sha512-4aRQRqDQU7qNPV5av0/hLcyc0guB9UP71nCYrQEYml7YphTo8tmWf3nDZWdTJMMjFikyz9xKXaURor7Chygdwg==} @@ -4289,6 +4347,13 @@ packages: universalify: 0.1.2 dev: true + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + /fs-monkey@1.0.6: resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} dev: true @@ -4356,7 +4421,6 @@ packages: /get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - dev: true /get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} @@ -4372,6 +4436,20 @@ packages: dependencies: resolve-pkg-maps: 1.0.0 + /giget@1.2.3: + resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} + hasBin: true + dependencies: + citty: 0.1.6 + consola: 3.2.3 + defu: 6.1.4 + node-fetch-native: 1.6.4 + nypm: 0.3.12 + ohash: 1.1.4 + pathe: 1.1.2 + tar: 6.2.1 + dev: false + /git-repo-info@2.1.1: resolution: {integrity: sha512-8aCohiDo4jwjOwma4FmYFd3i97urZulL8XL24nIPxuE+GZnfsAyy/g2Shqx6OjUiFKUXZM+Yy+KHnOmmA3FVcg==} engines: {node: '>= 4.0'} @@ -4543,7 +4621,6 @@ packages: /human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - dev: true /husky@9.1.6: resolution: {integrity: sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==} @@ -4824,7 +4901,6 @@ packages: /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} @@ -4879,7 +4955,6 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} @@ -4916,6 +4991,11 @@ packages: supports-color: 8.1.1 dev: true + /jiti@2.4.0: + resolution: {integrity: sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==} + hasBin: true + dev: false + /jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} dev: true @@ -5251,7 +5331,6 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -5309,7 +5388,6 @@ packages: /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true /mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} @@ -5332,6 +5410,41 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: false + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: false + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /mlly@1.7.2: + resolution: {integrity: sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==} + dependencies: + acorn: 8.14.0 + pathe: 1.1.2 + pkg-types: 1.2.1 + ufo: 1.5.4 + dev: false + /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: false @@ -5374,6 +5487,10 @@ packages: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} dev: true + /node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + dev: false + /node-libs-browser-okam@2.2.5: resolution: {integrity: sha512-kD+WXACEThc6C5DA146KoCNbubjpXeYzXDrukvtXWr6MRzV3uvHCI0eb/GuugWVYnMoD4g3/uaIzvDYOpC4QWw==} dependencies: @@ -5449,7 +5566,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 - dev: true /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -5457,6 +5573,19 @@ packages: boolbase: 1.0.0 dev: true + /nypm@0.3.12: + resolution: {integrity: sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==} + engines: {node: ^14.16.0 || >=16.10.0} + hasBin: true + dependencies: + citty: 0.1.6 + consola: 3.2.3 + execa: 8.0.1 + pathe: 1.1.2 + pkg-types: 1.2.1 + ufo: 1.5.4 + dev: false + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5502,6 +5631,10 @@ packages: /obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + /ohash@1.1.4: + resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} + dev: false + /on-exit-leak-free@0.2.0: resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} dev: true @@ -5529,7 +5662,6 @@ packages: engines: {node: '>=12'} dependencies: mimic-fn: 4.0.0 - dev: true /onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} @@ -5640,12 +5772,10 @@ packages: /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: true /path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - dev: true /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -5681,6 +5811,10 @@ packages: safe-buffer: 5.2.1 sha.js: 2.4.11 + /perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + dev: false + /picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -5734,6 +5868,14 @@ packages: optionalDependencies: '@napi-rs/nice': 1.0.1 + /pkg-types@1.2.1: + resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} + dependencies: + confbox: 0.1.8 + mlly: 1.7.2 + pathe: 1.1.2 + dev: false + /pkg-up@3.1.0: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} @@ -6276,6 +6418,13 @@ packages: unpipe: 1.0.0 dev: false + /rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + dependencies: + defu: 6.1.4 + destr: 2.0.3 + dev: false + /react-dom@19.0.0-rc-02c0e824-20241028(react@19.0.0-rc-02c0e824-20241028): resolution: {integrity: sha512-LrZf3DfHL6Fs07wwlUCHrzFTCMM19yA99MvJpfLokN4I2nBAZvREGZjZAn8VPiSfN72+i9j1eL4wB8gC695F3Q==} peerDependencies: @@ -6633,12 +6782,10 @@ packages: engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - dev: true /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: true /side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} @@ -6656,7 +6803,6 @@ packages: /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - dev: true /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -6863,7 +7009,6 @@ packages: /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - dev: true /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} @@ -6933,6 +7078,18 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + /tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + /terser-webpack-plugin@5.3.10(webpack@5.95.0): resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} @@ -7131,6 +7288,10 @@ packages: hasBin: true dev: true + /ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + dev: false + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -7474,7 +7635,6 @@ packages: hasBin: true dependencies: isexe: 2.0.0 - dev: true /why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} @@ -7508,7 +7668,6 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true /yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} diff --git a/src/build.ts b/src/build.ts index 6a69f85..a1abf30 100644 --- a/src/build.ts +++ b/src/build.ts @@ -1,18 +1,23 @@ import type { BuildParams } from '@umijs/mako'; import chokidar from 'chokidar'; import path from 'pathe'; +import type { Config } from './config'; +import { FRAMEWORK_NAME } from './constants'; import { prepare } from './prepare'; export async function build({ cwd, config, + devMakoConfig, watch, }: { cwd: string; - config?: BuildParams['config']; + config?: Config; + devMakoConfig?: BuildParams['config']; watch?: boolean; }) { - const tmpPath = path.join(cwd, 'src/.tnf'); + config ||= {}; + const tmpPath = path.join(cwd, `src/.${FRAMEWORK_NAME}`); const doPrepare = async () => { await prepare({ @@ -36,21 +41,25 @@ export async function build({ } const mako = await import('@umijs/mako'); - config ||= {}; - config.entry = { + const bundleConfig: BuildParams['config'] = {}; + bundleConfig.entry = { client: path.join(tmpPath, 'client.tsx'), }; - config.resolve ||= {}; - config.resolve.alias = [ - ...(config.resolve.alias || []), + bundleConfig.resolve ||= {}; + bundleConfig.resolve.alias = [ + ...(bundleConfig.resolve.alias || []), ['@', path.join(cwd, 'src')], ['react', resolveLib('react')], ['react-dom', resolveLib('react-dom')], ['@tanstack/react-router', resolveLib('@tanstack/react-router')], ['@tanstack/router-devtools', resolveLib('@tanstack/router-devtools')], ]; + bundleConfig.externals = config.externals; await mako.build({ - config, + config: { + ...bundleConfig, + ...devMakoConfig, + }, root: cwd, watch: !!watch, }); diff --git a/src/cli.ts b/src/cli.ts index 566dda7..e90f9e6 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,43 +1,49 @@ +import assert from 'assert'; import yargsParser from 'yargs-parser'; -import { MIN_NODE_VERSION, NODE_TITLE } from './constants.js'; +import { loadConfig } from './config.js'; +import { FRAMEWORK_NAME, MIN_NODE_VERSION } from './constants.js'; import { checkVersion, setNoDeprecation, setNodeTitle, } from './fishkit/node.js'; +interface RunOptions { + cwd: string; + name?: string; + template?: string; +} + +async function run(cmd: string, options: RunOptions) { + switch (cmd) { + case 'create': + const { create } = await import('./create.js'); + return create(options); + case 'build': + const { build } = await import('./build.js'); + const config = await loadConfig({ cwd: options.cwd }); + return build({ cwd: options.cwd, config }); + case 'dev': + const { dev } = await import('./dev.js'); + return dev({ cwd: options.cwd, config }); + default: + throw new Error(`Unknown command: ${cmd}`); + } +} + setNoDeprecation(); checkVersion(MIN_NODE_VERSION); -setNodeTitle(NODE_TITLE); +setNodeTitle(FRAMEWORK_NAME); const argv = yargsParser(process.argv.slice(2)); const cmd = argv._[0]; -switch (cmd) { - case 'create': - import('./create.js').then(({ create }) => { - create({ - cwd: process.cwd(), - name: argv._[1] as string | undefined, - template: argv.template, - }).catch(console.error); - }); - break; - case 'build': - import('./build.js').then(({ build }) => { - build({ - cwd: process.cwd(), - }).catch(console.error); - }); - break; - case 'dev': - import('./dev.js').then(({ dev }) => { - dev({ - cwd: process.cwd(), - }).catch(console.error); - }); - break; - default: - console.error(`Unknown command: ${cmd}`); - process.exit(1); -} +assert(cmd, 'Command is required'); +run(cmd as string, { + cwd: process.cwd(), + name: argv._[1] as string | undefined, + template: argv.template as string | undefined, +}).catch((err) => { + console.error(err.message); + process.exit(1); +}); diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..0a9f062 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,67 @@ +import { + loadConfig as loadC12Config, + watchConfig as watchC12Config, +} from 'c12'; +import { z } from 'zod'; +import { CONFIG_FILE } from './constants'; + +const ConfigSchema = z.object({ + externals: z.record(z.string()).optional(), + devServer: z + .object({ + port: z.number().optional(), + https: z + .object({ + hosts: z.array(z.string()).optional(), + }) + .optional(), + ip: z.string().optional(), + host: z.string().optional(), + }) + .optional(), +}); + +export type Config = z.infer; + +interface ConfigOpts { + cwd: string; + defaults?: Partial; + overrides?: Partial; +} + +export async function loadConfig(opts: ConfigOpts): Promise { + const { config: rawConfig } = await loadC12Config(createLoadConfigOpts(opts)); + const result = ConfigSchema.safeParse(rawConfig); + if (!result.success) { + throw new Error(`Invalid configuration: ${result.error.message}`); + } + return result.data; +} + +export function watchConfig(opts: ConfigOpts) { + return watchC12Config({ + ...createLoadConfigOpts(opts), + onWatch(event) { + console.log(event); + }, + onUpdate({ oldConfig, newConfig, getDiff }) { + const result = ConfigSchema.safeParse(newConfig); + if (!result.success) { + console.error(`Invalid configuration: ${result.error.message}`); + return; + } + console.log('onUpdate', oldConfig, result.data, getDiff()); + }, + }); +} + +function createLoadConfigOpts({ cwd, defaults, overrides }: ConfigOpts) { + return { + cwd, + configFile: CONFIG_FILE, + rcFile: false as const, + globalRc: false as const, + defaults, + overrides, + }; +} diff --git a/src/constants.ts b/src/constants.ts index ed4ce9b..cbcb2c5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,3 +1,4 @@ export const MIN_NODE_VERSION = 18; -export const NODE_TITLE = 'tnf'; +export const FRAMEWORK_NAME = 'tnf'; +export const CONFIG_FILE = `.${FRAMEWORK_NAME}rc`; export const DEFAULT_PORT = 8000; diff --git a/src/dev.ts b/src/dev.ts index 264f8a3..2e5c53f 100644 --- a/src/dev.ts +++ b/src/dev.ts @@ -1,45 +1,42 @@ import type { BuildParams } from '@umijs/mako'; import { getPort } from 'get-port-please'; import { build } from './build'; +import type { Config } from './config'; import { DEFAULT_PORT } from './constants'; import { createServer } from './fishkit/server'; export interface DevOpts { cwd: string; - port?: number; - https?: { - hosts?: string[]; - }; - ip?: string; - host?: string; + config?: Config; } export async function dev(opts: DevOpts) { - const port = opts.port || DEFAULT_PORT; - const _port = await getPort(port); - const hmrPort = await getPort(_port + 1); - const host = opts.host || 'localhost'; + const devServer = opts.config?.devServer || {}; + const port = await getPort(devServer.port || DEFAULT_PORT); + const hmrPort = await getPort(port + 1); + const host = devServer.host || 'localhost'; await createServer({ - port: _port, + port, hmrPort, host, - https: opts.https, - ip: opts.ip, + https: devServer.https, + ip: devServer.ip, }); // build mako config - let config: BuildParams['config'] = {}; + let devMakoConfig: BuildParams['config'] = {}; if (process.env.HMR === 'none') { - config.hmr = false; + devMakoConfig.hmr = false; } else { - config.hmr = {}; + devMakoConfig.hmr = {}; } - config.devServer = { port: hmrPort, host }; + devMakoConfig.devServer = { port: hmrPort, host }; await build({ ...opts, - config, + config: opts.config, + devMakoConfig, watch: true, }); }