Compare commits
4 Commits
@blitzjs/g
...
mix-max-wi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f58a0e42f7 | ||
|
|
cb63a0ea5b | ||
|
|
a78bd33706 | ||
|
|
79c5e86d71 |
@@ -3794,7 +3794,8 @@
|
||||
"profile": "http://tobiasjordans.de",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
5
.changeset/big-boats-lay.md
Normal file
5
.changeset/big-boats-lay.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@blitzjs/generator": patch
|
||||
---
|
||||
|
||||
Guard `blitz g` input via an allow-list of characters; throw if unwanted characters are found. Prevents to break the blitz command by accident (https://github.com/blitz-js/blitz/issues/4021).
|
||||
5
.changeset/tasty-squids-sin.md
Normal file
5
.changeset/tasty-squids-sin.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@blitzjs/generator": patch
|
||||
---
|
||||
|
||||
Add missing Layout.tsx for generated mimimalapp
|
||||
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
@@ -136,8 +139,6 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
shell: bash
|
||||
|
||||
- name: Install playwright
|
||||
|
||||
102
.github/workflows/pr-release.yml
vendored
Normal file
102
.github/workflows/pr-release.yml
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
# https://github.com/withastro/astro/blob/main/.github/workflows/snapshot-release.yml
|
||||
|
||||
name: Create a Snapshot Release
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
jobs:
|
||||
snapshot-release:
|
||||
name: Create a snapshot release of a pull request
|
||||
if: ${{ github.repository_owner == 'blitz-js' && github.event.issue.pull_request && startsWith(github.event.comment.body, '!preview') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Check if user has admin access (only admins can publish snapshot releases)."
|
||||
uses: "lannonbr/repo-permission-check-action@2.0.0"
|
||||
with:
|
||||
permission: "admin"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: resolve pr refs
|
||||
id: refs
|
||||
uses: eficode/resolve-pr-refs@main
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ steps.refs.outputs.head_ref }}
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Short SHA
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Extract the snapshot name from comment body
|
||||
id: getSnapshotName
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const splitComment = context.payload.comment.body.split(' ');
|
||||
if(splitComment.length !== 2) {
|
||||
return "${{ steps.vars.outputs.sha_short }}";
|
||||
}
|
||||
return splitComment[1].trim();
|
||||
result-encoding: string
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm run build
|
||||
|
||||
- name: Bump Package Versions
|
||||
id: changesets
|
||||
run: |
|
||||
pnpm changeset pre exit
|
||||
pnpm changeset version --snapshot ${{ steps.getSnapshotName.outputs.result }} > changesets.output.txt 2>&1
|
||||
echo ::set-output name=result::`cat changesets.output.txt`
|
||||
env:
|
||||
# Needs access to run the script
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Publish Release
|
||||
id: publish
|
||||
run: |
|
||||
pnpm run release --tag next--${{ steps.getSnapshotName.outputs.result }} > publish.output.txt 2>&1
|
||||
echo ::set-output name=result::`cat publish.output.txt`
|
||||
env:
|
||||
# Needs access to publish to npm
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Pull Request Notification
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
MESSAGE: ${{ steps.publish.outputs.result }}
|
||||
with:
|
||||
script: |
|
||||
console.log(process.env.MESSAGE);
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '```\n' + process.env.MESSAGE + '\n```',
|
||||
})
|
||||
|
||||
@@ -736,7 +736,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="a11rew.dev"><img src="https://avatars.githubusercontent.com/u/87580113?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Glago</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=a11rew" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=a11rew" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://tobiasjordans.de"><img src="https://avatars.githubusercontent.com/u/111561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tobias</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://tobiasjordans.de"><img src="https://avatars.githubusercontent.com/u/111561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tobias</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/iagor-moraes/"><img src="https://avatars.githubusercontent.com/u/13892132?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Iagor Moraes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=iagormoraes" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=iagormoraes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/trensik"><img src="https://avatars.githubusercontent.com/u/18584155?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dawid Urbaniak</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Trancever" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Trancever" title="Code">💻</a></td>
|
||||
</tr>
|
||||
|
||||
@@ -2,11 +2,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 {checkInputsOrRaise} from "../utils/checkInputOrRaise"
|
||||
import {getTemplateRoot} from "../utils/get-template-root"
|
||||
import {log} from "../utils/log"
|
||||
|
||||
export interface ModelGeneratorOptions extends GeneratorOptions {
|
||||
modelName: string
|
||||
@@ -59,9 +60,13 @@ export class ModelGenerator extends Generator<ModelGeneratorOptions> {
|
||||
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 splitInputCommans = (input: typeof extraArgs) => {
|
||||
const inputs = input.length === 1 && input[0]?.includes(" ") ? input[0]?.split(" ") : input
|
||||
checkInputsOrRaise(inputs)
|
||||
return inputs
|
||||
}
|
||||
|
||||
let fields = splitInputCommans(extraArgs).flatMap((input) => Field.parse(input, schema))
|
||||
|
||||
const modelDefinition = new Model(modelName, fields)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as ast from "@mrleebo/prisma-ast"
|
||||
import {checkInputsOrRaise} from "../utils/checkInputOrRaise"
|
||||
import {capitalize, singlePascal, uncapitalize} from "../utils/inflector"
|
||||
|
||||
export enum FieldType {
|
||||
@@ -55,6 +56,8 @@ export class Field {
|
||||
|
||||
// 'name:type?[]:attribute' => Field
|
||||
static parse(input: string, schema?: ast.Schema): Field[] {
|
||||
checkInputsOrRaise(input)
|
||||
|
||||
const [_fieldName, _fieldType = "String", _attribute] = input.split(":")
|
||||
let attribute = _attribute as string
|
||||
let fieldName = uncapitalize(_fieldName as string)
|
||||
|
||||
28
packages/generator/src/utils/checkInputOrRaise.ts
Normal file
28
packages/generator/src/utils/checkInputOrRaise.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import chalk from "chalk"
|
||||
import {log} from "./log"
|
||||
|
||||
export const checkInputsOrRaise = (inputs: string[] | string) => {
|
||||
if (typeof inputs === "string") {
|
||||
checkInputOrRaise(inputs)
|
||||
} else {
|
||||
inputs.forEach((input) => checkInputOrRaise(input))
|
||||
}
|
||||
}
|
||||
|
||||
const checkInputOrRaise = (input: string) => {
|
||||
const regex = /^[a-zA-Z0-9-_:=\?[\]\s]+$/
|
||||
if (!regex.test(input)) {
|
||||
const firstInvalidCharacter = input.match(/[^a-zA-Z0-9-_:=\?[\]\s]/)
|
||||
if (firstInvalidCharacter) {
|
||||
log.branded(
|
||||
"Blitz Generator Parser Error: " +
|
||||
chalk.red(
|
||||
`Input contains invalid character: "${firstInvalidCharacter[0]}" in ${firstInvalidCharacter.input} at position ${firstInvalidCharacter.index}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
throw new Error(
|
||||
"Input should only contain alphanumeric characters, spaces, and the following characters: - _ : = ? [ ]",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import Head from "next/head"
|
||||
import React, {FC} from "react"
|
||||
import {BlitzLayout} from "@blitzjs/next"
|
||||
|
||||
const Layout: BlitzLayout<{title?: string; children?: React.ReactNode}> = ({title, children}) => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{title || "__name__"}</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
@@ -0,0 +1,26 @@
|
||||
import {checkInputsOrRaise} from "../../../../generator/src/utils/checkInputOrRaise"
|
||||
import {describe, expect, it} from "vitest"
|
||||
|
||||
describe("checkInputsOrRaise()", () => {
|
||||
describe("with input string", () => {
|
||||
it("does not raise when input string OK", () => {
|
||||
expect(() => checkInputsOrRaise("Foo:foo=bar[]?:-_ ")).not.toThrow()
|
||||
})
|
||||
it("raisees when input has unwanted characters", () => {
|
||||
expect(() => checkInputsOrRaise("()!")).toThrowError(
|
||||
"Input should only contain alphanumeric characters, spaces, and the following characters: - _ : = ? [ ]",
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("with input string[]", () => {
|
||||
it("does not raise when input strings OK", () => {
|
||||
expect(() => checkInputsOrRaise(["ok:ok=ok", "also ok:ok"])).not.toThrow()
|
||||
})
|
||||
it("raisees when one input has unwanted characters", () => {
|
||||
expect(() => checkInputsOrRaise(["ok:ok=ok", "not ok!"])).toThrowError(
|
||||
"Input should only contain alphanumeric characters, spaces, and the following characters: - _ : = ? [ ]",
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -28,6 +28,14 @@ describe("Field", () => {
|
||||
expect(field?.default).toMatchObject({name: "uuid"})
|
||||
})
|
||||
|
||||
it("disallow brackes `()` as default attribute", () => {
|
||||
expect(() => Field.parse("id:string:default=now()")).toThrow()
|
||||
})
|
||||
|
||||
it("disallow not allowed characters like `!`", () => {
|
||||
expect(() => Field.parse("id:string!")).toThrow()
|
||||
})
|
||||
|
||||
it("handles uuid convenience syntax", () => {
|
||||
const [field] = Field.parse("someSpecialToken:uuid")
|
||||
expect(field?.type).toBe("String")
|
||||
|
||||
Reference in New Issue
Block a user