Standardize prettier options across all Blitz code bases (#703)
Co-authored-by: Brandon Bayer <b@bayer.ws> (meta)
This commit is contained in:
38
.eslintrc.js
38
.eslintrc.js
@@ -1,38 +1,38 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
sourceType: 'module',
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
project: `./tsconfig.json`,
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'import', 'unicorn'],
|
||||
extends: ['react-app'],
|
||||
plugins: ["@typescript-eslint", "import", "unicorn"],
|
||||
extends: ["react-app"],
|
||||
rules: {
|
||||
'react/react-in-jsx-scope': 'off', // React is always in scope with Blitz
|
||||
'jsx-a11y/anchor-is-valid': 'off', //Doesn't play well with Blitz/Next <Link> usage
|
||||
'import/first': 'off',
|
||||
'import/no-default-export': 'error',
|
||||
'require-await': 'error',
|
||||
'no-async-promise-executor': 'error',
|
||||
'unicorn/filename-case': [
|
||||
'error',
|
||||
"react/react-in-jsx-scope": "off", // React is always in scope with Blitz
|
||||
"jsx-a11y/anchor-is-valid": "off", //Doesn't play well with Blitz/Next <Link> usage
|
||||
"import/first": "off",
|
||||
"import/no-default-export": "error",
|
||||
"require-await": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"unicorn/filename-case": [
|
||||
"error",
|
||||
{
|
||||
case: 'kebabCase',
|
||||
case: "kebabCase",
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
},
|
||||
ignorePatterns: ['packages/cli/', 'packages/generator/templates'],
|
||||
ignorePatterns: ["packages/cli/", "packages/generator/templates"],
|
||||
overrides: [
|
||||
{
|
||||
files: ['examples/**', 'packages/gui/**'],
|
||||
files: ["examples/**", "packages/gui/**"],
|
||||
rules: {
|
||||
'import/no-default-export': 'off',
|
||||
'unicorn/filename-case': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
"import/no-default-export": "off",
|
||||
"unicorn/filename-case": "off",
|
||||
"@typescript-eslint/no-floating-promises": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,4 +1,4 @@
|
||||
github: blitz-js
|
||||
custom: ['https://paypal.me/thebayers']
|
||||
custom: ["https://paypal.me/thebayers"]
|
||||
open_collective: blitzjs
|
||||
patreon: flybayer
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/feature_request.md
vendored
6
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: Feature/change request
|
||||
about: Something new or better!
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
title: ""
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
### What do you want and why?
|
||||
|
||||
4
.github/checkInstallTime.js
vendored
4
.github/checkInstallTime.js
vendored
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs')
|
||||
const yarnOut = fs.readFileSync(0, {encoding: 'utf8'})
|
||||
const fs = require("fs")
|
||||
const yarnOut = fs.readFileSync(0, {encoding: "utf8"})
|
||||
|
||||
const [installTimeString] = /(?<=^Done in )\d+\.\d+(?=s\.$)/m.exec(yarnOut)
|
||||
const installTime = Number(installTimeString)
|
||||
|
||||
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.16.1'
|
||||
node-version: "12.16.1"
|
||||
- name: Test Install time
|
||||
run: |
|
||||
cd ../ && mkdir test && cd test
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.16.1'
|
||||
node-version: "12.16.1"
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
const {fs} = require('memfs')
|
||||
const {fs} = require("memfs")
|
||||
|
||||
module.exports = fs
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
export default function MyApp({Component, pageProps}) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Head, Link } from "blitz"
|
||||
import {Head, Link} from "blitz"
|
||||
const modelSnippet = `model Project {
|
||||
id Int @default(autoincrement()) @id
|
||||
name String
|
||||
@@ -189,8 +189,8 @@ const Home = () => (
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Suspense } from "react"
|
||||
import { Head, Link, useRouter, useQuery } from "blitz"
|
||||
import {Suspense} from "react"
|
||||
import {Head, Link, useRouter, useQuery} from "blitz"
|
||||
import getProject from "app/projects/queries/getProject"
|
||||
import deleteProject from "app/projects/mutations/deleteProject"
|
||||
export const Project = () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Suspense } from "react"
|
||||
import { Head, Link, useRouter, useQuery } from "blitz"
|
||||
import {Suspense} from "react"
|
||||
import {Head, Link, useRouter, useQuery} from "blitz"
|
||||
import getProject from "app/projects/queries/getProject"
|
||||
import updateProject from "app/projects/mutations/updateProject"
|
||||
export const EditProject = () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Suspense } from "react"
|
||||
import { Head, Link, useQuery } from "blitz"
|
||||
import {Suspense} from "react"
|
||||
import {Head, Link, useQuery} from "blitz"
|
||||
import getProjects from "app/projects/queries/getProjects"
|
||||
|
||||
export const ProjectsList = () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Head, Link, useRouter } from "blitz"
|
||||
import {Head, Link, useRouter} from "blitz"
|
||||
import createProject from "app/projects/mutations/createProject"
|
||||
|
||||
const NewProjectPage = () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
||||
webpack: (config, {buildId, dev, isServer, defaultLoaders, webpack}) => {
|
||||
// Note: we provide webpack above so you should not `require` it
|
||||
// Perform customizations to webpack config
|
||||
// Important: return the modified config
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import {PrismaClient} from "@prisma/client"
|
||||
export * from "@prisma/client"
|
||||
|
||||
let prisma
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
],
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 110
|
||||
"printWidth": 100,
|
||||
"bracketSpacing": false,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
presets: ['next/babel'],
|
||||
presets: ["next/babel"],
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Link } from "blitz"
|
||||
import {Link} from "blitz"
|
||||
|
||||
function StoreAdminPage() {
|
||||
return (
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Suspense } from "react"
|
||||
import { Link, useRouter, useQuery, useParam } from "blitz"
|
||||
import {Suspense} from "react"
|
||||
import {Link, useRouter, useQuery, useParam} from "blitz"
|
||||
import getProduct from "app/products/queries/getProduct"
|
||||
import ProductForm from "app/products/components/ProductForm"
|
||||
|
||||
function Product() {
|
||||
const router = useRouter()
|
||||
const id = useParam("id", "number")
|
||||
const [product, { mutate }] = useQuery(getProduct, { where: { id } })
|
||||
const [product, {mutate}] = useQuery(getProduct, {where: {id}})
|
||||
|
||||
return (
|
||||
<ProductForm
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Suspense } from "react"
|
||||
import { useQuery, Link, useRouterQuery } from "blitz"
|
||||
import {Suspense} from "react"
|
||||
import {useQuery, Link, useRouterQuery} from "blitz"
|
||||
import getProducts from "app/products/queries/getProducts"
|
||||
import getProduct from "app/products/queries/getProduct"
|
||||
|
||||
function ProductsList() {
|
||||
const { orderby = "id", order = "desc" } = useRouterQuery()
|
||||
const {orderby = "id", order = "desc"} = useRouterQuery()
|
||||
|
||||
const [products] = useQuery(getProducts, {
|
||||
orderBy: {
|
||||
@@ -17,7 +17,7 @@ function ProductsList() {
|
||||
{products.map((product) => (
|
||||
<li key={product.id}>
|
||||
<Link href="/admin/products/[id]" as={`/admin/products/${product.id}`}>
|
||||
<a onMouseEnter={() => getProduct({ where: { id: product.id } })}>{product.name}</a>
|
||||
<a onMouseEnter={() => getProduct({where: {id: product.id}})}>{product.name}</a>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
@@ -35,7 +35,7 @@ function AdminProducts() {
|
||||
<a>Create Product</a>
|
||||
</Link>
|
||||
<Link href="/admin">
|
||||
<a style={{ marginLeft: 16 }}>Admin</a>
|
||||
<a style={{marginLeft: 16}}>Admin</a>
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Link, useRouter } from "blitz"
|
||||
import {Link, useRouter} from "blitz"
|
||||
import ProductForm from "app/products/components/ProductForm"
|
||||
|
||||
function AdminNewProductPage() {
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from "react"
|
||||
export default class ErrorBoundary extends React.Component<{
|
||||
fallback: (error: any) => React.ReactNode
|
||||
}> {
|
||||
state = { hasError: false, error: null }
|
||||
state = {hasError: false, error: null}
|
||||
|
||||
static getDerivedStateFromError(error: any) {
|
||||
return {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
export default function MyApp({Component, pageProps}) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Document, Html, DocumentHead, Main, BlitzScript, DocumentContext } from "@blitzjs/core"
|
||||
import {Document, Html, DocumentHead, Main, BlitzScript, DocumentContext} from "@blitzjs/core"
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx: DocumentContext) {
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
return { ...initialProps }
|
||||
return {...initialProps}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Head, Link } from "blitz"
|
||||
import {Head, Link} from "blitz"
|
||||
|
||||
const Home = () => (
|
||||
<div className="container">
|
||||
@@ -8,7 +8,7 @@ const Home = () => (
|
||||
</Head>
|
||||
|
||||
<main>
|
||||
<h1 className="title" style={{ marginBottom: 24 }}>
|
||||
<h1 className="title" style={{marginBottom: 24}}>
|
||||
Blitz Store Example
|
||||
</h1>
|
||||
<ul>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Form, Field } from "react-final-form"
|
||||
import { Product, ProductCreateInput, ProductUpdateInput } from "db"
|
||||
import {Form, Field} from "react-final-form"
|
||||
import {Product, ProductCreateInput, ProductUpdateInput} from "db"
|
||||
import createProduct from "../mutations/createProduct"
|
||||
import updateProduct from "../mutations/updateProduct"
|
||||
|
||||
@@ -15,52 +15,52 @@ type ProductFormProps = {
|
||||
onSuccess: (product: Product) => any
|
||||
}
|
||||
|
||||
function ProductForm({ product, style, onSuccess, ...props }: ProductFormProps) {
|
||||
function ProductForm({product, style, onSuccess, ...props}: ProductFormProps) {
|
||||
return (
|
||||
<Form
|
||||
initialValues={product || { name: null, handle: null, description: null, price: null }}
|
||||
initialValues={product || {name: null, handle: null, description: null, price: null}}
|
||||
onSubmit={async (data: ProductInput) => {
|
||||
if (isNew(data)) {
|
||||
try {
|
||||
const product = await createProduct({ data })
|
||||
const product = await createProduct({data})
|
||||
onSuccess(product)
|
||||
} catch (error) {
|
||||
alert("Error creating product " + JSON.stringify(error, null, 2))
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const product = await updateProduct({ where: { id: data.id }, data })
|
||||
const product = await updateProduct({where: {id: data.id}, data})
|
||||
onSuccess(product)
|
||||
} catch (error) {
|
||||
alert("Error updating product " + JSON.stringify(error, null, 2))
|
||||
}
|
||||
}
|
||||
}}
|
||||
render={({ handleSubmit }) => (
|
||||
<form onSubmit={handleSubmit} style={{ maxWidth: 400, ...style }} {...props}>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<label style={{ display: "flex", flexDirection: "column" }}>
|
||||
render={({handleSubmit}) => (
|
||||
<form onSubmit={handleSubmit} style={{maxWidth: 400, ...style}} {...props}>
|
||||
<div style={{marginBottom: 16}}>
|
||||
<label style={{display: "flex", flexDirection: "column"}}>
|
||||
Product Name
|
||||
<Field name="name" component="input" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<label style={{ display: "flex", flexDirection: "column" }}>
|
||||
<div style={{marginBottom: 16}}>
|
||||
<label style={{display: "flex", flexDirection: "column"}}>
|
||||
Handle
|
||||
<Field name="handle" component="input" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<label style={{ display: "flex", flexDirection: "column" }}>
|
||||
<div style={{marginBottom: 16}}>
|
||||
<label style={{display: "flex", flexDirection: "column"}}>
|
||||
Description
|
||||
<Field name="description" component="textarea" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<label style={{ display: "flex", flexDirection: "column" }}>
|
||||
<div style={{marginBottom: 16}}>
|
||||
<label style={{display: "flex", flexDirection: "column"}}>
|
||||
Price
|
||||
<Field
|
||||
name="price"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import db, { ProductCreateArgs } from "db"
|
||||
import db, {ProductCreateArgs} from "db"
|
||||
|
||||
type CreateProductInput = {
|
||||
data: ProductCreateArgs["data"]
|
||||
}
|
||||
export default async function createProduct({ data }: CreateProductInput) {
|
||||
const product = await db.product.create({ data })
|
||||
export default async function createProduct({data}: CreateProductInput) {
|
||||
const product = await db.product.create({data})
|
||||
|
||||
return product
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import db, { ProductDeleteArgs } from "db"
|
||||
import db, {ProductDeleteArgs} from "db"
|
||||
|
||||
type DeleteProductInput = {
|
||||
where: ProductDeleteArgs["where"]
|
||||
}
|
||||
|
||||
export default async function deleteProduct({ where }: DeleteProductInput) {
|
||||
const product = await db.product.delete({ where })
|
||||
export default async function deleteProduct({where}: DeleteProductInput) {
|
||||
const product = await db.product.delete({where})
|
||||
|
||||
return product
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import db, { ProductUpdateArgs } from "db"
|
||||
import db, {ProductUpdateArgs} from "db"
|
||||
|
||||
type UpdateProductInput = {
|
||||
where: ProductUpdateArgs["where"]
|
||||
data: ProductUpdateArgs["data"]
|
||||
}
|
||||
|
||||
export default async function updateProduct({ where, data }: UpdateProductInput) {
|
||||
export default async function updateProduct({where, data}: UpdateProductInput) {
|
||||
// Don't allow updating
|
||||
delete data.id
|
||||
|
||||
const product = await db.product.update({ where, data })
|
||||
const product = await db.product.update({where, data})
|
||||
|
||||
return product
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import { Link, BlitzPage, GetStaticProps, GetStaticPaths } from "blitz"
|
||||
import {Link, BlitzPage, GetStaticProps, GetStaticPaths} from "blitz"
|
||||
import getProduct from "app/products/queries/getProduct"
|
||||
import getProducts from "app/products/queries/getProducts"
|
||||
import { Product } from "db"
|
||||
import {Product} from "db"
|
||||
|
||||
type StaticProps = {
|
||||
product: Product
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps<StaticProps> = async (ctx) => {
|
||||
const product = await getProduct({ where: { handle: ctx.params.handle as string } })
|
||||
const product = await getProduct({where: {handle: ctx.params.handle as string}})
|
||||
|
||||
return {
|
||||
props: { product },
|
||||
props: {product},
|
||||
// Unstable beacuse revalidate is still under RFC: https://nextjs.link/issg
|
||||
unstable_revalidate: 1,
|
||||
}
|
||||
}
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
const paths = (await getProducts({ orderBy: { id: "desc" } })).map(({ handle }) => ({
|
||||
params: { handle },
|
||||
const paths = (await getProducts({orderBy: {id: "desc"}})).map(({handle}) => ({
|
||||
params: {handle},
|
||||
}))
|
||||
return {
|
||||
paths,
|
||||
@@ -26,7 +26,7 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const Page: BlitzPage<StaticProps> = function ({ product }) {
|
||||
const Page: BlitzPage<StaticProps> = function ({product}) {
|
||||
if (!product) {
|
||||
return <div>Building Page...</div>
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { Link, BlitzPage, GetStaticProps } from "blitz"
|
||||
import {Link, BlitzPage, GetStaticProps} from "blitz"
|
||||
import getProducts from "../../queries/getProducts"
|
||||
import { Product } from "db"
|
||||
import {Product} from "db"
|
||||
|
||||
type StaticProps = {
|
||||
products: Product[]
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps<StaticProps> = async () => {
|
||||
const products = await getProducts({ orderBy: { id: "desc" } })
|
||||
const products = await getProducts({orderBy: {id: "desc"}})
|
||||
|
||||
return {
|
||||
props: { products },
|
||||
props: {products},
|
||||
// Unstable because revalidate is still under RFC: https://nextjs.link/issg
|
||||
unstable_revalidate: 1,
|
||||
}
|
||||
}
|
||||
|
||||
const Page: BlitzPage<StaticProps> = function ({ products }) {
|
||||
const Page: BlitzPage<StaticProps> = function ({products}) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Products</h1>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { Suspense, Fragment } from "react"
|
||||
import { BlitzPage, useInfiniteQuery } from "blitz"
|
||||
import {Suspense, Fragment} from "react"
|
||||
import {BlitzPage, useInfiniteQuery} from "blitz"
|
||||
import getProductsInfinite from "app/products/queries/getProductsInfinite"
|
||||
|
||||
const Products = () => {
|
||||
const [
|
||||
groupedProducts,
|
||||
{ isFetching, isFetchingMore, fetchMore, canFetchMore },
|
||||
] = useInfiniteQuery(getProductsInfinite, (page = { take: 3, skip: 0 }) => page, {
|
||||
getFetchMore: (lastGroup) => lastGroup.nextPage,
|
||||
})
|
||||
const [groupedProducts, {isFetching, isFetchingMore, fetchMore, canFetchMore}] = useInfiniteQuery(
|
||||
getProductsInfinite,
|
||||
(page = {take: 3, skip: 0}) => page,
|
||||
{
|
||||
getFetchMore: (lastGroup) => lastGroup.nextPage,
|
||||
},
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Suspense, useState } from "react"
|
||||
import { Link, BlitzPage, usePaginatedQuery } from "blitz"
|
||||
import {Suspense, useState} from "react"
|
||||
import {Link, BlitzPage, usePaginatedQuery} from "blitz"
|
||||
import getProducts from "app/products/queries/getProducts"
|
||||
|
||||
const ITEMS_PER_PAGE = 3
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { ssrQuery, GetServerSideProps, Link, BlitzPage, PromiseReturnType } from "blitz"
|
||||
import {ssrQuery, GetServerSideProps, Link, BlitzPage, PromiseReturnType} from "blitz"
|
||||
import getProducts from "app/products/queries/getProducts"
|
||||
|
||||
type PageProps = {
|
||||
products: PromiseReturnType<typeof getProducts>
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<PageProps> = async ({ req, res }) => {
|
||||
const products = await ssrQuery(getProducts, { orderBy: { id: "desc" } }, { req, res })
|
||||
export const getServerSideProps: GetServerSideProps<PageProps> = async ({req, res}) => {
|
||||
const products = await ssrQuery(getProducts, {orderBy: {id: "desc"}}, {req, res})
|
||||
|
||||
return {
|
||||
props: { products },
|
||||
props: {products},
|
||||
}
|
||||
}
|
||||
|
||||
const Page: BlitzPage<PageProps> = function ({ products }) {
|
||||
const Page: BlitzPage<PageProps> = function ({products}) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Products</h1>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import db, { FindOneProductArgs } from "db"
|
||||
import db, {FindOneProductArgs} from "db"
|
||||
|
||||
type GetProductInput = {
|
||||
where: FindOneProductArgs["where"]
|
||||
@@ -6,8 +6,8 @@ type GetProductInput = {
|
||||
// include?: FindOneProductArgs['include']
|
||||
}
|
||||
|
||||
export default async function getProduct({ where }: GetProductInput) {
|
||||
const product = await db.product.findOne({ where })
|
||||
export default async function getProduct({where}: GetProductInput) {
|
||||
const product = await db.product.findOne({where})
|
||||
|
||||
return product
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Middleware } from "blitz"
|
||||
import db, { FindManyProductArgs } from "db"
|
||||
import {Middleware} from "blitz"
|
||||
import db, {FindManyProductArgs} from "db"
|
||||
|
||||
type GetProductsInput = {
|
||||
where?: FindManyProductArgs["where"]
|
||||
@@ -12,8 +12,8 @@ type GetProductsInput = {
|
||||
}
|
||||
|
||||
export default async function getProducts(
|
||||
{ where, orderBy, skip, cursor, take }: GetProductsInput,
|
||||
ctx: Record<any, unknown> = {}
|
||||
{where, orderBy, skip, cursor, take}: GetProductsInput,
|
||||
ctx: Record<any, unknown> = {},
|
||||
) {
|
||||
if (ctx.referer) {
|
||||
console.log("HTTP referer:", ctx.referer)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import db, { FindManyProductArgs } from "db"
|
||||
import db, {FindManyProductArgs} from "db"
|
||||
|
||||
type GetProductsInput = {
|
||||
where?: FindManyProductArgs["where"]
|
||||
@@ -10,7 +10,7 @@ type GetProductsInput = {
|
||||
// include?: FindManyProductArgs['include']
|
||||
}
|
||||
|
||||
export default async function getProducts({ where, orderBy, take, skip }: GetProductsInput) {
|
||||
export default async function getProducts({where, orderBy, take, skip}: GetProductsInput) {
|
||||
const products = await db.product.findMany({
|
||||
where,
|
||||
orderBy,
|
||||
@@ -20,7 +20,7 @@ export default async function getProducts({ where, orderBy, take, skip }: GetPro
|
||||
|
||||
const count = await db.product.count()
|
||||
const hasMore = skip + take < count
|
||||
const nextPage = hasMore ? { take, skip: skip + take } : null
|
||||
const nextPage = hasMore ? {take, skip: skip + take} : null
|
||||
|
||||
return {
|
||||
products,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { insert, data, fields } from "./helper"
|
||||
import {insert, data, fields} from "./helper"
|
||||
|
||||
describe("admin/products/[handle] page", () => {
|
||||
beforeEach(() => {
|
||||
@@ -22,7 +22,7 @@ describe("admin/products/[handle] page", () => {
|
||||
|
||||
const count = {}
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const { label, type } = fields[i]
|
||||
const {label, type} = fields[i]
|
||||
const [element, inputType] = type.split("|")
|
||||
let item = data[i]
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export const fields = [
|
||||
{ label: "Product Name", type: "input|", uniq: true },
|
||||
{ label: "Handle", type: "input|", uniq: true },
|
||||
{ label: "Description", type: "textarea|" },
|
||||
{ label: "Price", type: "input|" }, // TODO: Add input type here input|number
|
||||
{label: "Product Name", type: "input|", uniq: true},
|
||||
{label: "Handle", type: "input|", uniq: true},
|
||||
{label: "Description", type: "textarea|"},
|
||||
{label: "Price", type: "input|"}, // TODO: Add input type here input|number
|
||||
]
|
||||
export const data = ["Apples", "apples", "Fresh apples", "32"]
|
||||
|
||||
@@ -16,7 +16,7 @@ export const insert = (): string => {
|
||||
|
||||
const count = {}
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const { label, type, uniq } = fields[i]
|
||||
const {label, type, uniq} = fields[i]
|
||||
const [element, inputType] = type.split("|")
|
||||
let item = data[i]
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { insert } from "./helper"
|
||||
import {insert} from "./helper"
|
||||
|
||||
describe("admin/products page", () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { insert } from "./helper"
|
||||
import {insert} from "./helper"
|
||||
|
||||
describe("admin/products/new page", () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import {PrismaClient} from "@prisma/client"
|
||||
export * from "@prisma/client"
|
||||
|
||||
let prisma: PrismaClient
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 100
|
||||
"printWidth": 100,
|
||||
"bracketSpacing": false,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/cli": "2.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from "react"
|
||||
export default class ErrorBoundary extends React.Component<{
|
||||
fallback: (error: any) => React.ReactNode
|
||||
}> {
|
||||
state = { hasError: false, error: null }
|
||||
state = {hasError: false, error: null}
|
||||
|
||||
static getDerivedStateFromError(error: any) {
|
||||
return {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Link } from "blitz"
|
||||
import {Link} from "blitz"
|
||||
|
||||
const links = [
|
||||
{ href: "https://github.com/blitz-js/blitz", label: "GitHub" },
|
||||
{ href: "https://github.com/blitz-js/blitz/blob/canary/USER_GUIDE.md", label: "Docs" },
|
||||
{href: "https://github.com/blitz-js/blitz", label: "GitHub"},
|
||||
{href: "https://github.com/blitz-js/blitz/blob/canary/USER_GUIDE.md", label: "Docs"},
|
||||
]
|
||||
|
||||
export default function Nav() {
|
||||
@@ -15,7 +15,7 @@ export default function Nav() {
|
||||
</Link>
|
||||
</li>
|
||||
<ul className="flex justify-between items-center">
|
||||
{links.map(({ href, label }) => (
|
||||
{links.map(({href, label}) => (
|
||||
<li key={`${href}${label}`} className="ml-4">
|
||||
<a href={href} className="btn-blue no-underline">
|
||||
{label}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import "app/styles/index.css"
|
||||
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
export default function MyApp({Component, pageProps}) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Document, Html, DocumentHead, Main, BlitzScript /*DocumentContext*/ } from "@blitzjs/core"
|
||||
import {Document, Html, DocumentHead, Main, BlitzScript /*DocumentContext*/} from "@blitzjs/core"
|
||||
|
||||
class MyDocument extends Document {
|
||||
// Only uncomment if you need to customize this behaviour
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
||||
webpack: (config, {buildId, dev, isServer, defaultLoaders, webpack}) => {
|
||||
// Note: we provide webpack above so you should not `require` it
|
||||
// Perform customizations to webpack config
|
||||
// Important: return the modified config
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import {PrismaClient} from "@prisma/client"
|
||||
export * from "@prisma/client"
|
||||
|
||||
let prisma: PrismaClient
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
],
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 110
|
||||
"printWidth": 100,
|
||||
"bracketSpacing": false,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
require('@testing-library/jest-dom')
|
||||
require("@testing-library/jest-dom")
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import pkg from './package.json'
|
||||
import typescript from '@wessberg/rollup-plugin-ts'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import external from 'rollup-plugin-peer-deps-external'
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import json from 'rollup-plugin-json'
|
||||
import pkg from "./package.json"
|
||||
import typescript from "@wessberg/rollup-plugin-ts"
|
||||
import commonjs from "rollup-plugin-commonjs"
|
||||
import external from "rollup-plugin-peer-deps-external"
|
||||
import resolve from "rollup-plugin-node-resolve"
|
||||
import json from "rollup-plugin-json"
|
||||
|
||||
const common = {
|
||||
external: [
|
||||
...Object.keys(pkg.dependencies || {}),
|
||||
...Object.keys(pkg.peerDependencies || {}),
|
||||
'react',
|
||||
'react-dom',
|
||||
'next',
|
||||
'fs',
|
||||
'path',
|
||||
"react",
|
||||
"react-dom",
|
||||
"next",
|
||||
"fs",
|
||||
"path",
|
||||
],
|
||||
plugins: [
|
||||
json(),
|
||||
@@ -30,23 +30,23 @@ const common = {
|
||||
}
|
||||
|
||||
const lib = {
|
||||
input: './src/index.ts',
|
||||
input: "./src/index.ts",
|
||||
output: {
|
||||
file: pkg['main'],
|
||||
exports: 'named',
|
||||
sourcemap: 'true',
|
||||
format: 'cjs',
|
||||
file: pkg["main"],
|
||||
exports: "named",
|
||||
sourcemap: "true",
|
||||
format: "cjs",
|
||||
},
|
||||
...common,
|
||||
}
|
||||
|
||||
const cli = {
|
||||
input: './src/bin/cli.ts',
|
||||
input: "./src/bin/cli.ts",
|
||||
output: {
|
||||
file: './dist/cli.js',
|
||||
exports: 'named',
|
||||
sourcemap: 'true',
|
||||
format: 'cjs',
|
||||
file: "./dist/cli.js",
|
||||
exports: "named",
|
||||
sourcemap: "true",
|
||||
format: "cjs",
|
||||
},
|
||||
...common,
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from '@blitzjs/core'
|
||||
export * from "@blitzjs/core"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const isServer = typeof window === 'undefined'
|
||||
export const isServer = typeof window === "undefined"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
it.skip('todo', () => {
|
||||
it.skip("todo", () => {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['ts', 'js', 'json'],
|
||||
coverageReporters: ['json', 'lcov', 'text', 'clover'],
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
moduleFileExtensions: ["ts", "js", "json"],
|
||||
coverageReporters: ["json", "lcov", "text", "clover"],
|
||||
// collectCoverage: !!`Boolean(process.env.CI)`,
|
||||
collectCoverageFrom: ['src/**/*.ts'],
|
||||
modulePathIgnorePatterns: ['<rootDir>/tmp', '<rootDir>/lib'],
|
||||
testPathIgnorePatterns: ['src/commands/test.ts'],
|
||||
collectCoverageFrom: ["src/**/*.ts"],
|
||||
modulePathIgnorePatterns: ["<rootDir>/tmp", "<rootDir>/lib"],
|
||||
testPathIgnorePatterns: ["src/commands/test.ts"],
|
||||
testTimeout: 30000,
|
||||
// TODO enable threshold
|
||||
// coverageThreshold: {
|
||||
@@ -19,8 +19,8 @@ module.exports = {
|
||||
// },
|
||||
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsConfig: 'test/tsconfig.json',
|
||||
"ts-jest": {
|
||||
tsConfig: "test/tsconfig.json",
|
||||
isolatedModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {Hook} from '@oclif/config'
|
||||
import chalk from 'chalk'
|
||||
import {Hook} from "@oclif/config"
|
||||
import chalk from "chalk"
|
||||
|
||||
import {isBlitzRoot, IsBlitzRootError} from './utils/is-blitz-root'
|
||||
import {isBlitzRoot, IsBlitzRootError} from "./utils/is-blitz-root"
|
||||
|
||||
const whitelistGlobal = ['-h', '--help', 'help', 'new']
|
||||
const whitelistGlobal = ["-h", "--help", "help", "new"]
|
||||
|
||||
export const hook: Hook<'init'> = async function (options) {
|
||||
export const hook: Hook<"init"> = async function (options) {
|
||||
const {id} = options
|
||||
if (id && whitelistGlobal.includes(id)) return
|
||||
|
||||
@@ -16,13 +16,13 @@ export const hook: Hook<'init'> = async function (options) {
|
||||
case IsBlitzRootError.NotBlitz:
|
||||
return this.error(
|
||||
`You are not inside a Blitz project, so this command won't work.\nYou can create a new app with ${chalk.bold(
|
||||
'blitz new myapp',
|
||||
)} or see help with ${chalk.bold('blitz help')}`,
|
||||
"blitz new myapp",
|
||||
)} or see help with ${chalk.bold("blitz help")}`,
|
||||
)
|
||||
case IsBlitzRootError.NotRoot:
|
||||
const help = depth
|
||||
? `\nUse ${chalk.bold('cd ' + '../'.repeat(depth))} to get to the root of your project`
|
||||
: ''
|
||||
? `\nUse ${chalk.bold("cd " + "../".repeat(depth))} to get to the root of your project`
|
||||
: ""
|
||||
|
||||
return this.error(
|
||||
`You are currently in a sub-folder of your Blitz app, but this command must be used from the root of your project.${help}`,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Command as OclifCommand} from '@oclif/command'
|
||||
import Enquirer = require('enquirer')
|
||||
import {Command as OclifCommand} from "@oclif/command"
|
||||
import Enquirer = require("enquirer")
|
||||
|
||||
export abstract class Command extends OclifCommand {
|
||||
protected enquirer = new Enquirer()
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import {Command, flags} from '@oclif/command'
|
||||
import {build} from '@blitzjs/server'
|
||||
import {runPrismaGeneration} from './db'
|
||||
import {Command, flags} from "@oclif/command"
|
||||
import {build} from "@blitzjs/server"
|
||||
import {runPrismaGeneration} from "./db"
|
||||
|
||||
export class Build extends Command {
|
||||
static description = 'Create a production build'
|
||||
static aliases = ['b']
|
||||
static description = "Create a production build"
|
||||
static aliases = ["b"]
|
||||
|
||||
static flags = {
|
||||
port: flags.integer({
|
||||
char: 'p',
|
||||
description: 'Set port number',
|
||||
char: "p",
|
||||
description: "Set port number",
|
||||
default: 3000,
|
||||
}),
|
||||
hostname: flags.string({
|
||||
char: 'H',
|
||||
description: 'Set server hostname',
|
||||
default: 'localhost',
|
||||
char: "H",
|
||||
description: "Set server hostname",
|
||||
default: "localhost",
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
import {runRepl} from '@blitzjs/repl'
|
||||
import {Command} from '@oclif/command'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import pkgDir from 'pkg-dir'
|
||||
import {log} from '@blitzjs/display'
|
||||
import chalk from 'chalk'
|
||||
import {runRepl} from "@blitzjs/repl"
|
||||
import {Command} from "@oclif/command"
|
||||
import path from "path"
|
||||
import fs from "fs"
|
||||
import pkgDir from "pkg-dir"
|
||||
import {log} from "@blitzjs/display"
|
||||
import chalk from "chalk"
|
||||
|
||||
import {setupTsnode} from '../utils/setup-ts-node'
|
||||
import {runPrismaGeneration} from './db'
|
||||
import {setupTsnode} from "../utils/setup-ts-node"
|
||||
import {runPrismaGeneration} from "./db"
|
||||
|
||||
const projectRoot = pkgDir.sync() || process.cwd()
|
||||
const isTypescript = fs.existsSync(path.join(projectRoot, 'tsconfig.json'))
|
||||
const isTypescript = fs.existsSync(path.join(projectRoot, "tsconfig.json"))
|
||||
|
||||
export class Console extends Command {
|
||||
static description = 'Run the Blitz console REPL'
|
||||
static aliases = ['c']
|
||||
static description = "Run the Blitz console REPL"
|
||||
static aliases = ["c"]
|
||||
|
||||
static replOptions = {
|
||||
prompt: '⚡️ > ',
|
||||
prompt: "⚡️ > ",
|
||||
useColors: true,
|
||||
}
|
||||
|
||||
async run() {
|
||||
log.branded('You have entered the Blitz console')
|
||||
console.log(chalk.yellow('Tips: - Exit by typing .exit or pressing Ctrl-D'))
|
||||
console.log(chalk.yellow(' - Use your db like this: await db.project.findMany()'))
|
||||
console.log(chalk.yellow(' - Use your queries/mutations like this: await getProjects({})'))
|
||||
log.branded("You have entered the Blitz console")
|
||||
console.log(chalk.yellow("Tips: - Exit by typing .exit or pressing Ctrl-D"))
|
||||
console.log(chalk.yellow(" - Use your db like this: await db.project.findMany()"))
|
||||
console.log(chalk.yellow(" - Use your queries/mutations like this: await getProjects({})"))
|
||||
|
||||
const spinner = log.spinner('Loading your code').start()
|
||||
const spinner = log.spinner("Loading your code").start()
|
||||
if (isTypescript) {
|
||||
setupTsnode()
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {resolveBinAsync} from '@blitzjs/server'
|
||||
import {log} from '@blitzjs/display'
|
||||
import {Command, flags} from '@oclif/command'
|
||||
import chalk from 'chalk'
|
||||
import {spawn} from 'cross-spawn'
|
||||
import {prompt} from 'enquirer'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import {promisify} from 'util'
|
||||
import {projectRoot} from '../utils/get-project-root'
|
||||
import {resolveBinAsync} from "@blitzjs/server"
|
||||
import {log} from "@blitzjs/display"
|
||||
import {Command, flags} from "@oclif/command"
|
||||
import chalk from "chalk"
|
||||
import {spawn} from "cross-spawn"
|
||||
import {prompt} from "enquirer"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import {promisify} from "util"
|
||||
import {projectRoot} from "../utils/get-project-root"
|
||||
|
||||
const schemaPath = path.join(process.cwd(), 'db', 'schema.prisma')
|
||||
const schemaPath = path.join(process.cwd(), "db", "schema.prisma")
|
||||
const schemaArg = `--schema=${schemaPath}`
|
||||
const getPrismaBin = () => resolveBinAsync('@prisma/cli', 'prisma')
|
||||
const getPrismaBin = () => resolveBinAsync("@prisma/cli", "prisma")
|
||||
|
||||
// Prisma client generation will fail if no model is defined in the schema.
|
||||
// So the silent option is here to ignore that failure
|
||||
@@ -20,27 +20,32 @@ export const runPrismaGeneration = async ({silent = false} = {}) => {
|
||||
const prismaBin = await getPrismaBin()
|
||||
|
||||
return new Promise((resolve) => {
|
||||
spawn(prismaBin, ['generate', schemaArg], {stdio: silent ? 'ignore' : 'inherit'}).on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
resolve()
|
||||
} else if (silent) {
|
||||
resolve()
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
spawn(prismaBin, ["generate", schemaArg], {stdio: silent ? "ignore" : "inherit"}).on(
|
||||
"exit",
|
||||
(code) => {
|
||||
if (code === 0) {
|
||||
resolve()
|
||||
} else if (silent) {
|
||||
resolve()
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
} catch (error) {
|
||||
if (silent) return
|
||||
throw new Error("Oops, we can't find Prisma Client. Please make sure it's installed in your project")
|
||||
throw new Error(
|
||||
"Oops, we can't find Prisma Client. Please make sure it's installed in your project",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const runMigrateUp = (prismaBin: string, resolve: (value?: unknown) => void) => {
|
||||
const cp = spawn(prismaBin, ['migrate', 'up', schemaArg, '--create-db', '--experimental'], {
|
||||
stdio: 'inherit',
|
||||
const cp = spawn(prismaBin, ["migrate", "up", schemaArg, "--create-db", "--experimental"], {
|
||||
stdio: "inherit",
|
||||
})
|
||||
cp.on('exit', async (code) => {
|
||||
cp.on("exit", async (code) => {
|
||||
if (code === 0) {
|
||||
await runPrismaGeneration()
|
||||
resolve()
|
||||
@@ -53,13 +58,13 @@ const runMigrateUp = (prismaBin: string, resolve: (value?: unknown) => void) =>
|
||||
export const runMigrate = async () => {
|
||||
const prismaBin = await getPrismaBin()
|
||||
return new Promise((resolve) => {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
runMigrateUp(prismaBin, resolve)
|
||||
} else {
|
||||
const cp = spawn(prismaBin, ['migrate', 'save', schemaArg, '--create-db', '--experimental'], {
|
||||
stdio: 'inherit',
|
||||
const cp = spawn(prismaBin, ["migrate", "save", schemaArg, "--create-db", "--experimental"], {
|
||||
stdio: "inherit",
|
||||
})
|
||||
cp.on('exit', (code) => {
|
||||
cp.on("exit", (code) => {
|
||||
if (code === 0) {
|
||||
runMigrateUp(prismaBin, resolve)
|
||||
} else {
|
||||
@@ -79,13 +84,13 @@ export async function resetPostgres(connectionString: string, db: any): Promise<
|
||||
)
|
||||
// currently assuming the public schema is being used
|
||||
// delete schema and recreate with the appropriate privileges
|
||||
await db.raw('DROP SCHEMA public cascade;')
|
||||
await db.raw('CREATE SCHEMA public;')
|
||||
await db.raw('GRANT ALL ON schema public TO postgres;')
|
||||
await db.raw('GRANT ALL ON schema public TO public;')
|
||||
await db.raw("DROP SCHEMA public cascade;")
|
||||
await db.raw("CREATE SCHEMA public;")
|
||||
await db.raw("GRANT ALL ON schema public TO postgres;")
|
||||
await db.raw("GRANT ALL ON schema public TO public;")
|
||||
// run migration
|
||||
await runMigrate()
|
||||
log.success('Your database has been reset.')
|
||||
log.success("Your database has been reset.")
|
||||
process.exit(0)
|
||||
} catch (err) {
|
||||
log.error(`Resetting the database has failed with an error from the database: `)
|
||||
@@ -101,7 +106,7 @@ export async function resetMysql(connectionString: string, db: any): Promise<voi
|
||||
await db.raw(`DROP DATABASE \`${dbName}\``)
|
||||
// run migration
|
||||
await runMigrate()
|
||||
log.success('Your database has been reset.')
|
||||
log.success("Your database has been reset.")
|
||||
process.exit(0)
|
||||
} catch (err) {
|
||||
log.error(`Resetting the database has failed with an error from the database: `)
|
||||
@@ -111,14 +116,14 @@ export async function resetMysql(connectionString: string, db: any): Promise<voi
|
||||
}
|
||||
|
||||
export async function resetSqlite(connectionString: string): Promise<void> {
|
||||
const dbPath: string = connectionString.replace(/^(?:\.\.[\\/])+/, '')
|
||||
const dbPath: string = connectionString.replace(/^(?:\.\.[\\/])+/, "")
|
||||
const unlink = promisify(fs.unlink)
|
||||
try {
|
||||
// delete database from folder
|
||||
await unlink(dbPath)
|
||||
// run migration
|
||||
await runMigrate()
|
||||
log.success('Your database has been reset.')
|
||||
log.success("Your database has been reset.")
|
||||
process.exit(0)
|
||||
} catch (err) {
|
||||
log.error(`Resetting the database has failed with an error from the file system: `)
|
||||
@@ -128,7 +133,7 @@ export async function resetSqlite(connectionString: string): Promise<void> {
|
||||
}
|
||||
|
||||
export function getDbName(connectionString: string): string {
|
||||
const dbUrlParts: string[] = connectionString!.split('/')
|
||||
const dbUrlParts: string[] = connectionString!.split("/")
|
||||
const dbName: string = dbUrlParts[dbUrlParts.length - 1]
|
||||
return dbName
|
||||
}
|
||||
@@ -136,97 +141,100 @@ export function getDbName(connectionString: string): string {
|
||||
export class Db extends Command {
|
||||
static description = `Run database commands
|
||||
|
||||
${chalk.bold('migrate')} Run any needed migrations via Prisma 2 and generate Prisma Client.
|
||||
${chalk.bold("migrate")} Run any needed migrations via Prisma 2 and generate Prisma Client.
|
||||
|
||||
${chalk.bold(
|
||||
'introspect',
|
||||
"introspect",
|
||||
)} Will introspect the database defined in db/schema.prisma and automatically generate a complete schema.prisma file for you. Lastly, it'll generate Prisma Client.
|
||||
|
||||
${chalk.bold(
|
||||
'studio',
|
||||
"studio",
|
||||
)} Open the Prisma Studio UI at http://localhost:5555 so you can easily see and change data in your database.
|
||||
|
||||
${chalk.bold('reset')} Reset the database and run a fresh migration via Prisma 2.
|
||||
${chalk.bold("reset")} Reset the database and run a fresh migration via Prisma 2.
|
||||
`
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: 'command',
|
||||
description: 'Run specific db command',
|
||||
name: "command",
|
||||
description: "Run specific db command",
|
||||
required: true,
|
||||
},
|
||||
]
|
||||
|
||||
static flags = {
|
||||
help: flags.help({char: 'h'}),
|
||||
help: flags.help({char: "h"}),
|
||||
}
|
||||
|
||||
async run() {
|
||||
const {args} = this.parse(Db)
|
||||
const command = args['command']
|
||||
const command = args["command"]
|
||||
|
||||
const prismaBin = await getPrismaBin()
|
||||
|
||||
if (command === 'migrate' || command === 'm') {
|
||||
if (command === "migrate" || command === "m") {
|
||||
await runMigrate()
|
||||
} else if (command === 'introspect') {
|
||||
const cp = spawn(prismaBin, ['introspect', schemaArg], {
|
||||
stdio: 'inherit',
|
||||
} else if (command === "introspect") {
|
||||
const cp = spawn(prismaBin, ["introspect", schemaArg], {
|
||||
stdio: "inherit",
|
||||
})
|
||||
cp.on('exit', (code) => {
|
||||
cp.on("exit", (code) => {
|
||||
if (code === 0) {
|
||||
spawn(prismaBin, ['generate', schemaArg], {stdio: 'inherit'}).on('exit', (code: number) => {
|
||||
if (code !== 0) {
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
spawn(prismaBin, ["generate", schemaArg], {stdio: "inherit"}).on(
|
||||
"exit",
|
||||
(code: number) => {
|
||||
if (code !== 0) {
|
||||
process.exit(1)
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
} else if (command === 'studio') {
|
||||
const cp = spawn(prismaBin, ['studio', schemaArg, '--experimental'], {
|
||||
stdio: 'inherit',
|
||||
} else if (command === "studio") {
|
||||
const cp = spawn(prismaBin, ["studio", schemaArg, "--experimental"], {
|
||||
stdio: "inherit",
|
||||
})
|
||||
cp.on('exit', (code) => {
|
||||
cp.on("exit", (code) => {
|
||||
if (code === 0) {
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
} else if (command === 'reset') {
|
||||
const spinner = log.spinner('Loading your database').start()
|
||||
} else if (command === "reset") {
|
||||
const spinner = log.spinner("Loading your database").start()
|
||||
await runPrismaGeneration({silent: true})
|
||||
spinner.succeed()
|
||||
await prompt<{confirm: string}>({
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: 'Are you sure you want to reset your database and erase ALL data?',
|
||||
type: "confirm",
|
||||
name: "confirm",
|
||||
message: "Are you sure you want to reset your database and erase ALL data?",
|
||||
}).then((res) => {
|
||||
if (res.confirm) {
|
||||
const prismaClientPath = require.resolve('@prisma/client', {paths: [projectRoot]})
|
||||
const prismaClientPath = require.resolve("@prisma/client", {paths: [projectRoot]})
|
||||
const {PrismaClient} = require(prismaClientPath)
|
||||
const db = new PrismaClient()
|
||||
const dataSource: any = db.internalDatasources[0]
|
||||
const connectorType: string = dataSource.connectorType
|
||||
const connectionString: string = dataSource.url.value
|
||||
if (connectorType === 'postgresql') {
|
||||
if (connectorType === "postgresql") {
|
||||
resetPostgres(connectionString, db)
|
||||
} else if (connectorType === 'mysql') {
|
||||
} else if (connectorType === "mysql") {
|
||||
resetMysql(connectionString, db)
|
||||
} else if (connectorType === 'sqlite') {
|
||||
} else if (connectorType === "sqlite") {
|
||||
resetSqlite(connectionString)
|
||||
} else {
|
||||
this.log('Could not find a valid database configuration')
|
||||
this.log("Could not find a valid database configuration")
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.log('\nUh oh, Blitz does not support that command.')
|
||||
this.log('You can try running a prisma command directly with:')
|
||||
this.log('\n `npm run prisma COMMAND` or `yarn prisma COMMAND`\n')
|
||||
this.log('Or you can list available db commands with with:')
|
||||
this.log('\n `npm run blitz db --help` or `yarn blitz db --help`\n')
|
||||
this.log("\nUh oh, Blitz does not support that command.")
|
||||
this.log("You can try running a prisma command directly with:")
|
||||
this.log("\n `npm run prisma COMMAND` or `yarn prisma COMMAND`\n")
|
||||
this.log("Or you can list available db commands with with:")
|
||||
this.log("\n `npm run blitz db --help` or `yarn blitz db --help`\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
import {Command} from '../command'
|
||||
import {flags} from '@oclif/command'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import enquirer from 'enquirer'
|
||||
import _pluralize from 'pluralize'
|
||||
import {Command} from "../command"
|
||||
import {flags} from "@oclif/command"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import enquirer from "enquirer"
|
||||
import _pluralize from "pluralize"
|
||||
import {
|
||||
PageGenerator,
|
||||
MutationGenerator,
|
||||
QueryGenerator,
|
||||
FormGenerator,
|
||||
ModelGenerator,
|
||||
} from '@blitzjs/generator'
|
||||
import {PromptAbortedError} from '../errors/prompt-aborted'
|
||||
import {log} from '@blitzjs/display'
|
||||
import camelCase from 'camelcase'
|
||||
import pkgDir from 'pkg-dir'
|
||||
const debug = require('debug')('blitz:generate')
|
||||
} from "@blitzjs/generator"
|
||||
import {PromptAbortedError} from "../errors/prompt-aborted"
|
||||
import {log} from "@blitzjs/display"
|
||||
import camelCase from "camelcase"
|
||||
import pkgDir from "pkg-dir"
|
||||
const debug = require("debug")("blitz:generate")
|
||||
|
||||
const pascalCase = (str: string) => camelCase(str, {pascalCase: true})
|
||||
|
||||
const projectRoot = pkgDir.sync() || process.cwd()
|
||||
const isTypescript = fs.existsSync(path.join(projectRoot, 'tsconfig.json'))
|
||||
const isTypescript = fs.existsSync(path.join(projectRoot, "tsconfig.json"))
|
||||
|
||||
enum ResourceType {
|
||||
All = 'all',
|
||||
Crud = 'crud',
|
||||
Model = 'model',
|
||||
Mutations = 'mutations',
|
||||
Pages = 'pages',
|
||||
Queries = 'queries',
|
||||
Resource = 'resource',
|
||||
All = "all",
|
||||
Crud = "crud",
|
||||
Model = "model",
|
||||
Mutations = "mutations",
|
||||
Pages = "pages",
|
||||
Queries = "queries",
|
||||
Resource = "resource",
|
||||
}
|
||||
|
||||
interface Flags {
|
||||
context?: string
|
||||
'dry-run'?: boolean
|
||||
"dry-run"?: boolean
|
||||
parent?: string
|
||||
}
|
||||
|
||||
@@ -51,21 +51,27 @@ function singular(input: string): string {
|
||||
return _pluralize.isSingular(input) ? input : _pluralize.singular(input)
|
||||
}
|
||||
|
||||
function modelName(input: string = '') {
|
||||
function modelName(input: string = "") {
|
||||
return camelCase(singular(input))
|
||||
}
|
||||
function modelNames(input: string = '') {
|
||||
function modelNames(input: string = "") {
|
||||
return camelCase(pluralize(input))
|
||||
}
|
||||
function ModelName(input: string = '') {
|
||||
function ModelName(input: string = "") {
|
||||
return pascalCase(singular(input))
|
||||
}
|
||||
function ModelNames(input: string = '') {
|
||||
function ModelNames(input: string = "") {
|
||||
return pascalCase(pluralize(input))
|
||||
}
|
||||
|
||||
const generatorMap = {
|
||||
[ResourceType.All]: [ModelGenerator, PageGenerator, FormGenerator, QueryGenerator, MutationGenerator],
|
||||
[ResourceType.All]: [
|
||||
ModelGenerator,
|
||||
PageGenerator,
|
||||
FormGenerator,
|
||||
QueryGenerator,
|
||||
MutationGenerator,
|
||||
],
|
||||
[ResourceType.Crud]: [MutationGenerator, QueryGenerator],
|
||||
[ResourceType.Model]: [ModelGenerator],
|
||||
[ResourceType.Mutations]: [MutationGenerator],
|
||||
@@ -75,38 +81,38 @@ const generatorMap = {
|
||||
}
|
||||
|
||||
export class Generate extends Command {
|
||||
static description = 'Generate new files for your Blitz project'
|
||||
static aliases = ['g']
|
||||
static description = "Generate new files for your Blitz project"
|
||||
static aliases = ["g"]
|
||||
static strict = false
|
||||
static args = [
|
||||
{
|
||||
name: 'type',
|
||||
name: "type",
|
||||
required: true,
|
||||
description: 'What files to generate',
|
||||
description: "What files to generate",
|
||||
options: Object.keys(generatorMap).map((s) => s.toLowerCase()),
|
||||
},
|
||||
{
|
||||
name: 'model',
|
||||
name: "model",
|
||||
required: true,
|
||||
description: 'The name of your model, like "user". Can be singular or plural - same result',
|
||||
},
|
||||
]
|
||||
|
||||
static flags = {
|
||||
help: flags.help({char: 'h'}),
|
||||
help: flags.help({char: "h"}),
|
||||
context: flags.string({
|
||||
char: 'c',
|
||||
char: "c",
|
||||
description:
|
||||
"Provide a context folder within which we'll place the generated files for better code organization. You can also supply this in the name of the model to be generated (e.g. `blitz generate query admin/projects`). Combining the `--context` flags and supplying context via the model name in the same command is not supported.",
|
||||
}),
|
||||
parent: flags.string({
|
||||
char: 'p',
|
||||
char: "p",
|
||||
description:
|
||||
"Specify a parent model to be used for generating nested routes for dependent data when generating pages, or to create hierarchical validation in queries and mutations. The code will be generated with the nested data model in mind. Most often this should be used in conjunction with 'blitz generate all'",
|
||||
}),
|
||||
'dry-run': flags.boolean({
|
||||
char: 'd',
|
||||
description: 'Show what files will be created without writing them to disk',
|
||||
"dry-run": flags.boolean({
|
||||
char: "d",
|
||||
description: "Show what files will be created without writing them to disk",
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -146,9 +152,9 @@ export class Generate extends Command {
|
||||
async promptForTargetDirectory(paths: string[]): Promise<string> {
|
||||
return enquirer
|
||||
.prompt<{directory: string}>({
|
||||
name: 'directory',
|
||||
type: 'select',
|
||||
message: 'Please select a target directory:',
|
||||
name: "directory",
|
||||
type: "select",
|
||||
message: "Please select a target directory:",
|
||||
choices: paths,
|
||||
})
|
||||
.then((resp) => resp.directory)
|
||||
@@ -157,18 +163,18 @@ export class Generate extends Command {
|
||||
async genericConfirmPrompt(message: string): Promise<boolean> {
|
||||
return enquirer
|
||||
.prompt<{continue: string}>({
|
||||
name: 'continue',
|
||||
type: 'select',
|
||||
name: "continue",
|
||||
type: "select",
|
||||
message: message,
|
||||
choices: ['Yes', 'No'],
|
||||
choices: ["Yes", "No"],
|
||||
})
|
||||
.then((resp) => resp.continue === 'Yes')
|
||||
.then((resp) => resp.continue === "Yes")
|
||||
}
|
||||
|
||||
async handleNoContext(message: string): Promise<void> {
|
||||
const shouldCreateNewRoot = await this.genericConfirmPrompt(message)
|
||||
if (!shouldCreateNewRoot) {
|
||||
log.error('Could not determine proper location for files. Aborting.')
|
||||
log.error("Could not determine proper location for files. Aborting.")
|
||||
this.exit(0)
|
||||
}
|
||||
}
|
||||
@@ -199,8 +205,8 @@ export class Generate extends Command {
|
||||
|
||||
async run() {
|
||||
const {args, argv, flags}: {args: Args; argv: string[]; flags: Flags} = this.parse(Generate)
|
||||
debug('args: ', args)
|
||||
debug('flags: ', flags)
|
||||
debug("args: ", args)
|
||||
debug("flags: ", flags)
|
||||
|
||||
try {
|
||||
const {model, context} = this.getModelNameAndContext(args.model, flags.context)
|
||||
@@ -210,7 +216,7 @@ export class Generate extends Command {
|
||||
for (const GeneratorClass of generators) {
|
||||
const generator = new GeneratorClass({
|
||||
destinationRoot: path.resolve(),
|
||||
extraArgs: argv.slice(2).filter((arg) => !arg.startsWith('-')),
|
||||
extraArgs: argv.slice(2).filter((arg) => !arg.startsWith("-")),
|
||||
modelName: singularRootContext,
|
||||
modelNames: modelNames(singularRootContext),
|
||||
ModelName: ModelName(singularRootContext),
|
||||
@@ -219,14 +225,14 @@ export class Generate extends Command {
|
||||
parentModels: modelNames(flags.parent),
|
||||
ParentModel: ModelName(flags.parent),
|
||||
ParentModels: ModelNames(flags.parent),
|
||||
dryRun: flags['dry-run'],
|
||||
dryRun: flags["dry-run"],
|
||||
context: context,
|
||||
useTs: isTypescript,
|
||||
})
|
||||
await generator.run()
|
||||
}
|
||||
|
||||
console.log(' ') // new line
|
||||
console.log(" ") // new line
|
||||
} catch (err) {
|
||||
if (err instanceof PromptAbortedError) this.exit(0)
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {Command, flags} from '@oclif/command'
|
||||
import {Command, flags} from "@oclif/command"
|
||||
|
||||
import Help from '@oclif/plugin-help'
|
||||
import Help from "@oclif/plugin-help"
|
||||
|
||||
export class HelpCommand extends Command {
|
||||
static description = 'display help for <%= config.bin %>'
|
||||
static description = "display help for <%= config.bin %>"
|
||||
|
||||
static aliases = ['h']
|
||||
static aliases = ["h"]
|
||||
|
||||
static flags = {
|
||||
all: flags.boolean({description: 'see all commands in CLI'}),
|
||||
all: flags.boolean({description: "see all commands in CLI"}),
|
||||
}
|
||||
|
||||
static args = [{name: 'command', required: false, description: 'command to show help for'}]
|
||||
static args = [{name: "command", required: false, description: "command to show help for"}]
|
||||
|
||||
static strict = false
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import {Command} from '../command'
|
||||
import * as path from 'path'
|
||||
import {Installer} from '@blitzjs/installer'
|
||||
import _got from 'got'
|
||||
import {log} from '@blitzjs/display'
|
||||
import {dedent} from '../utils/dedent'
|
||||
import {Stream} from 'stream'
|
||||
import {promisify} from 'util'
|
||||
import tar from 'tar'
|
||||
import {mkdirSync, readFileSync, existsSync} from 'fs-extra'
|
||||
import rimraf from 'rimraf'
|
||||
import spawn from 'cross-spawn'
|
||||
import * as os from 'os'
|
||||
import {Command} from "../command"
|
||||
import * as path from "path"
|
||||
import {Installer} from "@blitzjs/installer"
|
||||
import _got from "got"
|
||||
import {log} from "@blitzjs/display"
|
||||
import {dedent} from "../utils/dedent"
|
||||
import {Stream} from "stream"
|
||||
import {promisify} from "util"
|
||||
import tar from "tar"
|
||||
import {mkdirSync, readFileSync, existsSync} from "fs-extra"
|
||||
import rimraf from "rimraf"
|
||||
import spawn from "cross-spawn"
|
||||
import * as os from "os"
|
||||
|
||||
const pipeline = promisify(Stream.pipeline)
|
||||
|
||||
@@ -27,12 +27,12 @@ async function isUrlValid(url: string) {
|
||||
}
|
||||
|
||||
function requireJSON(file: string) {
|
||||
return JSON.parse(readFileSync(file).toString('utf-8'))
|
||||
return JSON.parse(readFileSync(file).toString("utf-8"))
|
||||
}
|
||||
|
||||
const GH_ROOT = 'https://github.com/'
|
||||
const API_ROOT = 'https://api.github.com/repos/'
|
||||
const CODE_ROOT = 'https://codeload.github.com/'
|
||||
const GH_ROOT = "https://github.com/"
|
||||
const API_ROOT = "https://api.github.com/repos/"
|
||||
const CODE_ROOT = "https://codeload.github.com/"
|
||||
|
||||
export enum RecipeLocation {
|
||||
Local,
|
||||
@@ -46,21 +46,22 @@ interface RecipeMeta {
|
||||
}
|
||||
|
||||
export class Install extends Command {
|
||||
static description = 'Install a third-party package into your Blitz app'
|
||||
static aliases = ['i']
|
||||
static description = "Install a third-party package into your Blitz app"
|
||||
static aliases = ["i"]
|
||||
static strict = false
|
||||
static hidden = true
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: 'recipe',
|
||||
name: "recipe",
|
||||
required: true,
|
||||
description:
|
||||
'Name of a Blitz recipe from @blitzjs/blitz/recipes, or a file path to a local recipe definition',
|
||||
"Name of a Blitz recipe from @blitzjs/blitz/recipes, or a file path to a local recipe definition",
|
||||
},
|
||||
{
|
||||
name: 'recipe-flags',
|
||||
description: 'A list of flags to pass to the recipe. Blitz will only parse these in the form key=value',
|
||||
name: "recipe-flags",
|
||||
description:
|
||||
"A list of flags to pass to the recipe. Blitz will only parse these in the form key=value",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -84,7 +85,9 @@ export class Install extends Command {
|
||||
repoUrl = `${GH_ROOT}${recipeArg}`
|
||||
break
|
||||
default:
|
||||
throw new Error('should be impossible, the 3 cases are the only way to get into this switch')
|
||||
throw new Error(
|
||||
"should be impossible, the 3 cases are the only way to get into this switch",
|
||||
)
|
||||
}
|
||||
return {
|
||||
path: repoUrl,
|
||||
@@ -107,18 +110,22 @@ export class Install extends Command {
|
||||
* @param repoFullName username and repository name in the form {{user}}/{{repo}}
|
||||
* @param defaultBranch the name of the repository's default branch
|
||||
*/
|
||||
async cloneRepo(repoFullName: string, defaultBranch: string, subdirectory?: string): Promise<string> {
|
||||
const recipeDir = path.join(os.tmpdir(), `blitz-recipe-${repoFullName.replace('/', '-')}`)
|
||||
async cloneRepo(
|
||||
repoFullName: string,
|
||||
defaultBranch: string,
|
||||
subdirectory?: string,
|
||||
): Promise<string> {
|
||||
const recipeDir = path.join(os.tmpdir(), `blitz-recipe-${repoFullName.replace("/", "-")}`)
|
||||
// clean up from previous run in case of error
|
||||
rimraf.sync(recipeDir)
|
||||
mkdirSync(recipeDir)
|
||||
process.chdir(recipeDir)
|
||||
|
||||
const repoName = repoFullName.split('/')[1]
|
||||
const repoName = repoFullName.split("/")[1]
|
||||
// `tar` top-level filder is `${repoName}-${defaultBranch}`, and then we want to get our recipe path
|
||||
// within that folder
|
||||
const extractPath = subdirectory ? [`${repoName}-${defaultBranch}/${subdirectory}`] : undefined
|
||||
const depth = subdirectory ? subdirectory.split('/').length + 1 : 1
|
||||
const depth = subdirectory ? subdirectory.split("/").length + 1 : 1
|
||||
await pipeline(
|
||||
_got.stream(`${CODE_ROOT}${repoFullName}/tar.gz/${defaultBranch}`),
|
||||
tar.extract({strip: depth}, extractPath),
|
||||
@@ -132,8 +139,8 @@ export class Install extends Command {
|
||||
const recipeArgs = this.argv.slice(1).reduce(
|
||||
(acc, arg) => ({
|
||||
...acc,
|
||||
[arg.split('=')[0].replace(/--/g, '')]: arg.split('=')[1]
|
||||
? JSON.parse(`"${arg.split('=')[1]}"`)
|
||||
[arg.split("=")[0].replace(/--/g, "")]: arg.split("=")[1]
|
||||
? JSON.parse(`"${arg.split("=")[1]}"`)
|
||||
: true, // if no value is provided, assume it's a boolean flag
|
||||
}),
|
||||
{},
|
||||
@@ -143,7 +150,7 @@ export class Install extends Command {
|
||||
|
||||
async run() {
|
||||
const {args} = this.parse(Install)
|
||||
const pkgManager = existsSync(path.resolve('yarn.lock')) ? 'yarn' : 'npm'
|
||||
const pkgManager = existsSync(path.resolve("yarn.lock")) ? "yarn" : "npm"
|
||||
const originalCwd = process.cwd()
|
||||
const recipeInfo = this.normalizeRecipePath(args.recipe)
|
||||
|
||||
@@ -168,14 +175,14 @@ export class Install extends Command {
|
||||
)
|
||||
spinner.stop()
|
||||
|
||||
spinner = log.spinner('Installing package.json dependencies').start()
|
||||
spinner = log.spinner("Installing package.json dependencies").start()
|
||||
await new Promise((resolve) => {
|
||||
const installProcess = spawn(pkgManager, ['install'])
|
||||
installProcess.on('exit', resolve)
|
||||
const installProcess = spawn(pkgManager, ["install"])
|
||||
installProcess.on("exit", resolve)
|
||||
})
|
||||
spinner.stop()
|
||||
|
||||
const recipePackageMain = requireJSON('./package.json').main
|
||||
const recipePackageMain = requireJSON("./package.json").main
|
||||
const recipeEntry = path.resolve(recipePackageMain)
|
||||
process.chdir(originalCwd)
|
||||
|
||||
|
||||
@@ -1,56 +1,58 @@
|
||||
import * as path from 'path'
|
||||
import {flags} from '@oclif/command'
|
||||
import {Command} from '../command'
|
||||
import {AppGenerator} from '@blitzjs/generator'
|
||||
import chalk from 'chalk'
|
||||
import hasbin from 'hasbin'
|
||||
import {log} from '@blitzjs/display'
|
||||
const debug = require('debug')('blitz:new')
|
||||
import * as path from "path"
|
||||
import {flags} from "@oclif/command"
|
||||
import {Command} from "../command"
|
||||
import {AppGenerator} from "@blitzjs/generator"
|
||||
import chalk from "chalk"
|
||||
import hasbin from "hasbin"
|
||||
import {log} from "@blitzjs/display"
|
||||
const debug = require("debug")("blitz:new")
|
||||
|
||||
import {PromptAbortedError} from '../errors/prompt-aborted'
|
||||
import {PromptAbortedError} from "../errors/prompt-aborted"
|
||||
|
||||
export interface Flags {
|
||||
ts: boolean
|
||||
yarn: boolean
|
||||
'skip-install': boolean
|
||||
"skip-install": boolean
|
||||
}
|
||||
|
||||
export class New extends Command {
|
||||
static description = 'Create a new Blitz project'
|
||||
static description = "Create a new Blitz project"
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
name: "name",
|
||||
required: true,
|
||||
description: 'name of your new project',
|
||||
description: "name of your new project",
|
||||
},
|
||||
]
|
||||
|
||||
static flags = {
|
||||
help: flags.help({char: 'h'}),
|
||||
help: flags.help({char: "h"}),
|
||||
js: flags.boolean({
|
||||
description: 'Generates a JS project. TypeScript is the default unless you add this flag.',
|
||||
description: "Generates a JS project. TypeScript is the default unless you add this flag.",
|
||||
default: false,
|
||||
hidden: true,
|
||||
}),
|
||||
npm: flags.boolean({
|
||||
description: 'Use npm as the package manager. Yarn is the default if installed',
|
||||
default: !hasbin.sync('yarn'),
|
||||
description: "Use npm as the package manager. Yarn is the default if installed",
|
||||
default: !hasbin.sync("yarn"),
|
||||
allowNo: true,
|
||||
}),
|
||||
'skip-install': flags.boolean({
|
||||
description: 'Skip package installation',
|
||||
"skip-install": flags.boolean({
|
||||
description: "Skip package installation",
|
||||
hidden: true,
|
||||
default: false,
|
||||
allowNo: true,
|
||||
}),
|
||||
'dry-run': flags.boolean({description: 'show what files will be created without writing them to disk'}),
|
||||
"dry-run": flags.boolean({
|
||||
description: "show what files will be created without writing them to disk",
|
||||
}),
|
||||
}
|
||||
|
||||
async run() {
|
||||
const {args, flags} = this.parse(New)
|
||||
debug('args: ', args)
|
||||
debug('flags: ', flags)
|
||||
debug("args: ", args)
|
||||
debug("flags: ", flags)
|
||||
|
||||
const destinationRoot = path.resolve(args.name)
|
||||
const appName = path.basename(destinationRoot)
|
||||
@@ -58,17 +60,17 @@ export class New extends Command {
|
||||
const generator = new AppGenerator({
|
||||
destinationRoot,
|
||||
appName,
|
||||
dryRun: flags['dry-run'],
|
||||
dryRun: flags["dry-run"],
|
||||
useTs: !flags.js,
|
||||
yarn: !flags.npm,
|
||||
version: this.config.version,
|
||||
skipInstall: flags['skip-install'],
|
||||
skipInstall: flags["skip-install"],
|
||||
})
|
||||
|
||||
try {
|
||||
this.log('\n' + log.withBrand('Hang tight while we set up your new Blitz app!') + '\n')
|
||||
this.log("\n" + log.withBrand("Hang tight while we set up your new Blitz app!") + "\n")
|
||||
await generator.run()
|
||||
this.log('\n' + log.withBrand('Your new Blitz app is ready! Next steps:') + '\n')
|
||||
this.log("\n" + log.withBrand("Your new Blitz app is ready! Next steps:") + "\n")
|
||||
this.log(chalk.yellow(` 1. cd ${args.name}`))
|
||||
this.log(chalk.yellow(` 2. blitz start`))
|
||||
this.log(chalk.yellow(` 3. You create new pages by placing components inside app/pages/\n`))
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import {Command, flags} from '@oclif/command'
|
||||
import {dev, prod} from '@blitzjs/server'
|
||||
import {Command, flags} from "@oclif/command"
|
||||
import {dev, prod} from "@blitzjs/server"
|
||||
|
||||
import {runPrismaGeneration} from './db'
|
||||
import {runPrismaGeneration} from "./db"
|
||||
|
||||
export class Start extends Command {
|
||||
static description = 'Start a development server'
|
||||
static aliases = ['s']
|
||||
static description = "Start a development server"
|
||||
static aliases = ["s"]
|
||||
|
||||
static flags = {
|
||||
production: flags.boolean({
|
||||
description: 'Create and start a production server',
|
||||
description: "Create and start a production server",
|
||||
}),
|
||||
port: flags.integer({
|
||||
char: 'p',
|
||||
description: 'Set port number',
|
||||
char: "p",
|
||||
description: "Set port number",
|
||||
default: 3000,
|
||||
}),
|
||||
hostname: flags.string({
|
||||
char: 'H',
|
||||
description: 'Set server hostname',
|
||||
default: 'localhost',
|
||||
char: "H",
|
||||
description: "Set server hostname",
|
||||
default: "localhost",
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import {spawn} from 'cross-spawn'
|
||||
import {Command} from '@oclif/command'
|
||||
import hasYarn from 'has-yarn'
|
||||
import {spawn} from "cross-spawn"
|
||||
import {Command} from "@oclif/command"
|
||||
import hasYarn from "has-yarn"
|
||||
|
||||
export class Test extends Command {
|
||||
static description = 'Run project tests'
|
||||
static aliases = ['t']
|
||||
static description = "Run project tests"
|
||||
static aliases = ["t"]
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: 'watch',
|
||||
description: 'Run test:watch',
|
||||
name: "watch",
|
||||
description: "Run test:watch",
|
||||
},
|
||||
]
|
||||
|
||||
async run() {
|
||||
const {args} = this.parse(Test)
|
||||
let watchMode: boolean = false
|
||||
const watch = args['watch']
|
||||
const watch = args["watch"]
|
||||
if (watch) {
|
||||
watchMode = watch === 'watch' || watch === 'w'
|
||||
watchMode = watch === "watch" || watch === "w"
|
||||
}
|
||||
const packageManager = hasYarn() ? 'yarn' : 'npm'
|
||||
const packageManager = hasYarn() ? "yarn" : "npm"
|
||||
|
||||
if (watchMode) spawn(packageManager, ['test:watch'], {stdio: 'inherit'})
|
||||
else spawn(packageManager, ['test'], {stdio: 'inherit'})
|
||||
if (watchMode) spawn(packageManager, ["test:watch"], {stdio: "inherit"})
|
||||
else spawn(packageManager, ["test"], {stdio: "inherit"})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export class PromptAbortedError extends Error {
|
||||
constructor() {
|
||||
super('Prompt aborted')
|
||||
super("Prompt aborted")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {run as oclifRun} from '@oclif/command'
|
||||
import {run as oclifRun} from "@oclif/command"
|
||||
|
||||
// Load the .env environment variable so it's available for all commands
|
||||
require('dotenv').config()
|
||||
require("dotenv").config()
|
||||
|
||||
export function run() {
|
||||
oclifRun()
|
||||
.then(require('@oclif/command/flush'))
|
||||
.then(require("@oclif/command/flush"))
|
||||
// @ts-ignore (TS complains about using `catch`)
|
||||
.catch(require('@oclif/errors/handle'))
|
||||
.catch(require("@oclif/errors/handle"))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export function dedent(strings: TemplateStringsArray, ...args: any[]) {
|
||||
return strings
|
||||
.map((str, idx) => str + String(args[idx] || ''))
|
||||
.join('')
|
||||
.split('\n')
|
||||
.map((str, idx) => str + String(args[idx] || ""))
|
||||
.join("")
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.join('\n')
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import pkgDir from 'pkg-dir'
|
||||
import pkgDir from "pkg-dir"
|
||||
|
||||
export const projectRoot = pkgDir.sync() || process.cwd()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {readJSON} from 'fs-extra'
|
||||
import pkgDir from 'pkg-dir'
|
||||
import {resolve} from 'path'
|
||||
import {readJSON} from "fs-extra"
|
||||
import pkgDir from "pkg-dir"
|
||||
import {resolve} from "path"
|
||||
|
||||
export enum IsBlitzRootError {
|
||||
NotBlitz,
|
||||
@@ -9,13 +9,13 @@ export enum IsBlitzRootError {
|
||||
}
|
||||
|
||||
const checkParent = async (): Promise<false | number> => {
|
||||
const rootDir = await pkgDir('./')
|
||||
const rootDir = await pkgDir("./")
|
||||
|
||||
if (rootDir) {
|
||||
const file = await readJSON(resolve(rootDir, 'package.json'))
|
||||
const file = await readJSON(resolve(rootDir, "package.json"))
|
||||
|
||||
if (file && Object.keys(file.dependencies || {}).includes('blitz')) {
|
||||
return process.cwd().slice(rootDir.length).split('/').length - 1
|
||||
if (file && Object.keys(file.dependencies || {}).includes("blitz")) {
|
||||
return process.cwd().slice(rootDir.length).split("/").length - 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,11 +31,15 @@ const checkParent = async (): Promise<false | number> => {
|
||||
* badPackageJson -> an error occurred while reading local package.json
|
||||
*/
|
||||
|
||||
export const isBlitzRoot = async (): Promise<{err: boolean; message?: IsBlitzRootError; depth?: number}> => {
|
||||
export const isBlitzRoot = async (): Promise<{
|
||||
err: boolean
|
||||
message?: IsBlitzRootError
|
||||
depth?: number
|
||||
}> => {
|
||||
try {
|
||||
const local = await readJSON('./package.json')
|
||||
const local = await readJSON("./package.json")
|
||||
if (local) {
|
||||
if (local.dependencies['blitz'] || local.devDependencies['blitz']) {
|
||||
if (local.dependencies["blitz"] || local.devDependencies["blitz"]) {
|
||||
return {err: false}
|
||||
} else {
|
||||
return {
|
||||
@@ -47,7 +51,7 @@ export const isBlitzRoot = async (): Promise<{err: boolean; message?: IsBlitzRoo
|
||||
return {err: true, message: IsBlitzRootError.BadPackageJson}
|
||||
} catch (err) {
|
||||
// No local package.json
|
||||
if (err.code === 'ENOENT') {
|
||||
if (err.code === "ENOENT") {
|
||||
const out = await checkParent()
|
||||
|
||||
if (out === false) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {REGISTER_INSTANCE} from 'ts-node'
|
||||
import {REGISTER_INSTANCE} from "ts-node"
|
||||
|
||||
export const setupTsnode = () => {
|
||||
if (!process[REGISTER_INSTANCE]) {
|
||||
// During blitz interal dev, oclif automaticaly sets up ts-node so we have to check
|
||||
require('ts-node').register({compilerOptions: {module: 'commonjs'}})
|
||||
require("ts-node").register({compilerOptions: {module: "commonjs"}})
|
||||
}
|
||||
require('tsconfig-paths/register')
|
||||
require("tsconfig-paths/register")
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {Installer} from '@blitzjs/installer'
|
||||
import {Installer} from "@blitzjs/installer"
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default new Installer(
|
||||
{
|
||||
packageDescription: 'test package',
|
||||
packageName: 'test',
|
||||
packageOwner: 'blitz@blitzjs.com',
|
||||
packageRepoLink: 'https://github.com/blitz-js/blitz',
|
||||
packageDescription: "test package",
|
||||
packageName: "test",
|
||||
packageOwner: "blitz@blitzjs.com",
|
||||
packageRepoLink: "https://github.com/blitz-js/blitz",
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const build = jest.fn(() => {})
|
||||
jest.mock('@blitzjs/server', () => ({build, resolveBinAsync: jest.fn()}))
|
||||
jest.mock("@blitzjs/server", () => ({build, resolveBinAsync: jest.fn()}))
|
||||
|
||||
let onSpy: jest.Mock
|
||||
const spawn = jest.fn(() => {
|
||||
@@ -9,23 +9,23 @@ const spawn = jest.fn(() => {
|
||||
return {on: onSpy}
|
||||
})
|
||||
|
||||
jest.doMock('cross-spawn', () => ({spawn}))
|
||||
jest.doMock("cross-spawn", () => ({spawn}))
|
||||
|
||||
import {Build} from '../../src/commands/build'
|
||||
import {resolve} from 'path'
|
||||
import {Build} from "../../src/commands/build"
|
||||
import {resolve} from "path"
|
||||
|
||||
describe('Build command', () => {
|
||||
describe("Build command", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
const options = {
|
||||
rootFolder: resolve(__dirname, '../../'),
|
||||
rootFolder: resolve(__dirname, "../../"),
|
||||
port: 3000,
|
||||
hostname: 'localhost',
|
||||
hostname: "localhost",
|
||||
}
|
||||
|
||||
it('runs the build script', async () => {
|
||||
it("runs the build script", async () => {
|
||||
await Build.run([])
|
||||
expect(build).toBeCalledWith(options, Promise.resolve())
|
||||
})
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {Console} from '../../src/commands/console'
|
||||
import {Console} from "../../src/commands/console"
|
||||
|
||||
import * as repl from '@blitzjs/repl'
|
||||
import * as db from '../../src/commands/db'
|
||||
import * as repl from "@blitzjs/repl"
|
||||
import * as db from "../../src/commands/db"
|
||||
|
||||
jest.spyOn(global.console, 'log').mockImplementation()
|
||||
jest.spyOn(global.console, "log").mockImplementation()
|
||||
|
||||
jest.mock(
|
||||
'@blitzjs/server',
|
||||
"@blitzjs/server",
|
||||
jest.fn(() => {
|
||||
return {
|
||||
log: {
|
||||
@@ -23,12 +23,12 @@ jest.mock(
|
||||
|
||||
jest.mock(`${process.cwd()}/package.json`, () => ({
|
||||
dependencies: {
|
||||
ramda: '1.0.0',
|
||||
ramda: "1.0.0",
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock(
|
||||
'@blitzjs/repl',
|
||||
"@blitzjs/repl",
|
||||
jest.fn(() => {
|
||||
return {
|
||||
runRepl: jest.fn(),
|
||||
@@ -37,7 +37,7 @@ jest.mock(
|
||||
)
|
||||
|
||||
jest.mock(
|
||||
'../../src/commands/db',
|
||||
"../../src/commands/db",
|
||||
jest.fn(() => {
|
||||
return {
|
||||
runPrismaGeneration: jest.fn(),
|
||||
@@ -45,27 +45,27 @@ jest.mock(
|
||||
}),
|
||||
)
|
||||
|
||||
describe('Console command', () => {
|
||||
describe("Console command", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks()
|
||||
})
|
||||
|
||||
it('runs PrismaGeneration', async () => {
|
||||
it("runs PrismaGeneration", async () => {
|
||||
await Console.prototype.run()
|
||||
expect(db.runPrismaGeneration).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('runs PrismaGeneration with silent allowed', async () => {
|
||||
it("runs PrismaGeneration with silent allowed", async () => {
|
||||
await Console.prototype.run()
|
||||
expect(db.runPrismaGeneration).toHaveBeenCalledWith({silent: true})
|
||||
})
|
||||
|
||||
it('runs repl', async () => {
|
||||
it("runs repl", async () => {
|
||||
await Console.prototype.run()
|
||||
expect(repl.runRepl).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('runs repl with replOptions', async () => {
|
||||
it("runs repl with replOptions", async () => {
|
||||
await Console.prototype.run()
|
||||
expect(repl.runRepl).toHaveBeenCalledWith(Console.replOptions)
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as path from 'path'
|
||||
import {resolveBinAsync} from '@blitzjs/server'
|
||||
import * as path from "path"
|
||||
import {resolveBinAsync} from "@blitzjs/server"
|
||||
|
||||
let onSpy: jest.Mock
|
||||
const spawn = jest.fn(() => {
|
||||
@@ -9,37 +9,37 @@ const spawn = jest.fn(() => {
|
||||
return {on: onSpy}
|
||||
})
|
||||
|
||||
jest.doMock('cross-spawn', () => ({spawn}))
|
||||
jest.doMock("cross-spawn", () => ({spawn}))
|
||||
|
||||
import {Db} from '../../src/commands/db'
|
||||
import {Db} from "../../src/commands/db"
|
||||
|
||||
let schemaArg: string
|
||||
let prismaBin: string
|
||||
let migrateSaveParams: any[]
|
||||
let migrateUpParams: any[]
|
||||
beforeAll(async () => {
|
||||
schemaArg = `--schema=${path.join(process.cwd(), 'db', 'schema.prisma')}`
|
||||
prismaBin = await resolveBinAsync('@prisma/cli', 'prisma')
|
||||
schemaArg = `--schema=${path.join(process.cwd(), "db", "schema.prisma")}`
|
||||
prismaBin = await resolveBinAsync("@prisma/cli", "prisma")
|
||||
|
||||
migrateSaveParams = [
|
||||
prismaBin,
|
||||
['migrate', 'save', schemaArg, '--create-db', '--experimental'],
|
||||
{stdio: 'inherit'},
|
||||
["migrate", "save", schemaArg, "--create-db", "--experimental"],
|
||||
{stdio: "inherit"},
|
||||
]
|
||||
migrateUpParams = [
|
||||
prismaBin,
|
||||
['migrate', 'up', schemaArg, '--create-db', '--experimental'],
|
||||
{stdio: 'inherit'},
|
||||
["migrate", "up", schemaArg, "--create-db", "--experimental"],
|
||||
{stdio: "inherit"},
|
||||
]
|
||||
})
|
||||
|
||||
describe('Db command', () => {
|
||||
describe("Db command", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
process.env.NODE_ENV = 'test'
|
||||
process.env.NODE_ENV = "test"
|
||||
})
|
||||
|
||||
function expectDbMigrateOutcome() {
|
||||
@@ -61,42 +61,42 @@ describe('Db command', () => {
|
||||
expect(spawn).toBeCalledWith(...migrateUpParams)
|
||||
}
|
||||
|
||||
it('runs db migrate', async () => {
|
||||
await Db.run(['migrate'])
|
||||
it("runs db migrate", async () => {
|
||||
await Db.run(["migrate"])
|
||||
expectDbMigrateOutcome()
|
||||
})
|
||||
|
||||
it('runs db migrate in the production environment.', async () => {
|
||||
process.env.NODE_ENV = 'production'
|
||||
await Db.run(['migrate'])
|
||||
it("runs db migrate in the production environment.", async () => {
|
||||
process.env.NODE_ENV = "production"
|
||||
await Db.run(["migrate"])
|
||||
expectProductionDbMigrateOutcome()
|
||||
})
|
||||
|
||||
it('runs db migrate (alias)', async () => {
|
||||
await Db.run(['m'])
|
||||
it("runs db migrate (alias)", async () => {
|
||||
await Db.run(["m"])
|
||||
expectDbMigrateOutcome()
|
||||
})
|
||||
|
||||
it('runs db migrate (alias) in the production environment.', async () => {
|
||||
process.env.NODE_ENV = 'production'
|
||||
await Db.run(['m'])
|
||||
it("runs db migrate (alias) in the production environment.", async () => {
|
||||
process.env.NODE_ENV = "production"
|
||||
await Db.run(["m"])
|
||||
expectProductionDbMigrateOutcome()
|
||||
})
|
||||
|
||||
it('runs db introspect', async () => {
|
||||
await Db.run(['introspect'])
|
||||
it("runs db introspect", async () => {
|
||||
await Db.run(["introspect"])
|
||||
|
||||
expect(spawn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('runs db studio', async () => {
|
||||
await Db.run(['studio'])
|
||||
it("runs db studio", async () => {
|
||||
await Db.run(["studio"])
|
||||
|
||||
expect(spawn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not run db in case of invalid command', async () => {
|
||||
await Db.run(['invalid'])
|
||||
it("does not run db in case of invalid command", async () => {
|
||||
await Db.run(["invalid"])
|
||||
|
||||
expect(spawn.mock.calls.length).toBe(0)
|
||||
})
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
import {Generate} from '../../src/commands/generate'
|
||||
import * as path from 'path'
|
||||
import {Generate} from "../../src/commands/generate"
|
||||
import * as path from "path"
|
||||
|
||||
describe('`generate` command', () => {
|
||||
describe('#getModelNameAndContext', () => {
|
||||
it('properly extracts context from arguments', () => {
|
||||
describe("`generate` command", () => {
|
||||
describe("#getModelNameAndContext", () => {
|
||||
it("properly extracts context from arguments", () => {
|
||||
const getModelNameAndContext = Generate.prototype.getModelNameAndContext
|
||||
expect(getModelNameAndContext('admin/tasks')).toEqual({
|
||||
model: 'tasks',
|
||||
context: 'admin',
|
||||
expect(getModelNameAndContext("admin/tasks")).toEqual({
|
||||
model: "tasks",
|
||||
context: "admin",
|
||||
})
|
||||
|
||||
expect(getModelNameAndContext('admin/projects/tasks')).toEqual({
|
||||
model: 'tasks',
|
||||
context: path.join('admin', 'projects'),
|
||||
expect(getModelNameAndContext("admin/projects/tasks")).toEqual({
|
||||
model: "tasks",
|
||||
context: path.join("admin", "projects"),
|
||||
})
|
||||
|
||||
// this should fail on windows if generic filesystem-specific code makes it in
|
||||
expect(getModelNameAndContext('admin\\projects\\tasks')).toEqual({
|
||||
model: 'tasks',
|
||||
context: path.join('admin', 'projects'),
|
||||
expect(getModelNameAndContext("admin\\projects\\tasks")).toEqual({
|
||||
model: "tasks",
|
||||
context: path.join("admin", "projects"),
|
||||
})
|
||||
})
|
||||
|
||||
describe('when passing context', () => {
|
||||
it('returns both model and context in their own field', () => {
|
||||
describe("when passing context", () => {
|
||||
it("returns both model and context in their own field", () => {
|
||||
const getModelNameAndContext = Generate.prototype.getModelNameAndContext
|
||||
expect(getModelNameAndContext('tasks', 'admin')).toEqual({
|
||||
model: 'tasks',
|
||||
context: 'admin',
|
||||
expect(getModelNameAndContext("tasks", "admin")).toEqual({
|
||||
model: "tasks",
|
||||
context: "admin",
|
||||
})
|
||||
})
|
||||
|
||||
it('returns context undefined if not set', () => {
|
||||
it("returns context undefined if not set", () => {
|
||||
const getModelNameAndContext = Generate.prototype.getModelNameAndContext
|
||||
expect(getModelNameAndContext('tasks')).toEqual({
|
||||
model: 'tasks',
|
||||
expect(getModelNameAndContext("tasks")).toEqual({
|
||||
model: "tasks",
|
||||
context: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
it('returns context undefined if empty string', () => {
|
||||
it("returns context undefined if empty string", () => {
|
||||
const getModelNameAndContext = Generate.prototype.getModelNameAndContext
|
||||
expect(getModelNameAndContext('tasks', '')).toEqual({
|
||||
model: 'tasks',
|
||||
expect(getModelNameAndContext("tasks", "")).toEqual({
|
||||
model: "tasks",
|
||||
context: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
import {Install, RecipeLocation} from '../../src/commands/install'
|
||||
import * as path from 'path'
|
||||
import tempInstaller from '../__fixtures__/installer'
|
||||
import {Install, RecipeLocation} from "../../src/commands/install"
|
||||
import * as path from "path"
|
||||
import tempInstaller from "../__fixtures__/installer"
|
||||
|
||||
jest.mock('../__fixtures__/installer')
|
||||
jest.mock('@blitzjs/installer')
|
||||
jest.mock("../__fixtures__/installer")
|
||||
jest.mock("@blitzjs/installer")
|
||||
|
||||
describe('`install` command', () => {
|
||||
describe("`install` command", () => {
|
||||
afterAll(() => {
|
||||
jest.resetAllMocks()
|
||||
})
|
||||
it('runs local installer', async (done) => {
|
||||
await Install.run([path.resolve(__dirname, '../__fixtures__/installer')])
|
||||
it("runs local installer", async (done) => {
|
||||
await Install.run([path.resolve(__dirname, "../__fixtures__/installer")])
|
||||
expect(tempInstaller.run).toHaveBeenCalledWith({})
|
||||
done()
|
||||
})
|
||||
|
||||
it('properly parses remote installer args', () => {
|
||||
it("properly parses remote installer args", () => {
|
||||
const normalizePath = Install.prototype.normalizeRecipePath
|
||||
expect(normalizePath('test-installer')).toEqual({
|
||||
path: 'https://github.com/blitz-js/blitz',
|
||||
subdirectory: 'recipes/test-installer',
|
||||
expect(normalizePath("test-installer")).toEqual({
|
||||
path: "https://github.com/blitz-js/blitz",
|
||||
subdirectory: "recipes/test-installer",
|
||||
location: RecipeLocation.Remote,
|
||||
})
|
||||
expect(normalizePath('user/test-installer')).toEqual({
|
||||
path: 'https://github.com/user/test-installer',
|
||||
expect(normalizePath("user/test-installer")).toEqual({
|
||||
path: "https://github.com/user/test-installer",
|
||||
location: RecipeLocation.Remote,
|
||||
})
|
||||
expect(normalizePath('https://github.com/user/test-installer')).toEqual({
|
||||
path: 'https://github.com/user/test-installer',
|
||||
expect(normalizePath("https://github.com/user/test-installer")).toEqual({
|
||||
path: "https://github.com/user/test-installer",
|
||||
location: RecipeLocation.Remote,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import {New} from '../../src/commands/new'
|
||||
import {getLatestVersion} from '@blitzjs/generator/src/utils/get-latest-version'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
import fetch from 'node-fetch'
|
||||
import nock from 'nock'
|
||||
import rimraf from 'rimraf'
|
||||
import {New} from "../../src/commands/new"
|
||||
import {getLatestVersion} from "@blitzjs/generator/src/utils/get-latest-version"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import * as os from "os"
|
||||
import fetch from "node-fetch"
|
||||
import nock from "nock"
|
||||
import rimraf from "rimraf"
|
||||
|
||||
jest.setTimeout(120 * 1000)
|
||||
const blitzCliPackageJson = require('../../package.json')
|
||||
const blitzCliPackageJson = require("../../package.json")
|
||||
|
||||
async function getBlitzDistTags() {
|
||||
const response = await fetch('https://registry.npmjs.org/-/package/blitz/dist-tags')
|
||||
const response = await fetch("https://registry.npmjs.org/-/package/blitz/dist-tags")
|
||||
return await response.json()
|
||||
}
|
||||
|
||||
describe('`new` command', () => {
|
||||
describe('when scaffolding new project', () => {
|
||||
describe("`new` command", () => {
|
||||
describe("when scaffolding new project", () => {
|
||||
jest.setTimeout(120 * 1000)
|
||||
|
||||
async function whileStayingInCWD(task: () => PromiseLike<void>) {
|
||||
@@ -27,18 +27,18 @@ describe('`new` command', () => {
|
||||
|
||||
async function withNewApp(test: (dirName: string, packageJson: any) => Promise<void> | void) {
|
||||
function makeTempDir() {
|
||||
const tmpDirPath = path.join(os.tmpdir(), 'blitzjs-test-')
|
||||
const tmpDirPath = path.join(os.tmpdir(), "blitzjs-test-")
|
||||
|
||||
return fs.mkdtempSync(tmpDirPath)
|
||||
}
|
||||
|
||||
const tempDir = makeTempDir()
|
||||
|
||||
await whileStayingInCWD(() => New.run([tempDir, '--skip-install']))
|
||||
await whileStayingInCWD(() => New.run([tempDir, "--skip-install"]))
|
||||
|
||||
const packageJsonFile = fs.readFileSync(path.join(tempDir, 'package.json'), {
|
||||
encoding: 'utf8',
|
||||
flag: 'r',
|
||||
const packageJsonFile = fs.readFileSync(path.join(tempDir, "package.json"), {
|
||||
encoding: "utf8",
|
||||
flag: "r",
|
||||
})
|
||||
const packageJson = JSON.parse(packageJsonFile)
|
||||
|
||||
@@ -47,49 +47,52 @@ describe('`new` command', () => {
|
||||
rimraf.sync(tempDir)
|
||||
}
|
||||
|
||||
it('pins Blitz to the current version', async () =>
|
||||
it("pins Blitz to the current version", async () =>
|
||||
await withNewApp(async (_, packageJson) => {
|
||||
const {
|
||||
dependencies: {blitz: blitzVersion},
|
||||
} = packageJson
|
||||
|
||||
const {latest, canary} = await getBlitzDistTags()
|
||||
if (blitzCliPackageJson.version.includes('canary')) {
|
||||
if (blitzCliPackageJson.version.includes("canary")) {
|
||||
expect(blitzVersion).toEqual(canary)
|
||||
} else {
|
||||
expect(blitzVersion).toEqual(latest)
|
||||
}
|
||||
}))
|
||||
|
||||
it('fetches latest version from template', async () => {
|
||||
const expectedVersion = '3.0.0'
|
||||
const templatePackage = {name: 'eslint-plugin-react-hooks', version: '3.x'}
|
||||
it("fetches latest version from template", async () => {
|
||||
const expectedVersion = "3.0.0"
|
||||
const templatePackage = {name: "eslint-plugin-react-hooks", version: "3.x"}
|
||||
|
||||
const scope = nock('https://registry.npmjs.org')
|
||||
const scope = nock("https://registry.npmjs.org")
|
||||
|
||||
scope
|
||||
.get(`/${templatePackage.name}`)
|
||||
.reply(200, {versions: {'4.0.0': {}, '3.0.0': {}}})
|
||||
.reply(200, {versions: {"4.0.0": {}, "3.0.0": {}}})
|
||||
.persist()
|
||||
|
||||
scope
|
||||
.get(`/-/package/${templatePackage.name}/dist-tags`)
|
||||
.reply(200, {
|
||||
latest: '4.0.0',
|
||||
latest: "4.0.0",
|
||||
})
|
||||
.persist()
|
||||
|
||||
const {value: latestVersion} = await getLatestVersion(templatePackage.name, templatePackage.version)
|
||||
const {value: latestVersion} = await getLatestVersion(
|
||||
templatePackage.name,
|
||||
templatePackage.version,
|
||||
)
|
||||
expect(latestVersion).toBe(expectedVersion)
|
||||
})
|
||||
|
||||
describe('with network trouble', () => {
|
||||
it('uses template versions', async () => {
|
||||
nock('https://registry.npmjs.org').get(/.*/).reply(500).persist()
|
||||
describe("with network trouble", () => {
|
||||
it("uses template versions", async () => {
|
||||
nock("https://registry.npmjs.org").get(/.*/).reply(500).persist()
|
||||
|
||||
await withNewApp(async (_, packageJson) => {
|
||||
const {dependencies} = packageJson
|
||||
expect(dependencies.blitz).toBe('latest')
|
||||
expect(dependencies.blitz).toBe("latest")
|
||||
})
|
||||
|
||||
nock.restore()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const dev = jest.fn(() => {})
|
||||
const prod = jest.fn(() => {})
|
||||
|
||||
jest.mock('@blitzjs/server', () => ({dev, prod, resolveBinAsync: jest.fn()}))
|
||||
jest.mock("@blitzjs/server", () => ({dev, prod, resolveBinAsync: jest.fn()}))
|
||||
|
||||
let onSpy: jest.Mock
|
||||
const spawn = jest.fn(() => {
|
||||
@@ -11,29 +11,29 @@ const spawn = jest.fn(() => {
|
||||
return {on: onSpy}
|
||||
})
|
||||
|
||||
jest.doMock('cross-spawn', () => ({spawn}))
|
||||
jest.doMock("cross-spawn", () => ({spawn}))
|
||||
|
||||
import {Start} from '../../src/commands/start'
|
||||
import {resolve} from 'path'
|
||||
import {Start} from "../../src/commands/start"
|
||||
import {resolve} from "path"
|
||||
|
||||
describe('Start command', () => {
|
||||
describe("Start command", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
const options = {
|
||||
rootFolder: resolve(__dirname, '../../'),
|
||||
rootFolder: resolve(__dirname, "../../"),
|
||||
port: 3000,
|
||||
hostname: 'localhost',
|
||||
hostname: "localhost",
|
||||
}
|
||||
|
||||
it('runs the dev script', async () => {
|
||||
it("runs the dev script", async () => {
|
||||
await Start.run([])
|
||||
expect(dev).toBeCalledWith(options, Promise.resolve())
|
||||
})
|
||||
|
||||
it('runs the prod script when passed the production flag', async () => {
|
||||
await Start.run(['--production'])
|
||||
it("runs the prod script when passed the production flag", async () => {
|
||||
await Start.run(["--production"])
|
||||
expect(prod).toBeCalledWith(options, Promise.resolve())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
jest.mock('cross-spawn')
|
||||
jest.mock('has-yarn')
|
||||
jest.mock("cross-spawn")
|
||||
jest.mock("has-yarn")
|
||||
|
||||
import crossSpawn from 'cross-spawn'
|
||||
import hasYarn from 'has-yarn'
|
||||
import {Test} from '../../src/commands/test'
|
||||
import crossSpawn from "cross-spawn"
|
||||
import hasYarn from "has-yarn"
|
||||
import {Test} from "../../src/commands/test"
|
||||
|
||||
const testParams = [['test'], {stdio: 'inherit'}]
|
||||
const testWatchParams = [['test:watch'], {stdio: 'inherit'}]
|
||||
const testParams = [["test"], {stdio: "inherit"}]
|
||||
const testWatchParams = [["test:watch"], {stdio: "inherit"}]
|
||||
|
||||
describe('Test command', () => {
|
||||
describe("Test command", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('runs yarn test script', async () => {
|
||||
jest.spyOn(hasYarn, 'default').mockReturnValue(true)
|
||||
it("runs yarn test script", async () => {
|
||||
jest.spyOn(hasYarn, "default").mockReturnValue(true)
|
||||
|
||||
await Test.run([])
|
||||
|
||||
expect(crossSpawn.spawn).toBeCalledWith('yarn', ...testParams)
|
||||
expect(crossSpawn.spawn).toBeCalledWith("yarn", ...testParams)
|
||||
})
|
||||
|
||||
it('runs npm test script', async () => {
|
||||
jest.spyOn(hasYarn, 'default').mockReturnValue(false)
|
||||
it("runs npm test script", async () => {
|
||||
jest.spyOn(hasYarn, "default").mockReturnValue(false)
|
||||
|
||||
await Test.run([])
|
||||
|
||||
expect(crossSpawn.spawn).toBeCalledWith('npm', ...testParams)
|
||||
expect(crossSpawn.spawn).toBeCalledWith("npm", ...testParams)
|
||||
})
|
||||
|
||||
it('runs yarn test:watch script', async () => {
|
||||
jest.spyOn(hasYarn, 'default').mockReturnValue(true)
|
||||
it("runs yarn test:watch script", async () => {
|
||||
jest.spyOn(hasYarn, "default").mockReturnValue(true)
|
||||
|
||||
await Test.run(['watch'])
|
||||
await Test.run(["watch"])
|
||||
|
||||
expect(crossSpawn.spawn).toBeCalledWith('yarn', ...testWatchParams)
|
||||
expect(crossSpawn.spawn).toBeCalledWith("yarn", ...testWatchParams)
|
||||
})
|
||||
|
||||
it('runs yarn test:watch script with alias', async () => {
|
||||
jest.spyOn(hasYarn, 'default').mockReturnValue(true)
|
||||
it("runs yarn test:watch script with alias", async () => {
|
||||
jest.spyOn(hasYarn, "default").mockReturnValue(true)
|
||||
|
||||
await Test.run(['w'])
|
||||
await Test.run(["w"])
|
||||
|
||||
expect(crossSpawn.spawn).toBeCalledWith('yarn', ...testWatchParams)
|
||||
expect(crossSpawn.spawn).toBeCalledWith("yarn", ...testWatchParams)
|
||||
})
|
||||
|
||||
it('runs yarn test and ignores invalid argument', async () => {
|
||||
jest.spyOn(hasYarn, 'default').mockReturnValue(true)
|
||||
it("runs yarn test and ignores invalid argument", async () => {
|
||||
jest.spyOn(hasYarn, "default").mockReturnValue(true)
|
||||
|
||||
await Test.run(['invalid'])
|
||||
await Test.run(["invalid"])
|
||||
|
||||
expect(crossSpawn.spawn).toBeCalledWith('yarn', ...testParams)
|
||||
expect(crossSpawn.spawn).toBeCalledWith("yarn", ...testParams)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {dedent} from '../../src/utils/dedent'
|
||||
import {dedent} from "../../src/utils/dedent"
|
||||
|
||||
describe('dedent', () => {
|
||||
it('strips leading spaces', () => {
|
||||
expect(dedent` testing`).toBe('testing')
|
||||
describe("dedent", () => {
|
||||
it("strips leading spaces", () => {
|
||||
expect(dedent` testing`).toBe("testing")
|
||||
})
|
||||
})
|
||||
|
||||
2
packages/cli/types/index.d.ts
vendored
2
packages/cli/types/index.d.ts
vendored
@@ -1 +1 @@
|
||||
declare module 'hasbin'
|
||||
declare module "hasbin"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||
coverageReporters: ['json', 'lcov', 'text', 'clover'],
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
moduleFileExtensions: ["ts", "tsx", "js", "json"],
|
||||
coverageReporters: ["json", "lcov", "text", "clover"],
|
||||
// collectCoverage: !!`Boolean(process.env.CI)`,
|
||||
collectCoverageFrom: ['src/**/*.ts'],
|
||||
coveragePathIgnorePatterns: ['/templates/'],
|
||||
modulePathIgnorePatterns: ['<rootDir>/tmp', '<rootDir>/dist'],
|
||||
collectCoverageFrom: ["src/**/*.ts"],
|
||||
coveragePathIgnorePatterns: ["/templates/"],
|
||||
modulePathIgnorePatterns: ["<rootDir>/tmp", "<rootDir>/dist"],
|
||||
// TODO enable threshold
|
||||
// coverageThreshold: {
|
||||
// global: {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
require('@testing-library/jest-dom')
|
||||
require("@testing-library/jest-dom")
|
||||
|
||||
global.fetch = jest.fn(() => Promise.resolve({json: () => ({result: null, error: null})}))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import pkgDir from 'pkg-dir'
|
||||
import {join} from 'path'
|
||||
import {existsSync} from 'fs'
|
||||
import pkgDir from "pkg-dir"
|
||||
import {join} from "path"
|
||||
import {existsSync} from "fs"
|
||||
|
||||
const configFiles = ['next.config.js']
|
||||
const configFiles = ["next.config.js"]
|
||||
/**
|
||||
* @param {boolean | undefined} reload - reimport config files to reset global cache
|
||||
*/
|
||||
@@ -19,7 +19,7 @@ export const getConfig = (reload?: boolean): Record<string, unknown> => {
|
||||
const path = join(projectRoot, configFile)
|
||||
const file = require(path)
|
||||
let contents
|
||||
if (typeof file === 'function') {
|
||||
if (typeof file === "function") {
|
||||
contents = file()
|
||||
} else {
|
||||
contents = file
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||
coverageReporters: ['json', 'lcov', 'text', 'clover'],
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
moduleFileExtensions: ["ts", "tsx", "js", "json"],
|
||||
coverageReporters: ["json", "lcov", "text", "clover"],
|
||||
// collectCoverage: !!`Boolean(process.env.CI)`,
|
||||
collectCoverageFrom: ['src/**/*.ts'],
|
||||
coveragePathIgnorePatterns: ['/templates/'],
|
||||
modulePathIgnorePatterns: ['<rootDir>/tmp', '<rootDir>/dist'],
|
||||
collectCoverageFrom: ["src/**/*.ts"],
|
||||
coveragePathIgnorePatterns: ["/templates/"],
|
||||
modulePathIgnorePatterns: ["<rootDir>/tmp", "<rootDir>/dist"],
|
||||
// TODO enable threshold
|
||||
// coverageThreshold: {
|
||||
// global: {
|
||||
|
||||
@@ -1 +1 @@
|
||||
require('@testing-library/jest-dom')
|
||||
require("@testing-library/jest-dom")
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
export * from './use-query'
|
||||
export * from './use-paginated-query'
|
||||
export * from './use-params'
|
||||
export * from './use-infinite-query'
|
||||
export * from './ssr-query'
|
||||
export * from './rpc'
|
||||
export * from './with-router'
|
||||
export * from './use-router'
|
||||
export * from './use-router-query'
|
||||
export * from './middleware'
|
||||
export * from './types'
|
||||
export * from "./use-query"
|
||||
export * from "./use-paginated-query"
|
||||
export * from "./use-params"
|
||||
export * from "./use-infinite-query"
|
||||
export * from "./ssr-query"
|
||||
export * from "./rpc"
|
||||
export * from "./with-router"
|
||||
export * from "./use-router"
|
||||
export * from "./use-router-query"
|
||||
export * from "./middleware"
|
||||
export * from "./types"
|
||||
|
||||
// --------------------
|
||||
// Exports from Next.js
|
||||
@@ -22,15 +22,15 @@ export {
|
||||
NextPage as BlitzPage,
|
||||
NextApiRequest as BlitzApiRequest,
|
||||
NextApiResponse as BlitzApiResponse,
|
||||
} from 'next'
|
||||
} from "next"
|
||||
|
||||
export {AppProps} from 'next/app'
|
||||
export {AppProps} from "next/app"
|
||||
|
||||
export {default as Head} from 'next/head'
|
||||
export {default as Head} from "next/head"
|
||||
|
||||
export {default as Link} from 'next/link'
|
||||
export {default as Link} from "next/link"
|
||||
|
||||
export {Router} from 'next/router'
|
||||
export {Router} from "next/router"
|
||||
|
||||
export {
|
||||
default as Document,
|
||||
@@ -40,8 +40,8 @@ export {
|
||||
NextScript as BlitzScript,
|
||||
DocumentContext,
|
||||
DocumentInitialProps,
|
||||
} from 'next/document'
|
||||
} from "next/document"
|
||||
|
||||
export {default as dynamic} from 'next/dynamic'
|
||||
export {default as dynamic} from "next/dynamic"
|
||||
|
||||
export {default as Error} from 'next/error'
|
||||
export {default as Error} from "next/error"
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import {apiResolver} from 'next/dist/next-server/server/api-utils'
|
||||
import http from 'http'
|
||||
import listen from 'test-listen'
|
||||
import fetch from 'isomorphic-unfetch'
|
||||
import {apiResolver} from "next/dist/next-server/server/api-utils"
|
||||
import http from "http"
|
||||
import listen from "test-listen"
|
||||
import fetch from "isomorphic-unfetch"
|
||||
|
||||
import {BlitzApiRequest, BlitzApiResponse} from '.'
|
||||
import {Middleware, handleRequestWithMiddleware} from './middleware'
|
||||
import {BlitzApiRequest, BlitzApiResponse} from "."
|
||||
import {Middleware, handleRequestWithMiddleware} from "./middleware"
|
||||
|
||||
describe('handleRequestWithMiddleware', () => {
|
||||
it('works without await', async () => {
|
||||
describe("handleRequestWithMiddleware", () => {
|
||||
it("works without await", async () => {
|
||||
const middleware: Middleware[] = [
|
||||
(_req, res, next) => {
|
||||
res.status(201)
|
||||
return next()
|
||||
},
|
||||
(_req, res, next) => {
|
||||
res.setHeader('test', 'works')
|
||||
res.json({a: 'b'})
|
||||
res.setHeader("test", "works")
|
||||
res.json({a: "b"})
|
||||
return next()
|
||||
},
|
||||
]
|
||||
@@ -23,11 +23,11 @@ describe('handleRequestWithMiddleware', () => {
|
||||
await mockServer(middleware, async (url) => {
|
||||
const res = await fetch(url)
|
||||
expect(res.status).toBe(201)
|
||||
expect(res.headers.get('test')).toBe('works')
|
||||
expect(res.headers.get("test")).toBe("works")
|
||||
})
|
||||
})
|
||||
|
||||
it('works with await', async () => {
|
||||
it("works with await", async () => {
|
||||
const middleware: Middleware[] = [
|
||||
async (_req, res, next) => {
|
||||
res.status(201)
|
||||
@@ -35,22 +35,22 @@ describe('handleRequestWithMiddleware', () => {
|
||||
},
|
||||
async (_req, res, next) => {
|
||||
await next()
|
||||
res.setHeader('test', 'works')
|
||||
res.setHeader("test", "works")
|
||||
},
|
||||
]
|
||||
|
||||
await mockServer(middleware, async (url) => {
|
||||
const res = await fetch(url)
|
||||
expect(res.status).toBe(201)
|
||||
expect(res.headers.get('test')).toBe('works')
|
||||
expect(res.headers.get("test")).toBe("works")
|
||||
})
|
||||
})
|
||||
|
||||
it('works with flipped order', async () => {
|
||||
it("works with flipped order", async () => {
|
||||
const middleware: Middleware[] = [
|
||||
async (_req, res, next) => {
|
||||
await next()
|
||||
res.setHeader('test', 'works')
|
||||
res.setHeader("test", "works")
|
||||
},
|
||||
async (_req, res, next) => {
|
||||
res.status(201)
|
||||
@@ -61,16 +61,16 @@ describe('handleRequestWithMiddleware', () => {
|
||||
await mockServer(middleware, async (url) => {
|
||||
const res = await fetch(url)
|
||||
expect(res.status).toBe(201)
|
||||
expect(res.headers.get('test')).toBe('works')
|
||||
expect(res.headers.get("test")).toBe("works")
|
||||
})
|
||||
})
|
||||
|
||||
it('middleware can throw', async () => {
|
||||
it("middleware can throw", async () => {
|
||||
console.log = jest.fn()
|
||||
console.error = jest.fn()
|
||||
const middleware: Middleware[] = [
|
||||
(_req, _res, _next) => {
|
||||
throw new Error('test')
|
||||
throw new Error("test")
|
||||
},
|
||||
]
|
||||
|
||||
@@ -80,14 +80,14 @@ describe('handleRequestWithMiddleware', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('middleware can return error', async () => {
|
||||
it("middleware can return error", async () => {
|
||||
console.log = jest.fn()
|
||||
const middleware: Middleware[] = [
|
||||
(_req, _res, next) => {
|
||||
return next(new Error('test'))
|
||||
return next(new Error("test"))
|
||||
},
|
||||
(_req, _res, _next) => {
|
||||
throw new Error('Remaining middleware should not run if previous has error')
|
||||
throw new Error("Remaining middleware should not run if previous has error")
|
||||
},
|
||||
]
|
||||
|
||||
@@ -107,9 +107,9 @@ async function mockServer(middleware: Middleware[], callback: (url: string) => P
|
||||
|
||||
let server = http.createServer((req, res) =>
|
||||
apiResolver(req, res, null, apiEndpoint, {
|
||||
previewModeId: 'previewModeId',
|
||||
previewModeEncryptionKey: 'previewModeEncryptionKey',
|
||||
previewModeSigningKey: 'previewModeSigningKey',
|
||||
previewModeId: "previewModeId",
|
||||
previewModeEncryptionKey: "previewModeEncryptionKey",
|
||||
previewModeSigningKey: "previewModeSigningKey",
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {BlitzApiRequest, BlitzApiResponse} from '.'
|
||||
import {IncomingMessage, ServerResponse} from 'http'
|
||||
import {EnhancedResolverModule} from './rpc'
|
||||
import {getConfig} from '@blitzjs/config'
|
||||
import {log} from '@blitzjs/display'
|
||||
import {BlitzApiRequest, BlitzApiResponse} from "."
|
||||
import {IncomingMessage, ServerResponse} from "http"
|
||||
import {EnhancedResolverModule} from "./rpc"
|
||||
import {getConfig} from "@blitzjs/config"
|
||||
import {log} from "@blitzjs/display"
|
||||
|
||||
export interface MiddlewareRequest extends BlitzApiRequest {}
|
||||
export interface MiddlewareResponse extends BlitzApiResponse {
|
||||
@@ -71,9 +71,9 @@ export async function handleRequestWithMiddleware(
|
||||
if (!res.writableFinished) {
|
||||
res.statusCode = (error as any).code || (error as any).status || 500
|
||||
res.end(error.message || res.statusCode.toString())
|
||||
log.error('Error while processing the request:\n')
|
||||
log.error("Error while processing the request:\n")
|
||||
} else {
|
||||
log.error('Error occured in middleware after the response was already sent to the browser:\n')
|
||||
log.error("Error occured in middleware after the response was already sent to the browser:\n")
|
||||
}
|
||||
throw error
|
||||
}
|
||||
@@ -85,12 +85,12 @@ export async function handleRequestWithMiddleware(
|
||||
// -------------------------------------------------------------------------------
|
||||
export function compose(middleware: Middleware[]) {
|
||||
if (!Array.isArray(middleware)) {
|
||||
throw new TypeError('Middleware stack must be an array!')
|
||||
throw new TypeError("Middleware stack must be an array!")
|
||||
}
|
||||
|
||||
for (const handler of middleware) {
|
||||
if (typeof handler !== 'function') {
|
||||
throw new TypeError('Middleware must be composed of functions!')
|
||||
if (typeof handler !== "function") {
|
||||
throw new TypeError("Middleware must be composed of functions!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ export function compose(middleware: Middleware[]) {
|
||||
let index = -1
|
||||
|
||||
function dispatch(i: number): Promise<void> {
|
||||
if (i <= index) throw new Error('next() called multiple times')
|
||||
if (i <= index) throw new Error("next() called multiple times")
|
||||
index = i
|
||||
|
||||
let handler = middleware[i]
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import {deserializeError} from 'serialize-error'
|
||||
import {queryCache} from 'react-query'
|
||||
import {getQueryKey} from './utils'
|
||||
import {ResolverModule, Middleware} from './middleware'
|
||||
import {deserializeError} from "serialize-error"
|
||||
import {queryCache} from "react-query"
|
||||
import {getQueryKey} from "./utils"
|
||||
import {ResolverModule, Middleware} from "./middleware"
|
||||
|
||||
type Options = {
|
||||
fromQueryHook?: boolean
|
||||
}
|
||||
|
||||
export async function executeRpcCall(url: string, params: any, opts: Options = {}) {
|
||||
if (typeof window === 'undefined') return
|
||||
if (typeof window === "undefined") return
|
||||
const result = await window.fetch(url, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
redirect: 'follow',
|
||||
redirect: "follow",
|
||||
body: JSON.stringify({params}),
|
||||
})
|
||||
|
||||
@@ -38,9 +38,9 @@ export async function executeRpcCall(url: string, params: any, opts: Options = {
|
||||
}
|
||||
|
||||
executeRpcCall.warm = (url: string) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (typeof window !== "undefined") {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
window.fetch(url, {method: 'HEAD'})
|
||||
window.fetch(url, {method: "HEAD"})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export function getIsomorphicRpcHandler(
|
||||
resolverName: string,
|
||||
resolverType: string,
|
||||
) {
|
||||
const apiUrl = resolverPath.replace(/^app\/_resolvers/, '/api')
|
||||
const apiUrl = resolverPath.replace(/^app\/_resolvers/, "/api")
|
||||
const enhance = <T extends ResolverEnhancement>(fn: T): T => {
|
||||
fn._meta = {
|
||||
name: resolverName,
|
||||
@@ -79,8 +79,9 @@ export function getIsomorphicRpcHandler(
|
||||
return fn
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
let rpcFn: EnhancedRpcFunction = ((params: any, opts = {}) => executeRpcCall(apiUrl, params, opts)) as any
|
||||
if (typeof window !== "undefined") {
|
||||
let rpcFn: EnhancedRpcFunction = ((params: any, opts = {}) =>
|
||||
executeRpcCall(apiUrl, params, opts)) as any
|
||||
|
||||
rpcFn = enhance(rpcFn)
|
||||
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
import http, {IncomingMessage, ServerResponse} from 'http'
|
||||
import listen from 'test-listen'
|
||||
import fetch from 'isomorphic-unfetch'
|
||||
import delay from 'delay'
|
||||
import http, {IncomingMessage, ServerResponse} from "http"
|
||||
import listen from "test-listen"
|
||||
import fetch from "isomorphic-unfetch"
|
||||
import delay from "delay"
|
||||
|
||||
import {ssrQuery} from './ssr-query'
|
||||
import {EnhancedResolverModule} from './rpc'
|
||||
import {ssrQuery} from "./ssr-query"
|
||||
import {EnhancedResolverModule} from "./rpc"
|
||||
|
||||
describe('ssrQuery', () => {
|
||||
it('works without middleware', async () => {
|
||||
describe("ssrQuery", () => {
|
||||
it("works without middleware", async () => {
|
||||
const resolverModule = (jest.fn().mockImplementation(async (input) => {
|
||||
await delay(1)
|
||||
return input
|
||||
}) as unknown) as EnhancedResolverModule
|
||||
resolverModule._meta = {
|
||||
name: 'getTest',
|
||||
type: 'query',
|
||||
path: 'some/test/path',
|
||||
apiUrl: 'some/test/path',
|
||||
name: "getTest",
|
||||
type: "query",
|
||||
path: "some/test/path",
|
||||
apiUrl: "some/test/path",
|
||||
}
|
||||
|
||||
await mockServer(
|
||||
async (req, res) => {
|
||||
const result = await ssrQuery(resolverModule as any, 'test', {req, res})
|
||||
const result = await ssrQuery(resolverModule as any, "test", {req, res})
|
||||
|
||||
expect(result).toBe('test')
|
||||
expect(result).toBe("test")
|
||||
},
|
||||
async (url) => {
|
||||
const res = await fetch(url)
|
||||
@@ -32,16 +32,16 @@ describe('ssrQuery', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('works with middleware', async () => {
|
||||
it("works with middleware", async () => {
|
||||
const resolverModule = (jest.fn().mockImplementation(async (input) => {
|
||||
await delay(1)
|
||||
return input
|
||||
}) as unknown) as EnhancedResolverModule
|
||||
resolverModule._meta = {
|
||||
name: 'getTest',
|
||||
type: 'query',
|
||||
path: 'some/test/path',
|
||||
apiUrl: 'some/test/path',
|
||||
name: "getTest",
|
||||
type: "query",
|
||||
path: "some/test/path",
|
||||
apiUrl: "some/test/path",
|
||||
}
|
||||
resolverModule.middleware = [
|
||||
(_req, res, next) => {
|
||||
@@ -49,21 +49,21 @@ describe('ssrQuery', () => {
|
||||
return next()
|
||||
},
|
||||
(_req, res, next) => {
|
||||
res.setHeader('test', 'works')
|
||||
res.setHeader("test", "works")
|
||||
return next()
|
||||
},
|
||||
]
|
||||
|
||||
await mockServer(
|
||||
async (req, res) => {
|
||||
const result = await ssrQuery(resolverModule as any, 'test', {req, res})
|
||||
const result = await ssrQuery(resolverModule as any, "test", {req, res})
|
||||
|
||||
expect(result).toBe('test')
|
||||
expect(result).toBe("test")
|
||||
},
|
||||
async (url) => {
|
||||
const res = await fetch(url)
|
||||
expect(res.status).toBe(201)
|
||||
expect(res.headers.get('test')).toBe('works')
|
||||
expect(res.headers.get("test")).toBe("works")
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import {IncomingMessage, ServerResponse} from 'http'
|
||||
import {log} from '@blitzjs/display'
|
||||
import {InferUnaryParam} from './types'
|
||||
import {getAllMiddlewareForModule, handleRequestWithMiddleware, MiddlewareResponse} from './middleware'
|
||||
import {EnhancedResolverModule} from './rpc'
|
||||
import {IncomingMessage, ServerResponse} from "http"
|
||||
import {log} from "@blitzjs/display"
|
||||
import {InferUnaryParam} from "./types"
|
||||
import {
|
||||
getAllMiddlewareForModule,
|
||||
handleRequestWithMiddleware,
|
||||
MiddlewareResponse,
|
||||
} from "./middleware"
|
||||
import {EnhancedResolverModule} from "./rpc"
|
||||
|
||||
type QueryFn = (...args: any) => Promise<any>
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@ import {
|
||||
useInfiniteQuery as useInfiniteReactQuery,
|
||||
InfiniteQueryResult,
|
||||
InfiniteQueryOptions,
|
||||
} from 'react-query'
|
||||
import {PromiseReturnType, InferUnaryParam, QueryFn} from './types'
|
||||
import {getQueryCacheFunctions, QueryCacheFunctions} from './utils/query-cache'
|
||||
import {EnhancedRpcFunction} from './rpc'
|
||||
} from "react-query"
|
||||
import {PromiseReturnType, InferUnaryParam, QueryFn} from "./types"
|
||||
import {getQueryCacheFunctions, QueryCacheFunctions} from "./utils/query-cache"
|
||||
import {EnhancedRpcFunction} from "./rpc"
|
||||
|
||||
type RestQueryResult<T extends QueryFn> = Omit<
|
||||
InfiniteQueryResult<PromiseReturnType<T>, any>,
|
||||
'resolvedData'
|
||||
"resolvedData"
|
||||
> &
|
||||
QueryCacheFunctions<PromiseReturnType<T>[]>
|
||||
|
||||
@@ -18,11 +18,11 @@ export function useInfiniteQuery<T extends QueryFn>(
|
||||
params: InferUnaryParam<T> | (() => InferUnaryParam<T>),
|
||||
options: InfiniteQueryOptions<PromiseReturnType<T>, any>,
|
||||
): [PromiseReturnType<T>[], RestQueryResult<T>] {
|
||||
if (typeof queryFn === 'undefined') {
|
||||
throw new Error('useInfiniteQuery is missing the first argument - it must be a query function')
|
||||
if (typeof queryFn === "undefined") {
|
||||
throw new Error("useInfiniteQuery is missing the first argument - it must be a query function")
|
||||
}
|
||||
|
||||
if (typeof params === 'undefined') {
|
||||
if (typeof params === "undefined") {
|
||||
throw new Error(
|
||||
"useInfiniteQuery is missing the second argument. This will be the input to your query function on the server. Pass `null` if the query function doesn't take any arguments",
|
||||
)
|
||||
@@ -31,11 +31,14 @@ export function useInfiniteQuery<T extends QueryFn>(
|
||||
const queryRpcFn = (queryFn as unknown) as EnhancedRpcFunction
|
||||
|
||||
const {data, ...queryRest} = useInfiniteReactQuery({
|
||||
queryKey: () => [queryRpcFn._meta.apiUrl, typeof params === 'function' ? (params as Function)() : params],
|
||||
queryKey: () => [
|
||||
queryRpcFn._meta.apiUrl,
|
||||
typeof params === "function" ? (params as Function)() : params,
|
||||
],
|
||||
queryFn: (_: string, params, more?) => queryRpcFn({...params, ...more}, {fromQueryHook: true}),
|
||||
config: {
|
||||
suspense: true,
|
||||
retry: process.env.NODE_ENV === 'production' ? 3 : false,
|
||||
retry: process.env.NODE_ENV === "production" ? 3 : false,
|
||||
...options,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import {usePaginatedQuery as usePaginatedReactQuery, PaginatedQueryResult, QueryOptions} from 'react-query'
|
||||
import {PromiseReturnType, InferUnaryParam, QueryFn} from './types'
|
||||
import {QueryCacheFunctions, getQueryCacheFunctions} from './utils/query-cache'
|
||||
import {EnhancedRpcFunction} from './rpc'
|
||||
import {
|
||||
usePaginatedQuery as usePaginatedReactQuery,
|
||||
PaginatedQueryResult,
|
||||
QueryOptions,
|
||||
} from "react-query"
|
||||
import {PromiseReturnType, InferUnaryParam, QueryFn} from "./types"
|
||||
import {QueryCacheFunctions, getQueryCacheFunctions} from "./utils/query-cache"
|
||||
import {EnhancedRpcFunction} from "./rpc"
|
||||
|
||||
type RestQueryResult<T extends QueryFn> = Omit<PaginatedQueryResult<PromiseReturnType<T>>, 'resolvedData'> &
|
||||
type RestQueryResult<T extends QueryFn> = Omit<
|
||||
PaginatedQueryResult<PromiseReturnType<T>>,
|
||||
"resolvedData"
|
||||
> &
|
||||
QueryCacheFunctions<PromiseReturnType<T>>
|
||||
|
||||
export function usePaginatedQuery<T extends QueryFn>(
|
||||
@@ -11,11 +18,11 @@ export function usePaginatedQuery<T extends QueryFn>(
|
||||
params: InferUnaryParam<T> | (() => InferUnaryParam<T>),
|
||||
options?: QueryOptions<PaginatedQueryResult<PromiseReturnType<T>>>,
|
||||
): [PromiseReturnType<T>, RestQueryResult<T>] {
|
||||
if (typeof queryFn === 'undefined') {
|
||||
throw new Error('usePaginatedQuery is missing the first argument - it must be a query function')
|
||||
if (typeof queryFn === "undefined") {
|
||||
throw new Error("usePaginatedQuery is missing the first argument - it must be a query function")
|
||||
}
|
||||
|
||||
if (typeof params === 'undefined') {
|
||||
if (typeof params === "undefined") {
|
||||
throw new Error(
|
||||
"usePaginatedQuery is missing the second argument. This will be the input to your query function on the server. Pass `null` if the query function doesn't take any arguments",
|
||||
)
|
||||
@@ -24,11 +31,14 @@ export function usePaginatedQuery<T extends QueryFn>(
|
||||
const queryRpcFn = (queryFn as unknown) as EnhancedRpcFunction
|
||||
|
||||
const {resolvedData, ...queryRest} = usePaginatedReactQuery({
|
||||
queryKey: () => [queryRpcFn._meta.apiUrl, typeof params === 'function' ? (params as Function)() : params],
|
||||
queryKey: () => [
|
||||
queryRpcFn._meta.apiUrl,
|
||||
typeof params === "function" ? (params as Function)() : params,
|
||||
],
|
||||
queryFn: (_: string, params) => queryRpcFn(params, {fromQueryHook: true}),
|
||||
config: {
|
||||
suspense: true,
|
||||
retry: process.env.NODE_ENV === 'production' ? 3 : false,
|
||||
retry: process.env.NODE_ENV === "production" ? 3 : false,
|
||||
...options,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useRouter} from 'next/router'
|
||||
import {useRouterQuery} from './use-router-query'
|
||||
import {useRouter} from "next/router"
|
||||
import {useRouterQuery} from "./use-router-query"
|
||||
|
||||
type ParsedUrlQueryValue = string | string[] | undefined
|
||||
|
||||
@@ -33,7 +33,8 @@ function areQueryValuesEqual(value1: ParsedUrlQueryValue, value2: ParsedUrlQuery
|
||||
export function extractRouterParams(routerQuery: ParsedUrlQuery, query: ParsedUrlQuery) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(routerQuery).filter(
|
||||
([key, value]) => typeof query[key] === 'undefined' || !areQueryValuesEqual(value, query[key]),
|
||||
([key, value]) =>
|
||||
typeof query[key] === "undefined" || !areQueryValuesEqual(value, query[key]),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -46,34 +47,34 @@ export function useParams() {
|
||||
}
|
||||
|
||||
export function useParam(key: string): undefined | string | string[]
|
||||
export function useParam(key: string, returnType: 'string'): string
|
||||
export function useParam(key: string, returnType: 'number'): number
|
||||
export function useParam(key: string, returnType: 'array'): string[]
|
||||
export function useParam(key: string, returnType: "string"): string
|
||||
export function useParam(key: string, returnType: "number"): number
|
||||
export function useParam(key: string, returnType: "array"): string[]
|
||||
export function useParam(
|
||||
key: string,
|
||||
returnType?: 'string' | 'number' | 'array',
|
||||
returnType?: "string" | "number" | "array",
|
||||
): undefined | number | string | string[] {
|
||||
const params = useParams()
|
||||
const rawValue = params[key]
|
||||
|
||||
if (returnType === 'number') {
|
||||
if (returnType === "number") {
|
||||
return Number(rawValue)
|
||||
}
|
||||
|
||||
if (returnType === 'string') {
|
||||
if (typeof rawValue === 'undefined') {
|
||||
return ''
|
||||
if (returnType === "string") {
|
||||
if (typeof rawValue === "undefined") {
|
||||
return ""
|
||||
}
|
||||
|
||||
return rawValue
|
||||
}
|
||||
|
||||
if (returnType === 'array') {
|
||||
if (typeof rawValue === 'undefined') {
|
||||
if (returnType === "array") {
|
||||
if (typeof rawValue === "undefined") {
|
||||
return []
|
||||
}
|
||||
|
||||
if (typeof rawValue === 'string') {
|
||||
if (typeof rawValue === "string") {
|
||||
return [rawValue]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {useQuery as useReactQuery, QueryResult, QueryOptions} from 'react-query'
|
||||
import {PromiseReturnType, InferUnaryParam, QueryFn} from './types'
|
||||
import {QueryCacheFunctions, getQueryCacheFunctions} from './utils/query-cache'
|
||||
import {EnhancedRpcFunction} from './rpc'
|
||||
import {useQuery as useReactQuery, QueryResult, QueryOptions} from "react-query"
|
||||
import {PromiseReturnType, InferUnaryParam, QueryFn} from "./types"
|
||||
import {QueryCacheFunctions, getQueryCacheFunctions} from "./utils/query-cache"
|
||||
import {EnhancedRpcFunction} from "./rpc"
|
||||
|
||||
type RestQueryResult<T extends QueryFn> = Omit<QueryResult<PromiseReturnType<T>>, 'data'> &
|
||||
type RestQueryResult<T extends QueryFn> = Omit<QueryResult<PromiseReturnType<T>>, "data"> &
|
||||
QueryCacheFunctions<PromiseReturnType<T>>
|
||||
|
||||
export function useQuery<T extends QueryFn>(
|
||||
@@ -11,11 +11,11 @@ export function useQuery<T extends QueryFn>(
|
||||
params: InferUnaryParam<T> | (() => InferUnaryParam<T>),
|
||||
options?: QueryOptions<QueryResult<PromiseReturnType<T>>>,
|
||||
): [PromiseReturnType<T>, RestQueryResult<T>] {
|
||||
if (typeof queryFn === 'undefined') {
|
||||
throw new Error('useQuery is missing the first argument - it must be a query function')
|
||||
if (typeof queryFn === "undefined") {
|
||||
throw new Error("useQuery is missing the first argument - it must be a query function")
|
||||
}
|
||||
|
||||
if (typeof params === 'undefined') {
|
||||
if (typeof params === "undefined") {
|
||||
throw new Error(
|
||||
"useQuery is missing the second argument. This will be the input to your query function on the server. Pass `null` if the query function doesn't take any arguments",
|
||||
)
|
||||
@@ -24,11 +24,14 @@ export function useQuery<T extends QueryFn>(
|
||||
const queryRpcFn = (queryFn as unknown) as EnhancedRpcFunction
|
||||
|
||||
const {data, ...queryRest} = useReactQuery({
|
||||
queryKey: () => [queryRpcFn._meta.apiUrl, typeof params === 'function' ? (params as Function)() : params],
|
||||
queryKey: () => [
|
||||
queryRpcFn._meta.apiUrl,
|
||||
typeof params === "function" ? (params as Function)() : params,
|
||||
],
|
||||
queryFn: (_: string, params) => queryRpcFn(params, {fromQueryHook: true}),
|
||||
config: {
|
||||
suspense: true,
|
||||
retry: process.env.NODE_ENV === 'production' ? 3 : false,
|
||||
retry: process.env.NODE_ENV === "production" ? 3 : false,
|
||||
...options,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useRouter} from 'next/router'
|
||||
import {parse} from 'url'
|
||||
import {useRouter} from "next/router"
|
||||
import {parse} from "url"
|
||||
|
||||
export function useRouterQuery() {
|
||||
const router = useRouter()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {useRouter as useNextRouter} from 'next/router'
|
||||
import {useParams} from './use-params'
|
||||
import {useRouterQuery} from './use-router-query'
|
||||
import {useRouter as useNextRouter} from "next/router"
|
||||
import {useParams} from "./use-params"
|
||||
import {useRouterQuery} from "./use-router-query"
|
||||
|
||||
export function useRouter() {
|
||||
const router = useNextRouter()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user