1
0
mirror of synced 2026-02-07 12:00:13 -05:00

Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot]
21b83fb7bf Version Packages (beta) (#4038)
* Version Packages (beta)

* pnpm lock

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Siddharth Suresh <siddh.suresh@gmail.com>
2023-01-12 10:43:33 +05:30
95 changed files with 572 additions and 1927 deletions

View File

@@ -70,6 +70,7 @@
"chilly-candles-care",
"chilly-nails-nail",
"clean-hats-pump",
"clean-hounds-laugh",
"clean-walls-wink",
"clever-radios-lie",
"cool-doors-invent",
@@ -116,6 +117,7 @@
"gentle-lions-explode",
"giant-mails-tap",
"giant-students-carry",
"giant-timers-search",
"gold-horses-punch",
"good-apes-drum",
"good-insects-wink",
@@ -153,6 +155,7 @@
"lemon-games-press",
"lemon-pillows-switch",
"lemon-seas-push",
"lemon-teachers-jam",
"light-donkeys-double",
"light-squids-draw",
"little-pears-ring",
@@ -203,6 +206,7 @@
"popular-teachers-pay",
"pretty-games-march",
"purple-donkeys-smash",
"purple-jars-begin",
"purple-singers-greet",
"quick-cycles-confess",
"quick-dots-fetch",
@@ -240,6 +244,7 @@
"smooth-stingrays-drum",
"smooth-tools-train",
"soft-adults-smell",
"soft-fans-carry",
"sour-lemons-hunt",
"sour-mails-lick",
"spicy-beds-float",
@@ -255,6 +260,7 @@
"stupid-walls-sell",
"sweet-kiwis-cross",
"swift-drinks-dress",
"swift-poets-travel",
"tall-meals-learn",
"tame-keys-reply",
"tame-pumpkins-nail",
@@ -273,6 +279,7 @@
"tidy-clouds-smoke",
"tidy-llamas-compare",
"tough-toes-pull",
"tricky-kids-press",
"twelve-hornets-sip",
"twelve-lemons-smile",
"twelve-needles-worry",

View File

@@ -1,6 +0,0 @@
---
"blitz": patch
"@blitzjs/generator": patch
---
Multiple fields forms using templates during generation - TODO

View File

@@ -1,47 +0,0 @@
name: PR-Release
on:
pull_request:
types: [issue_comment]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
changeset:
if: ${{ contains(github.event.pull_request.labels.*.name, 'release/next') && github.event.pull_request.merged == false && contains(github.event.comment.body,'/publish') && github.event.comment.author_association == 'MEMBER' }}
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 16
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Version
run: |
pnpm changeset pre exit
pnpm changeset version --snapshot next-${{ github.event.pull_request.number }}
- name: Publish
run: pnpm changeset publish --tag next@${{ github.event.pull_request.number }}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Comment on PR
uses: peter-evans/create-or-update-comment@v2
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
The new version of this PR is available as next in npm:
```
npm install <package>@next${{ github.event.pull_request.number }}
```

View File

@@ -30,7 +30,7 @@
"@hookform/error-message": "2.0.0",
"@hookform/resolvers": "2.9.10",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"next": "12.2.5",
"openid-client": "5.2.1",
"prisma": "4.6.0",

View File

@@ -31,7 +31,7 @@
"@hookform/error-message": "2.0.0",
"@hookform/resolvers": "2.9.10",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"next": "12.2.5",
"prisma": "4.6.0",
"react": "18.2.0",

View File

@@ -1,63 +0,0 @@
import { ComponentPropsWithoutRef, forwardRef, PropsWithoutRef } from "react"
import { useFormContext } from "react-hook-form"
import { ErrorMessage } from "@hookform/error-message"
export interface LabeledSelectFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["select"]> {
/** Field name. */
name: string
/** Field label. */
label: string
/** Field type. Doesn't include radio buttons and checkboxes */
options: any[]
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
labelProps?: ComponentPropsWithoutRef<"label">
}
export const LabeledSelectField = forwardRef<HTMLSelectElement, LabeledSelectFieldProps>(
({ label, outerProps, labelProps, name, options, ...props }, ref) => {
const {
register,
formState: { isSubmitting, errors },
} = useFormContext()
return (
<div {...outerProps}>
<label {...labelProps}>
{label}
<select {...register(name)} disabled={isSubmitting} {...props}>
{options &&
options.map((value) => (
<option value={value.id} key={value.id}>
{value[name]}
</option>
))}
</select>
</label>
<ErrorMessage
render={({ message }) => (
<div role="alert" style={{ color: "red" }}>
{message}
</div>
)}
errors={errors}
name={name}
/>
<style jsx>{`
label {
display: flex;
flex-direction: column;
align-items: start;
font-size: 1rem;
}
select {
font-size: 1rem;
padding: 0.25rem 0.5rem;
border-radius: 3px;
border: 1px solid purple;
appearance: none;
margin-top: 0.5rem;
}
`}</style>
</div>
)
}
)

View File

@@ -1,31 +0,0 @@
import { paginate } from "blitz"
import { resolver } from "@blitzjs/rpc"
import db, { Prisma } from "db"
interface GetProjectsInput
extends Pick<Prisma.UserFindManyArgs, "where" | "orderBy" | "skip" | "take"> {}
export default resolver.pipe(
resolver.authorize(),
async ({ where, orderBy, skip = 0, take = 100 }: GetProjectsInput) => {
// TODO: in multi-tenant app, you must add validation to ensure correct tenant
const {
items: users,
hasMore,
nextPage,
count,
} = await paginate({
skip,
take,
count: () => db.user.count({ where }),
query: (paginateArgs) => db.user.findMany({ ...paginateArgs, where, orderBy }),
})
return {
users,
nextPage,
hasMore,
count,
}
}
)

View File

@@ -17,14 +17,14 @@
"prisma:studio": "prisma studio"
},
"dependencies": {
"@blitzjs/auth": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "workspace:2.0.0-beta.22",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"@hookform/error-message": "2.0.0",
"@hookform/resolvers": "2.9.10",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"delay": "5.0.0",
"next": "12.2.5",
"prisma": "4.6.0",

View File

@@ -17,11 +17,11 @@
"prisma:studio": "prisma studio"
},
"dependencies": {
"@blitzjs/auth": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "workspace:2.0.0-beta.22",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"lowdb": "3.0.0",
"next": "12.2.5",
"prisma": "4.6.0",

View File

@@ -16,11 +16,11 @@
"schema": "db/schema.prisma"
},
"dependencies": {
"@blitzjs/auth": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"lowdb": "3.0.0",
"next": "12.2.5",
"prisma": "4.6.0",
@@ -28,7 +28,7 @@
"react-dom": "18.2.0"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@next/bundle-analyzer": "12.0.8",
"@types/express": "4.17.13",
"@types/fs-extra": "9.0.13",

View File

@@ -11,10 +11,10 @@
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
},
"dependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"blitz": "workspace:2.0.0-beta.22",
"next": "12.2.5",
"react": "18.2.0",
"react-dom": "18.2.0"

View File

@@ -16,11 +16,11 @@
"prisma:studio": "prisma studio"
},
"dependencies": {
"@blitzjs/auth": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"lowdb": "3.0.0",
"next": "12.2.5",
"prisma": "4.6.0",
@@ -28,7 +28,7 @@
"react-dom": "18.2.0"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@next/bundle-analyzer": "12.0.8",
"@types/express": "4.17.13",
"@types/fs-extra": "9.0.13",

View File

@@ -8,13 +8,13 @@
"clean": "rm -rf .turbo && rm -rf node_modules"
},
"dependencies": {
"@blitzjs/auth": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "workspace:2.0.0-beta.22",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"@prisma/client": "4.6.0",
"@tanstack/react-query": "4.0.10",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"next": "12.2.5",
"prisma": "4.6.0",
"react": "18.2.0",

View File

@@ -16,10 +16,10 @@
"schema": "db/schema.prisma"
},
"dependencies": {
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"lowdb": "3.0.0",
"next": "12.2.5",
"prisma": "4.6.0",
@@ -27,7 +27,7 @@
"react-dom": "18.2.0"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@next/bundle-analyzer": "12.0.8",
"@types/express": "4.17.13",
"@types/fs-extra": "9.0.13",

View File

@@ -7,10 +7,10 @@
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
},
"dependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"blitz": "workspace:2.0.0-beta.22",
"next": "12.2.5",
"react": "18.2.0",
"react-dom": "18.2.0"

View File

@@ -7,10 +7,10 @@
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
},
"dependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"blitz": "workspace:2.0.0-beta.22",
"next": "12.2.5",
"react": "18.2.0",
"react-dom": "18.2.0"

View File

@@ -16,11 +16,11 @@
"schema": "db/schema.prisma"
},
"dependencies": {
"@blitzjs/auth": "workspace:2.0.0-beta.21",
"@blitzjs/next": "workspace:2.0.0-beta.21",
"@blitzjs/rpc": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "workspace:2.0.0-beta.22",
"@blitzjs/next": "workspace:2.0.0-beta.22",
"@blitzjs/rpc": "workspace:2.0.0-beta.22",
"@prisma/client": "4.6.0",
"blitz": "workspace:2.0.0-beta.21",
"blitz": "workspace:2.0.0-beta.22",
"lowdb": "3.0.0",
"next": "12.2.5",
"prisma": "4.6.0",
@@ -28,7 +28,7 @@
"react-dom": "18.2.0"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@next/bundle-analyzer": "12.0.8",
"@types/express": "4.17.13",
"@types/fs-extra": "9.0.13",

View File

@@ -1,5 +1,17 @@
# @blitzjs/auth
## 2.0.0-beta.22
### Minor Changes
- 145d5a02b: fix failed localStorage access to not crash the application
### Patch Changes
- Updated dependencies [989691ec8]
- Updated dependencies [8aa22a0b2]
- blitz@2.0.0-beta.22
## 2.0.0-beta.21
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/auth",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"scripts": {
"build": "unbuild",
"predev": "wait-on -d 250 ../blitz/dist/index-server.d.ts",
@@ -39,10 +39,10 @@
"url": "0.11.0"
},
"peerDependencies": {
"blitz": "2.0.0-beta.21"
"blitz": "2.0.0-beta.22"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@testing-library/react": "13.4.0",
"@testing-library/react-hooks": "8.0.1",
"@types/cookie": "0.4.1",
@@ -50,7 +50,7 @@
"@types/jsonwebtoken": "8.5.8",
"@types/react": "18.0.25",
"@types/react-dom": "17.0.14",
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "^4.8.4",

View File

@@ -1,5 +1,15 @@
# @blitzjs/next
## 2.0.0-beta.22
### Patch Changes
- Updated dependencies [270361886]
- Updated dependencies [989691ec8]
- Updated dependencies [8aa22a0b2]
- @blitzjs/rpc@2.0.0-beta.22
- blitz@2.0.0-beta.22
## 2.0.0-beta.21
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/next",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"scripts": {
"build": "unbuild",
"dev": "pnpm predev && pnpm watch unbuild src --wait=0.2",
@@ -24,7 +24,7 @@
"eslint.js"
],
"dependencies": {
"@blitzjs/rpc": "2.0.0-beta.21",
"@blitzjs/rpc": "2.0.0-beta.22",
"@tanstack/react-query": "4.0.10",
"@types/hoist-non-react-statics": "3.3.1",
"debug": "4.3.3",
@@ -34,12 +34,12 @@
"supports-color": "8.1.1"
},
"peerDependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"next": "*",
"react": "*"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@testing-library/dom": "8.13.0",
"@testing-library/jest-dom": "5.16.3",
"@testing-library/react": "13.4.0",
@@ -49,7 +49,7 @@
"@types/react": "18.0.25",
"@types/react-dom": "17.0.14",
"@types/testing-library__react-hooks": "4.0.0",
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"cross-spawn": "7.0.3",
"find-up": "4.1.0",
"next": "12.2.5",

View File

