Compare commits
16 Commits
subtemplat
...
react-18-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4299bb6c1a | ||
|
|
0e46ff35f4 | ||
|
|
de26e44b1b | ||
|
|
1ed39d1dc3 | ||
|
|
254e923922 | ||
|
|
2b4412e28d | ||
|
|
1627db14da | ||
|
|
e2a0a36f26 | ||
|
|
06ae0dbe44 | ||
|
|
dd7fd57715 | ||
|
|
3ce42ae2ba | ||
|
|
c9727a2487 | ||
|
|
0d30fc7b0e | ||
|
|
117d76f8f5 | ||
|
|
bf47b609b9 | ||
|
|
decd93406f |
@@ -3590,69 +3590,6 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dineshgadge",
|
||||
"name": "Dinesh Gadge",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/186976?v=4",
|
||||
"profile": "https://github.com/dineshgadge",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "maltekiessling",
|
||||
"name": "Malte Kießling",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/30420110?v=4",
|
||||
"profile": "https://github.com/maltekiessling",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ospfranco",
|
||||
"name": "Oscar Franco",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1634213?v=4",
|
||||
"profile": "ospfranco.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Nfinished",
|
||||
"name": "Adam Trager",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1719791?v=4",
|
||||
"profile": "adamtrager.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "shellord",
|
||||
"name": "saheenshoukath",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2632896?v=4",
|
||||
"profile": "https://saheen.codes",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "husnuljahneer",
|
||||
"name": "Husnul Jahneer",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/54552763?v=4",
|
||||
"profile": "https://jahneer.me",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ReykCS",
|
||||
"name": "Reyk",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/40463716?v=4",
|
||||
"profile": "https://github.com/ReykCS",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
25
README.md
25
README.md
@@ -6,7 +6,7 @@
|
||||
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
|
||||
</a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-388-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-381-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
<a aria-label="License" href="https://github.com/blitz-js/blitz/blob/canary/LICENSE">
|
||||
<img alt="" src="https://img.shields.io/npm/l/blitz.svg?style=for-the-badge&labelColor=000000&color=blue">
|
||||
@@ -109,6 +109,12 @@ Your financial contributions help ensure Blitz continues to be developed and mai
|
||||
<tr>
|
||||
<td><a aria-label="Andreas Asprou" href="https://andreas.fyi">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/andreas.jpg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="Digas" href="https://digsas.com">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/digsas.svg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="userTrack" href="https://www.usertrack.net/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/usertrack.png" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="MeetKai" href="https://meetkai.com/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/meetkai.png" width="40px"/>
|
||||
@@ -228,14 +234,6 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://www.saheen.me/">
|
||||
<img src="https://avatars.githubusercontent.com/shellord" width="100px;" alt="Saheen Shoukath avatar" /><br />
|
||||
<sub>
|
||||
<b>Saheen Shoukath</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
@@ -742,15 +740,6 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://github.com/c-ciobanu"><img src="https://avatars.githubusercontent.com/u/33382714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cristi Ciobanu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=c-ciobanu" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://arpitdalal.dev"><img src="https://avatars.githubusercontent.com/u/61059807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arpit Dalal</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arpitdalal" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/robertrisch"><img src="https://avatars.githubusercontent.com/u/73828816?v=4?s=100" width="100px;" alt=""/><br /><sub><b>robertrisch</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robertrisch" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/dineshgadge"><img src="https://avatars.githubusercontent.com/u/186976?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dinesh Gadge</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dineshgadge" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/maltekiessling"><img src="https://avatars.githubusercontent.com/u/30420110?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Malte Kießling</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maltekiessling" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="ospfranco.com"><img src="https://avatars.githubusercontent.com/u/1634213?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Oscar Franco</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ospfranco" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="adamtrager.com"><img src="https://avatars.githubusercontent.com/u/1719791?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adam Trager</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Nfinished" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://saheen.codes"><img src="https://avatars.githubusercontent.com/u/2632896?v=4?s=100" width="100px;" alt=""/><br /><sub><b>saheenshoukath</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=shellord" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://jahneer.me"><img src="https://avatars.githubusercontent.com/u/54552763?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Husnul Jahneer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=husnuljahneer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ReykCS"><img src="https://avatars.githubusercontent.com/u/40463716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Reyk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ReykCS" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
24
assets/digsas.svg
Normal file
24
assets/digsas.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M79.4831 1.95572C70.2813 -0.81923 55.2811 -0.617415 46.1549 2.4098L18.6125 11.5167C9.48627 14.5313 9.38542 19.7784 18.3856 23.1588L49.9743 35.028C58.9744 38.4084 73.6217 38.194 82.5084 34.5487L110.883 22.9192C119.782 19.2739 119.53 14.0267 110.316 11.2518L79.4831 1.95572Z" fill="url(#paint0_linear)"/>
|
||||
<path d="M84.235 38.6101C75.3357 42.2554 68.0625 53.1029 68.0625 62.727V113.635C68.0625 123.259 74.9071 127.245 83.2644 122.489L109.282 107.706C117.639 102.951 124.912 91.208 125.442 81.6092L127.837 37.8281C128.366 28.2167 121.509 23.3479 112.609 26.9932L84.235 38.6101Z" fill="url(#paint1_linear)"/>
|
||||
<path d="M0.0071345 37.8409C-0.257575 28.2295 6.877 23.1211 15.8771 26.5015L47.4658 38.3707C56.466 41.7511 63.8274 52.3842 63.8274 62.0082V112.916C63.8274 122.54 56.882 126.715 48.386 122.212L17.0998 105.6C8.60392 101.085 1.44415 89.5306 1.16683 79.9192L0.0071345 37.8409Z" fill="url(#paint2_linear)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="63.9326" y1="0" x2="63.9326" y2="124.497" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#036EB8"/>
|
||||
<stop offset="1" stop-color="#469196"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="63.9326" y1="0" x2="63.9326" y2="124.497" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#036EB8"/>
|
||||
<stop offset="1" stop-color="#469196"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear" x1="63.9326" y1="0" x2="63.9326" y2="124.497" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#036EB8"/>
|
||||
<stop offset="1" stop-color="#469196"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0">
|
||||
<rect width="128" height="128" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/usertrack.png
Normal file
BIN
assets/usertrack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -16,6 +16,9 @@ module.exports = withBundleAnalyzer({
|
||||
cli: {
|
||||
clearConsoleOnBlitzDev: false,
|
||||
},
|
||||
codegen: {
|
||||
templateDir: "./my-templates",
|
||||
},
|
||||
log: {
|
||||
// level: "trace",
|
||||
},
|
||||
@@ -37,69 +40,4 @@ module.exports = withBundleAnalyzer({
|
||||
return config
|
||||
},
|
||||
*/
|
||||
codegen: {
|
||||
templateDir: "./my-templates",
|
||||
fieldTypeMap: {
|
||||
string: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
},
|
||||
boolean: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "boolean",
|
||||
prismaType: "Boolean",
|
||||
},
|
||||
int: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
},
|
||||
number: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
},
|
||||
bigint: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "BigInt",
|
||||
},
|
||||
float: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Float",
|
||||
},
|
||||
decimal: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Decimal",
|
||||
},
|
||||
datetime: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "string",
|
||||
zodType: "string",
|
||||
prismaType: "DateTime",
|
||||
},
|
||||
uuid: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "string().uuid",
|
||||
prismaType: "Uuid",
|
||||
},
|
||||
json: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "any",
|
||||
prismaType: "Json",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -30,26 +30,27 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"passport-auth0": "1.4.0",
|
||||
"passport-github2": "0.1.12",
|
||||
"passport-twitter": "1.0.4",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/skip-test": "2.6.0",
|
||||
"@next/bundle-analyzer": "^10.0.6",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react": "13.0.0-alpha.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/passport-auth0": "1.0.4",
|
||||
"@types/passport-github2": "1.2.4",
|
||||
"@types/passport-twitter": "1.0.36",
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -31,19 +31,20 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2",
|
||||
"secure-password": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/skip-test": "2.6.0",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react": "13.0.0-alpha.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -34,17 +34,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2",
|
||||
"zod": "3.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/cypress": "8.0.1",
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/testing-library__cypress": "5.0.9",
|
||||
"chance": "1.1.8",
|
||||
"cross-env": "7.0.3",
|
||||
|
||||
@@ -28,18 +28,19 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"graphql": "15.5.0",
|
||||
"graphql-request": "3.4.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react": "13.0.0-alpha.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"eslint": "7.21.0",
|
||||
"eslint-config-react-app": "~6.0.0",
|
||||
|
||||
@@ -26,17 +26,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"next-rosetta": "1.3.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2",
|
||||
"zod": "3.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"eslint": "7.21.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
|
||||
@@ -26,14 +26,15 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"knex": "0.21.16",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"sqlite3": "5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"eslint": "7.21.0",
|
||||
"eslint-config-react-app": "~6.0.0",
|
||||
"eslint-plugin-flowtype": "~5.2.0",
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71"
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -33,16 +33,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"eslint": "7.21.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
|
||||
@@ -21,15 +21,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.2",
|
||||
"blitz": "0.45.0-canary.0",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"cypress": "6.2.1",
|
||||
"start-server-and-test": "1.11.7"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"packages": ["packages/*"],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"@mdx-js/loader": "0.18.0",
|
||||
"@svgr/webpack": "5.5.0",
|
||||
"@swc/core": "1.2.74",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react": "13.0.0-alpha.5",
|
||||
"@types/b64-lite": "1.3.0",
|
||||
"@types/cheerio": "0.22.16",
|
||||
"@types/cookie-session": "2.0.42",
|
||||
@@ -126,10 +126,8 @@
|
||||
"prettier": "2.2.1",
|
||||
"pretty-bytes": "5.3.0",
|
||||
"pretty-ms": "7.0.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-18": "npm:react@next",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom-18": "npm:react-dom@next",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-ssr-prepass": "1.0.8",
|
||||
"release": "6.3.0",
|
||||
"request-promise-core": "1.1.2",
|
||||
@@ -158,5 +156,8 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"volta": {
|
||||
"extends": "../package.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eslint-config-blitz",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"description": "Blitz.js eslint config",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/installer",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"description": "Package installation for the Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"license": "MIT",
|
||||
@@ -30,10 +30,11 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.1",
|
||||
"@blitzjs/generator": "0.45.2",
|
||||
"@blitzjs/generator": "0.45.0-canary.0",
|
||||
"@mrleebo/prisma-ast": "0.2.6",
|
||||
"@prisma/sdk": "2.19.0",
|
||||
"@types/jscodeshift": "0.11.2",
|
||||
"@types/react": "17.0.37",
|
||||
"ast-types": "0.14.2",
|
||||
"cross-spawn": "7.0.3",
|
||||
"diff": "5.0.0",
|
||||
@@ -44,6 +45,7 @@
|
||||
"ink-spinner": "4.0.3",
|
||||
"ink-testing-library": "2.1.0",
|
||||
"jscodeshift": "0.13.0",
|
||||
"react": "18.0.0-rc.0",
|
||||
"recast": "0.20.5"
|
||||
},
|
||||
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
import { spawn } from 'cross-spawn'
|
||||
import { Box, Text } from 'ink'
|
||||
import Spinner from 'ink-spinner'
|
||||
import * as React from 'react'
|
||||
import { Newline } from '../components/newline'
|
||||
import { RecipeCLIArgs } from '../types'
|
||||
import { useEnterToContinue } from '../utils/use-enter-to-continue'
|
||||
import { useUserInput } from '../utils/use-user-input'
|
||||
import { Executor, ExecutorConfig, getExecutorArgument } from './executor'
|
||||
|
||||
export type CliCommand = string | [string, ...string[]]
|
||||
|
||||
export interface Config extends ExecutorConfig {
|
||||
command: CliCommand
|
||||
}
|
||||
export interface CommitChildProps {
|
||||
commandInstalled: boolean
|
||||
handleChangeCommitted: () => void
|
||||
command: CliCommand
|
||||
cliArgs: RecipeCLIArgs
|
||||
step: Config
|
||||
}
|
||||
|
||||
export const type = 'run-command'
|
||||
|
||||
function Command({
|
||||
command,
|
||||
loading,
|
||||
}: {
|
||||
command: CliCommand
|
||||
loading: boolean
|
||||
}) {
|
||||
return (
|
||||
<Text>
|
||||
{` `}
|
||||
{loading ? <Spinner /> : '✅'}
|
||||
{` ${typeof command === 'string' ? command : command.join(' ')}`}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
|
||||
const CommandList = ({
|
||||
lede = 'Hang tight! Running...',
|
||||
commandLoading = false,
|
||||
step,
|
||||
command,
|
||||
}: {
|
||||
lede?: string
|
||||
commandLoading?: boolean
|
||||
step: Config
|
||||
command: CliCommand
|
||||
}) => {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>{lede}</Text>
|
||||
<Newline />
|
||||
<Command key={step.stepId} command={command} loading={commandLoading} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INFO: Exported for unit testing purposes
|
||||
*
|
||||
* This function calls the defined command with their optional arguments if defined
|
||||
*
|
||||
* @param {CliCommand} input The Command and arguments
|
||||
* @return Promise<void>
|
||||
*
|
||||
* @example await executeCommand("ls")
|
||||
* @example await executeCommand(["ls"])
|
||||
* @example await executeCommand(["ls", ...["-a", "-l"]])
|
||||
*/
|
||||
export async function executeCommand(input: CliCommand): Promise<void> {
|
||||
// from https://stackoverflow.com/a/43766456/9950655
|
||||
const argsRegex = /("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|\/[^/\\]*(?:\\[\S\s][^/\\]*)*\/[gimy]*(?=\s|$)|(?:\\\s|\S)+)/g
|
||||
const command: string[] = Array.isArray(input)
|
||||
? input
|
||||
: input.match(argsRegex) || []
|
||||
|
||||
if (command.length === 0) {
|
||||
throw new Error(`The command is too short: \`${JSON.stringify(input)}\``)
|
||||
}
|
||||
|
||||
await new Promise((resolve) => {
|
||||
const cp = spawn(command[0], command.slice(1), {
|
||||
stdio: ['inherit', 'pipe', 'pipe'],
|
||||
})
|
||||
cp.on('exit', resolve)
|
||||
})
|
||||
}
|
||||
|
||||
export const Commit: Executor['Commit'] = ({
|
||||
cliArgs,
|
||||
cliFlags,
|
||||
step,
|
||||
onChangeCommitted,
|
||||
}) => {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const [commandInstalled, setCommandInstalled] = React.useState(false)
|
||||
const executorCommand = getExecutorArgument((step as Config).command, cliArgs)
|
||||
|
||||
const handleChangeCommitted = React.useCallback(() => {
|
||||
onChangeCommitted(`Executed command ${executorCommand}`)
|
||||
}, [executorCommand, onChangeCommitted])
|
||||
|
||||
React.useEffect(() => {
|
||||
async function runCommand() {
|
||||
await executeCommand(executorCommand)
|
||||
setCommandInstalled(true)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
runCommand()
|
||||
}, [cliArgs, step, executorCommand])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (commandInstalled) {
|
||||
handleChangeCommitted()
|
||||
}
|
||||
}, [commandInstalled, handleChangeCommitted])
|
||||
|
||||
const childProps: CommitChildProps = {
|
||||
commandInstalled,
|
||||
handleChangeCommitted,
|
||||
command: executorCommand,
|
||||
cliArgs,
|
||||
step: step as Config,
|
||||
}
|
||||
|
||||
if (userInput) return <CommitWithInput {...childProps} />
|
||||
else return <CommitWithoutInput {...childProps} />
|
||||
}
|
||||
|
||||
const CommitWithInput = ({
|
||||
commandInstalled,
|
||||
handleChangeCommitted,
|
||||
command,
|
||||
step,
|
||||
}: CommitChildProps) => {
|
||||
useEnterToContinue(handleChangeCommitted, commandInstalled)
|
||||
|
||||
return (
|
||||
<CommandList
|
||||
commandLoading={!commandInstalled}
|
||||
step={step}
|
||||
command={command}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const CommitWithoutInput = ({
|
||||
commandInstalled,
|
||||
command,
|
||||
step,
|
||||
}: CommitChildProps) => (
|
||||
<CommandList
|
||||
commandLoading={!commandInstalled}
|
||||
step={step}
|
||||
command={command}
|
||||
/>
|
||||
)
|
||||
@@ -2,7 +2,6 @@ import * as AddDependencyExecutor from './executors/add-dependency-executor'
|
||||
import * as TransformFileExecutor from './executors/file-transform-executor'
|
||||
import * as NewFileExecutor from './executors/new-file-executor'
|
||||
import * as PrintMessageExecutor from './executors/print-message-executor'
|
||||
import * as RunCommandExecutor from './executors/run-command-executor'
|
||||
import { ExecutorConfigUnion, RecipeExecutor } from './recipe-executor'
|
||||
import { RecipeMeta } from './types'
|
||||
|
||||
@@ -23,10 +22,6 @@ export interface IRecipeBuilder {
|
||||
addTransformFilesStep(
|
||||
step: Omit<TransformFileExecutor.Config, 'stepType'>
|
||||
): IRecipeBuilder
|
||||
addRunCommandStep(
|
||||
step: Omit<RunCommandExecutor.Config, 'stepType'>
|
||||
): IRecipeBuilder
|
||||
|
||||
build(): RecipeExecutor<any>
|
||||
}
|
||||
|
||||
@@ -83,13 +78,6 @@ export function RecipeBuilder(): IRecipeBuilder {
|
||||
})
|
||||
return this
|
||||
},
|
||||
addRunCommandStep(step: Omit<RunCommandExecutor.Config, 'stepType'>) {
|
||||
steps.push({
|
||||
stepType: RunCommandExecutor.type,
|
||||
...step,
|
||||
})
|
||||
return this
|
||||
},
|
||||
build() {
|
||||
return new RecipeExecutor(meta as RecipeMeta, steps)
|
||||
},
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Executor, ExecutorConfig, Frontmatter } from './executors/executor'
|
||||
import * as FileTransformExecutor from './executors/file-transform-executor'
|
||||
import * as NewFileExecutor from './executors/new-file-executor'
|
||||
import * as PrintMessageExecutor from './executors/print-message-executor'
|
||||
import * as RunCommandExecutor from './executors/run-command-executor'
|
||||
import { RecipeCLIArgs, RecipeCLIFlags, RecipeMeta } from './types'
|
||||
import { useEnterToContinue } from './utils/use-enter-to-continue'
|
||||
import { useUserInput } from './utils/use-user-input'
|
||||
@@ -33,7 +32,6 @@ const ExecutorMap: { [key: string]: Executor } = {
|
||||
[NewFileExecutor.type]: NewFileExecutor,
|
||||
[PrintMessageExecutor.type]: PrintMessageExecutor,
|
||||
[FileTransformExecutor.type]: FileTransformExecutor,
|
||||
[RunCommandExecutor.type]: RunCommandExecutor,
|
||||
} as const
|
||||
|
||||
interface State {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/env",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"keywords": [
|
||||
"react",
|
||||
"next",
|
||||
|
||||
@@ -50,7 +50,6 @@ const specialImports: Record<string, string> = {
|
||||
getAntiCSRFToken: 'next/data-client',
|
||||
useSession: 'next/data-client',
|
||||
useAuthenticatedSession: 'next/data-client',
|
||||
useRedirectAuthenticated: 'next/data-client',
|
||||
useAuthorize: 'next/data-client',
|
||||
useQuery: 'next/data-client',
|
||||
usePaginatedQuery: 'next/data-client',
|
||||
|
||||
@@ -3,7 +3,6 @@ import chalk from 'chalk'
|
||||
import crypto from 'crypto'
|
||||
import { readFileSync } from 'fs'
|
||||
import { codeFrameColumns } from 'next/dist/compiled/babel/code-frame'
|
||||
import semver from 'next/dist/compiled/semver'
|
||||
import { isWebpack5, webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import path, { join as pathJoin, relative as relativePath } from 'path'
|
||||
import {
|
||||
@@ -13,7 +12,6 @@ import {
|
||||
PAGES_DIR_ALIAS,
|
||||
} from '../lib/constants'
|
||||
import { fileExists } from '../lib/file-exists'
|
||||
import { getPackageVersion } from '../lib/get-package-version'
|
||||
import { CustomRoutes } from '../lib/load-custom-routes.js'
|
||||
import { getTypeScriptConfiguration } from '../lib/typescript/getTypeScriptConfiguration'
|
||||
import {
|
||||
@@ -246,22 +244,9 @@ export default async function getBaseWebpackConfig(
|
||||
rewrites.afterFiles.length > 0 ||
|
||||
rewrites.fallback.length > 0
|
||||
const hasReactRefresh: boolean = dev && !isServer
|
||||
const reactDomVersion = await getPackageVersion({
|
||||
cwd: dir,
|
||||
name: 'react-dom',
|
||||
})
|
||||
const hasReactExperimental: boolean =
|
||||
Boolean(reactDomVersion) && reactDomVersion!.includes('experimental') // blitz
|
||||
const hasReact18: boolean =
|
||||
(Boolean(reactDomVersion) &&
|
||||
(semver.gte(reactDomVersion!, '18.0.0') ||
|
||||
semver.coerce(reactDomVersion)?.version === '18.0.0')) ||
|
||||
hasReactExperimental // blitz
|
||||
const hasReactRoot: boolean = config.experimental.reactRoot ?? hasReact18
|
||||
// Have to set this suspense env for the actual build, because the webpack
|
||||
// string replace below only affects the build output, not anything during
|
||||
// the build like static page optimization
|
||||
process.env.__BLITZ_SUSPENSE_ENABLED = String(hasReactRoot)
|
||||
const defaultSuspense = config.reactQueryDefaultBehavior === 'suspense'
|
||||
|
||||
process.env.__BLITZ_DEFAULT_SUSPENSE = String(defaultSuspense)
|
||||
|
||||
const babelConfigFile = await [
|
||||
'.babelrc',
|
||||
@@ -1191,7 +1176,7 @@ export default async function getBaseWebpackConfig(
|
||||
'process.env.__NEXT_DIST_DIR': JSON.stringify(distDir),
|
||||
}
|
||||
: {}),
|
||||
'process.env.__BLITZ_SUSPENSE_ENABLED': JSON.stringify(hasReactRoot),
|
||||
'process.env.__BLITZ_DEFAULT_SUSPENSE': JSON.stringify(defaultSuspense),
|
||||
'process.env.__NEXT_TRAILING_SLASH': JSON.stringify(
|
||||
config.trailingSlash
|
||||
),
|
||||
@@ -1204,7 +1189,6 @@ export default async function getBaseWebpackConfig(
|
||||
'process.env.__NEXT_STRICT_MODE': JSON.stringify(
|
||||
config.reactStrictMode
|
||||
),
|
||||
'process.env.__NEXT_REACT_ROOT': JSON.stringify(hasReactRoot),
|
||||
'process.env.__NEXT_OPTIMIZE_FONTS': JSON.stringify(
|
||||
config.optimizeFonts && !dev
|
||||
),
|
||||
@@ -1447,7 +1431,6 @@ export default async function getBaseWebpackConfig(
|
||||
productionBrowserSourceMaps: !!config.productionBrowserSourceMaps,
|
||||
plugins: config.experimental.plugins,
|
||||
reactStrictMode: config.reactStrictMode,
|
||||
reactMode: config.experimental.reactMode,
|
||||
optimizeFonts: config.optimizeFonts,
|
||||
optimizeImages: config.experimental.optimizeImages,
|
||||
optimizeCss: config.experimental.optimizeCss,
|
||||
|
||||
@@ -549,7 +549,7 @@ export function renderError(renderErrorProps: RenderErrorProps): Promise<any> {
|
||||
})
|
||||
}
|
||||
|
||||
let reactRoot: any = null
|
||||
let reactRoot: ReactDOM.Root | null = null
|
||||
// On initial render a hydrate should always happen
|
||||
let shouldHydrate: boolean = true
|
||||
|
||||
@@ -563,29 +563,17 @@ function renderReactElement(
|
||||
}
|
||||
|
||||
const reactEl = fn(shouldHydrate ? markHydrateComplete : markRenderComplete)
|
||||
if (process.env.__NEXT_REACT_ROOT) {
|
||||
// start blitz
|
||||
if (!reactRoot) {
|
||||
const createRootName =
|
||||
typeof (ReactDOM as any).unstable_createRoot === 'function'
|
||||
? 'unstable_createRoot'
|
||||
: 'createRoot'
|
||||
reactRoot = (ReactDOM as any)[createRootName](domEl, {
|
||||
hydrate: shouldHydrate,
|
||||
})
|
||||
}
|
||||
reactRoot.render(reactEl)
|
||||
shouldHydrate = false
|
||||
// end blitz
|
||||
} else {
|
||||
// The check for `.hydrate` is there to support React alternatives like preact
|
||||
// start blitz
|
||||
if (!reactRoot) {
|
||||
if (shouldHydrate) {
|
||||
ReactDOM.hydrate(reactEl, domEl)
|
||||
shouldHydrate = false
|
||||
reactRoot = ReactDOM.hydrateRoot(domEl, reactEl)
|
||||
} else {
|
||||
ReactDOM.render(reactEl, domEl)
|
||||
reactRoot = ReactDOM.createRoot(domEl)
|
||||
}
|
||||
}
|
||||
reactRoot.render(reactEl)
|
||||
shouldHydrate = false
|
||||
// end blitz
|
||||
}
|
||||
|
||||
function markHydrateComplete(): void {
|
||||
|
||||
@@ -130,7 +130,7 @@ interface UseSessionOptions {
|
||||
|
||||
export const useSession = (options: UseSessionOptions = {}): ClientSession => {
|
||||
const suspense =
|
||||
options?.suspense ?? Boolean(process.env.__BLITZ_SUSPENSE_ENABLED)
|
||||
options?.suspense ?? Boolean(process.env.__BLITZ_DEFAULT_SUSPENSE)
|
||||
|
||||
let initialState: ClientSession
|
||||
if (options.initialPublicData) {
|
||||
|
||||
@@ -13,7 +13,7 @@ type MutateOptions = {
|
||||
export const initializeQueryClient = () => {
|
||||
let suspenseEnabled = true
|
||||
if (!process.env.CLI_COMMAND_CONSOLE && !process.env.CLI_COMMAND_DB) {
|
||||
suspenseEnabled = Boolean(process.env.__BLITZ_SUSPENSE_ENABLED)
|
||||
suspenseEnabled = Boolean(process.env.__BLITZ_DEFAULT_SUSPENSE)
|
||||
}
|
||||
|
||||
return new QueryClient({
|
||||
|
||||
@@ -77,7 +77,7 @@ export function useQuery<
|
||||
)
|
||||
}
|
||||
|
||||
const suspenseEnabled = Boolean(process.env.__BLITZ_SUSPENSE_ENABLED)
|
||||
const suspenseEnabled = Boolean(process.env.__BLITZ_DEFAULT_SUSPENSE)
|
||||
let enabled =
|
||||
isServer && suspenseEnabled
|
||||
? false
|
||||
@@ -167,7 +167,7 @@ export function usePaginatedQuery<
|
||||
)
|
||||
}
|
||||
|
||||
const suspenseEnabled = Boolean(process.env.__BLITZ_SUSPENSE_ENABLED)
|
||||
const suspenseEnabled = Boolean(process.env.__BLITZ_DEFAULT_SUSPENSE)
|
||||
let enabled =
|
||||
isServer && suspenseEnabled
|
||||
? false
|
||||
@@ -266,7 +266,7 @@ export function useInfiniteQuery<
|
||||
)
|
||||
}
|
||||
|
||||
const suspenseEnabled = Boolean(process.env.__BLITZ_SUSPENSE_ENABLED)
|
||||
const suspenseEnabled = Boolean(process.env.__BLITZ_DEFAULT_SUSPENSE)
|
||||
let enabled =
|
||||
isServer && suspenseEnabled
|
||||
? false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"nextjsVersion": "11.1.0",
|
||||
"description": "The React Framework",
|
||||
"main": "./dist/server/next.js",
|
||||
@@ -73,7 +73,7 @@
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"@babel/runtime": "7.12.5",
|
||||
"@blitzjs/env": "0.45.2",
|
||||
"@blitzjs/env": "0.45.0-canary.0",
|
||||
"@hapi/accept": "5.0.2",
|
||||
"@next/polyfill-module": "11.1.0",
|
||||
"@next/react-dev-overlay": "11.1.0",
|
||||
@@ -200,8 +200,8 @@
|
||||
"@types/lru-cache": "5.1.0",
|
||||
"@types/node-fetch": "2.5.8",
|
||||
"@types/path-to-regexp": "1.7.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react-dom": "16.9.4",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/react-is": "16.7.1",
|
||||
"@types/semver": "7.3.1",
|
||||
"@types/send": "0.14.4",
|
||||
|
||||
@@ -71,20 +71,6 @@ export interface ESLintConfig {
|
||||
ignoreDuringBuilds?: boolean
|
||||
}
|
||||
|
||||
export type CodegenField = {
|
||||
component: string
|
||||
inputType: string
|
||||
zodType: string
|
||||
prismaType: string
|
||||
default?: string
|
||||
[index: string]: string | undefined
|
||||
}
|
||||
|
||||
export type CodegenConfig = {
|
||||
templateDir?: string
|
||||
fieldTypeMap?: Record<string, CodegenField>
|
||||
}
|
||||
|
||||
export type NextConfig = { [key: string]: any } & {
|
||||
i18n?: I18NConfig | null
|
||||
|
||||
@@ -141,7 +127,9 @@ export type NextConfig = { [key: string]: any } & {
|
||||
httpsProxy?: string
|
||||
noProxy?: string
|
||||
}
|
||||
codegen?: CodegenConfig
|
||||
codegen?: {
|
||||
templateDir?: string
|
||||
}
|
||||
log?: {
|
||||
level?: LogLevel
|
||||
type?: LogType
|
||||
@@ -150,6 +138,7 @@ export type NextConfig = { [key: string]: any } & {
|
||||
customServer?: {
|
||||
hotReload?: boolean
|
||||
}
|
||||
reactQueryDefaultBehavior?: 'legacy' | 'suspense'
|
||||
// -- Blitz end
|
||||
|
||||
future?: {
|
||||
@@ -166,7 +155,6 @@ export type NextConfig = { [key: string]: any } & {
|
||||
plugins?: boolean
|
||||
profiling?: boolean
|
||||
isrFlushToDisk?: boolean
|
||||
reactMode?: 'legacy' | 'concurrent' | 'blocking'
|
||||
workerThreads?: boolean
|
||||
pageEnv?: boolean
|
||||
optimizeImages?: boolean
|
||||
@@ -181,7 +169,6 @@ export type NextConfig = { [key: string]: any } & {
|
||||
skipValidation?: boolean
|
||||
}
|
||||
initServer?: () => void // blitz
|
||||
reactRoot?: boolean
|
||||
disableOptimizedLoading?: boolean
|
||||
gzipSize?: boolean
|
||||
craCompat?: boolean
|
||||
@@ -237,6 +224,7 @@ export const defaultConfig: NextConfig = {
|
||||
serverRuntimeConfig: {},
|
||||
publicRuntimeConfig: {},
|
||||
reactStrictMode: false,
|
||||
reactQueryDefaultBehavior: 'suspense',
|
||||
httpAgentOptions: {
|
||||
keepAlive: true,
|
||||
},
|
||||
|
||||
@@ -51,16 +51,19 @@ function assignDefaults(userConfig: { [key: string]: any }) {
|
||||
if (typeof userConfig.experimental?.reactMode !== 'undefined') {
|
||||
console.warn(
|
||||
chalk.yellow.bold('Warning: ') +
|
||||
'The experimental "reactMode" option has been replaced with "reactRoot". Please update your blitz.config.js.'
|
||||
'The experimental "reactMode" has been removed as "concurrent mode" doesn\'t exist anymore. Please update your blitz.config.js.'
|
||||
)
|
||||
if (typeof userConfig.experimental?.reactRoot === 'undefined') {
|
||||
userConfig.experimental.reactRoot = ['concurrent', 'blocking'].includes(
|
||||
userConfig.experimental.reactMode
|
||||
)
|
||||
}
|
||||
delete userConfig.experimental.reactMode
|
||||
}
|
||||
|
||||
if (typeof userConfig.experimental?.reactRoot !== 'undefined') {
|
||||
console.warn(
|
||||
chalk.yellow.bold('Warning: ') +
|
||||
'The experimental "reactRoot" has been removed as "concurrent mode" doesn\'t exist anymore. Please update your blitz.config.js.'
|
||||
)
|
||||
delete userConfig.experimental.reactRoot
|
||||
}
|
||||
|
||||
const config = Object.keys(userConfig).reduce<{ [key: string]: any }>(
|
||||
(currentConfig, key) => {
|
||||
const value = userConfig[key]
|
||||
|
||||
@@ -139,6 +139,22 @@ export const secureProxyMiddleware: Middleware = function (
|
||||
_res: MiddlewareResponse,
|
||||
next: (error?: Error) => void
|
||||
) {
|
||||
req.protocol = 'https'
|
||||
req.protocol = getProtocol(req)
|
||||
next()
|
||||
}
|
||||
|
||||
function getProtocol(req: MiddlewareRequest) {
|
||||
// @ts-ignore
|
||||
// For some reason there is no encrypted on socket while it is expected
|
||||
if (req.connection.encrypted) {
|
||||
return 'https'
|
||||
}
|
||||
const forwardedProto =
|
||||
req.headers &&
|
||||
((req.headers['forwarded'] as string)?.match(/(?<=proto=).+/g)?.[0] ||
|
||||
(req.headers['x-forwarded-proto'] as string))
|
||||
if (forwardedProto) {
|
||||
return forwardedProto.split(/\s*,\s*/)[0]
|
||||
}
|
||||
return 'http'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import SuperJson from 'superjson'
|
||||
import type { UrlObject } from 'url'
|
||||
|
||||
const errorProps = ['name', 'message', 'code', 'statusCode', 'meta', 'url']
|
||||
const errorProps = ['name', 'message', 'code', 'statusCode', 'meta']
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.allowErrorProps(...errorProps)
|
||||
}
|
||||
|
||||
6
nextjs/packages/next/types/index.d.ts
vendored
6
nextjs/packages/next/types/index.d.ts
vendored
@@ -1,8 +1,10 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="react" />
|
||||
/// <reference types="react-dom" />
|
||||
/// <reference types="react/next" />
|
||||
/// <reference types="react-dom/next" />
|
||||
/// <reference types="styled-jsx" />
|
||||
|
||||
// TODO: Update `react/next` with `react` reference when React 18.0.0 releases
|
||||
|
||||
import React from 'react'
|
||||
import { ParsedUrlQuery } from 'querystring'
|
||||
import { IncomingMessage, ServerResponse } from 'http'
|
||||
|
||||
@@ -257,7 +257,7 @@ export default (context, renderViaHTTP) => {
|
||||
'Unknown'
|
||||
)
|
||||
).toMatch(
|
||||
'Objects are not valid as a React child (found: /search/). If you meant to render a collection of children, use an array instead.'
|
||||
'Objects are not valid as a React child (found: [object RegExp]). If you meant to render a collection of children, use an array instead.'
|
||||
)
|
||||
|
||||
aboutPage.restore()
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
experimental: {
|
||||
reactRoot: false,
|
||||
},
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
experimental: {
|
||||
reactRoot: false,
|
||||
},
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
experimental: {
|
||||
reactRoot: false,
|
||||
},
|
||||
}
|
||||
@@ -14,7 +14,7 @@ describe('Link rendering', () => {
|
||||
)
|
||||
const html = ReactDOM.renderToString(element)
|
||||
expect(html).toMatchInlineSnapshot(
|
||||
`"<a href=\\"/my-path\\" data-reactroot=\\"\\">to another page</a>"`
|
||||
`"<a href=\\"/my-path\\">to another page</a>"`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -59,11 +59,29 @@ describe('secure proxy middleware', () => {
|
||||
expect(reqSecure.protocol).toEqual('https')
|
||||
})
|
||||
|
||||
it('should set http protocol if X-Forwarded-Proto is http', () => {
|
||||
// @ts-ignore
|
||||
void secureProxyMiddleware(reqHttp, res, () => null)
|
||||
expect(reqHttp.protocol).toEqual('http')
|
||||
})
|
||||
|
||||
it('should set https protocol if Forwarded is proto=https', () => {
|
||||
// @ts-ignore
|
||||
void secureProxyMiddleware(reqForwardSecure, res, () => null)
|
||||
expect(reqForwardSecure.protocol).toEqual('https')
|
||||
})
|
||||
|
||||
it('should set http protocol if Forwarded is proto=http', () => {
|
||||
// @ts-ignore
|
||||
void secureProxyMiddleware(reqForwardHttp, res, () => null)
|
||||
expect(reqForwardHttp.protocol).toEqual('http')
|
||||
})
|
||||
|
||||
it('should set http protocol if X-Forwarded-Proto and Forwarded are absent', () => {
|
||||
// @ts-ignore
|
||||
void secureProxyMiddleware(reqNoHeader, res, () => null)
|
||||
expect(reqNoHeader.protocol).toEqual('http')
|
||||
})
|
||||
})
|
||||
|
||||
describe('handleRequestWithMiddleware', () => {
|
||||
|
||||
@@ -17,12 +17,12 @@ import {
|
||||
beforeAll(() => {
|
||||
queryClient.clear()
|
||||
process.env.__BLITZ_SESSION_COOKIE_PREFIX = 'blitz-test'
|
||||
process.env.__BLITZ_SUSPENSE_ENABLED = 'true'
|
||||
process.env.__BLITZ_DEFAULT_SUSPENSE = 'true'
|
||||
})
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
process.env.__BLITZ_SESSION_COOKIE_PREFIX = undefined
|
||||
process.env.__BLITZ_SUSPENSE_ENABLED = undefined
|
||||
process.env.__BLITZ_DEFAULT_SUSPENSE = undefined
|
||||
})
|
||||
|
||||
describe('useQuery', () => {
|
||||
|
||||
154
nextjs/yarn.lock
154
nextjs/yarn.lock
@@ -2896,6 +2896,17 @@
|
||||
"@types/yargs" "^16.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@jest/types@^27.4.2":
|
||||
version "27.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5"
|
||||
integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||
"@types/istanbul-reports" "^3.0.0"
|
||||
"@types/node" "*"
|
||||
"@types/yargs" "^16.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@lerna/add@4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f"
|
||||
@@ -4449,27 +4460,27 @@
|
||||
dependencies:
|
||||
chokidar "^1.7.0"
|
||||
|
||||
"@testing-library/dom@^7.28.1":
|
||||
version "7.29.4"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.29.4.tgz#1647c2b478789621ead7a50614ad81ab5ae5b86c"
|
||||
integrity sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA==
|
||||
"@testing-library/dom@^8.5.0":
|
||||
version "8.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.11.1.tgz#03fa2684aa09ade589b460db46b4c7be9fc69753"
|
||||
integrity sha512-3KQDyx9r0RKYailW2MiYrSSKEfH0GTkI51UGEvJenvcoDoeRYs0PZpi2SXqtnMClQvCqdtTTpOfFETDTVADpAg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/aria-query" "^4.2.0"
|
||||
aria-query "^4.2.2"
|
||||
aria-query "^5.0.0"
|
||||
chalk "^4.1.0"
|
||||
dom-accessibility-api "^0.5.4"
|
||||
dom-accessibility-api "^0.5.9"
|
||||
lz-string "^1.4.4"
|
||||
pretty-format "^26.6.2"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/react@11.2.5":
|
||||
version "11.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.5.tgz#ae1c36a66c7790ddb6662c416c27863d87818eb9"
|
||||
integrity sha512-yEx7oIa/UWLe2F2dqK0FtMF9sJWNXD+2PPtp39BvE0Kh9MJ9Kl0HrZAgEuhUJR+Lx8Di6Xz+rKwSdEPY2UV8ZQ==
|
||||
"@testing-library/react@13.0.0-alpha.5":
|
||||
version "13.0.0-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.0.0-alpha.5.tgz#29bfc36b550e2a1025cbebf7254d5a0a46cb58c5"
|
||||
integrity sha512-QrxKC/7pTE0ze3wLZNaenGJqsLcbAJL71XqU/ryJTL2pqZBjiJHuxZavl2ZQAxnBQkDQF9oh9my3bKPstWfnhA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@testing-library/dom" "^7.28.1"
|
||||
"@testing-library/dom" "^8.5.0"
|
||||
|
||||
"@timsuchanek/copy@^1.4.5":
|
||||
version "1.4.5"
|
||||
@@ -4979,10 +4990,10 @@
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||
|
||||
"@types/react-dom@16.9.4":
|
||||
version "16.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.4.tgz#0b58df09a60961dcb77f62d4f1832427513420df"
|
||||
integrity sha512-fya9xteU/n90tda0s+FtN5Ym4tbgxpq/hb/Af24dvs6uYnYn+fspaxw5USlw0R8apDNwxsqumdRoCoKitckQqw==
|
||||
"@types/react-dom@17.0.11":
|
||||
version "17.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.11.tgz#e1eadc3c5e86bdb5f7684e00274ae228e7bcc466"
|
||||
integrity sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
@@ -5000,12 +5011,13 @@
|
||||
"@types/prop-types" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
"@types/react@17.0.2":
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8"
|
||||
integrity sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==
|
||||
"@types/react@17.0.37":
|
||||
version "17.0.37"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.37.tgz#6884d0aa402605935c397ae689deed115caad959"
|
||||
integrity sha512-2FS1oTqBGcH/s0E+CjrCCR9+JMpsu9b69RTFO+40ua43ZqP5MmQ4iUde/dMjWR909KxZwmOQIFq6AV6NjEG5xg==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/resolve@1.17.1":
|
||||
@@ -5038,6 +5050,11 @@
|
||||
"@types/glob" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/scheduler@*":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
|
||||
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
|
||||
|
||||
"@types/secure-password@3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/secure-password/-/secure-password-3.1.0.tgz#3070abfbfa63c43d0f50e2fbe59dd24dce913968"
|
||||
@@ -5982,6 +5999,11 @@ aria-query@^4.2.2:
|
||||
"@babel/runtime" "^7.10.2"
|
||||
"@babel/runtime-corejs3" "^7.10.2"
|
||||
|
||||
aria-query@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c"
|
||||
integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==
|
||||
|
||||
arity-n@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745"
|
||||
@@ -8653,6 +8675,13 @@ debug@^4.3.2:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^4.3.2:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@~0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-0.8.1.tgz#20ff4d26f5e422cb68a1bacbbb61039ad8c1c130"
|
||||
@@ -8914,10 +8943,10 @@ doctrine@^3.0.0:
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
dom-accessibility-api@^0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166"
|
||||
integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==
|
||||
dom-accessibility-api@^0.5.9:
|
||||
version "0.5.10"
|
||||
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz#caa6d08f60388d0bb4539dd75fe458a9a1d0014c"
|
||||
integrity sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g==
|
||||
|
||||
dom-serializer@0:
|
||||
version "0.2.2"
|
||||
@@ -10865,7 +10894,7 @@ globby@11.0.1:
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globby@11.0.2, globby@^11.0.2:
|
||||
globby@11.0.2:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83"
|
||||
integrity sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==
|
||||
@@ -10877,7 +10906,7 @@ globby@11.0.2, globby@^11.0.2:
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globby@^11.0.0, globby@^11.0.4:
|
||||
globby@^11.0.0, globby@^11.0.1, globby@^11.0.2 globby@^11.0.4:
|
||||
version "11.0.4"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
|
||||
integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
|
||||
@@ -10889,18 +10918,6 @@ globby@^11.0.0, globby@^11.0.4:
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globby@^11.0.1:
|
||||
version "11.0.3"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb"
|
||||
integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==
|
||||
dependencies:
|
||||
array-union "^2.1.0"
|
||||
dir-glob "^3.0.1"
|
||||
fast-glob "^3.1.1"
|
||||
ignore "^5.1.4"
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globby@^9.2.0:
|
||||
version "9.2.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d"
|
||||
@@ -17046,6 +17063,16 @@ pretty-format@^27.0.0-next.8:
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
pretty-format@^27.0.2:
|
||||
version "27.4.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.2.tgz#e4ce92ad66c3888423d332b40477c87d1dac1fb8"
|
||||
integrity sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==
|
||||
dependencies:
|
||||
"@jest/types" "^27.4.2"
|
||||
ansi-regex "^5.0.1"
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
pretty-hrtime@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
||||
@@ -17427,14 +17454,6 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8:
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
"react-18@npm:react@next":
|
||||
version "18.0.0-alpha-c76e4dbbc-20210722"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.0.0-alpha-c76e4dbbc-20210722.tgz#a1591fa4926bb1c514552f77efcc4b4744448f2f"
|
||||
integrity sha512-dtRjRJVHPA25oi29ZFEuLX6R7Rdk5ikCamiDRD0LCB1IpR5hiGKGcNjSxU/rN7rAxs8iRggi15Fg9k1jAK7oBQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
react-devtools-core@^4.19.1:
|
||||
version "4.21.0"
|
||||
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.21.0.tgz#a54c9a0fd7261491e616d6c87d1869e011d8521d"
|
||||
@@ -17443,23 +17462,14 @@ react-devtools-core@^4.19.1:
|
||||
shell-quote "^1.6.1"
|
||||
ws "^7"
|
||||
|
||||
"react-dom-18@npm:react-dom@next":
|
||||
version "18.0.0-alpha-c76e4dbbc-20210722"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.0.0-alpha-c76e4dbbc-20210722.tgz#4fc4518926332983788d48aaad0c6ca5e5d806e5"
|
||||
integrity sha512-lV/+kWzfPq8HLdFnDN1UrJ5blXVFRYCrdOJyZyr9YMZODBl63kpPR7gtszSC4lWiPiMw6K8X+4a3UFU96L7pHQ==
|
||||
react-dom@18.0.0-rc.0:
|
||||
version "18.0.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.0.0-rc.0.tgz#aa07044bdd6399ff94c664b2985e2e25948fbf3e"
|
||||
integrity sha512-tdD1n0svTndHBQvVAq/f2Kx7FgQ30CpSLp87/neQKAHPW5WtdgW1sBSwmFAcMQOrmstTuP0M+zRlH86f9kMX/A==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "0.21.0-alpha-c76e4dbbc-20210722"
|
||||
|
||||
react-dom@0.0.0-experimental-6a589ad71:
|
||||
version "0.0.0-experimental-6a589ad71"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-experimental-6a589ad71.tgz#24ace0c6b0464bdafbc42ebcec783a99aa40d175"
|
||||
integrity sha512-BMJnyJtnqU/1kzcTS2DHwHZDgy2xKijcFtY48KzuZ+0a2dTW4oe5CWPe5O3D7kfP9hLfyPlUt5aWPNv+myxkmA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "0.0.0-experimental-6a589ad71"
|
||||
scheduler "^0.21.0-rc.0"
|
||||
|
||||
react-is@17.0.2:
|
||||
version "17.0.2"
|
||||
@@ -17504,10 +17514,10 @@ react-ssr-prepass@1.0.8:
|
||||
dependencies:
|
||||
object-is "^1.0.1"
|
||||
|
||||
react@0.0.0-experimental-6a589ad71:
|
||||
version "0.0.0-experimental-6a589ad71"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-0.0.0-experimental-6a589ad71.tgz#31a6e680646f715e318acd502d8fa683e19ed7aa"
|
||||
integrity sha512-g+cR05rMkxnFsx90a1Nu/Yb0JAJ7gO0CV84D6E3RIJgsglBKIOrRA2yWE+aQeGFvyoPisY3FzR0w1dmjrhn2Sg==
|
||||
react@18.0.0-rc.0:
|
||||
version "18.0.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.0.0-rc.0.tgz#60bfcf1edd0b35fbeeeca852515c6cc2ce06a6eb"
|
||||
integrity sha512-PawosMBgF8k5Nlc3++ibzjFqPvo1XKv80MNtVYqz3abHHB2w3IpU65sSdSmBd2ooCwVhcp9b1vkx/twqhakNtA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
@@ -18551,18 +18561,10 @@ saxes@^5.0.1:
|
||||
dependencies:
|
||||
xmlchars "^2.2.0"
|
||||
|
||||
scheduler@0.0.0-experimental-6a589ad71:
|
||||
version "0.0.0-experimental-6a589ad71"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.0.0-experimental-6a589ad71.tgz#7eb02e050b4334704a3e89d699b7f8ee7c43812b"
|
||||
integrity sha512-68ixKn+3Q6nWUuyMQXpsDaR4HbE+28qPwgOJ85gyj6ZxNuXpQCf7u9bIuDVxPibqssqf9nOICttpCA0iKuTvlA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
scheduler@0.21.0-alpha-c76e4dbbc-20210722:
|
||||
version "0.21.0-alpha-c76e4dbbc-20210722"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0-alpha-c76e4dbbc-20210722.tgz#7172827a6ed0829e41d1c07cbbf7d9fea6b018ba"
|
||||
integrity sha512-X4Xv2zq1OXxsQNR48reXnOQ9kGnS/mY0cCAusJ6Sm/JBUT83+zetG2sPZPFQSS1np2zkmgMa4+f5H/t2U6AW6Q==
|
||||
scheduler@^0.21.0-rc.0:
|
||||
version "0.21.0-rc.0-next-f2a59df48-20211208"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0-rc.0-next-f2a59df48-20211208.tgz#54e18e1d360194fd54b47a00616e46403fcabdf1"
|
||||
integrity sha512-x0oLd3YIih9GHqWTaFYejVe6Au+4TadOWZciAq8m4+Fuo5qCi4/3M35a9irVSIP3+qcg/fCqHKJETT9G0ejD1A==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
12
package.json
12
package.json
@@ -98,7 +98,7 @@
|
||||
"@rollup/pluginutils": "4.1.0",
|
||||
"@size-limit/preset-small-lib": "4.9.2",
|
||||
"@testing-library/jest-dom": "5.11.9",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react": "13.0.0-alpha.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@testing-library/user-event": "13.1.9",
|
||||
"@types/b64-lite": "1.3.0",
|
||||
@@ -131,8 +131,8 @@
|
||||
"@types/progress": "^2.0.3",
|
||||
"@types/pump": "1.1.0",
|
||||
"@types/pumpify": "1.4.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react-dom": "16.9.4",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/readable-stream": "2.3.9",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/tar": "4.0.4",
|
||||
@@ -184,9 +184,9 @@
|
||||
"prettier": "2.2.1",
|
||||
"prettier-plugin-prisma": "0.4.0",
|
||||
"prompt": "1.1.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-test-renderer": "17.0.1",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"react-test-renderer": "18.0.0-rc.0",
|
||||
"release": "6.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "2.36.1",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "blitz",
|
||||
"description": "Blitz is a Rails-like framework for monolithic, full-stack React apps — built on Next.js",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
@@ -51,25 +51,25 @@
|
||||
"url": "https://github.com/blitz-js/blitz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/cli": "0.45.2",
|
||||
"@blitzjs/generator": "0.45.2",
|
||||
"@blitzjs/server": "0.45.2",
|
||||
"@blitzjs/cli": "0.45.0-canary.0",
|
||||
"@blitzjs/generator": "0.45.0-canary.0",
|
||||
"@blitzjs/server": "0.45.0-canary.0",
|
||||
"@testing-library/jest-dom": "5.11.9",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react": "13.0.0-alpha.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/jest": "26.0.20",
|
||||
"chalk": "^4.1.0",
|
||||
"cross-spawn": "7.0.3",
|
||||
"debug": "4.3.1",
|
||||
"envinfo": "^7.7.3",
|
||||
"eslint-config-blitz": "0.45.2",
|
||||
"eslint-config-blitz": "0.45.0-canary.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-watch-typeahead": "^0.6.1",
|
||||
"minimist": "1.2.5",
|
||||
"next": "0.45.2",
|
||||
"next": "0.45.0-canary.0",
|
||||
"os-name": "^4.0.0",
|
||||
"pkg-dir": "^5.0.0",
|
||||
"react-test-renderer": "17.0.1",
|
||||
"react-test-renderer": "18.0.0-rc.0",
|
||||
"resolve-from": "^5.0.0",
|
||||
"symlink-dir": "4.1.0",
|
||||
"ts-jest": "26.5.0"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@blitzjs/cli",
|
||||
"description": "Blitz.js CLI",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "rimraf lib && tsc --watch --pretty --preserveWatchOutput",
|
||||
@@ -22,9 +22,9 @@
|
||||
"/lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/generator": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/server": "0.45.2",
|
||||
"@blitzjs/generator": "0.45.0-canary.0",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"@blitzjs/server": "0.45.0-canary.0",
|
||||
"@oclif/command": "1.8.0",
|
||||
"@oclif/config": "1.17.0",
|
||||
"@oclif/plugin-autocomplete": "0.3.0",
|
||||
|
||||
@@ -2,15 +2,15 @@ import {
|
||||
capitalize,
|
||||
FormGenerator,
|
||||
ModelGenerator,
|
||||
ModelName,
|
||||
modelName,
|
||||
ModelNames,
|
||||
modelNames,
|
||||
MutationGenerator,
|
||||
MutationsGenerator,
|
||||
PageGenerator,
|
||||
pluralCamel,
|
||||
pluralPascal,
|
||||
QueriesGenerator,
|
||||
QueryGenerator,
|
||||
singleCamel,
|
||||
singlePascal,
|
||||
uncapitalize,
|
||||
} from "@blitzjs/generator"
|
||||
import {flags} from "@oclif/command"
|
||||
@@ -51,6 +51,19 @@ interface Args {
|
||||
model: string
|
||||
}
|
||||
|
||||
function modelName(input: string = "") {
|
||||
return singleCamel(input)
|
||||
}
|
||||
function modelNames(input: string = "") {
|
||||
return pluralCamel(input)
|
||||
}
|
||||
function ModelName(input: string = "") {
|
||||
return singlePascal(input)
|
||||
}
|
||||
function ModelNames(input: string = "") {
|
||||
return pluralPascal(input)
|
||||
}
|
||||
|
||||
const generatorMap = {
|
||||
[ResourceType.All]: [
|
||||
PageGenerator,
|
||||
@@ -241,7 +254,6 @@ export class Generate extends Command {
|
||||
modelNames: modelNames(singularRootContext),
|
||||
ModelName: ModelName(singularRootContext),
|
||||
ModelNames: ModelNames(singularRootContext),
|
||||
rawParentModelName: flags.parent,
|
||||
parentModel: modelName(flags.parent),
|
||||
parentModels: modelNames(flags.parent),
|
||||
ParentModel: ModelName(flags.parent),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/generator",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"description": "File generation for the Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"license": "MIT",
|
||||
@@ -33,14 +33,13 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.1",
|
||||
"@blitzjs/server": "0.45.2",
|
||||
"@blitzjs/server": "0.45.0-canary.0",
|
||||
"@mrleebo/prisma-ast": "0.2.6",
|
||||
"@types/jscodeshift": "0.11.2",
|
||||
"chalk": "^4.1.0",
|
||||
"cross-spawn": "7.0.3",
|
||||
"diff": "5.0.0",
|
||||
"enquirer": "2.3.6",
|
||||
"fast-glob": "^3.1.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"got": "^11.8.1",
|
||||
"jscodeshift": "0.13.0",
|
||||
|
||||
@@ -3,7 +3,6 @@ import * as babel from "@babel/core"
|
||||
import babelTransformTypescript from "@babel/plugin-transform-typescript"
|
||||
import Enquirer from "enquirer"
|
||||
import {EventEmitter} from "events"
|
||||
import {escapePath} from "fast-glob"
|
||||
import * as fs from "fs-extra"
|
||||
import j from "jscodeshift"
|
||||
import {create as createStore, Store} from "mem-fs"
|
||||
@@ -13,8 +12,6 @@ import * as path from "path"
|
||||
import getBabelOptions, {Overrides} from "recast/parsers/_babel_options"
|
||||
import * as babelParser from "recast/parsers/babel"
|
||||
import {ConflictChecker} from "./conflict-checker"
|
||||
import {IBuilder} from "./generators/template-builders/builder"
|
||||
import {NullBuilder} from "./generators/template-builders/null-builder"
|
||||
import {pipe} from "./utils/pipe"
|
||||
import {readdirRecursive} from "./utils/readdir-recursive"
|
||||
const debug = require("debug")("blitz:generator")
|
||||
@@ -163,12 +160,7 @@ export abstract class Generator<
|
||||
if (!this.options.destinationRoot) this.options.destinationRoot = process.cwd()
|
||||
}
|
||||
|
||||
public templateValuesBuilder: IBuilder<T, any> = NullBuilder
|
||||
|
||||
async getTemplateValues(): Promise<any> {
|
||||
const values = await this.templateValuesBuilder.getTemplateValues(this.options)
|
||||
return values
|
||||
}
|
||||
abstract getTemplateValues(): Promise<any>
|
||||
|
||||
abstract getTargetDirectory(): string
|
||||
|
||||
@@ -204,10 +196,6 @@ export abstract class Generator<
|
||||
return result
|
||||
}
|
||||
|
||||
public fieldTemplateRegExp: RegExp = new RegExp(
|
||||
/({?\/\*\s*template: (.*) \*\/}?|\s*\/\/\s*template: (.*))/g,
|
||||
)
|
||||
|
||||
process(
|
||||
input: Buffer,
|
||||
pathEnding: string,
|
||||
@@ -223,21 +211,6 @@ export abstract class Generator<
|
||||
if (codeFileExtensions.test(pathEnding)) {
|
||||
templatedFile = this.replaceConditionals(inputStr, templateValues, prettierOptions || {})
|
||||
}
|
||||
|
||||
const fieldTemplateString = templatedFile
|
||||
.match(this.fieldTemplateRegExp)?.[0]
|
||||
.replace(this.fieldTemplateRegExp, "$2$3")
|
||||
|
||||
if (fieldTemplateString) {
|
||||
const fieldTemplatePosition = templatedFile.search(this.fieldTemplateRegExp)
|
||||
templatedFile = [
|
||||
templatedFile.slice(0, fieldTemplatePosition),
|
||||
...(templateValues.fieldTemplateValues?.map((values: any) =>
|
||||
this.replaceTemplateValues(fieldTemplateString, values),
|
||||
) || []),
|
||||
templatedFile.slice(fieldTemplatePosition),
|
||||
].join("")
|
||||
}
|
||||
templatedFile = this.replaceTemplateValues(templatedFile, templateValues)
|
||||
if (!this.useTs && tsExtension.test(pathEnding)) {
|
||||
templatedFile =
|
||||
@@ -286,34 +259,16 @@ export abstract class Generator<
|
||||
pathSuffix = path.join(this.getTargetDirectory(), pathSuffix)
|
||||
const templateValues = await this.getTemplateValues()
|
||||
|
||||
let sourcePath = this.sourcePath(filePath)
|
||||
let destinationPath = this.destinationPath(pathSuffix)
|
||||
|
||||
this.fs.copy(this.sourcePath(filePath), this.destinationPath(pathSuffix), {
|
||||
process: (input) =>
|
||||
this.process(input, pathSuffix, templateValues, prettierOptions ?? undefined),
|
||||
})
|
||||
let templatedPathSuffix = this.replaceTemplateValues(pathSuffix, templateValues)
|
||||
if (!this.useTs && tsExtension.test(this.destinationPath(pathSuffix))) {
|
||||
templatedPathSuffix = templatedPathSuffix.replace(tsExtension, ".js")
|
||||
}
|
||||
let templatedDestinationPath = this.destinationPath(templatedPathSuffix)
|
||||
|
||||
const destinationExists = fs.existsSync(templatedDestinationPath)
|
||||
|
||||
if (destinationExists) {
|
||||
const newContent = this.process(
|
||||
this.fs.read(templatedDestinationPath, {raw: true}) as any,
|
||||
pathSuffix,
|
||||
templateValues,
|
||||
prettierOptions ?? undefined,
|
||||
)
|
||||
this.fs.write(templatedDestinationPath, newContent)
|
||||
} else {
|
||||
this.fs.copy(escapePath(sourcePath), escapePath(destinationPath), {
|
||||
process: (input) =>
|
||||
this.process(input, pathSuffix, templateValues, prettierOptions ?? undefined),
|
||||
})
|
||||
|
||||
if (templatedPathSuffix !== pathSuffix) {
|
||||
this.fs.move(destinationPath, templatedDestinationPath)
|
||||
}
|
||||
if (templatedPathSuffix !== pathSuffix) {
|
||||
this.fs.move(this.destinationPath(pathSuffix), this.destinationPath(templatedPathSuffix))
|
||||
}
|
||||
} catch (error) {
|
||||
baseLogger({displayDateTime: false}).error(`Error generating ${filePath}`)
|
||||
|
||||
@@ -3,10 +3,10 @@ import spawn from "cross-spawn"
|
||||
import {readJSONSync, writeJson} from "fs-extra"
|
||||
import {baseLogger, log} from "next/dist/server/lib/logging"
|
||||
import {join} from "path"
|
||||
import username from "username"
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
|
||||
import {fetchLatestVersionsFor} from "../utils/fetch-latest-version-for"
|
||||
import {getBlitzDependencyVersion} from "../utils/get-blitz-dependency-version"
|
||||
import {AppValuesBuilder} from "./template-builders/app-values-builder"
|
||||
|
||||
function assert(condition: any, message: string): asserts condition {
|
||||
if (!condition) throw new Error(message)
|
||||
@@ -30,11 +30,6 @@ export interface AppGeneratorOptions extends GeneratorOptions {
|
||||
form?: "React Final Form" | "React Hook Form" | "Formik"
|
||||
onPostInstall?: () => Promise<void>
|
||||
}
|
||||
export interface AppTemplateValues {
|
||||
name: string,
|
||||
safeNameSlug: string,
|
||||
username: string | undefined
|
||||
}
|
||||
type PkgManager = "npm" | "yarn" | "pnpm"
|
||||
|
||||
export class AppGenerator extends Generator<AppGeneratorOptions> {
|
||||
@@ -57,7 +52,13 @@ export class AppGenerator extends Generator<AppGeneratorOptions> {
|
||||
return ["jsconfig.json", "jest.config.js", "package.js.json", "pre-push-js"]
|
||||
}
|
||||
|
||||
templateValuesBuilder = new AppValuesBuilder(this.fs)
|
||||
async getTemplateValues() {
|
||||
return {
|
||||
name: this.options.appName,
|
||||
safeNameSlug: this.options.appName.replace(/[^a-zA-Z0-9-_]/g, "-"),
|
||||
username: await username(),
|
||||
}
|
||||
}
|
||||
|
||||
getTargetDirectory() {
|
||||
return ""
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import {FieldValuesBuilder, ResourceGeneratorOptions} from ".."
|
||||
import {Generator, SourceRootType} from "../generator"
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
|
||||
import {getTemplateRoot} from "../utils/get-template-root"
|
||||
import {camelCaseToKebabCase} from "../utils/inflector"
|
||||
|
||||
export interface FormGeneratorOptions extends ResourceGeneratorOptions {}
|
||||
export interface FormGeneratorOptions extends GeneratorOptions {
|
||||
ModelName: string
|
||||
ModelNames: string
|
||||
modelName: string
|
||||
modelNames: string
|
||||
parentModel?: string
|
||||
parentModels?: string
|
||||
ParentModel?: string
|
||||
ParentModels?: string
|
||||
}
|
||||
|
||||
export class FormGenerator extends Generator<FormGeneratorOptions> {
|
||||
sourceRoot: SourceRootType
|
||||
@@ -14,7 +22,33 @@ export class FormGenerator extends Generator<FormGeneratorOptions> {
|
||||
|
||||
static subdirectory = "queries"
|
||||
|
||||
templateValuesBuilder = new FieldValuesBuilder()
|
||||
private getId(input: string = "") {
|
||||
if (!input) return input
|
||||
return `${input}Id`
|
||||
}
|
||||
|
||||
private getParam(input: string = "") {
|
||||
if (!input) return input
|
||||
return `[${input}]`
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async getTemplateValues() {
|
||||
return {
|
||||
parentModelId: this.getId(this.options.parentModel),
|
||||
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
|
||||
parentModel: this.options.parentModel,
|
||||
parentModels: this.options.parentModels,
|
||||
ParentModel: this.options.ParentModel,
|
||||
ParentModels: this.options.ParentModels,
|
||||
modelId: this.getId(this.options.modelName),
|
||||
modelIdParam: this.getParam(this.getId(this.options.modelName)),
|
||||
modelName: this.options.modelName,
|
||||
modelNames: this.options.modelNames,
|
||||
ModelName: this.options.ModelName,
|
||||
ModelNames: this.options.ModelNames,
|
||||
}
|
||||
}
|
||||
|
||||
getTargetDirectory() {
|
||||
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}/` : ""
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as ast from "@mrleebo/prisma-ast"
|
||||
import {spawn} from "cross-spawn"
|
||||
import {log,newline} from "next/dist/server/lib/logging"
|
||||
import {baseLogger, log, newline} from "next/dist/server/lib/logging"
|
||||
import which from "npm-which"
|
||||
import path from "path"
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
|
||||
import {Field} from "../prisma/field"
|
||||
import {Model} from "../prisma/model"
|
||||
import {getPrismaSchema} from "../utils/get-prisma-schema"
|
||||
import {getTemplateRoot} from "../utils/get-template-root"
|
||||
|
||||
export interface ModelGeneratorOptions extends GeneratorOptions {
|
||||
@@ -23,6 +23,8 @@ export class ModelGenerator extends Generator<ModelGeneratorOptions> {
|
||||
static subdirectory = "../.."
|
||||
unsafe_disableConflictChecker = true
|
||||
|
||||
async getTemplateValues() {}
|
||||
|
||||
getTargetDirectory() {
|
||||
return ""
|
||||
}
|
||||
@@ -39,15 +41,26 @@ export class ModelGenerator extends Generator<ModelGeneratorOptions> {
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async write() {
|
||||
const {schema, schemaPath} = getPrismaSchema(this.fs)
|
||||
const schemaPath = path.resolve("db/schema.prisma")
|
||||
if (!this.fs.exists(schemaPath)) {
|
||||
throw new Error("Prisma schema file was not found")
|
||||
}
|
||||
|
||||
let schema: ast.Schema
|
||||
try {
|
||||
schema = ast.getSchema(this.fs.read(schemaPath))
|
||||
} catch (err) {
|
||||
baseLogger({displayDateTime: false}).error("Failed to parse db/schema.prisma file")
|
||||
throw err
|
||||
}
|
||||
const {modelName, extraArgs, dryRun} = this.options
|
||||
let updatedOrCreated = "created"
|
||||
|
||||
let fieldPromises = (extraArgs.length === 1 && extraArgs[0].includes(" ")
|
||||
let fields = (extraArgs.length === 1 && extraArgs[0].includes(" ")
|
||||
? extraArgs[0].split(" ")
|
||||
: extraArgs
|
||||
).map((input) => Field.parse(input, schema))
|
||||
let fields = (await Promise.all(fieldPromises)).flatMap(fieldArray => fieldArray)
|
||||
).flatMap((input) => Field.parse(input, schema))
|
||||
|
||||
const modelDefinition = new Model(modelName, fields)
|
||||
|
||||
let model: ast.Model | undefined
|
||||
@@ -86,13 +99,10 @@ export class ModelGenerator extends Generator<ModelGeneratorOptions> {
|
||||
}
|
||||
|
||||
async postWrite() {
|
||||
const prismaBin = which(process.cwd()).sync("prisma")
|
||||
//@ts-ignore
|
||||
spawn.sync(prismaBin, ["format"], {stdio: "inherit"})
|
||||
|
||||
const shouldMigrate = await this.prismaMigratePrompt()
|
||||
if (shouldMigrate) {
|
||||
await new Promise<void>((res, rej) => {
|
||||
const prismaBin = which(process.cwd()).sync("prisma")
|
||||
const child = spawn(prismaBin, ["migrate", "dev"], {stdio: "inherit"})
|
||||
child.on("exit", (code) => (code === 0 ? res() : rej()))
|
||||
})
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import {FieldValuesBuilder, ResourceGeneratorOptions} from ".."
|
||||
import {Generator, SourceRootType} from "../generator"
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
|
||||
import {getTemplateRoot} from "../utils/get-template-root"
|
||||
import {camelCaseToKebabCase} from "../utils/inflector"
|
||||
|
||||
export interface MutationsGeneratorOptions extends ResourceGeneratorOptions {}
|
||||
export interface MutationsGeneratorOptions extends GeneratorOptions {
|
||||
ModelName: string
|
||||
ModelNames: string
|
||||
modelName: string
|
||||
modelNames: string
|
||||
parentModel?: string
|
||||
parentModels?: string
|
||||
ParentModel?: string
|
||||
ParentModels?: string
|
||||
}
|
||||
|
||||
export class MutationsGenerator extends Generator<MutationsGeneratorOptions> {
|
||||
sourceRoot: SourceRootType
|
||||
@@ -13,7 +21,33 @@ export class MutationsGenerator extends Generator<MutationsGeneratorOptions> {
|
||||
}
|
||||
static subdirectory = "mutations"
|
||||
|
||||
templateValuesBuilder = new FieldValuesBuilder(this.fs)
|
||||
private getId(input: string = "") {
|
||||
if (!input) return input
|
||||
return `${input}Id`
|
||||
}
|
||||
|
||||
private getParam(input: string = "") {
|
||||
if (!input) return input
|
||||
return `[${input}]`
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async getTemplateValues() {
|
||||
return {
|
||||
parentModelId: this.getId(this.options.parentModel),
|
||||
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
|
||||
parentModel: this.options.parentModel,
|
||||
parentModels: this.options.parentModels,
|
||||
ParentModel: this.options.ParentModel,
|
||||
ParentModels: this.options.ParentModels,
|
||||
modelId: this.getId(this.options.modelName),
|
||||
modelIdParam: this.getParam(this.getId(this.options.modelName)),
|
||||
modelName: this.options.modelName,
|
||||
modelNames: this.options.modelNames,
|
||||
ModelName: this.options.ModelName,
|
||||
ModelNames: this.options.ModelNames,
|
||||
}
|
||||
}
|
||||
|
||||
getTargetDirectory() {
|
||||
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}/` : ""
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import {FieldValuesBuilder, ResourceGeneratorOptions} from ".."
|
||||
import {Generator, SourceRootType} from "../generator"
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
|
||||
import {getTemplateRoot} from "../utils/get-template-root"
|
||||
import {camelCaseToKebabCase} from "../utils/inflector"
|
||||
|
||||
export interface PageGeneratorOptions extends ResourceGeneratorOptions {}
|
||||
export interface PageGeneratorOptions extends GeneratorOptions {
|
||||
ModelName: string
|
||||
ModelNames: string
|
||||
modelName: string
|
||||
modelNames: string
|
||||
parentModel?: string
|
||||
parentModels?: string
|
||||
ParentModel?: string
|
||||
ParentModels?: string
|
||||
}
|
||||
|
||||
export class PageGenerator extends Generator<PageGeneratorOptions> {
|
||||
sourceRoot: SourceRootType
|
||||
@@ -13,7 +21,42 @@ export class PageGenerator extends Generator<PageGeneratorOptions> {
|
||||
}
|
||||
static subdirectory = "pages"
|
||||
|
||||
templateValuesBuilder = new FieldValuesBuilder(this.fs)
|
||||
private getId(input: string = "") {
|
||||
if (!input) return input
|
||||
return `${input}Id`
|
||||
}
|
||||
|
||||
private getParam(input: string = "") {
|
||||
if (!input) return input
|
||||
return `[${input}]`
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async getTemplateValues() {
|
||||
return {
|
||||
parentModelId: this.getId(this.options.parentModel),
|
||||
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
|
||||
parentModel: this.options.parentModel,
|
||||
parentModels: this.options.parentModels,
|
||||
ParentModel: this.options.ParentModel,
|
||||
ParentModels: this.options.ParentModels,
|
||||
modelId: this.getId(this.options.modelName),
|
||||
modelIdParam: this.getParam(this.getId(this.options.modelName)),
|
||||
modelName: this.options.modelName,
|
||||
modelNames: this.options.modelNames,
|
||||
ModelName: this.options.ModelName,
|
||||
ModelNames: this.options.ModelNames,
|
||||
modelNamesPath: this.getModelNamesPath(),
|
||||
}
|
||||
}
|
||||
|
||||
getModelNamesPath() {
|
||||
const kebabCaseContext = this.options.context
|
||||
? `${camelCaseToKebabCase(this.options.context)}/`
|
||||
: ""
|
||||
const kebabCaseModelNames = camelCaseToKebabCase(this.options.modelNames)
|
||||
return kebabCaseContext + kebabCaseModelNames
|
||||
}
|
||||
|
||||
getTargetDirectory() {
|
||||
const kebabCaseModelName = camelCaseToKebabCase(this.options.modelNames)
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import {FieldValuesBuilder, ResourceGeneratorOptions} from ".."
|
||||
import {Generator, SourceRootType} from "../generator"
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
|
||||
import {getTemplateRoot} from "../utils/get-template-root"
|
||||
import {camelCaseToKebabCase} from "../utils/inflector"
|
||||
|
||||
export interface QueriesGeneratorOptions extends ResourceGeneratorOptions {}
|
||||
export interface QueriesGeneratorOptions extends GeneratorOptions {
|
||||
ModelName: string
|
||||
ModelNames: string
|
||||
modelName: string
|
||||
modelNames: string
|
||||
parentModel?: string
|
||||
parentModels?: string
|
||||
ParentModel?: string
|
||||
ParentModels?: string
|
||||
}
|
||||
|
||||
export class QueriesGenerator extends Generator<QueriesGeneratorOptions> {
|
||||
sourceRoot: SourceRootType
|
||||
@@ -13,7 +21,33 @@ export class QueriesGenerator extends Generator<QueriesGeneratorOptions> {
|
||||
}
|
||||
static subdirectory = "queries"
|
||||
|
||||
templateValuesBuilder = new FieldValuesBuilder(this.fs)
|
||||
private getId(input: string = "") {
|
||||
if (!input) return input
|
||||
return `${input}Id`
|
||||
}
|
||||
|
||||
private getParam(input: string = "") {
|
||||
if (!input) return input
|
||||
return `[${input}]`
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async getTemplateValues() {
|
||||
return {
|
||||
parentModelId: this.getId(this.options.parentModel),
|
||||
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
|
||||
parentModel: this.options.parentModel,
|
||||
parentModels: this.options.parentModels,
|
||||
ParentModel: this.options.ParentModel,
|
||||
ParentModels: this.options.ParentModels,
|
||||
modelId: this.getId(this.options.modelName),
|
||||
modelIdParam: this.getParam(this.getId(this.options.modelName)),
|
||||
modelName: this.options.modelName,
|
||||
modelNames: this.options.modelNames,
|
||||
ModelName: this.options.ModelName,
|
||||
ModelNames: this.options.ModelNames,
|
||||
}
|
||||
}
|
||||
|
||||
getTargetDirectory() {
|
||||
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}/` : ""
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import username from "username"
|
||||
import {AppGeneratorOptions, AppTemplateValues} from "../.."
|
||||
import {Builder} from "./builder"
|
||||
|
||||
export class AppValuesBuilder extends Builder<AppGeneratorOptions, AppTemplateValues> {
|
||||
public async getTemplateValues(options: AppGeneratorOptions): Promise<AppTemplateValues> {
|
||||
const values = {
|
||||
name: options.appName,
|
||||
safeNameSlug: options.appName.replace(/[^a-zA-Z0-9-_]/g, "-"),
|
||||
username: await username(),
|
||||
}
|
||||
return values
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
import {Editor} from "mem-fs-editor"
|
||||
import {CodegenField} from "next/dist/server/config-shared"
|
||||
import {GeneratorOptions} from "../../generator"
|
||||
import {getCodegen, getResourceValueFromCodegen} from "../../utils/get-codegen"
|
||||
import {
|
||||
addSpaceBeforeCapitals,
|
||||
camelCaseToKebabCase,
|
||||
singleCamel,
|
||||
singlePascal,
|
||||
} from "../../utils/inflector"
|
||||
|
||||
export interface IBuilder<T, U> {
|
||||
getTemplateValues(Options: T): Promise<U>
|
||||
}
|
||||
|
||||
export interface ResourceGeneratorOptions extends GeneratorOptions {
|
||||
ModelName: string
|
||||
ModelNames: string
|
||||
modelName: string
|
||||
modelNames: string
|
||||
rawParentModelName?: string
|
||||
parentModel?: string
|
||||
parentModels?: string
|
||||
ParentModel?: string
|
||||
ParentModels?: string
|
||||
extraArgs?: string[]
|
||||
}
|
||||
|
||||
export interface CommonTemplateValues {
|
||||
parentModelId: string
|
||||
parentModelParam: string
|
||||
parentModel?: string
|
||||
parentModels?: string
|
||||
ParentModel?: string
|
||||
ParentModels?: string
|
||||
parentModelIdZodType?: string
|
||||
modelId: string
|
||||
modelIdZodType?: string
|
||||
modelIdParam: string
|
||||
modelName: string
|
||||
modelNames: string
|
||||
ModelName: string
|
||||
ModelNames: string
|
||||
modelNamesPath: string
|
||||
fieldTemplateValues?: {[x: string]: any}
|
||||
}
|
||||
|
||||
export abstract class Builder<T, U> implements IBuilder<T, U> {
|
||||
public constructor(fs?: Editor) {
|
||||
this.fs = fs
|
||||
}
|
||||
|
||||
abstract getTemplateValues(Options: T): Promise<U>
|
||||
|
||||
public fs: Editor | undefined
|
||||
|
||||
public defaultFieldConfig: CodegenField = {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
}
|
||||
|
||||
public getId(input: string = "") {
|
||||
if (!input) return input
|
||||
return `${input}Id`
|
||||
}
|
||||
|
||||
public getParam(input: string = "") {
|
||||
if (!input) return input
|
||||
return `[${input}]`
|
||||
}
|
||||
|
||||
public getModelNamesPath(context: string | undefined, modelNames: string) {
|
||||
const kebabCaseContext = context ? `${camelCaseToKebabCase(context)}/` : ""
|
||||
const kebabCaseModelNames = camelCaseToKebabCase(modelNames)
|
||||
return kebabCaseContext + kebabCaseModelNames
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
public async getZodType(type: string = "") {
|
||||
return getResourceValueFromCodegen(type, "zodType")
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
public async getComponentForType(type: string = "") {
|
||||
return getResourceValueFromCodegen(type, "component")
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
public async getInputType(type: string = "") {
|
||||
return getResourceValueFromCodegen(type, "inputType")
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
public async getFieldTemplateValues(args: string[]) {
|
||||
const argsPromises = args.map(async (arg: string) => {
|
||||
let [valueName, typeName] = arg.split(":")
|
||||
if (typeName.includes("?")) {
|
||||
typeName = typeName.replace("?", "")
|
||||
}
|
||||
let values = {
|
||||
attributeName: singleCamel(valueName),
|
||||
fieldName: singleCamel(valueName),
|
||||
FieldName: singlePascal(valueName),
|
||||
field_name: addSpaceBeforeCapitals(valueName).toLocaleLowerCase(), // field name
|
||||
Field_name: singlePascal(addSpaceBeforeCapitals(valueName).toLocaleLowerCase()), // Field name
|
||||
Field_Name: singlePascal(addSpaceBeforeCapitals(valueName)), // Field Name
|
||||
}
|
||||
const codegen = await getCodegen()
|
||||
// iterate over resources defined for this field type
|
||||
const fieldConfig = codegen.fieldTypeMap?.[typeName] || this.defaultFieldConfig
|
||||
values = {...values, ...fieldConfig}
|
||||
return values
|
||||
})
|
||||
return Promise.all(argsPromises)
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
import * as ast from "@mrleebo/prisma-ast"
|
||||
import {create as createStore} from "mem-fs"
|
||||
import {create as createEditor, Editor} from "mem-fs-editor"
|
||||
import {getResourceValueFromCodegen} from "../../utils/get-codegen"
|
||||
import {getPrismaSchema} from "../../utils/get-prisma-schema"
|
||||
import {ModelName, modelName, ModelNames, modelNames} from "../../utils/model-names"
|
||||
import {Builder, CommonTemplateValues, ResourceGeneratorOptions} from "./builder"
|
||||
|
||||
export class FieldValuesBuilder extends Builder<ResourceGeneratorOptions, CommonTemplateValues> {
|
||||
private getEditor = (): Editor => {
|
||||
if (this.fs !== undefined) {
|
||||
return this.fs
|
||||
}
|
||||
const store = createStore()
|
||||
this.fs = createEditor(store)
|
||||
return this.fs
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
public async getTemplateValues(options: ResourceGeneratorOptions): Promise<CommonTemplateValues> {
|
||||
const values: CommonTemplateValues = {
|
||||
parentModelId: this.getId(options.parentModel),
|
||||
parentModelIdZodType: undefined,
|
||||
parentModelParam: this.getParam(this.getId(options.parentModel)),
|
||||
parentModel: options.parentModel,
|
||||
parentModels: options.parentModels,
|
||||
ParentModel: options.ParentModel,
|
||||
ParentModels: options.ParentModels,
|
||||
modelId: this.getId(options.modelName),
|
||||
modelIdZodType: "number",
|
||||
modelIdParam: this.getParam(this.getId(options.modelName)),
|
||||
modelName: options.modelName,
|
||||
modelNames: options.modelNames,
|
||||
ModelName: options.ModelName,
|
||||
ModelNames: options.ModelNames,
|
||||
modelNamesPath: this.getModelNamesPath(options.context, options.modelNames),
|
||||
}
|
||||
if (options.extraArgs) {
|
||||
// specialArgs - these are arguments like 'id' or 'belongsTo', which are not meant to
|
||||
// be processed as fields but have their own special logic
|
||||
let specialArgs: {[key in string]: string} = {}
|
||||
|
||||
const processSpecialArgs: Promise<void>[] = options.extraArgs.map(async (arg) => {
|
||||
const [valueName, typeName] = arg.split(":")
|
||||
if (valueName === "id") {
|
||||
values.modelIdZodType = await this.getZodType(typeName)
|
||||
specialArgs[arg] = "present"
|
||||
}
|
||||
if (valueName === "belongsTo") {
|
||||
// TODO: Determine how this is done. The model will generate with a field with the id name
|
||||
// and type of the parent of this model, and forms etc. should
|
||||
// In addition, need to do the same logic that the options.parentModel != undefined below does
|
||||
specialArgs[arg] = "present"
|
||||
process.env.parentModel = typeName
|
||||
options.rawParentModelName = typeName
|
||||
options.parentModel = modelName(typeName)
|
||||
options.parentModels = modelNames(typeName)
|
||||
options.ParentModel = ModelName(typeName)
|
||||
options.ParentModels = ModelNames(typeName)
|
||||
}
|
||||
})
|
||||
await Promise.all(processSpecialArgs)
|
||||
// Filter out special args by making sure the argument isn't present in the list
|
||||
const nonSpecialArgs = options.extraArgs.filter((arg) => specialArgs[arg] !== "present")
|
||||
|
||||
// Get the parent model it type if options.parentModel exists
|
||||
if (options.parentModel !== undefined && options.parentModel.length > 0) {
|
||||
const {schema} = getPrismaSchema(this.getEditor())
|
||||
// O(N) - N is total ast Blocks
|
||||
const model = schema.list.find(function (component): component is ast.Model {
|
||||
return component.type === "model" && component.name === options.rawParentModelName
|
||||
})
|
||||
|
||||
if (model !== undefined) {
|
||||
// O(N) - N is number of properties in parent model
|
||||
const idField = model.properties.find(function (property): property is ast.Field {
|
||||
return (
|
||||
property.type === "field" &&
|
||||
property.attributes?.findIndex((attr) => attr.name === "id") !== -1
|
||||
)
|
||||
})
|
||||
|
||||
// TODO: Do we want a map between prisma types and "user types", we can then use that map instead of these conditionals
|
||||
// We have a map from "user types" (which are what users type into the blitz generate command)
|
||||
// to primsa type and other types, but we dont have a reverse map 1:1. This is because we lose
|
||||
// some information for certain maps. E.g.: fieldname:uuid will be converted into a Prisma field with
|
||||
// the String type, and the uuid portion is added to a decorator at the end of the field.
|
||||
// This means it is more complicated to extract the original "user specified type" than creating a reverse map
|
||||
if (idField?.fieldType === "Int") {
|
||||
// TODO: Check if ints have decorators that make them a different type, like Bigint, etc.
|
||||
// And see if that has to map to a different user specified type
|
||||
values.parentModelIdZodType = await getResourceValueFromCodegen("int", "zodType")
|
||||
} else if (idField?.fieldType === "String") {
|
||||
if (
|
||||
idField.attributes?.find(
|
||||
(attr) =>
|
||||
attr.name === "default" &&
|
||||
attr.args?.findIndex((arg) => arg.value === "uuid") !== -1,
|
||||
)
|
||||
) {
|
||||
values.parentModelIdZodType = await getResourceValueFromCodegen("uuid", "zodType")
|
||||
} else {
|
||||
values.parentModelIdZodType = await getResourceValueFromCodegen("string", "zodType")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: handle scenario where parent wasnt found in existing schema. Should we throw an error, or a warning asking the user to verify that the parent model exists?
|
||||
}
|
||||
}
|
||||
if (nonSpecialArgs.length > 0) {
|
||||
const ftv = await this.getFieldTemplateValues(nonSpecialArgs)
|
||||
return {...values, fieldTemplateValues: ftv}
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import {IBuilder} from "./builder"
|
||||
|
||||
export const NullBuilder: IBuilder<any,any> = {
|
||||
// eslint-disable-next-line require-await
|
||||
getTemplateValues: async () => {
|
||||
return {}
|
||||
},
|
||||
}
|
||||
@@ -8,11 +8,6 @@ export * from "./generators/query-generator"
|
||||
export * from "./generators/form-generator"
|
||||
export * from "./generator"
|
||||
export * from "./conflict-checker"
|
||||
export * from "./generators/template-builders/builder"
|
||||
export * from "./generators/template-builders/null-builder"
|
||||
export * from "./generators/template-builders/app-values-builder"
|
||||
export * from "./generators/template-builders/field-values-builder"
|
||||
export * from "./utils/model-names"
|
||||
export {getLatestVersion} from "./utils/get-latest-version"
|
||||
export {
|
||||
singleCamel,
|
||||
@@ -21,5 +16,4 @@ export {
|
||||
pluralPascal,
|
||||
capitalize,
|
||||
uncapitalize,
|
||||
addSpaceBeforeCapitals,
|
||||
} from "./utils/inflector"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as ast from "@mrleebo/prisma-ast"
|
||||
import {baseLogger, log} from "next/dist/server/lib/logging"
|
||||
import {getResourceConfigFromCodegen} from "../utils/get-codegen"
|
||||
import {capitalize, singlePascal, uncapitalize} from "../utils/inflector"
|
||||
const debug = require("debug")("blitz:field")
|
||||
|
||||
export enum FieldType {
|
||||
Boolean = "Boolean",
|
||||
@@ -57,39 +55,25 @@ export class Field {
|
||||
relationToFields?: string[]
|
||||
|
||||
// 'name:type?[]:attribute' => Field
|
||||
static async parse(input: string, schema?: ast.Schema): Promise<Field[]> {
|
||||
debug(`parsing "Field" for input ${input}`)
|
||||
|
||||
static parse(input: string, schema?: ast.Schema): Field[] {
|
||||
const [_fieldName, _fieldType = "String", _attribute] = input.split(":")
|
||||
let attribute = _attribute
|
||||
let fieldName = uncapitalize(_fieldName)
|
||||
let fieldType = capitalize(_fieldType)
|
||||
// Check if it would make sense to expose that to users as well?
|
||||
// Also in the case of a relationship, need to use the raw model name, cant capitalize it.
|
||||
const isId = fieldName === "id"
|
||||
let isRequired = true
|
||||
let isList = false
|
||||
let isUpdatedAt = false
|
||||
let isUnique = false
|
||||
let defaultValue = undefined
|
||||
let relationFromFields = undefined
|
||||
let relationToFields = undefined
|
||||
let maybeIdField = undefined
|
||||
let isUnique = false
|
||||
|
||||
if (fieldType.includes("?")) {
|
||||
fieldType = fieldType.replace("?", "")
|
||||
isRequired = false
|
||||
}
|
||||
|
||||
const {prismaType, default: defaultConfigValue} =
|
||||
(await Field.getConfigForPrismaType(fieldType)) ?? {}
|
||||
if (prismaType) {
|
||||
fieldType = prismaType
|
||||
}
|
||||
if (defaultConfigValue) {
|
||||
attribute = `default=${defaultConfigValue}`
|
||||
}
|
||||
|
||||
if (fieldType.includes("[]")) {
|
||||
fieldType = fieldType.replace("[]", "")
|
||||
fieldName = uncapitalize(fieldName)
|
||||
@@ -179,10 +163,6 @@ export class Field {
|
||||
}
|
||||
}
|
||||
|
||||
public static getConfigForPrismaType = async (fieldType: string) => {
|
||||
return await getResourceConfigFromCodegen(fieldType.toLowerCase())
|
||||
}
|
||||
|
||||
constructor(name: string, options: FieldArgs) {
|
||||
if (!name) throw new MissingFieldNameError("[PrismaField]: A field name is required")
|
||||
if (!options.type) {
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
import {CodegenConfig, CodegenField, NextConfigComplete} from "next/dist/server/config-shared"
|
||||
import {baseLogger} from "next/dist/server/lib/logging"
|
||||
|
||||
export const defaultCodegenConfig: CodegenConfig = {
|
||||
fieldTypeMap: {
|
||||
string: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
},
|
||||
boolean: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "boolean",
|
||||
prismaType: "Boolean",
|
||||
},
|
||||
int: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
},
|
||||
number: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
},
|
||||
bigint: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "BigInt",
|
||||
},
|
||||
float: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Float",
|
||||
},
|
||||
decimal: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "number",
|
||||
zodType: "number",
|
||||
prismaType: "Decimal",
|
||||
},
|
||||
datetime: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "string",
|
||||
prismaType: "DateTime",
|
||||
},
|
||||
uuid: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "string().uuid",
|
||||
prismaType: "String",
|
||||
default: "uuid",
|
||||
},
|
||||
json: {
|
||||
component: "LabeledTextField",
|
||||
inputType: "text",
|
||||
zodType: "any",
|
||||
prismaType: "Json",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const getResourceValueFromCodegen = async (
|
||||
fieldType: string,
|
||||
resource: keyof CodegenField,
|
||||
): Promise<string | undefined> => {
|
||||
const codegen = await getCodegen()
|
||||
const templateValue = codegen.fieldTypeMap?.[fieldType]?.[resource]
|
||||
return templateValue
|
||||
}
|
||||
|
||||
export const getResourceConfigFromCodegen = async (
|
||||
fieldType: string,
|
||||
): Promise<CodegenField | undefined> => {
|
||||
const codegen = await getCodegen()
|
||||
const config = codegen.fieldTypeMap?.[fieldType]
|
||||
return config
|
||||
}
|
||||
|
||||
export const getCodegen = async (): Promise<NextConfigComplete["codegen"]> => {
|
||||
try {
|
||||
const {loadConfigAtRuntime} = await import("next/dist/server/config-shared")
|
||||
const config = await loadConfigAtRuntime()
|
||||
|
||||
if (config.codegen !== undefined) {
|
||||
// TODO: potentially verify that codegen is well formed using zod
|
||||
return config.codegen
|
||||
}
|
||||
return defaultCodegenConfig
|
||||
} catch (ex) {
|
||||
baseLogger({displayDateTime: false}).warn("Failed loading config from blitz.config file " + ex)
|
||||
return defaultCodegenConfig
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import * as ast from "@mrleebo/prisma-ast"
|
||||
import {Editor} from "mem-fs-editor"
|
||||
import { baseLogger } from "next/dist/server/lib/logging"
|
||||
import path from "path"
|
||||
|
||||
export const getPrismaSchema = (memFsEditor : Editor): {schema: ast.Schema, schemaPath: string} => {
|
||||
const schemaPath = path.resolve("db/schema.prisma")
|
||||
if (!memFsEditor.exists(schemaPath)) {
|
||||
throw new Error("Prisma schema file was not found")
|
||||
}
|
||||
|
||||
let schema: ast.Schema
|
||||
try {
|
||||
schema = ast.getSchema(memFsEditor.read(schemaPath))
|
||||
} catch (err) {
|
||||
baseLogger({displayDateTime: false}).error("Failed to parse db/schema.prisma file")
|
||||
throw err
|
||||
}
|
||||
return {schema, schemaPath}
|
||||
}
|
||||
@@ -25,7 +25,3 @@ export const pluralCamel = pipe(plural, uncapitalize)
|
||||
export function camelCaseToKebabCase(transformString: string) {
|
||||
return transformString.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase()
|
||||
}
|
||||
|
||||
export function addSpaceBeforeCapitals(input: string): string {
|
||||
return singleCamel(input).replace(/(?!^)([A-Z])/g, " $1")
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import {pluralCamel, pluralPascal, singleCamel, singlePascal} from "../index"
|
||||
|
||||
export function modelName(input: string = "") {
|
||||
return singleCamel(input)
|
||||
}
|
||||
export function modelNames(input: string = "") {
|
||||
return pluralCamel(input)
|
||||
}
|
||||
export function ModelName(input: string = "") {
|
||||
return singlePascal(input)
|
||||
}
|
||||
export function ModelNames(input: string = "") {
|
||||
return pluralPascal(input)
|
||||
}
|
||||
@@ -6,7 +6,7 @@ const config: BlitzConfig = {
|
||||
cookiePrefix: "__safeNameSlug__",
|
||||
isAuthorized: simpleRolesIsAuthorized,
|
||||
}),
|
||||
],
|
||||
],
|
||||
/* Uncomment this to customize the webpack config
|
||||
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
||||
// Note: we provide webpack above so you should not `require` it
|
||||
@@ -14,6 +14,6 @@ const config: BlitzConfig = {
|
||||
// Important: return the modified config
|
||||
return config
|
||||
},
|
||||
*/
|
||||
*/
|
||||
}
|
||||
module.exports = config
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "3.x",
|
||||
"blitz": "latest",
|
||||
"react-dom": "18.0.0-alpha-5ca4b0433-20211020",
|
||||
"react": "18.0.0-beta-149b420f6-20211119",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"zod": "3.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -26,13 +26,14 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "3.x",
|
||||
"blitz": "latest",
|
||||
"react-dom": "18.0.0-alpha-5ca4b0433-20211020",
|
||||
"react": "18.0.0-beta-149b420f6-20211119",
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0",
|
||||
"zod": "3.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/preview-email": "2.x",
|
||||
"@types/react": "17.x",
|
||||
"@types/react-dom": "17.x",
|
||||
"eslint": "7.x",
|
||||
"husky": "7.x",
|
||||
"lint-staged": "11.x",
|
||||
|
||||
@@ -6,7 +6,7 @@ export {FORM_ERROR} from "app/core/components/Form"
|
||||
export function __ModelName__Form<S extends z.ZodType<any, any>>(props: FormProps<S>) {
|
||||
return (
|
||||
<Form<S> {...props}>
|
||||
{/* template: <__component__ name="__fieldName__" label="__Field_Name__" placeholder="__Field_Name__" type="__inputType__" /> */}
|
||||
<LabeledTextField name="name" label="Name" placeholder="Name" />
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "latest",
|
||||
"react-dom": "18.0.0-alpha-5ca4b0433-20211020",
|
||||
"react": "18.0.0-beta-149b420f6-20211119"
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "7.x",
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "latest",
|
||||
"react-dom": "18.0.0-alpha-5ca4b0433-20211020",
|
||||
"react": "18.0.0-beta-149b420f6-20211119"
|
||||
"react": "18.0.0-rc.0",
|
||||
"react-dom": "18.0.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.x",
|
||||
"@types/react-dom": "17.x",
|
||||
"eslint": "7.x",
|
||||
"husky": "7.x",
|
||||
"lint-staged": "11.x",
|
||||
|
||||
@@ -4,12 +4,12 @@ import {z} from "zod"
|
||||
|
||||
if (process.env.parentModel) {
|
||||
const Create__ModelName__ = z.object({
|
||||
__parentModelId__: z.__parentModelIdZodType__(),
|
||||
// template: __fieldName__: z.__zodType__(),
|
||||
name: z.string(),
|
||||
__parentModelId__: z.number()
|
||||
})
|
||||
} else {
|
||||
const Create__ModelName__ = z.object({
|
||||
// template: __fieldName__: z.__zodType__(),
|
||||
name: z.string(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import db from "db"
|
||||
import {z} from "zod"
|
||||
|
||||
const Delete__ModelName__ = z.object({
|
||||
id: z.__modelIdZodType__(),
|
||||
id: z.number(),
|
||||
})
|
||||
|
||||
export default resolver.pipe(
|
||||
|
||||
@@ -3,8 +3,8 @@ import db from "db"
|
||||
import {z} from "zod"
|
||||
|
||||
const Update__ModelName__ = z.object({
|
||||
id: z.__modelIdZodType__(),
|
||||
// template: __fieldName__: z.__zodType__(),
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
})
|
||||
|
||||
export default resolver.pipe(
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
import {FieldValuesBuilder} from "../../src/generators/template-builders/field-values-builder"
|
||||
|
||||
describe("Form Generator", () => {
|
||||
process.env.BLITZ_APP_DIR = process.cwd()
|
||||
const generator = new FieldValuesBuilder()
|
||||
|
||||
it("Should work with simple types", async () => {
|
||||
expect(
|
||||
await generator.getFieldTemplateValues(["field1:string", "field2:string"]),
|
||||
).toStrictEqual([
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field1",
|
||||
Field_Name: "Field1",
|
||||
Field_name: "Field1",
|
||||
attributeName: "field1",
|
||||
fieldName: "field1",
|
||||
field_name: "field1",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
inputType: "text",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field2",
|
||||
Field_Name: "Field2",
|
||||
Field_name: "Field2",
|
||||
attributeName: "field2",
|
||||
fieldName: "field2",
|
||||
field_name: "field2",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
inputType: "text",
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("Should work with optional types", async () => {
|
||||
expect(
|
||||
await generator.getFieldTemplateValues(["field1:string?", "field2:number"]),
|
||||
).toStrictEqual([
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field1",
|
||||
Field_Name: "Field1",
|
||||
Field_name: "Field1",
|
||||
attributeName: "field1",
|
||||
fieldName: "field1",
|
||||
field_name: "field1",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
inputType: "text",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field2",
|
||||
Field_Name: "Field2",
|
||||
Field_name: "Field2",
|
||||
attributeName: "field2",
|
||||
fieldName: "field2",
|
||||
field_name: "field2",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
inputType: "number",
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("Should work with default values", async () => {
|
||||
expect(await generator.getFieldTemplateValues(["field1:string:default='test'"])).toStrictEqual([
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field1",
|
||||
Field_Name: "Field1",
|
||||
Field_name: "Field1",
|
||||
attributeName: "field1",
|
||||
fieldName: "field1",
|
||||
field_name: "field1",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
inputType: "text",
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("Should work with different input types", async () => {
|
||||
const fields = [
|
||||
"field1:string?",
|
||||
"field2:boolean",
|
||||
"field3:int",
|
||||
"field4:number",
|
||||
"field5:bigint?",
|
||||
"field6:float",
|
||||
"field7:decimal",
|
||||
"field8:datetime",
|
||||
"field9:uuid",
|
||||
"field10:json?",
|
||||
]
|
||||
expect(await generator.getFieldTemplateValues(fields)).toStrictEqual([
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field1",
|
||||
Field_Name: "Field1",
|
||||
Field_name: "Field1",
|
||||
attributeName: "field1",
|
||||
fieldName: "field1",
|
||||
field_name: "field1",
|
||||
zodType: "string",
|
||||
prismaType: "String",
|
||||
inputType: "text",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field2",
|
||||
Field_Name: "Field2",
|
||||
Field_name: "Field2",
|
||||
attributeName: "field2",
|
||||
fieldName: "field2",
|
||||
field_name: "field2",
|
||||
zodType: "boolean",
|
||||
prismaType: "Boolean",
|
||||
inputType: "text",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field3",
|
||||
Field_Name: "Field3",
|
||||
Field_name: "Field3",
|
||||
attributeName: "field3",
|
||||
fieldName: "field3",
|
||||
field_name: "field3",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
inputType: "number",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field4",
|
||||
Field_Name: "Field4",
|
||||
Field_name: "Field4",
|
||||
attributeName: "field4",
|
||||
fieldName: "field4",
|
||||
field_name: "field4",
|
||||
zodType: "number",
|
||||
prismaType: "Int",
|
||||
inputType: "number",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field5",
|
||||
Field_Name: "Field5",
|
||||
Field_name: "Field5",
|
||||
attributeName: "field5",
|
||||
fieldName: "field5",
|
||||
field_name: "field5",
|
||||
zodType: "number",
|
||||
prismaType: "BigInt",
|
||||
inputType: "number",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field6",
|
||||
Field_Name: "Field6",
|
||||
Field_name: "Field6",
|
||||
attributeName: "field6",
|
||||
fieldName: "field6",
|
||||
field_name: "field6",
|
||||
zodType: "number",
|
||||
prismaType: "Float",
|
||||
inputType: "number",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field7",
|
||||
Field_Name: "Field7",
|
||||
Field_name: "Field7",
|
||||
attributeName: "field7",
|
||||
fieldName: "field7",
|
||||
field_name: "field7",
|
||||
zodType: "number",
|
||||
prismaType: "Decimal",
|
||||
inputType: "number",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field8",
|
||||
Field_Name: "Field8",
|
||||
Field_name: "Field8",
|
||||
attributeName: "field8",
|
||||
fieldName: "field8",
|
||||
field_name: "field8",
|
||||
zodType: "string",
|
||||
prismaType: "DateTime",
|
||||
inputType: "text",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field9",
|
||||
Field_Name: "Field9",
|
||||
Field_name: "Field9",
|
||||
attributeName: "field9",
|
||||
fieldName: "field9",
|
||||
field_name: "field9",
|
||||
zodType: "string().uuid",
|
||||
prismaType: "String",
|
||||
inputType: "text",
|
||||
default: "uuid",
|
||||
},
|
||||
{
|
||||
component: "LabeledTextField",
|
||||
FieldName: "Field10",
|
||||
Field_Name: "Field10",
|
||||
Field_name: "Field10",
|
||||
attributeName: "field10",
|
||||
fieldName: "field10",
|
||||
field_name: "field10",
|
||||
zodType: "any",
|
||||
prismaType: "Json",
|
||||
inputType: "text",
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,47 +0,0 @@
|
||||
import {FormGenerator} from "../../src/generators/form-generator"
|
||||
|
||||
describe("Form Generator", () => {
|
||||
process.env.BLITZ_APP_DIR = process.cwd()
|
||||
const generator = new FormGenerator({
|
||||
ModelName: "project",
|
||||
ModelNames: "projects",
|
||||
modelName: "project",
|
||||
modelNames: "projects",
|
||||
extraArgs: ["myProjectName:string"],
|
||||
})
|
||||
|
||||
it("Correctly generates field names", async () => {
|
||||
const templateValues = await generator.getTemplateValues()
|
||||
expect(templateValues.fieldTemplateValues[0].fieldName).toEqual("myProjectName")
|
||||
expect(templateValues.fieldTemplateValues[0].FieldName).toEqual("MyProjectName")
|
||||
expect(templateValues.fieldTemplateValues[0].field_name).toEqual("my project name")
|
||||
expect(templateValues.fieldTemplateValues[0].Field_name).toEqual("My project name")
|
||||
expect(templateValues.fieldTemplateValues[0].Field_Name).toEqual("My Project Name")
|
||||
})
|
||||
|
||||
it("matches template comments correctly", () => {
|
||||
const regex = generator.fieldTemplateRegExp
|
||||
const curlyBraceComment1 = `{/* template: <__component__ name="__fieldName__" label="__Field_Name__" placeholder="__Field_Name__" /> */}`
|
||||
expect(curlyBraceComment1.match(regex)?.[0].replace(regex, "$2$3")).toBe(
|
||||
`<__component__ name="__fieldName__" label="__Field_Name__" placeholder="__Field_Name__" />`,
|
||||
)
|
||||
expect(curlyBraceComment1.match(regex)?.[0].replace(regex, "$2$3")).not.toBe(`something Random`)
|
||||
|
||||
const normalComment1 = `// template: __fieldName__: z.__zodType__(),`
|
||||
|
||||
expect(normalComment1.match(regex)?.[0].replace(regex, "$2$3")).toBe(
|
||||
`__fieldName__: z.__zodType__(),`,
|
||||
)
|
||||
expect(normalComment1.match(regex)?.[0].replace(regex, "$2$3")).not.toBe(`something Random`)
|
||||
|
||||
const commentWithSpacing = `// template: __fieldName__: z.__zodType__(),`
|
||||
const commentWithNoSpacing = `//template: __fieldName__: z.__zodType__(),`
|
||||
|
||||
expect(commentWithSpacing.match(regex)?.[0].replace(regex, "$2$3")).toBe(
|
||||
`__fieldName__: z.__zodType__(),`,
|
||||
)
|
||||
expect(commentWithNoSpacing.match(regex)?.[0].replace(regex, "$2$3")).toBe(
|
||||
`__fieldName__: z.__zodType__(),`,
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -9,10 +9,8 @@ describe("PageGenerator", () => {
|
||||
})
|
||||
|
||||
describe("#getModelNamesPath", () => {
|
||||
it("returns path only with default modelNames", async () => {
|
||||
expect((await generator.getTemplateValues()).modelNamesPath).toBe(
|
||||
"projects",
|
||||
)
|
||||
it("returns path only with default modelNames", () => {
|
||||
expect(generator.getModelNamesPath()).toEqual("projects")
|
||||
})
|
||||
|
||||
describe("when generator has context option", () => {
|
||||
@@ -24,10 +22,8 @@ describe("PageGenerator", () => {
|
||||
context: "marketing",
|
||||
})
|
||||
|
||||
it("returns path with context as prefix", async () => {
|
||||
expect((await generator.getTemplateValues()).modelNamesPath).toBe(
|
||||
"marketing/projects",
|
||||
)
|
||||
it("returns path with context as prefix", () => {
|
||||
expect(generator.getModelNamesPath()).toEqual("marketing/projects")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -38,7 +34,6 @@ describe("PageGenerator", () => {
|
||||
expect(values).toEqual({
|
||||
ModelName: "project",
|
||||
ModelNames: "projects",
|
||||
parentModelIdZodType: undefined,
|
||||
ParentModel: undefined,
|
||||
ParentModels: undefined,
|
||||
modelNamesPath: "projects",
|
||||
@@ -46,7 +41,6 @@ describe("PageGenerator", () => {
|
||||
modelIdParam: "[projectId]",
|
||||
modelName: "project",
|
||||
modelNames: "projects",
|
||||
modelIdZodType: "number",
|
||||
parentModel: undefined,
|
||||
parentModelId: "",
|
||||
parentModelParam: "",
|
||||
|
||||
@@ -2,86 +2,75 @@ import {Schema} from "@mrleebo/prisma-ast"
|
||||
import {Field} from "../../src/prisma/field"
|
||||
|
||||
describe("Field", () => {
|
||||
process.env.BLITZ_APP_DIR = process.cwd()
|
||||
it("parses optional types", async () => {
|
||||
const [field] = await await Field.parse("name:string?")
|
||||
it("parses optional types", () => {
|
||||
const [field] = Field.parse("name:string?")
|
||||
expect(field.isRequired).toBe(false)
|
||||
})
|
||||
|
||||
it("appends unique attribute", async () => {
|
||||
const [field] = await Field.parse("email:string?:unique")
|
||||
it("appends unique attribute", () => {
|
||||
const [field] = Field.parse("email:string?:unique")
|
||||
expect(field.isUnique).toBe(true)
|
||||
})
|
||||
|
||||
it("appends updatedAt attribute", async () => {
|
||||
const [field] = await Field.parse("updatedAt:DateTime:updatedAt")
|
||||
it("appends updatedAt attribute", () => {
|
||||
const [field] = Field.parse("updatedAt:DateTime:updatedAt")
|
||||
expect(field.isUpdatedAt).toBe(true)
|
||||
})
|
||||
|
||||
it("handles default simple attribute", async () => {
|
||||
const [field] = await Field.parse("isActive:boolean:default=true")
|
||||
it("handles default simple attribute", () => {
|
||||
const [field] = Field.parse("isActive:boolean:default=true")
|
||||
expect(field.default).toBe("true")
|
||||
})
|
||||
|
||||
it("handles default uuid attribute", async () => {
|
||||
const [field] = await Field.parse("id:string:default=uuid")
|
||||
it("handles default uuid attribute", () => {
|
||||
const [field] = Field.parse("id:string:default=uuid")
|
||||
expect(field.default).toMatchObject({name: "uuid"})
|
||||
})
|
||||
|
||||
it("handles uuid convenience syntax", async () => {
|
||||
const [field] = await Field.parse("someSpecialToken:uuid")
|
||||
it("handles uuid convenience syntax", () => {
|
||||
const [field] = Field.parse("someSpecialToken:uuid")
|
||||
expect(field.type).toBe("String")
|
||||
expect(field.default).toMatchObject({name: "uuid"})
|
||||
})
|
||||
|
||||
it("handles default autoincrement attribute", async () => {
|
||||
const [field] = await Field.parse("id:int:default=autoincrement")
|
||||
it("handles default autoincrement attribute", () => {
|
||||
const [field] = Field.parse("id:int:default=autoincrement")
|
||||
expect(field.default).toMatchObject({name: "autoincrement"})
|
||||
})
|
||||
|
||||
it("has default field type", async () => {
|
||||
const [field] = await Field.parse("name")
|
||||
it("has default field type", () => {
|
||||
const [field] = Field.parse("name")
|
||||
expect(field.type).toBe("String")
|
||||
})
|
||||
|
||||
it("allow number characters in model name", async () => {
|
||||
const [field] = await Field.parse("name2")
|
||||
it("allow number characters in model name", () => {
|
||||
const [field] = Field.parse("name2")
|
||||
expect(field.name).toBe("name2")
|
||||
})
|
||||
|
||||
it("allow underscore characters in model name", async () => {
|
||||
const [field] = await Field.parse("first_name")
|
||||
it("allow underscore characters in model name", () => {
|
||||
const [field] = Field.parse("first_name")
|
||||
expect(field.name).toBe("first_name")
|
||||
})
|
||||
|
||||
it("disallows number as a first character in model name", async () => {
|
||||
await expect(async () => await Field.parse("2first")).rejects.toThrowError(
|
||||
"[Field.parse]: received unknown special character in field name: 2first",
|
||||
)
|
||||
it("disallows number as a first character in model name", () => {
|
||||
expect(() => Field.parse("2first")).toThrow()
|
||||
})
|
||||
|
||||
it("disallows underscore as a first character in model name", async () => {
|
||||
await expect(async () => await Field.parse("_first")).rejects.toThrowError(
|
||||
"[Field.parse]: received unknown special character in field name: _first",
|
||||
)
|
||||
it("disallows underscore as a first character in model name", () => {
|
||||
expect(() => Field.parse("_first")).toThrow()
|
||||
})
|
||||
|
||||
it("disallows special characters in model name", async () => {
|
||||
await expect(async () => await Field.parse("app-user:int")).rejects.toThrowError(
|
||||
"[Field.parse]: received unknown special character in field name: app-user",
|
||||
)
|
||||
it("disallows special characters in model name", () => {
|
||||
expect(() => Field.parse("app-user:int")).toThrow()
|
||||
})
|
||||
|
||||
it("disallows optional list fields", async () => {
|
||||
await expect(async () => await Field.parse("users:int?[]")).rejects.toThrowError(
|
||||
"[PrismaField]: a type cannot be both optional and a list",
|
||||
)
|
||||
it("disallows optional list fields", () => {
|
||||
expect(() => Field.parse("users:int?[]")).toThrow()
|
||||
})
|
||||
|
||||
it("requires a name", async () => {
|
||||
await expect(async () => await Field.parse(":int")).rejects.toThrowError(
|
||||
"[Field.parse]: received unknown special character in field name: ",
|
||||
)
|
||||
it("requires a name", () => {
|
||||
expect(() => Field.parse(":int")).toThrow()
|
||||
})
|
||||
|
||||
describe("belongsTo", () => {
|
||||
@@ -113,8 +102,8 @@ describe("Field", () => {
|
||||
],
|
||||
}
|
||||
|
||||
it("simple relation", async () => {
|
||||
const [relation, foreignKey] = await Field.parse("belongsTo:task")
|
||||
it("simple relation", () => {
|
||||
const [relation, foreignKey] = Field.parse("belongsTo:task")
|
||||
expect(relation).toMatchObject({
|
||||
name: "task",
|
||||
type: "Task",
|
||||
@@ -124,8 +113,8 @@ describe("Field", () => {
|
||||
expect(foreignKey).toMatchObject({name: "taskId", type: "Int"})
|
||||
})
|
||||
|
||||
it("relation with schema", async () => {
|
||||
const [relation, foreignKey] = await Field.parse("belongsTo:project?", schema)
|
||||
it("relation with schema", () => {
|
||||
const [relation, foreignKey] = Field.parse("belongsTo:project?", schema)
|
||||
expect(relation).toMatchObject({
|
||||
name: "project",
|
||||
type: "Project",
|
||||
@@ -136,8 +125,8 @@ describe("Field", () => {
|
||||
expect(foreignKey).toMatchObject({name: "projectId", type: "String", isRequired: false})
|
||||
})
|
||||
|
||||
it("relation with list directive", async () => {
|
||||
const [relation, foreignKey] = await Field.parse("belongsTo:tasks[]", schema)
|
||||
it("relation with list directive", () => {
|
||||
const [relation, foreignKey] = Field.parse("belongsTo:tasks[]", schema)
|
||||
expect(relation).toMatchObject({name: "tasks", type: "Task", isList: false})
|
||||
expect(foreignKey).toMatchObject({name: "tasksId", type: "Int", isList: false})
|
||||
})
|
||||
|
||||
@@ -2,16 +2,16 @@ import {Field} from "../../src/prisma/field"
|
||||
import {Model} from "../../src/prisma/model"
|
||||
|
||||
describe("Prisma Model", () => {
|
||||
it("generates a proper model", async () => {
|
||||
it("generates a proper model", () => {
|
||||
expect(
|
||||
new Model(
|
||||
"user",
|
||||
[
|
||||
await Field.parse("email:string:unique"),
|
||||
await Field.parse("updated:dateTime:updatedAt"),
|
||||
await Field.parse("recentLogins:dateTime[]"),
|
||||
await Field.parse("twoFactorEnabled:boolean"),
|
||||
await Field.parse("twoFactorMethod:string?"),
|
||||
Field.parse("email:string:unique"),
|
||||
Field.parse("updated:dateTime:updatedAt"),
|
||||
Field.parse("recentLogins:dateTime[]"),
|
||||
Field.parse("twoFactorEnabled:boolean"),
|
||||
Field.parse("twoFactorMethod:string?"),
|
||||
].flat(),
|
||||
).toString(),
|
||||
).toMatchSnapshot()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@blitzjs/server",
|
||||
"description": "Blitz.js server functionality",
|
||||
"version": "0.45.2",
|
||||
"version": "0.45.0-canary.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest --passWithNoTests",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2"
|
||||
"@blitzjs/installer": "0.45.0-canary.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2"
|
||||
"@blitzjs/installer": "0.45.0-canary.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0",
|
||||
"uuid": "^8.3.1"
|
||||
},
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2"
|
||||
"@blitzjs/installer": "0.45.0-canary.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2"
|
||||
"@blitzjs/installer": "0.45.0-canary.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2"
|
||||
"@blitzjs/installer": "0.45.0-canary.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2"
|
||||
"@blitzjs/installer": "0.45.0-canary.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0",
|
||||
"uuid": "^8.3.1"
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"@blitzjs/installer": "0.45.2",
|
||||
"@blitzjs/installer": "0.45.0-canary.0",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user