@@ -1,5 +1,17 @@
# @blitzjs/rpc
## 2.0.0-beta.22
### Minor Changes
- 270361886: change rpc route basepath to be one folder higher when using includeRPC in monorepos
### Patch Changes
- Updated dependencies [989691ec8]
- Updated dependencies [8aa22a0b2]
- blitz@2.0.0-beta.22
## 2.0.0-beta.21
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/rpc",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"scripts": {
"build": "unbuild",
"predev": "wait-on -d 400 ../blitz/dist/index-server.d.ts && wait-on -d 400 ../blitz-auth/dist/index-browser.d.ts",
@@ -30,17 +30,17 @@
"supports-color": "8.1.1"
},
"peerDependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"next": "*",
"react": "*"
},
"devDependencies": {
"@blitzjs/auth": "2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/auth": "2.0.0-beta.22",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@types/debug": "4.1.7",
"@types/react": "18.0.25",
"@types/react-dom": "17.0.14",
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"next": "12.2.5",
"react": "18.2.0",
"react-dom": "18.2.0",

View File

@@ -1,5 +1,18 @@
# blitz
## 2.0.0-beta.22
### Minor Changes
- 8aa22a0b2: add `currentPassword` to the default fields that are masked in the logger
### Patch Changes
- 989691ec8: Use `src` instead of `app` folder for `blitz generate custom-template`
- Updated dependencies [bcef81fad]
- Updated dependencies [7abfb9086]
- @blitzjs/generator@2.0.0-beta.22
## 2.0.0-beta.21
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "blitz",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"scripts": {
"build": "unbuild",
"dev": "rm -rf dist && pnpm run predev && watch unbuild src --wait=0.2",
@@ -25,7 +25,7 @@
"blitz": "bin/blitz"
},
"dependencies": {
"@blitzjs/generator": "2.0.0-beta.21",
"@blitzjs/generator": "2.0.0-beta.22",
"@mrleebo/prisma-ast": "0.2.6",
"@types/global-agent": "2.1.1",
"arg": "5.0.1",
@@ -74,7 +74,7 @@
"watchpack": "2.1.1"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-beta.21",
"@blitzjs/config": "workspace:2.0.0-beta.22",
"@types/cookie": "0.4.1",
"@types/cross-spawn": "6.0.2",
"@types/debug": "4.1.7",

View File

@@ -15,10 +15,6 @@ import {
MutationsGenerator,
ModelGenerator,
QueryGenerator,
ModelName,
modelName,
ModelNames,
modelNames,
customTemplatesBlitzConfig,
} from "@blitzjs/generator"
import {log} from "../../logging"
@@ -39,6 +35,19 @@ enum ResourceType {
CustomTemplates = "custom-templates",
}
function modelName(input: string = "") {
return singleCamel(input)
}
function modelNames(input: string = "") {
return pluralCamel(input)
}
function ModelName(input: string = "") {
return singlePascal(input)
}
function ModelNames(input: string = "") {
return pluralPascal(input)
}
const createCustomTemplates = async () => {
const continuePrompt = await prompts({
type: "confirm",
@@ -57,6 +66,7 @@ const createCustomTemplates = async () => {
const templatesPathValue: string = templatesPath.value
const isTypeScript = await getIsTypeScript()
await customTemplatesBlitzConfig(isTypeScript, templatesPathValue, true) // to run the codemod
log.success(`🚀 Custom templates path added/updated in src/blitz-server file`)
const customTemplatesPath = require("path").join(process.cwd(), templatesPathValue)
const fsExtra = await import("fs-extra")
const blitzGeneratorPath = require.resolve("@blitzjs/generator")
@@ -276,7 +286,6 @@ const generate: CliCommand = async () => {
modelNames: modelNames(singularRootContext),
ModelName: ModelName(singularRootContext),
ModelNames: ModelNames(singularRootContext),
rawParentModelName: args["--parent"],
parentModel: modelName(selectedParent),
parentModels: modelNames(selectedParent),
ParentModel: ModelName(selectedParent),

View File

@@ -2,16 +2,6 @@ import {UrlObject} from "url"
// Context for plugins to declaration merge stuff into
export interface Ctx {}
export interface AuthenticatedMiddlewareCtx {}
export type CodegenField = {
component: string
inputType: string
zodType: string
prismaType: string
default?: string
}
export interface RouteUrlObject extends Pick<UrlObject, "pathname" | "query" | "href"> {
pathname: string
href: string
@@ -42,33 +32,9 @@ export type ResolverConfig = {
}
export type BlitzCliConfig = {
codegen?: {
fieldTypeMap?: Record<
| "string"
| "boolean"
| "int"
| "number"
| "bigint"
| "float"
| "decimal"
| "datetime"
| "uuid"
| "json",
CodegenField
>
}
customTemplates?: string
}
export type CodegenConfig = {
templateDir?: string
fieldTypeMap?: Record<string, CodegenField>
}
export interface RouteUrlObject extends Pick<UrlObject, "pathname" | "query"> {
pathname: string
}
export const isRouteUrlObject = (x: any): x is RouteUrlObject => {
return (
typeof x === "object" &&

View File

@@ -1,5 +1,16 @@
# @blitzjs/codemod
## 2.0.0-beta.22
### Patch Changes
- Updated dependencies [989691ec8]
- Updated dependencies [bcef81fad]
- Updated dependencies [8aa22a0b2]
- Updated dependencies [7abfb9086]
- blitz@2.0.0-beta.22
- @blitzjs/generator@2.0.0-beta.22
## 2.0.0-beta.21
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/codemod",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"scripts": {
"build": "unbuild",
"dev": "watch unbuild src --wait=0.2",
@@ -25,9 +25,9 @@
"@babel/plugin-proposal-class-properties": "7.17.12",
"@babel/plugin-syntax-jsx": "7.17.12",
"@babel/plugin-syntax-typescript": "7.17.12",
"@blitzjs/generator": "2.0.0-beta.21",
"@blitzjs/generator": "2.0.0-beta.22",
"arg": "5.0.1",
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"chalk": "^4.1.0",
"cross-spawn": "7.0.3",
"debug": "4.3.3",

View File

@@ -1,5 +1,7 @@
# @blitzjs/config
## 2.0.0-beta.22
## 2.0.0-beta.21
## 2.0.0-beta.20

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/config",
"private": true,
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "5.42.1",

View File

@@ -1,5 +1,15 @@
# @blitzjs/generator
## 2.0.0-beta.22
### Minor Changes
- 7abfb9086: Redesign the index page for newly generated blitz projects
### Patch Changes
- bcef81fad: Fix missing MockRouter prop in test utils
## 2.0.0-beta.21
### Patch Changes

View File

@@ -2,7 +2,7 @@ import {BuildConfig} from "unbuild"
const config: BuildConfig = {
entries: ["./src/index"],
externals: ["react", "zod"],
externals: ["react"],
declaration: true,
rollup: {
emitCJS: true,

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/generator",
"version": "2.0.0-beta.21",
"version": "2.0.0-beta.22",
"scripts": {
"dev": "watch unbuild src --wait=0.2",
"build": "unbuild && pnpm build:templates",
@@ -30,7 +30,6 @@
"cross-spawn": "7.0.3",
"diff": "5.0.0",
"enquirer": "2.3.6",
"fast-glob": "3.2.12",
"fs-extra": "10.0.1",
"globby": "13.1.2",
"got": "^11.8.1",
@@ -48,7 +47,7 @@
"vinyl": "2.2.1"
},
"devDependencies": {
"@blitzjs/config": "2.0.0-beta.21",
"@blitzjs/config": "2.0.0-beta.22",
"@juanm04/cpx": "2.0.1",
"@types/babel__core": "7.1.19",
"@types/diff": "5.0.2",
@@ -69,8 +68,7 @@
"react": "18.2.0",
"typescript": "^4.8.4",
"unbuild": "0.6.9",
"watch": "1.0.2",
"zod": "3.20.2"
"watch": "1.0.2"
},
"publishConfig": {
"access": "public"

View File

@@ -1,13 +1,10 @@
import * as babel from "@babel/core"
// @ts-ignore TS wants types for this module but none exist
import babelTransformTypescript from "@babel/plugin-transform-typescript"
import {escapePath} from "fast-glob"
import Enquirer from "enquirer"
import {EventEmitter} from "events"
import * as fs from "fs-extra"
import j from "jscodeshift"
import {CommonTemplateValues, IBuilder} from "./generators/template-builders/builder"
import {NullBuilder} from "./generators/template-builders/null-builder"
import {create as createStore, Store} from "mem-fs"
import {create as createEditor, Editor} from "mem-fs-editor"
import * as path from "path"
@@ -17,7 +14,6 @@ import {ConflictChecker} from "./conflict-checker"
import {pipe} from "./utils/pipe"
import {readdirRecursive} from "./utils/readdir-recursive"
import prettier from "prettier"
import {log} from "./utils/log"
const debug = require("debug")("blitz:generator")
export function getProjectRootSync() {
@@ -44,7 +40,7 @@ export const customTemplatesBlitzConfig = async (
if (blitzServer.length > 1) {
throw new Error("Found more than one blitz-server.js or blitz-server.ts in app or src folder")
}
const blitzServerPath = require("path").join(process.cwd(), blitzServer[0])
const blitzServerPath = require("path").join(process.cwd(), blitzServer.at(0))
const userConfigModuleSource = fs.readFileSync(blitzServerPath, {encoding: "utf-8"})
const userConfigModule = j(userConfigModuleSource, {parser: customTsParser})
const program = userConfigModule.get()
@@ -271,16 +267,7 @@ export abstract class Generator<
if (!this.options.destinationRoot) this.options.destinationRoot = process.cwd()
}
public templateValuesBuilder: IBuilder<T, any> = NullBuilder
async getTemplateValues(): Promise<any> {
const values = await this.templateValuesBuilder.getTemplateValues(this.options)
return values
}
public fieldTemplateRegExp: RegExp = new RegExp(
/({?\/\*\s*template: (.*) \*\/}?|\s*\/\/\s*template: (.*))/g,
)
abstract getTemplateValues(): Promise<any>
abstract getTargetDirectory(): string
@@ -308,12 +295,6 @@ export abstract class Generator<
replaceTemplateValues(input: string, templateValues: any) {
let result = input
for (let templateKey in templateValues) {
const token = `__${templateKey}__`
if (result.includes(token)) {
result = result.replace(new RegExp(token, "g"), templateValues[templateKey] as string)
}
}
for (let templateKey in templateValues.fieldTemplateValues) {
const token = `__${templateKey}__`
if (result.includes(token)) {
result = result.replace(new RegExp(token, "g"), templateValues[templateKey])
@@ -338,21 +319,6 @@ export abstract class Generator<
if (codeFileExtensions.test(pathEnding)) {
templatedFile = this.replaceConditionals(inputStr, templateValues, prettierOptions || {})
}
const fieldTemplateString = templatedFile
?.match(this.fieldTemplateRegExp)
?.at(0)
?.replace(this.fieldTemplateRegExp, "$2$3")
if (fieldTemplateString) {
const fieldTemplatePosition = templatedFile.search(this.fieldTemplateRegExp)
templatedFile = [
templatedFile.slice(0, fieldTemplatePosition),
...(templateValues.fieldTemplateValues?.map((values: any) =>
this.replaceTemplateValues(fieldTemplateString, values),
) || []),
templatedFile.slice(fieldTemplatePosition),
].join("")
}
templatedFile = this.replaceTemplateValues(templatedFile, templateValues)
if (!this.useTs && tsExtension.test(pathEnding)) {
templatedFile =
@@ -377,21 +343,12 @@ export abstract class Generator<
try {
templatedFile = this.prettier.format(templatedFile, options)
} catch (error) {
console.error(`Failed trying to run prettier: ` + error)
console.warn(`Failed trying to run prettier: ` + error)
}
}
return templatedFile
}
async preFileWrite(filePath: string): Promise<CommonTemplateValues> {
// allow subclasses to do something before writing a file
return this.getTemplateValues()
}
async postFileWrite(filePath: string, templateValues: CommonTemplateValues): Promise<void> {
// allow subclasses to do something after writing a file
}
async write(): Promise<void> {
debug("Generator.write...")
const sourcePath = this.sourcePath()
@@ -399,45 +356,33 @@ export abstract class Generator<
const additionalFilesToIgnore = this.filesToIgnore()
return ![...alwaysIgnoreFiles, ...additionalFilesToIgnore].includes(name)
})
const prettierOptions = await this.prettier?.resolveConfig(sourcePath)
for (let filePath of paths) {
try {
let templateValues = await this.getTemplateValues()
const pathSuffix = path.join(this.getTargetDirectory(), filePath)
const sourcePath = this.sourcePath(filePath)
const destinationPath = this.destinationPath(pathSuffix)
let templatedPathSuffix = this.replaceTemplateValues(pathSuffix, templateValues)
const templatedDestinationPath = this.destinationPath(templatedPathSuffix)
const destinationExists = fs.existsSync(templatedDestinationPath)
let pathSuffix = filePath
pathSuffix = path.join(this.getTargetDirectory(), pathSuffix)
const templateValues = await this.getTemplateValues()
templateValues = await this.preFileWrite(templatedPathSuffix)
let templatedPathSuffix = this.replaceTemplateValues(pathSuffix, templateValues)
const newContent = this.process(
this.fs.read(this.sourcePath(filePath), {raw: true}) as any,
pathSuffix,
templateValues,
prettierOptions ?? undefined,
)
this.fs.write(this.destinationPath(pathSuffix), newContent)
if (!this.useTs && tsExtension.test(this.destinationPath(pathSuffix))) {
templatedPathSuffix = templatedPathSuffix.replace(tsExtension, ".js")
}
if (destinationExists) {
const newContent = this.process(
this.fs.read(templatedDestinationPath, {raw: true}) as any,
pathSuffix,
templateValues,
prettierOptions ?? undefined,
)
this.fs.write(templatedDestinationPath, newContent)
} else {
this.fs.copy(escapePath(sourcePath), escapePath(destinationPath), {
process: (input) =>
this.process(input, pathSuffix, templateValues, prettierOptions ?? undefined),
})
if (templatedPathSuffix !== pathSuffix) {
this.fs.move(destinationPath, templatedDestinationPath)
}
if (templatedPathSuffix !== pathSuffix) {
this.fs.move(this.destinationPath(pathSuffix), this.destinationPath(templatedPathSuffix))
}
await this.postFileWrite(templatedPathSuffix, templateValues)
} catch (error) {
log.error(`Error generating ${filePath}`)
console.error(`Error generating ${filePath}`)
throw error
}
}

View File

@@ -2,7 +2,7 @@ import spawn from "cross-spawn"
import chalk from "chalk"
import {readJSONSync, writeJson} from "fs-extra"
import {join} from "path"
import {AppValuesBuilder} from "./template-builders/app-values-builder"
import username from "username"
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
import {baseLogger, log} from "../utils/log"
import {fetchLatestVersionsFor} from "../utils/fetch-latest-version-for"
@@ -12,12 +12,6 @@ function assert(condition: any, message: string): asserts condition {
if (!condition) throw new Error(message)
}
export interface AppTemplateValues {
name: string
safeNameSlug: string
username: string | undefined
}
type TemplateConfig = {
path: string
skipForms?: boolean
@@ -52,7 +46,13 @@ export class AppGenerator extends Generator<AppGeneratorOptions> {
return ["jsconfig.json", "package.js.json", "vitest.config.js"]
}
templateValuesBuilder = new AppValuesBuilder(this.fs)
async getTemplateValues() {
return {
name: this.options.appName,
safeNameSlug: this.options.appName.replace(/[^a-zA-Z0-9-_]/g, "-"),
username: await username(),
}
}
getTargetDirectory() {
return ""

View File

@@ -1,21 +1,17 @@
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
import {getTemplateRoot} from "../utils/get-template-root"
import {camelCaseToKebabCase} from "../utils/inflector"
import {
CommonTemplateValues,
createFieldTemplateValues,
FieldValuesBuilder,
ResourceGeneratorOptions,
} from ".."
import {customTsParser, Generator, SourceRootType} from "../generator"
import j from "jscodeshift"
import {
insertImportPagnatedQuery,
insertImportQuery,
insertLabeledSelectField,
updateFormWithParent,
} from "../../src/utils/codemod-utils"
export interface FormGeneratorOptions extends ResourceGeneratorOptions {}
export interface FormGeneratorOptions extends GeneratorOptions {
ModelName: string
ModelNames: string
modelName: string
modelNames: string
parentModel?: string
parentModels?: string
ParentModel?: string
ParentModels?: string
}
export class FormGenerator extends Generator<FormGeneratorOptions> {
sourceRoot: SourceRootType
@@ -26,35 +22,31 @@ export class FormGenerator extends Generator<FormGeneratorOptions> {
static subdirectory = "queries"
templateValuesBuilder = new FieldValuesBuilder()
async preFileWrite(): Promise<CommonTemplateValues> {
let templateValues = await this.getTemplateValues()
if (templateValues.parentModel) {
const newFieldTemplateValues = await createFieldTemplateValues(
templateValues.parentModelId,
templateValues.parentModelIdZodType,
true,
)
if (templateValues.fieldTemplateValues) {
templateValues.fieldTemplateValues.push(newFieldTemplateValues)
} else {
templateValues.fieldTemplateValues = [newFieldTemplateValues]
}
}
return templateValues
private getId(input: string = "") {
if (!input) return input
return `${input}Id`
}
async postFileWrite(filePath: string, templateValues: CommonTemplateValues): Promise<void> {
if (templateValues.parentModel && filePath.match(/components/g)) {
let program = j(this.fs.read(filePath), {
parser: customTsParser,
})
program = insertLabeledSelectField(program)
program = insertImportQuery(program, templateValues)
program = insertImportPagnatedQuery(program)
program = updateFormWithParent(program, templateValues)
this.fs.write(filePath, program.toSource())
private getParam(input: string = "") {
if (!input) return input
return `[${input}]`
}
// eslint-disable-next-line require-await
async getTemplateValues() {
return {
parentModelId: this.getId(this.options.parentModel),
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
parentModel: this.options.parentModel,
parentModels: this.options.parentModels,
ParentModel: this.options.ParentModel,
ParentModels: this.options.ParentModels,
modelId: this.getId(this.options.modelName),
modelIdParam: this.getParam(this.getId(this.options.modelName)),
modelName: this.options.modelName,
modelNames: this.options.modelNames,
ModelName: this.options.ModelName,
ModelNames: this.options.ModelNames,
}
}

View File

@@ -1,12 +1,12 @@
import * as ast from "@mrleebo/prisma-ast"
import {spawn} from "cross-spawn"
import which from "npm-which"
import path from "path"
import {log} from "../utils/log"
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
import {Field} from "../prisma/field"
import {Model} from "../prisma/model"
import {getTemplateRoot} from "../utils/get-template-root"
import {getPrismaSchema} from "../utils/get-prisma-schema"
export interface ModelGeneratorOptions extends GeneratorOptions {
modelName: string
@@ -22,7 +22,8 @@ export class ModelGenerator extends Generator<ModelGeneratorOptions> {
// default subdirectory is /app/[name], we need to back out of there to generate the model
static subdirectory = "../.."
unsafe_disableConflictChecker = true
prisma = true
async getTemplateValues() {}
getTargetDirectory() {
return ""
@@ -40,68 +41,73 @@ export class ModelGenerator extends Generator<ModelGeneratorOptions> {
// eslint-disable-next-line require-await
async write() {
const obj = getPrismaSchema(this.fs)
if (typeof obj !== "boolean") {
const {schema, schemaPath} = obj
const {modelName, extraArgs, dryRun} = this.options
let updatedOrCreated = "created"
const pkgJson = this.fs.readJSON("package.json", {}) as {[key: string]: any}
const rawSchemaPath = pkgJson?.prisma?.schema || "db/schema.prisma"
let fieldPromises = (
extraArgs.length === 1 && extraArgs[0]?.includes(" ") ? extraArgs[0]?.split(" ") : extraArgs
).map((input) => Field.parse(input, schema))
let fields = (await Promise.all(fieldPromises)).flatMap((fieldArray) => fieldArray)
const modelDefinition = new Model(modelName, fields)
const schemaPath = path.resolve(rawSchemaPath)
if (!this.fs.exists(schemaPath)) {
throw new Error("Prisma schema file was not found")
}
let model: ast.Model | undefined
if (!dryRun) {
model = schema.list.find(function (component): component is ast.Model {
return component.type === "model" && component.name === modelDefinition.name
})
try {
if (model) {
for (const field of fields) field.appendTo(model)
this.fs.write(schemaPath, ast.printSchema(schema))
updatedOrCreated = "updated"
} else {
model = modelDefinition.appendTo(schema)
this.fs.write(schemaPath, ast.printSchema(schema))
}
} catch (err) {
console.error(`Failed to apply changes to model '${modelDefinition.name}'`)
throw err
let schema: ast.Schema
try {
schema = ast.getSchema(this.fs.read(schemaPath))
} catch (err) {
console.error(`Failed to parse ${rawSchemaPath} file`)
throw err
}
const {modelName, extraArgs, dryRun} = this.options
let updatedOrCreated = "created"
let fields = (
extraArgs.length === 1 && extraArgs[0]?.includes(" ") ? extraArgs[0]?.split(" ") : extraArgs
).flatMap((input) => Field.parse(input, schema))
const modelDefinition = new Model(modelName, fields)
let model: ast.Model | undefined
if (!dryRun) {
model = schema.list.find(function (component): component is ast.Model {
return component.type === "model" && component.name === modelDefinition.name
})
try {
if (model) {
for (const field of fields) field.appendTo(model)
this.fs.write(schemaPath, ast.printSchema(schema))
updatedOrCreated = "updated"
} else {
model = modelDefinition.appendTo(schema)
this.fs.write(schemaPath, ast.printSchema(schema))
}
} catch (err) {
console.error(`Failed to apply changes to model '${modelDefinition.name}'`)
throw err
}
}
if (model) {
console.log("\n")
console.log(
`Model '${modelDefinition.name}'${
dryRun ? "" : ` ${updatedOrCreated} in schema.prisma`
}:\n`,
)
ast
.printSchema({type: "schema", list: [model]})
.split("\n")
.map(log.progress)
console.log("\n")
}
} else {
this.prisma = false
if (model) {
console.log("\n")
console.log(
`Model '${modelDefinition.name}'${
dryRun ? "" : ` ${updatedOrCreated} in schema.prisma`
}:\n`,
)
ast
.printSchema({type: "schema", list: [model]})
.split("\n")
.map(log.progress)
console.log("\n")
}
}
async postWrite() {
if (this.prisma) {
const prismaBin = which(process.cwd()).sync("prisma")
//@ts-ignore
spawn.sync(prismaBin, ["format"], {stdio: "inherit"})
const shouldMigrate = await this.prismaMigratePrompt()
if (shouldMigrate) {
await new Promise<void>((res, rej) => {
const child = spawn(prismaBin, ["migrate", "dev"], {stdio: "inherit"})
child.on("exit", (code) => (code === 0 ? res() : rej()))
})
}
const shouldMigrate = await this.prismaMigratePrompt()
if (shouldMigrate) {
await new Promise<void>((res, rej) => {
const prismaBin = which(process.cwd()).sync("prisma")
const child = spawn(prismaBin, ["migrate", "dev"], {stdio: "inherit"})
child.on("exit", (code) => (code === 0 ? res() : rej()))
})
}
}
}

View File

@@ -1,16 +1,17 @@
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
import {getTemplateRoot} from "../utils/get-template-root"
import {camelCaseToKebabCase} from "../utils/inflector"
import j from "jscodeshift"
import {
CommonTemplateValues,
createFieldTemplateValues,
FieldValuesBuilder,
ResourceGeneratorOptions,
} from ".."
import {customTsParser, Generator, SourceRootType} from "../generator"
import {replaceImportDbWithPrismaFolder} from "../../src/utils/codemod-utils"
export interface MutationsGeneratorOptions extends ResourceGeneratorOptions {}
export interface MutationsGeneratorOptions extends GeneratorOptions {
ModelName: string
ModelNames: string
modelName: string
modelNames: string
parentModel?: string
parentModels?: string
ParentModel?: string
ParentModels?: string
}
export class MutationsGenerator extends Generator<MutationsGeneratorOptions> {
sourceRoot: SourceRootType
@@ -20,31 +21,32 @@ export class MutationsGenerator extends Generator<MutationsGeneratorOptions> {
}
static subdirectory = "mutations"
templateValuesBuilder = new FieldValuesBuilder(this.fs)
private getId(input: string = "") {
if (!input) return input
return `${input}Id`
}
async preFileWrite(filePath: string): Promise<CommonTemplateValues> {
let templateValues = await this.getTemplateValues()
if (templateValues.parentModel && filePath.match(/.*mutations.*create.*/g)) {
const newFieldTemplateValues = await createFieldTemplateValues(
templateValues.parentModelId,
templateValues.parentModelIdZodType,
true,
)
if (templateValues.fieldTemplateValues) {
templateValues.fieldTemplateValues.push(newFieldTemplateValues)
} else {
templateValues.fieldTemplateValues = [newFieldTemplateValues]
}
}
if (this.fs.exists(filePath)) {
let program = j(this.fs.read(filePath) as any, {
parser: customTsParser,
})
program = replaceImportDbWithPrismaFolder(program)
this.fs.write(filePath, program.toSource())
}
private getParam(input: string = "") {
if (!input) return input
return `[${input}]`
}
return templateValues
// eslint-disable-next-line require-await
async getTemplateValues() {
return {
parentModelId: this.getId(this.options.parentModel),
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
parentModel: this.options.parentModel,
parentModels: this.options.parentModels,
ParentModel: this.options.ParentModel,
ParentModels: this.options.ParentModels,
modelId: this.getId(this.options.modelName),
modelIdParam: this.getParam(this.getId(this.options.modelName)),
modelName: this.options.modelName,
modelNames: this.options.modelNames,
ModelName: this.options.ModelName,
ModelNames: this.options.ModelNames,
}
}
getTargetDirectory() {

View File

@@ -1,12 +1,19 @@
import {CommonTemplateValues, FieldValuesBuilder, ResourceGeneratorOptions} from ".."
import {Generator, SourceRootType} from "../generator"
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
import {getTemplateRoot} from "../utils/get-template-root"
import {camelCaseToKebabCase} from "../utils/inflector"
import {spawn} from "cross-spawn"
import which from "npm-which"
import * as fs from "fs-extra"
export interface PageGeneratorOptions extends ResourceGeneratorOptions {}
export interface PageGeneratorOptions extends GeneratorOptions {
ModelName: string
ModelNames: string
modelName: string
modelNames: string
parentModel?: string
parentModels?: string
ParentModel?: string
ParentModels?: string
}
export class PageGenerator extends Generator<PageGeneratorOptions> {
sourceRoot: SourceRootType
@@ -16,7 +23,34 @@ export class PageGenerator extends Generator<PageGeneratorOptions> {
}
static subdirectory = "../../.."
templateValuesBuilder = new FieldValuesBuilder(this.fs)
private getId(input: string = "") {
if (!input) return input
return `${input}Id`
}
private getParam(input: string = "") {
if (!input) return input
return `[${input}]`
}
// eslint-disable-next-line require-await
async getTemplateValues() {
return {
parentModelId: this.getId(this.options.parentModel),
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
parentModel: this.options.parentModel,
parentModels: this.options.parentModels,
ParentModel: this.options.ParentModel,
ParentModels: this.options.ParentModels,
modelId: this.getId(this.options.modelName),
modelIdParam: this.getParam(this.getId(this.options.modelName)),
modelName: this.options.modelName,
modelNames: this.options.modelNames,
ModelName: this.options.ModelName,
ModelNames: this.options.ModelNames,
modelNamesPath: this.getModelNamesPath(),
}
}
getModelNamesPath() {
const kebabCaseContext = this.options.context
@@ -34,28 +68,6 @@ export class PageGenerator extends Generator<PageGeneratorOptions> {
return `src/pages/${parent}${kebabCaseModelName}`
}
async preFileWrite(): Promise<CommonTemplateValues> {
const templateValues = await this.getTemplateValues()
const targetDirectory = this.getTargetDirectory().replace(
"__parentModelParam__",
templateValues.parentModelParam,
)
if (templateValues.parentModel) {
const modelPages = fs.existsSync(
`src/pages/${camelCaseToKebabCase(templateValues.modelNames)}`,
)
if (modelPages) {
if (!fs.existsSync(targetDirectory)) {
fs.moveSync(
`src/pages/${camelCaseToKebabCase(templateValues.modelNames)}`,
targetDirectory,
)
}
}
}
return templateValues
}
async postWrite() {
await new Promise<void>((res, rej) => {
const blitzBin = which(process.cwd()).sync("blitz")

View File

@@ -1,11 +1,17 @@
import {CommonTemplateValues, FieldValuesBuilder, ResourceGeneratorOptions} from ".."
import {customTsParser, Generator, SourceRootType} from "../generator"
import {Generator, GeneratorOptions, SourceRootType} from "../generator"
import {getTemplateRoot} from "../utils/get-template-root"
import {camelCaseToKebabCase} from "../utils/inflector"
import j from "jscodeshift"
import {replaceImportDbWithPrismaFolder} from "../../src/utils/codemod-utils"
export interface QueriesGeneratorOptions extends ResourceGeneratorOptions {}
export interface QueriesGeneratorOptions extends GeneratorOptions {
ModelName: string
ModelNames: string
modelName: string
modelNames: string
parentModel?: string
parentModels?: string
ParentModel?: string
ParentModels?: string
}
export class QueriesGenerator extends Generator<QueriesGeneratorOptions> {
sourceRoot: SourceRootType
@@ -15,19 +21,32 @@ export class QueriesGenerator extends Generator<QueriesGeneratorOptions> {
}
static subdirectory = "queries"
templateValuesBuilder = new FieldValuesBuilder(this.fs)
private getId(input: string = "") {
if (!input) return input
return `${input}Id`
}
async preFileWrite(filePath: string): Promise<CommonTemplateValues> {
let templateValues = await this.getTemplateValues()
if (this.fs.exists(filePath)) {
let program = j(this.fs.read(filePath) as any, {
parser: customTsParser,
})
program = replaceImportDbWithPrismaFolder(program)
this.fs.write(filePath, program.toSource())
private getParam(input: string = "") {
if (!input) return input
return `[${input}]`
}
// eslint-disable-next-line require-await
async getTemplateValues() {
return {
parentModelId: this.getId(this.options.parentModel),
parentModelParam: this.getParam(this.getId(this.options.parentModel)),
parentModel: this.options.parentModel,
parentModels: this.options.parentModels,
ParentModel: this.options.ParentModel,
ParentModels: this.options.ParentModels,
modelId: this.getId(this.options.modelName),
modelIdParam: this.getParam(this.getId(this.options.modelName)),
modelName: this.options.modelName,
modelNames: this.options.modelNames,
ModelName: this.options.ModelName,
ModelNames: this.options.ModelNames,
}
return templateValues
}
getTargetDirectory() {

View File

@@ -1,14 +0,0 @@
import username from "username"
import {AppGeneratorOptions, AppTemplateValues} from "../.."
import {Builder} from "./builder"
export class AppValuesBuilder extends Builder<AppGeneratorOptions, AppTemplateValues> {
public async getTemplateValues(options: AppGeneratorOptions): Promise<AppTemplateValues> {
const values = {
name: options.appName,
safeNameSlug: options.appName.replace(/[^a-zA-Z0-9-_]/g, "-"),
username: await username(),
}
return values
}
}

View File

@@ -1,139 +0,0 @@
import {Editor} from "mem-fs-editor"
import {GeneratorOptions} from "../../generator"
import {getCodegen, getResourceValueFromCodegen} from "../../utils/get-codegen"
import {CodegenField} from "../../utils/get-codegen"
import {
addSpaceBeforeCapitals,
camelCaseToKebabCase,
singleCamel,
singlePascal,
} from "../../utils/inflector"
export interface IBuilder<T, U> {
getTemplateValues(Options: T): Promise<U>
}
const defaultFieldConfig: CodegenField = {
component: "LabeledTextField",
inputType: "text",
zodType: "string",
prismaType: "String",
}
export async function createFieldTemplateValues(
valueName: string | undefined,
typeName: string | undefined,
parent = false,
): Promise<{[x: string]: any}> {
{
let values: {[x: string]: any} = {
attributeName: singleCamel(valueName),
fieldName: singleCamel(valueName),
FieldName: singlePascal(valueName),
field_name: addSpaceBeforeCapitals(`${valueName}`).toLocaleLowerCase(), // field name
Field_name: singlePascal(addSpaceBeforeCapitals(`${valueName}`).toLocaleLowerCase()), // Field name
Field_Name: singlePascal(addSpaceBeforeCapitals(`${valueName}`)), // Field Name
}
const codegen = await getCodegen()
// iterate over resources defined for this field type
const fieldConfig =
codegen.fieldTypeMap?.[typeName as keyof typeof codegen.fieldTypeMap] || defaultFieldConfig
values = {...values, ...fieldConfig}
if (parent) {
values.inputType = singleCamel(valueName).replace("Id", "s")
values.component = "LabeledSelectField"
values.fieldName = "id"
return values
}
values.inputType = fieldConfig.inputType
return values
}
}
export interface ResourceGeneratorOptions extends GeneratorOptions {
ModelName: string
ModelNames: string
modelName: string
modelNames: string
rawParentModelName?: string
parentModel?: string
parentModels?: string
ParentModel?: string
ParentModels?: string
extraArgs?: string[]
}
export interface CommonTemplateValues {
prismaFolder?: string
parentModelId: string
parentModelParam: string
parentModel?: string
parentModels?: string
ParentModel?: string
ParentModels?: string
parentModelIdZodType?: string
modelId: string
modelIdZodType?: string
modelIdParam: string
modelName: string
modelNames: string
ModelName: string
ModelNames: string
modelNamesPath: string
fieldTemplateValues?: {[x: string]: any}
}
export abstract class Builder<T, U> implements IBuilder<T, U> {
public constructor(fs?: Editor) {
this.fs = fs
}
abstract getTemplateValues(Options: T): Promise<U>
public fs: Editor | undefined
public defaultFieldConfig = defaultFieldConfig
public getId(input: string = "") {
if (!input) return input
return `${input}Id`
}
public getParam(input: string = "") {
if (!input) return input
return `[${input}]`
}
public getModelNamesPath(context: string | undefined, modelNames: string) {
const kebabCaseContext = context ? `${camelCaseToKebabCase(context)}/` : ""
const kebabCaseModelNames = camelCaseToKebabCase(modelNames)
return kebabCaseContext + kebabCaseModelNames
}
// eslint-disable-next-line require-await
public async getZodType(type: string = "") {
return getResourceValueFromCodegen(type, "zodType")
}
// eslint-disable-next-line require-await
public async getComponentForType(type: string = "") {
return getResourceValueFromCodegen(type, "component")
}
// eslint-disable-next-line require-await
public async getInputType(type: string = "") {
return getResourceValueFromCodegen(type, "inputType")
}
// eslint-disable-next-line require-await
public async getFieldTemplateValues(args: string[]) {
const argsPromises = args.map(async (arg: string) => {
let [valueName, typeName] = arg.split(":")
if (typeName?.includes("?")) {
typeName = typeName.replace("?", "")
}
const values = await createFieldTemplateValues(valueName, typeName)
return values
})
return Promise.all(argsPromises)
}
}

View File

@@ -1,120 +0,0 @@
import * as ast from "@mrleebo/prisma-ast"
import {create as createStore} from "mem-fs"
import {create as createEditor, Editor} from "mem-fs-editor"
import {getResourceValueFromCodegen} from "../../utils/get-codegen"
import {getPrismaSchema} from "../../utils/get-prisma-schema"
import {ModelName, modelName, ModelNames, modelNames} from "../../utils/model-names"
import {Builder, CommonTemplateValues, ResourceGeneratorOptions} from "./builder"
export class FieldValuesBuilder extends Builder<ResourceGeneratorOptions, CommonTemplateValues> {
private getEditor = (): Editor => {
if (this.fs !== undefined) {
return this.fs
}
const store = createStore()
this.fs = createEditor(store)
return this.fs
}
// eslint-disable-next-line require-await
public async getTemplateValues(options: ResourceGeneratorOptions): Promise<CommonTemplateValues> {
const prismaFolder = getPrismaSchema(this.getEditor())
let values: CommonTemplateValues = {
prismaFolder: typeof prismaFolder !== "boolean" ? prismaFolder.dbFolder : "db",
parentModelId: this.getId(options.parentModel),
parentModelIdZodType: undefined,
parentModelParam: this.getParam(this.getId(options.parentModel)),
parentModel: options.parentModel,
parentModels: options.parentModels,
ParentModel: options.ParentModel,
ParentModels: options.ParentModels,
modelId: this.getId(options.modelName),
modelIdZodType: "number",
modelIdParam: this.getParam(this.getId(options.modelName)),
modelName: options.modelName,
modelNames: options.modelNames,
ModelName: options.ModelName,
ModelNames: options.ModelNames,
modelNamesPath: this.getModelNamesPath(options.context, options.modelNames),
}
if (options.extraArgs) {
// specialArgs - these are arguments like 'id' or 'belongsTo', which are not meant to
// be processed as fields but have their own special logic
const specialArgs: {[key in string]: string} = {}
const processSpecialArgs: Promise<void>[] = options.extraArgs.map(async (arg) => {
const [valueName, typeName] = arg.split(":")
if (valueName === "id") {
values.modelIdZodType = await this.getZodType(typeName)
specialArgs[arg] = "present"
}
if (valueName === "belongsTo") {
specialArgs[arg] = "present"
process.env.parentModel = typeName
options.rawParentModelName = typeName
options.parentModel = modelName(typeName)
options.parentModels = modelNames(typeName)
options.ParentModel = ModelName(typeName)
options.ParentModels = ModelNames(typeName)
values.parentModelId = this.getId(modelName(typeName))
}
})
await Promise.all(processSpecialArgs)
// Filter out special args by making sure the argument isn't present in the list
const nonSpecialArgs = options.extraArgs.filter((arg) => specialArgs[arg] !== "present")
// Get the parent model it type if options.parentModel exists
if (options.parentModel !== undefined && options.parentModel.length > 0) {
const obj = getPrismaSchema(this.getEditor())
if (typeof obj !== "boolean") {
const schema = obj.schema
// O(N) - N is total ast Blocks
const model = schema.list.find(function (component): component is ast.Model {
return component.type === "model" && component.name === options.rawParentModelName
})
if (model !== undefined) {
// O(N) - N is number of properties in parent model
const idField = model.properties.find(function (property): property is ast.Field {
return (
property.type === "field" &&
property.attributes?.findIndex((attr) => attr.name === "id") !== -1
)
})
// TODO: Do we want a map between prisma types and "user types", we can then use that map instead of these conditionals
// We have a map from "user types" (which are what users type into the blitz generate command)
// to primsa type and other types, but we dont have a reverse map 1:1. This is because we lose
// some information for certain maps. E.g.: fieldname:uuid will be converted into a Prisma field with
// the String type, and the uuid portion is added to a decorator at the end of the field.
// This means it is more complicated to extract the original "user specified type" than creating a reverse map
if (idField?.fieldType === "Int") {
// TODO: Check if ints have decorators that make them a different type, like Bigint, etc.
// And see if that has to map to a different user specified type
values.parentModelIdZodType = await getResourceValueFromCodegen("int", "zodType")
} else if (idField?.fieldType === "String") {
if (
idField.attributes?.find(
(attr) =>
attr.name === "default" &&
attr.args?.findIndex((arg) => arg.value === "uuid") !== -1,
)
) {
values.parentModelIdZodType = await getResourceValueFromCodegen("uuid", "zodType")
} else {
values.parentModelIdZodType = await getResourceValueFromCodegen("string", "zodType")
}
}
}
} else {
// TODO: handle scenario where parent wasnt found in existing schema. Should we throw an error, or a warning asking the user to verify that the parent model exists?
}
}
if (nonSpecialArgs.length > 0) {
const ftv = await this.getFieldTemplateValues(nonSpecialArgs)
return {...values, fieldTemplateValues: ftv}
}
}
return values
}
}

View File

@@ -1,8 +0,0 @@
import {IBuilder} from "./builder"
export const NullBuilder: IBuilder<any, any> = {
// eslint-disable-next-line require-await
getTemplateValues: async () => {
return {}
},
}

View File

@@ -7,11 +7,6 @@ export * from "./generators/queries-generator"
export * from "./generators/query-generator"
export * from "./generators/form-generator"
export * from "./generator"
export * from "./generators/template-builders/builder"
export * from "./generators/template-builders/null-builder"
export * from "./generators/template-builders/app-values-builder"
export * from "./generators/template-builders/field-values-builder"
export * from "./utils/model-names"
export * from "./conflict-checker"
export {getLatestVersion} from "./utils/get-latest-version"
export * from "./utils/npm-fetch"
@@ -23,5 +18,4 @@ export {
pluralPascal,
capitalize,
uncapitalize,
addSpaceBeforeCapitals,
} from "./utils/inflector"

View File

@@ -1,7 +1,5 @@
import * as ast from "@mrleebo/prisma-ast"
import {getResourceConfigFromCodegen} from "../utils/get-codegen"
import {capitalize, singlePascal, uncapitalize} from "../utils/inflector"
const debug = require("debug")("blitz:field")
export enum FieldType {
Boolean = "Boolean",
@@ -56,8 +54,7 @@ export class Field {
relationToFields?: string[]
// 'name:type?[]:attribute' => Field
static async parse(input: string, schema?: ast.Schema): Promise<Field[]> {
debug(`parsing "Field" for input ${input}`)
static parse(input: string, schema?: ast.Schema): Field[] {
const [_fieldName, _fieldType = "String", _attribute] = input.split(":")
let attribute = _attribute as string
let fieldName = uncapitalize(_fieldName as string)
@@ -76,16 +73,6 @@ export class Field {
fieldType = fieldType.replace("?", "")
isRequired = false
}
const {prismaType, default: defaultConfigValue} =
(await Field.getConfigForPrismaType(fieldType)) ?? {}
if (prismaType) {
fieldType = prismaType
}
if (defaultConfigValue) {
attribute = `default=${defaultConfigValue}`
}
if (fieldType.includes("[]")) {
fieldType = fieldType.replace("[]", "")
fieldName = uncapitalize(fieldName)
@@ -99,7 +86,7 @@ export class Field {
// has modified fieldName
if (typeof _fieldName === "string" && isRelation(_fieldName)) {
// this field is an object type, not a scalar type
const relationType = Relation[_fieldName as keyof typeof Relation]
const relationType = Relation[_fieldName]
// translate the type into the name since they should stay in sync
fieldName = uncapitalize(fieldType)
fieldType = singlePascal(fieldType)
@@ -172,10 +159,6 @@ export class Field {
}
}
public static getConfigForPrismaType = async (fieldType: string) => {
return await getResourceConfigFromCodegen(fieldType.toLowerCase())
}
constructor(name: string, options: FieldArgs) {
if (!name) throw new MissingFieldNameError("[PrismaField]: A field name is required")
if (!options.type) {
@@ -231,12 +214,7 @@ export class Field {
args: [
{
type: "attributeArgument",
value:
typeof this.default === "object"
? `${this.default.name}()`
: this.type === FieldType.String
? `"${this.default}"`
: this.default,
value: typeof this.default === "object" ? `${this.default.name}()` : String(this.default),
},
],
}

View File

@@ -1,155 +0,0 @@
import j, {Collection} from "jscodeshift"
import {capitalize, singleCamel} from "./inflector"
export function replaceImportDbWithPrismaFolder(program: Collection<any>) {
const importDb = program.find(j.ImportDeclaration).filter((path) => {
return path.value.source.value === "db"
})
importDb.replaceWith((path) => {
path.value.source.value = "__prismaFolder__"
return path.value
})
return program
}
export function insertLabeledSelectField(program: Collection<any>) {
const importExists = program
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === "src/core/components/LabelSelectField")
.size()
if (!importExists) {
program
.find(j.ImportDeclaration)
.at(-1)
.insertAfter(
j.importDeclaration(
[j.importSpecifier(j.identifier("LabeledSelectField"))],
j.literal("src/core/components/LabelSelectField"),
),
)
}
return program
}
export function insertImportQuery(program: Collection<any>, templateValues: any) {
program
.find(j.ImportDeclaration)
.at(-1)
.insertAfter(
j.importDeclaration(
[
j.importDefaultSpecifier(
j.identifier(
singleCamel("get" + capitalize(templateValues.parentModelId)).replace("Id", "s"),
),
),
],
j.literal(
`src/${templateValues.parentModelId.replace("Id", "s")}/queries/${
"get" + capitalize(templateValues.parentModelId).replace("Id", "s")
}`,
),
),
)
return program
}
export function insertImportPagnatedQuery(program: Collection<any>) {
const importPaginatedQuery = program
.find(j.ImportDeclaration)
.filter((path) => {
if (path.node.specifiers) {
return (
path.node.source.value === "@blitzjs/rpc" &&
path.node.specifiers.filter((specifier) => {
if (specifier.type === "ImportSpecifier") {
return specifier.imported.name === "usePaginatedQuery"
} else {
return false
}
}).length > 0
)
} else {
return false
}
})
.size()
if (!importPaginatedQuery) {
program
.find(j.ImportDeclaration)
.at(-1)
.insertAfter(
j.importDeclaration(
[j.importSpecifier(j.identifier("usePaginatedQuery"))],
j.literal("@blitzjs/rpc"),
),
)
}
return program
}
export function updateFormWithParent(program: Collection<any>, templateValues: any) {
const modalFormSuspense = program.find(j.FunctionDeclaration).filter((path) => {
if (path.node.id?.name) {
return path.node.id.name.includes("Form")
}
return false
})
if (modalFormSuspense.size()) {
modalFormSuspense
.find(j.ReturnStatement)
.at(-1)
.insertBefore(
j.variableDeclaration("const", [
j.variableDeclarator(
j.arrayPattern([
j.objectPattern([
j.objectProperty(
j.identifier(`${templateValues.parentModelId.replace("Id", "s")}`),
j.identifier(`${templateValues.parentModelId.replace("Id", "s")}`),
),
]),
]),
j.callExpression(j.identifier("usePaginatedQuery"), [
j.identifier("get" + capitalize(templateValues.parentModelId).replace("Id", "s")),
j.objectExpression([
j.objectProperty(
j.identifier("orderBy"),
j.objectExpression([
j.objectProperty(j.identifier("id"), j.stringLiteral("asc")),
]),
),
]),
]),
),
]),
)
modalFormSuspense
.find(j.JSXElement)
.filter((path) => {
return (
path.node.openingElement.name.type === "JSXIdentifier" &&
path.node.openingElement.name.name === "LabeledSelectField"
)
})
.forEach((path) => {
let value = ""
path.node.openingElement.attributes = path.node.openingElement.attributes?.filter(
(attribute) => {
if (attribute.type === "JSXAttribute" && attribute.name.name === "type") {
if (attribute.value?.type === "StringLiteral") {
value = attribute.value.value
}
return false
}
return true
},
)
path.node.openingElement.attributes?.push(
j.jsxAttribute(j.jsxIdentifier("options"), j.jsxExpressionContainer(j.identifier(value))),
)
})
}
return program
}

View File

@@ -1,165 +0,0 @@
import {log} from "../utils/log"
import * as z from "zod"
export type CodegenField = {
component: string
inputType: string
zodType: string
prismaType: string
default?: string
}
export type CodegenConfig = {
fieldTypeMap?: Record<
| "string"
| "boolean"
| "int"
| "number"
| "bigint"
| "float"
| "decimal"
| "datetime"
| "uuid"
| "json",
CodegenField
>
}
const CodegenSchema = z.object({
fieldTypeMap: z.record(
z.union([
z.literal("string"),
z.literal("boolean"),
z.literal("int"),
z.literal("number"),
z.literal("bigint"),
z.literal("float"),
z.literal("decimal"),
z.literal("datetime"),
z.literal("uuid"),
z.literal("json"),
]),
z.object({
component: z.string(),
inputType: z.string(),
zodType: z.string(),
prismaType: z.string(),
default: z.string().optional(),
}),
),
})
export const defaultCodegenConfig: CodegenConfig = {
fieldTypeMap: {
string: {
component: "LabeledTextField",
inputType: "text",
zodType: "string",
prismaType: "String",
},
boolean: {
component: "LabeledTextField",
inputType: "text",
zodType: "boolean",
prismaType: "Boolean",
},
int: {
component: "LabeledTextField",
inputType: "number",
zodType: "number",
prismaType: "Int",
},
number: {
component: "LabeledTextField",
inputType: "number",
zodType: "number",
prismaType: "Int",
},
bigint: {
component: "LabeledTextField",
inputType: "number",
zodType: "number",
prismaType: "BigInt",
},
float: {
component: "LabeledTextField",
inputType: "number",
zodType: "number",
prismaType: "Float",
},
decimal: {
component: "LabeledTextField",
inputType: "number",
zodType: "number",
prismaType: "Decimal",
},
datetime: {
component: "LabeledTextField",
inputType: "text",
zodType: "string().datetime()",
prismaType: "DateTime",
},
uuid: {
component: "LabeledTextField",
inputType: "text",
zodType: "string().uuid",
prismaType: "String",
default: "uuid",
},
json: {
component: "LabeledTextField",
inputType: "text",
zodType: "any",
prismaType: "Json",
},
},
}
export const getResourceValueFromCodegen = async (
fieldType: string,
resource: keyof CodegenField,
): Promise<string | undefined> => {
const codegen = await getCodegen()
const templateValue = codegen.fieldTypeMap?.[fieldType]?.[resource]
return templateValue
}
export const getResourceConfigFromCodegen = async (
fieldType: string,
): Promise<CodegenField | undefined> => {
const codegen = await getCodegen()
const config = codegen.fieldTypeMap?.[fieldType]
return config
}
const getIsTypeScript = async () =>
require("fs").existsSync(require("path").join(process.cwd(), "tsconfig.json"))
export const getCodegen = async () => {
try {
const isTypeScript = await getIsTypeScript()
const blitzServerPath = isTypeScript ? "app/blitz-server.ts" : "app/blitz-server.js"
const blitzServer = require("path").join(process.cwd(), blitzServerPath)
const {register} = require("esbuild-register/dist/node")
const {unregister} = register({
target: "es6",
})
const blitzConfig = require(blitzServer)
const config = blitzConfig
const {cliConfig} = config
unregister()
if (cliConfig.codegen !== undefined) {
const result = CodegenSchema.safeParse(cliConfig.codegen)
if (!result.success) {
log.error("Failed parsing codegen config. Check if it is well formed. Using default config")
return defaultCodegenConfig
}
return cliConfig.codegen
}
return defaultCodegenConfig
} catch (ex) {
log.debug("Failed loading config" + ex)
return defaultCodegenConfig
}
}

View File

@@ -1,65 +0,0 @@
import * as ast from "@mrleebo/prisma-ast"
import {Editor} from "mem-fs-editor"
import {log} from "../utils/log"
import fs from "fs"
import path from "path"
//create a custom error class when prisma does not exist
export class PrismaSchemaNotFoundError extends Error {
constructor() {
super("Prisma schema not found.")
this.name = "PrismaSchemaNotFoundError"
}
}
function getDbFolder() {
try {
const packageJsonPath = path.join(process.cwd(), "package.json")
if (fs.existsSync(packageJsonPath)) {
const packageJson = fs.readFileSync(packageJsonPath, "utf8")
const packageJsonObj = JSON.parse(packageJson)
if (!packageJsonObj.prisma || !packageJsonObj.prisma.schema) {
throw new PrismaSchemaNotFoundError()
}
const prismaSchemaPath = path.join(process.cwd(), packageJsonObj.prisma.schema)
if (!fs.existsSync(prismaSchemaPath)) {
throw new PrismaSchemaNotFoundError()
}
const folder = packageJsonObj.prisma.schema.split("/")[0] as string
return folder
} else {
throw new PrismaSchemaNotFoundError()
}
} catch (e) {
if (fs.existsSync(path.join(process.cwd(), "db/schema.prisma"))) {
return "db"
}
throw e
}
}
export const getPrismaSchema = (
memFsEditor: Editor,
): {schema: ast.Schema; schemaPath: string; dbFolder: string} | boolean => {
let dbFolder: string, schemaPath: string
try {
dbFolder = getDbFolder()
schemaPath = path.join(process.cwd(), dbFolder, "schema.prisma")
} catch (e) {
if (e instanceof PrismaSchemaNotFoundError) {
return false
}
throw e
}
if (!fs.existsSync(schemaPath)) {
return {schema: {type: "schema", list: []}, schemaPath, dbFolder}
}
let schema: ast.Schema
try {
schema = ast.getSchema(memFsEditor.read(schemaPath))
} catch (err) {
log.debug("Failed to parse schema.prisma file")
throw err
}
return {schema, schemaPath, dbFolder}
}

View File

@@ -5,10 +5,6 @@ export function plural(input: string): string {
return pluralize.isPlural(input) ? input : pluralize.plural(input)
}
export function addSpaceBeforeCapitals(input: string): string {
return singleCamel(input).replace(/(?!^)([A-Z])/g, " $1")
}
export function singular(input: string): string {
return pluralize.isSingular(input) ? input : pluralize.singular(input)
}

View File

@@ -167,19 +167,6 @@ const withProgress = (str: string) => {
return withCaret(str)
}
const greenText = (str: string) => {
return `${c.green(str)}`
}
/**
* Logs a red error message to stdout.
*
* @param {string} msg
*/
const error = (msg: string) => {
console.log(`${c.red(msg)}`)
}
/**
* Logs a branded purple message to stdout.
*
@@ -261,8 +248,6 @@ export const log = {
progress,
spinner,
success,
greenText,
error,
variable,
debug,
Table,

View File

@@ -1,14 +0,0 @@
import {pluralCamel, pluralPascal, singleCamel, singlePascal} from "../index"
export function modelName(input: string = "") {
return singleCamel(input)
}
export function modelNames(input: string = "") {
return pluralCamel(input)
}
export function ModelName(input: string = "") {
return singlePascal(input)
}
export function ModelNames(input: string = "") {
return pluralPascal(input)
}

View File

@@ -1,60 +0,0 @@
import { forwardRef, PropsWithoutRef } from "react"
import { useField } from "react-final-form"
export interface LabeledSelectFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["select"]> {
/** Field name. */
name: string
/** Field label. */
label: string
type?: "number" | "string"
options: any
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
}
export const LabeledSelectField = forwardRef<HTMLSelectElement, LabeledSelectFieldProps>(
({ name, label, outerProps, options, type="number", ...props }, ref) => {
const {
input,
meta: { touched, error, submitError, submitting },
} = useField(name, {
parse: type === "number" ? Number : undefined,
})
const normalizedError = Array.isArray(error) ? error.join(", ") : error || submitError
return (
<div {...outerProps}>
<label>
{label}
<select {...input} disabled={submitting} {...props} ref={ref}>
{options && options.map((value) => <option value={value.id}>{value[name]}</option>)}
</select>
</label>
{touched && normalizedError && (
<div role="alert" style={{ color: "red" }}>
{normalizedError}
</div>
)}
<style jsx>{`
label {
display: flex;
flex-direction: column;
align-items: start;
font-size: 1rem;
}
select {
font-size: 1rem;
padding: 0.25rem 0.5rem;
border-radius: 3px;
appearance: none;
margin-top: 0.5rem;
}
`}</style>
</div>
)
}
)
export default LabeledSelectField

View File

@@ -1,68 +0,0 @@
import { forwardRef, PropsWithoutRef } from "react";
import { useFormikContext, ErrorMessage, Field } from "formik";
export interface LabeledSelectFieldProps
extends PropsWithoutRef<JSX.IntrinsicElements["select"]> {
/** Field name. */
name: string;
/** Field label. */
label: string;
/** Field options. */
options: any;
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>;
}
export const LabeledSelectField = forwardRef<
HTMLSelectElement,
LabeledSelectFieldProps
>(({ name, label, outerProps, options, ...props }, ref) => {
const { isSubmitting } = useFormikContext();
return (
<div {...outerProps}>
<label
style={{
display: "flex",
flexDirection: "column",
alignItems: "start",
fontSize: "1rem",
}}
>
{label}
<Field
{...props}
disabled={isSubmitting}
ref={ref}
name={name}
as="select"
style={{
fontSize: "1rem",
padding: " 0.25rem 0.4rem",
borderRadius: "3px",
border: "1px solid purple",
marginTop: "0.5rem",
backgroundColor: "white",
}}
>
<option value="" selected disabled hidden>
Select {label}
</option>
{options.map((option, index) => (
<option key={index} value={option.id}>
{option[name]}
</option>
))}
</Field>
</label>
<ErrorMessage name={name}>
{(msg) => (
<div role="alert" style={{ color: "red" }}>
{msg}
</div>
)}
</ErrorMessage>
</div>
);
});
export default LabeledSelectField;

View File

@@ -1,58 +0,0 @@
import { ComponentPropsWithoutRef, forwardRef, PropsWithoutRef } from "react"
import { useFormContext } from "react-hook-form"
import { ErrorMessage } from "@hookform/error-message"
export interface LabeledSelectFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["select"]> {
/** Field name. */
name: string
/** Field label. */
label: string
/** Field type. Doesn't include radio buttons and checkboxes */
options: any[]
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
labelProps?: ComponentPropsWithoutRef<"label">
}
export const LabeledSelectField = forwardRef<HTMLSelectElement, LabeledSelectFieldProps>(
({ label, outerProps, labelProps, name, options, ...props }, ref) => {
const {
register,
formState: { isSubmitting, errors },
} = useFormContext()
return (
<div {...outerProps}>
<label {...labelProps}>
{label}
<select {...register(name)} disabled={isSubmitting} {...props}>
{options && options.map((value) => <option value={value.id}>{value[name]}</option>)}
</select>
</label>
<ErrorMessage
render={({ message }) => (
<div role="alert" style={{ color: "red" }}>
{message}
</div>
)}
errors={errors}
name={name}
/>
<style jsx>{`
label {
display: flex;
flex-direction: column;
align-items: start;
font-size: 1rem;
}
select {
font-size: 1rem;
padding: 0.25rem 0.5rem;
border-radius: 3px;
border: 1px solid purple;
appearance: none;
margin-top: 0.5rem;
}
`}</style>
</div>
)
}
)

View File

@@ -1,14 +1,13 @@
import React, {Suspense} from "react"
import {Form, FormProps} from "src/core/components/Form"
import {LabeledTextField} from "src/core/components/LabeledTextField"
import {z} from "zod"
export {FORM_ERROR} from "src/core/components/Form"
export function __ModelName__Form<S extends z.ZodType<any, any>>(props: FormProps<S>) {
return (
<Form<S> {...props}>
{/* template: <__component__ name="__fieldName__" label="__Field_Name__" placeholder="__Field_Name__" type="__inputType__" /> */}
<LabeledTextField name="name" label="Name" placeholder="Name" />
</Form>
)
}

View File

@@ -1,5 +1,5 @@
import { resolver } from "@blitzjs/rpc"
import db from "__prismaFolder__"
import db from "db"
import {z} from "zod"
const __Name__ = z.object({

View File

@@ -1,15 +1,15 @@
import { resolver } from "@blitzjs/rpc"
import db from "__prismaFolder__"
import db from "db"
import {z} from "zod"
if (process.env.parentModel) {
const Create__ModelName__ = z.object({
__parentModelId__: z.__parentModelIdZodType__(),
// template: __fieldName__: z.__zodType__(),
name: z.string(),
__parentModelId__: z.number()
})
} else {
const Create__ModelName__ = z.object({
// template: __fieldName__: z.__zodType__(),
name: z.string(),
})
}

View File

@@ -1,9 +1,9 @@
import { resolver } from "@blitzjs/rpc"
import db from "__prismaFolder__"
import db from "db"
import {z} from "zod"
const Delete__ModelName__ = z.object({
id: z.__modelIdZodType__(),
id: z.number(),
})
export default resolver.pipe(

View File

@@ -1,10 +1,10 @@
import { resolver } from "@blitzjs/rpc"
import db from "__prismaFolder__"
import db from "db"
import {z} from "zod"
const Update__ModelName__ = z.object({
id: z.__modelIdZodType__(),
// template: __fieldName__: z.__zodType__(),
id: z.number(),
name: z.string(),
})
export default resolver.pipe(

View File

@@ -36,7 +36,7 @@ export const Edit__ModelName__ = () => {
<div>
<h1>Edit __ModelName__ {__modelName__.id}</h1>
<pre>{JSON.stringify(__modelName__, null, 2)}</pre>
<Suspense fallback={<div>Loading...</div>}>
<__ModelName__Form
submitText="Update __ModelName__"
// TODO use a zod schema for form validation
@@ -64,7 +64,6 @@ export const Edit__ModelName__ = () => {
}
}}
/>
</Suspense>
</div>
</>
)

View File

@@ -12,7 +12,6 @@ if (process.env.parentModel) {
import Layout from "src/core/layouts/Layout"
import create__ModelName__ from "src/__modelNamesPath__/mutations/create__ModelName__"
import {__ModelName__Form, FORM_ERROR} from "src/__modelNamesPath__/components/__ModelName__Form"
import { Suspense } from 'react'
const New__ModelName__Page = () => {
const router = useRouter()
@@ -24,7 +23,7 @@ const New__ModelName__Page = () => {
return (
<Layout title={"Create New __ModelName__"}>
<h1>Create New __ModelName__</h1>
<Suspense fallback={<div>Loading...</div>}>
<__ModelName__Form
submitText="Create __ModelName__"
// TODO use a zod schema for form validation
@@ -52,7 +51,7 @@ const New__ModelName__Page = () => {
}
}}
/>
</Suspense>
<p>
<if condition="parentModel">
<Link href={Routes.__ModelNames__Page({ __parentModelId__: __parentModelId__! })}>

View File

@@ -1,6 +1,6 @@
import {NotFoundError} from "blitz"
import { resolver } from "@blitzjs/rpc"
import db from "__prismaFolder__"
import db from "db"
import {z} from "zod"
const Get__ModelName__ = z.object({

View File

@@ -1,6 +1,6 @@
import {paginate} from "blitz"
import { resolver } from "@blitzjs/rpc"
import db, {Prisma} from "__prismaFolder__"
import db, {Prisma} from "db"
interface Get__ModelNames__Input
extends Pick<Prisma.__ModelName__FindManyArgs, "where" | "orderBy" | "skip" | "take"> {}

View File

@@ -1,5 +1,5 @@
import { resolver } from "@blitzjs/rpc"
import db from "__prismaFolder__"
import db from "db"
import {z} from "zod"
const __Name__ = z.object({

View File

@@ -1,254 +0,0 @@
import {FieldValuesBuilder} from "../../../src/generators/template-builders/field-values-builder"
import {describe, it, expect} from "vitest"
describe("Form Generator", () => {
process.env.BLITZ_APP_DIR = process.cwd()
const generator = new FieldValuesBuilder()
it("Should work with two word field names", async () => {
expect(
await generator.getFieldTemplateValues(["orgName:string", "orgId:integer"]),
).toStrictEqual([
{
component: "LabeledTextField",
FieldName: "OrgName",
Field_Name: "Org Name",
Field_name: "Org name",
attributeName: "orgName",
fieldName: "orgName",
field_name: "org name",
zodType: "string",
prismaType: "String",
inputType: "text",
},
{
component: "LabeledTextField",
FieldName: "OrgId",
Field_Name: "Org Id",
Field_name: "Org id",
attributeName: "orgId",
fieldName: "orgId",
field_name: "org id",
zodType: "string",
prismaType: "String",
inputType: "text",
},
])
})
it("Should work with simple types", async () => {
expect(
await generator.getFieldTemplateValues(["field1:string", "field2:string"]),
).toStrictEqual([
{
component: "LabeledTextField",
FieldName: "Field1",
Field_Name: "Field1",
Field_name: "Field1",
attributeName: "field1",
fieldName: "field1",
field_name: "field1",
zodType: "string",
prismaType: "String",
inputType: "text",
},
{
component: "LabeledTextField",
FieldName: "Field2",
Field_Name: "Field2",
Field_name: "Field2",
attributeName: "field2",
fieldName: "field2",
field_name: "field2",
zodType: "string",
prismaType: "String",
inputType: "text",
},
])
})
it("Should work with optional types", async () => {
expect(
await generator.getFieldTemplateValues(["field1:string?", "field2:number"]),
).toStrictEqual([
{
component: "LabeledTextField",
FieldName: "Field1",
Field_Name: "Field1",
Field_name: "Field1",
attributeName: "field1",
fieldName: "field1",
field_name: "field1",
zodType: "string",
prismaType: "String",
inputType: "text",
},
{
component: "LabeledTextField",
FieldName: "Field2",
Field_Name: "Field2",
Field_name: "Field2",
attributeName: "field2",
fieldName: "field2",
field_name: "field2",
zodType: "number",
prismaType: "Int",
inputType: "number",
},
])
})
it("Should work with default values", async () => {
expect(await generator.getFieldTemplateValues(["field1:string:default=test"])).toStrictEqual([
{
component: "LabeledTextField",
FieldName: "Field1",
Field_Name: "Field1",
Field_name: "Field1",
attributeName: "field1",
fieldName: "field1",
field_name: "field1",
zodType: "string",
prismaType: "String",
inputType: "text",
},
])
})
it("Should work with different input types", async () => {
const fields = [
"field1:string?",
"field2:boolean",
"field3:int",
"field4:number",
"field5:bigint?",
"field6:float",
"field7:decimal",
"field8:datetime",
"field9:uuid",
"field10:json?",
]
expect(await generator.getFieldTemplateValues(fields)).toStrictEqual([
{
component: "LabeledTextField",
FieldName: "Field1",
Field_Name: "Field1",
Field_name: "Field1",
attributeName: "field1",
fieldName: "field1",
field_name: "field1",
zodType: "string",
prismaType: "String",
inputType: "text",
},
{
component: "LabeledTextField",
FieldName: "Field2",
Field_Name: "Field2",
Field_name: "Field2",
attributeName: "field2",
fieldName: "field2",
field_name: "field2",
zodType: "boolean",
prismaType: "Boolean",
inputType: "text",
},
{
component: "LabeledTextField",
FieldName: "Field3",
Field_Name: "Field3",
Field_name: "Field3",
attributeName: "field3",
fieldName: "field3",
field_name: "field3",
zodType: "number",
prismaType: "Int",
inputType: "number",
},
{
component: "LabeledTextField",
FieldName: "Field4",
Field_Name: "Field4",
Field_name: "Field4",
attributeName: "field4",
fieldName: "field4",
field_name: "field4",
zodType: "number",
prismaType: "Int",
inputType: "number",
},
{
component: "LabeledTextField",
FieldName: "Field5",
Field_Name: "Field5",
Field_name: "Field5",
attributeName: "field5",
fieldName: "field5",
field_name: "field5",
zodType: "number",
prismaType: "BigInt",
inputType: "number",
},
{
component: "LabeledTextField",
FieldName: "Field6",
Field_Name: "Field6",
Field_name: "Field6",
attributeName: "field6",
fieldName: "field6",
field_name: "field6",
zodType: "number",
prismaType: "Float",
inputType: "number",
},
{
component: "LabeledTextField",
FieldName: "Field7",
Field_Name: "Field7",
Field_name: "Field7",
attributeName: "field7",
fieldName: "field7",
field_name: "field7",
zodType: "number",
prismaType: "Decimal",
inputType: "number",
},
{
component: "LabeledTextField",
FieldName: "Field8",
Field_Name: "Field8",
Field_name: "Field8",
attributeName: "field8",
fieldName: "field8",
field_name: "field8",
zodType: "string().datetime()",
prismaType: "DateTime",
inputType: "text",
},
{
component: "LabeledTextField",
FieldName: "Field9",
Field_Name: "Field9",
Field_name: "Field9",
attributeName: "field9",
fieldName: "field9",
field_name: "field9",
zodType: "string().uuid",
prismaType: "String",
inputType: "text",
default: "uuid",
},
{
component: "LabeledTextField",
FieldName: "Field10",
Field_Name: "Field10",
Field_name: "Field10",
attributeName: "field10",
fieldName: "field10",
field_name: "field10",
zodType: "any",
prismaType: "Json",
inputType: "text",
},
])
})
})

View File

@@ -1,50 +0,0 @@
import {FormGenerator} from "../../src/generators/form-generator"
import {describe, it, expect} from "vitest"
describe("Form Generator", () => {
process.env.BLITZ_APP_DIR = process.cwd()
const generator = new FormGenerator({
ModelName: "project",
ModelNames: "projects",
modelName: "project",
modelNames: "projects",
extraArgs: ["myProjectName:string"],
})
it("Correctly generates field names", async () => {
const templateValues = await generator.getTemplateValues()
expect(templateValues.fieldTemplateValues[0].fieldName).toEqual("myProjectName")
expect(templateValues.fieldTemplateValues[0].FieldName).toEqual("MyProjectName")
expect(templateValues.fieldTemplateValues[0].field_name).toEqual("my project name")
expect(templateValues.fieldTemplateValues[0].Field_name).toEqual("My project name")
expect(templateValues.fieldTemplateValues[0].Field_Name).toEqual("My Project Name")
})
it("matches template comments correctly", () => {
const regex = generator.fieldTemplateRegExp
const curlyBraceComment1 = `{/* template: <__component__ name="__fieldName__" label="__Field_Name__" placeholder="__Field_Name__" /> */}`
expect(curlyBraceComment1.match(regex)?.[0]?.replace(regex, "$2$3")).toBe(
`<__component__ name="__fieldName__" label="__Field_Name__" placeholder="__Field_Name__" />`,
)
expect(curlyBraceComment1.match(regex)?.[0]?.replace(regex, "$2$3")).not.toBe(
`something Random`,
)
const normalComment1 = `// template: __fieldName__: z.__zodType__(),`
expect(normalComment1.match(regex)?.[0]?.replace(regex, "$2$3")).toBe(
`__fieldName__: z.__zodType__(),`,
)
expect(normalComment1.match(regex)?.[0]?.replace(regex, "$2$3")).not.toBe(`something Random`)
const commentWithSpacing = `// template: __fieldName__: z.__zodType__(),`
const commentWithNoSpacing = `//template: __fieldName__: z.__zodType__(),`
expect(commentWithSpacing.match(regex)?.[0]?.replace(regex, "$2$3")).toBe(
`__fieldName__: z.__zodType__(),`,
)
expect(commentWithNoSpacing.match(regex)?.[0]?.replace(regex, "$2$3")).toBe(
`__fieldName__: z.__zodType__(),`,
)
})
})

View File

@@ -39,7 +39,6 @@ describe("PageGenerator", () => {
ParentModels: undefined,
modelNamesPath: "projects",
modelId: "projectId",
modelIdZodType: "number",
modelIdParam: "[projectId]",
modelName: "project",
modelNames: "projects",
@@ -47,7 +46,6 @@ describe("PageGenerator", () => {
parentModelId: "",
parentModelParam: "",
parentModels: undefined,
prismaFolder: "db",
})
})

View File

@@ -3,75 +3,75 @@ import {Schema} from "@mrleebo/prisma-ast"
import {Field} from "../../src/prisma/field"
describe("Field", () => {
it("parses optional types", async () => {
const [field] = await Field.parse("name:string?")
it("parses optional types", () => {
const [field] = Field.parse("name:string?")
expect(field?.isRequired).toBe(false)
})
it("appends unique attribute", async () => {
const [field] = await Field.parse("email:string?:unique")
it("appends unique attribute", () => {
const [field] = Field.parse("email:string?:unique")
expect(field?.isUnique).toBe(true)
})
it("appends updatedAt attribute", async () => {
const [field] = await Field.parse("updatedAt:DateTime:updatedAt")
it("appends updatedAt attribute", () => {
const [field] = Field.parse("updatedAt:DateTime:updatedAt")
expect(field?.isUpdatedAt).toBe(true)
})
it("handles default simple attribute", async () => {
const [field] = await Field.parse("isActive:boolean:default=true")
it("handles default simple attribute", () => {
const [field] = Field.parse("isActive:boolean:default=true")
expect(field?.default).toBe("true")
})
it("handles default uuid attribute", async () => {
const [field] = await Field.parse("id:string:default=uuid")
it("handles default uuid attribute", () => {
const [field] = Field.parse("id:string:default=uuid")
expect(field?.default).toMatchObject({name: "uuid"})
})
it("handles uuid convenience syntax", async () => {
const [field] = await Field.parse("someSpecialToken:uuid")
it("handles uuid convenience syntax", () => {
const [field] = Field.parse("someSpecialToken:uuid")
expect(field?.type).toBe("String")
expect(field?.default).toMatchObject({name: "uuid"})
})
it("handles default autoincrement attribute", async () => {
const [field] = await Field.parse("id:int:default=autoincrement")
it("handles default autoincrement attribute", () => {
const [field] = Field.parse("id:int:default=autoincrement")
expect(field?.default).toMatchObject({name: "autoincrement"})
})
it("has default field type", async () => {
const [field] = await Field.parse("name")
it("has default field type", () => {
const [field] = Field.parse("name")
expect(field?.type).toBe("String")
})
it("allow number characters in model name", async () => {
const [field] = await Field.parse("name2")
it("allow number characters in model name", () => {
const [field] = Field.parse("name2")
expect(field?.name).toBe("name2")
})
it("allow underscore characters in model name", async () => {
const [field] = await Field.parse("first_name")
it("allow underscore characters in model name", () => {
const [field] = Field.parse("first_name")
expect(field?.name).toBe("first_name")
})
it("disallows number as a first character in model name", async () => {
await expect(async () => await Field.parse("2first")).rejects.toThrow()
it("disallows number as a first character in model name", () => {
expect(() => Field.parse("2first")).toThrow()
})
it("disallows underscore as a first character in model name", async () => {
await expect(async () => await Field.parse("_first")).rejects.toThrow()
it("disallows underscore as a first character in model name", () => {
expect(() => Field.parse("_first")).toThrow()
})
it("disallows special characters in model name", async () => {
await expect(async () => await Field.parse("app-user:int")).rejects.toThrow()
it("disallows special characters in model name", () => {
expect(() => Field.parse("app-user:int")).toThrow()
})
it("disallows optional list fields", async () => {
await expect(async () => await Field.parse("users:int?[]")).rejects.toThrow()
it("disallows optional list fields", () => {
expect(() => Field.parse("users:int?[]")).toThrow()
})
it("requires a name", async () => {
await expect(async () => await Field.parse(":int")).rejects.toThrow()
it("requires a name", () => {
expect(() => Field.parse(":int")).toThrow()
})
describe("belongsTo", () => {
@@ -103,8 +103,8 @@ describe("Field", () => {
],
}
it("simple relation", async () => {
const [relation, foreignKey] = await Field.parse("belongsTo:task")
it("simple relation", () => {
const [relation, foreignKey] = Field.parse("belongsTo:task")
expect(relation).toMatchObject({
name: "task",
type: "Task",
@@ -114,8 +114,8 @@ describe("Field", () => {
expect(foreignKey).toMatchObject({name: "taskId", type: "Int"})
})
it("relation with schema", async () => {
const [relation, foreignKey] = await Field.parse("belongsTo:project?", schema)
it("relation with schema", () => {
const [relation, foreignKey] = Field.parse("belongsTo:project?", schema)
expect(relation).toMatchObject({
name: "project",
type: "Project",
@@ -126,8 +126,8 @@ describe("Field", () => {
expect(foreignKey).toMatchObject({name: "projectId", type: "String", isRequired: false})
})
it("relation with list directive", async () => {
const [relation, foreignKey] = await Field.parse("belongsTo:tasks[]", schema)
it("relation with list directive", () => {
const [relation, foreignKey] = Field.parse("belongsTo:tasks[]", schema)
expect(relation).toMatchObject({name: "tasks", type: "Task", isList: false})
expect(foreignKey).toMatchObject({name: "tasksId", type: "Int", isList: false})
})

View File

@@ -3,13 +3,18 @@ import {Field} from "../../src/prisma/field"
import {Model} from "../../src/prisma/model"
describe("Prisma Model", () => {
it("generates a proper model", async () => {
const email = await Field.parse("email:string:unique")
const updated = await Field.parse("updated:dateTime:updatedAt")
const recentLogins = await Field.parse("recentLogins:dateTime[]")
const twoFactorEnabled = await Field.parse("twoFactorEnabled:boolean")
const twoFactorMethod = await Field.parse("twoFactorMethod:string?")
const fields = [email, updated, recentLogins, twoFactorEnabled, twoFactorMethod].flat()
expect(new Model("user", fields).toString()).toMatchSnapshot()
it("generates a proper model", () => {
expect(
new Model(
"user",
[
Field.parse("email:string:unique"),
Field.parse("updated:dateTime:updatedAt"),
Field.parse("recentLogins:dateTime[]"),
Field.parse("twoFactorEnabled:boolean"),
Field.parse("twoFactorMethod:string?"),
].flat(),
).toString(),
).toMatchSnapshot()
})
})

View File

@@ -25,7 +25,7 @@
"@typescript-eslint/parser": "5.9.1"
},
"devDependencies": {
"@blitzjs/config": "2.0.0-beta.21",
"@blitzjs/config": "2.0.0-beta.22",
"@types/react": "18.0.25",
"@types/react-dom": "17.0.14",
"react": "18.2.0",

185
pnpm-lock.yaml generated
View File

@@ -51,7 +51,7 @@ importers:
"@types/react": 18.0.25
"@typescript-eslint/eslint-plugin": 5.42.1
"@vitejs/plugin-react": 2.2.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
eslint-config-next: 12.3.1
eslint-config-prettier: 8.5.0
@@ -129,7 +129,7 @@ importers:
"@types/preview-email": 2.0.1
"@types/react": 18.0.25
"@typescript-eslint/eslint-plugin": 5.42.1
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
eslint-config-next: 12.3.1
eslint-config-prettier: 8.5.0
@@ -238,9 +238,9 @@ importers:
integration-tests/auth:
specifiers:
"@blitzjs/auth": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/auth": workspace:2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@next/bundle-analyzer": 12.0.8
"@prisma/client": 4.6.0
"@types/express": 4.17.13
@@ -249,7 +249,7 @@ importers:
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
get-port: 6.1.2
@@ -289,10 +289,10 @@ importers:
integration-tests/auth-with-rpc:
specifiers:
"@blitzjs/auth": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/auth": workspace:2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@hookform/error-message": 2.0.0
"@hookform/resolvers": 2.9.10
"@next/bundle-analyzer": 12.0.8
@@ -305,7 +305,7 @@ importers:
"@types/react": 18.0.25
"@typescript-eslint/eslint-plugin": 5.42.1
"@vitejs/plugin-react": 2.2.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
delay: 5.0.0
eslint: 8.27.0
eslint-config-next: 12.3.1
@@ -372,10 +372,10 @@ importers:
integration-tests/get-initial-props:
specifiers:
"@blitzjs/auth": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/auth": workspace:2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@next/bundle-analyzer": 12.0.8
"@prisma/client": 4.6.0
"@types/express": 4.17.13
@@ -383,7 +383,7 @@ importers:
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
get-port: 6.1.2
@@ -421,15 +421,15 @@ importers:
integration-tests/middleware:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@next/bundle-analyzer": 12.0.8
"@types/express": 4.17.13
"@types/fs-extra": 9.0.13
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
get-port: 6.1.2
@@ -460,10 +460,10 @@ importers:
integration-tests/no-suspense:
specifiers:
"@blitzjs/auth": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/auth": workspace:2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@next/bundle-analyzer": 12.0.8
"@prisma/client": 4.6.0
"@types/express": 4.17.13
@@ -471,7 +471,7 @@ importers:
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
get-port: 6.1.2
@@ -509,16 +509,16 @@ importers:
integration-tests/qm:
specifiers:
"@blitzjs/auth": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/auth": workspace:2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@prisma/client": 4.6.0
"@tanstack/react-query": 4.0.10
"@testing-library/react": 13.4.0
"@types/react": 18.0.25
"@vitejs/plugin-react": 1.3.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
delay: 5.0.0
eslint: 8.27.0
eslint-config-next: latest
@@ -554,9 +554,9 @@ importers:
integration-tests/react-query-utils:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@next/bundle-analyzer": 12.0.8
"@prisma/client": 4.6.0
"@types/express": 4.17.13
@@ -564,7 +564,7 @@ importers:
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
get-port: 6.1.2
@@ -601,15 +601,15 @@ importers:
integration-tests/rpc:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@types/express": 4.17.13
"@types/fs-extra": 9.0.13
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
next: 12.2.5
@@ -636,15 +636,15 @@ importers:
integration-tests/rpc-path-root:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@types/express": 4.17.13
"@types/fs-extra": 9.0.13
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
next: 12.2.5
@@ -671,10 +671,10 @@ importers:
integration-tests/trailing-slash:
specifiers:
"@blitzjs/auth": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/next": workspace:2.0.0-beta.21
"@blitzjs/rpc": workspace:2.0.0-beta.21
"@blitzjs/auth": workspace:2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/next": workspace:2.0.0-beta.22
"@blitzjs/rpc": workspace:2.0.0-beta.22
"@next/bundle-analyzer": 12.0.8
"@prisma/client": 4.6.0
"@types/express": 4.17.13
@@ -682,7 +682,7 @@ importers:
"@types/node-fetch": 2.6.1
"@types/react": 18.0.25
b64-lite: 1.4.0
blitz: workspace:2.0.0-beta.21
blitz: workspace:2.0.0-beta.22
eslint: 8.27.0
fs-extra: 10.0.1
get-port: 6.1.2
@@ -778,8 +778,8 @@ importers:
packages/blitz:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/generator": 2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/generator": 2.0.0-beta.22
"@mrleebo/prisma-ast": 0.2.6
"@types/cookie": 0.4.1
"@types/cross-spawn": 6.0.2
@@ -927,7 +927,7 @@ importers:
packages/blitz-auth:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@testing-library/react": 13.4.0
"@testing-library/react-hooks": 8.0.1
"@types/b64-lite": 1.3.0
@@ -941,7 +941,7 @@ importers:
"@types/secure-password": 3.1.1
b64-lite: 1.4.0
bad-behavior: 1.0.1
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
cookie: 0.4.1
cookie-session: 2.0.0
debug: 4.3.3
@@ -994,8 +994,8 @@ importers:
packages/blitz-next:
specifiers:
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/rpc": 2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.22
"@blitzjs/rpc": 2.0.0-beta.22
"@tanstack/react-query": 4.0.10
"@testing-library/dom": 8.13.0
"@testing-library/jest-dom": 5.16.3
@@ -1007,7 +1007,7 @@ importers:
"@types/react": 18.0.25
"@types/react-dom": 17.0.14
"@types/testing-library__react-hooks": 4.0.0
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
cross-spawn: 7.0.3
debug: 4.3.3
find-up: 4.1.0
@@ -1057,8 +1057,8 @@ importers:
packages/blitz-rpc:
specifiers:
"@blitzjs/auth": 2.0.0-beta.21
"@blitzjs/config": workspace:2.0.0-beta.21
"@blitzjs/auth": 2.0.0-beta.22
"@blitzjs/config": workspace:2.0.0-beta.22
"@swc/core": 1.3.7
"@tanstack/react-query": 4.0.10
"@types/debug": 4.1.7
@@ -1066,7 +1066,7 @@ importers:
"@types/react-dom": 17.0.14
b64-lite: 1.4.0
bad-behavior: 1.0.1
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
chalk: ^4.1.0
debug: 4.3.3
next: 12.2.5
@@ -1110,12 +1110,12 @@ importers:
"@babel/plugin-syntax-typescript": 7.17.12
"@babel/preset-env": 7.12.10
"@blitzjs/config": workspace:*
"@blitzjs/generator": 2.0.0-beta.21
"@blitzjs/generator": 2.0.0-beta.22
"@types/jscodeshift": 0.11.2
"@types/node": 18.11.9
arg: 5.0.1
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
chalk: ^4.1.0
cross-spawn: 7.0.3
debug: 4.3.3
@@ -1170,7 +1170,7 @@ importers:
"@babel/plugin-transform-typescript": 7.12.1
"@babel/preset-env": 7.12.10
"@babel/types": 7.12.10
"@blitzjs/config": 2.0.0-beta.21
"@blitzjs/config": 2.0.0-beta.22
"@juanm04/cpx": 2.0.1
"@mrleebo/prisma-ast": 0.4.1
"@types/babel__core": 7.1.19
@@ -1194,7 +1194,6 @@ importers:
diff: 5.0.0
enquirer: 2.3.6
eslint: 8.27.0
fast-glob: 3.2.12
fs-extra: 10.0.1
globby: 13.1.2
got: ^11.8.1
@@ -1214,7 +1213,6 @@ importers:
username: 5.1.0
vinyl: 2.2.1
watch: 1.0.2
zod: 3.20.2
dependencies:
"@babel/core": 7.12.10_supports-color@8.1.1
"@babel/plugin-transform-typescript": 7.12.1_ps3yxa7qdojvlda5ukda3zlwie
@@ -1226,7 +1224,6 @@ importers:
cross-spawn: 7.0.3
diff: 5.0.0
enquirer: 2.3.6
fast-glob: 3.2.12
fs-extra: 10.0.1
globby: 13.1.2
got: 11.8.1
@@ -1265,11 +1262,10 @@ importers:
typescript: 4.8.4
unbuild: 0.6.9_supports-color@8.1.1
watch: 1.0.2
zod: 3.20.2
packages/pkg-template:
specifiers:
"@blitzjs/config": 2.0.0-beta.21
"@blitzjs/config": 2.0.0-beta.22
"@types/react": 18.0.25
"@types/react-dom": 17.0.14
"@typescript-eslint/eslint-plugin": 5.42.1
@@ -1293,7 +1289,7 @@ importers:
recipes/base-web:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1304,7 +1300,7 @@ importers:
recipes/bulma:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1316,7 +1312,7 @@ importers:
specifiers:
"@types/jscodeshift": 0.11.2
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1329,7 +1325,7 @@ importers:
specifiers:
"@types/jscodeshift": 0.11.2
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1341,7 +1337,7 @@ importers:
recipes/emotion:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1351,20 +1347,20 @@ importers:
recipes/gh-action-yarn-mariadb:
specifiers:
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
dependencies:
blitz: link:../../packages/blitz
recipes/gh-action-yarn-postgres:
specifiers:
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
dependencies:
blitz: link:../../packages/blitz
recipes/ghost:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1375,7 +1371,7 @@ importers:
recipes/graphql-apollo-server:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
uuid: ^8.3.1
dependencies:
@@ -1388,7 +1384,7 @@ importers:
recipes/logrocket:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1399,7 +1395,7 @@ importers:
recipes/material-ui:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1411,7 +1407,7 @@ importers:
specifiers:
"@types/jscodeshift": 0.11.2
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1422,13 +1418,13 @@ importers:
recipes/passenger:
specifiers:
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
dependencies:
blitz: link:../../packages/blitz
recipes/quirrel:
specifiers:
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
dependencies:
blitz: link:../../packages/blitz
@@ -1436,7 +1432,7 @@ importers:
specifiers:
"@types/jscodeshift": 0.11.2
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1447,14 +1443,14 @@ importers:
recipes/render:
specifiers:
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
dependencies:
blitz: link:../../packages/blitz
recipes/secureheaders:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
uuid: ^8.3.1
dependencies:
@@ -1467,7 +1463,7 @@ importers:
recipes/stitches:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1479,7 +1475,7 @@ importers:
specifiers:
"@types/jscodeshift": 0.11.2
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1491,7 +1487,7 @@ importers:
recipes/tailwind:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1503,7 +1499,7 @@ importers:
specifiers:
"@types/jscodeshift": 0.11.2
ast-types: 0.14.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -1515,7 +1511,7 @@ importers:
recipes/vanilla-extract:
specifiers:
"@types/jscodeshift": 0.11.2
blitz: 2.0.0-beta.21
blitz: 2.0.0-beta.22
jscodeshift: 0.13.0
dependencies:
blitz: link:../../packages/blitz
@@ -11975,19 +11971,6 @@ packages:
merge2: 1.4.1
micromatch: 4.0.5
/fast-glob/3.2.12:
resolution:
{
integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==,
}
engines: {node: ">=8.6.0"}
dependencies:
"@nodelib/fs.stat": 2.0.5
"@nodelib/fs.walk": 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
micromatch: 4.0.5
/fast-json-stable-stringify/2.1.0:
resolution:
{
@@ -12668,7 +12651,7 @@ packages:
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
fast-glob: 3.2.12
fast-glob: 3.2.11
ignore: 5.2.0
merge2: 1.4.1
slash: 3.0.0

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -24,7 +24,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -24,7 +24,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -24,6 +24,6 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21"
"blitz": "2.0.0-beta.22"
}
}

View File

@@ -24,6 +24,6 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21"
"blitz": "2.0.0-beta.22"
}
}

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0",
"uuid": "^8.3.1"
},

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -23,6 +23,6 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21"
"blitz": "2.0.0-beta.22"
}
}

View File

@@ -22,6 +22,6 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21"
"blitz": "2.0.0-beta.22"
}
}

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -22,6 +22,6 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21"
"blitz": "2.0.0-beta.22"
}
}

View File

@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0",
"uuid": "^8.3.1"
},

View File

@@ -24,7 +24,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -24,7 +24,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {

View File

@@ -25,7 +25,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"blitz": "2.0.0-beta.21",
"blitz": "2.0.0-beta.22",
"jscodeshift": "0.13.0"
},
"devDependencies": {