+ className={`flex relative items-center justify-center w-12 h-12 text-${project.color}-600 bg-${project.color}-100 rounded-full`}
+ >
diff --git a/packages/gui/app/components/Sidebar/ProjectSwitches.tsx b/packages/gui/app/components/Sidebar/ProjectSwitches.tsx
index a6c807abf..a3289260d 100644
--- a/packages/gui/app/components/Sidebar/ProjectSwitches.tsx
+++ b/packages/gui/app/components/Sidebar/ProjectSwitches.tsx
@@ -1,8 +1,8 @@
-import {useQuery} from 'blitz'
-import {FC} from 'react'
+import {useQuery} from "blitz"
+import {FC} from "react"
-import getProjects from 'app/queries/getProjects'
-import {ProjectSwitch} from './ProjectSwitch'
+import getProjects from "app/queries/getProjects"
+import {ProjectSwitch} from "./ProjectSwitch"
export const ProjectSwitches: FC = () => {
const [projects] = useQuery(getProjects, {})
diff --git a/packages/gui/app/components/Sidebar/index.tsx b/packages/gui/app/components/Sidebar/index.tsx
index 26a0c8dcc..a08670da6 100644
--- a/packages/gui/app/components/Sidebar/index.tsx
+++ b/packages/gui/app/components/Sidebar/index.tsx
@@ -1,8 +1,8 @@
-import {Link} from 'blitz'
-import {FC, Suspense} from 'react'
+import {Link} from "blitz"
+import {FC, Suspense} from "react"
-import {NewSwitch} from './NewSwitch'
-import {ProjectSwitches} from './ProjectSwitches'
+import {NewSwitch} from "./NewSwitch"
+import {ProjectSwitches} from "./ProjectSwitches"
export const Sidebar: FC = () => (
diff --git a/packages/gui/app/components/Sidebar/types.ts b/packages/gui/app/components/Sidebar/types.ts
index 9581d8828..f7347d441 100644
--- a/packages/gui/app/components/Sidebar/types.ts
+++ b/packages/gui/app/components/Sidebar/types.ts
@@ -1,3 +1,3 @@
-import {Project} from 'db'
+import {Project} from "db"
export type ProjectSwitchProps = {project: Project}
diff --git a/packages/gui/app/mutations/createProject.ts b/packages/gui/app/mutations/createProject.ts
index a84a715e0..6c4c226d9 100644
--- a/packages/gui/app/mutations/createProject.ts
+++ b/packages/gui/app/mutations/createProject.ts
@@ -1,12 +1,12 @@
-import {existsSync} from 'fs'
-import hasbin from 'hasbin'
+import {existsSync} from "fs"
+import hasbin from "hasbin"
-import {AppGenerator} from '@blitzjs/generator'
-import db, {ProjectCreateArgs} from 'db'
-import pkg from 'package.json'
+import {AppGenerator} from "@blitzjs/generator"
+import db, {ProjectCreateArgs} from "db"
+import pkg from "package.json"
type CreateProjectInput = {
- data: ProjectCreateArgs['data']
+ data: ProjectCreateArgs["data"]
}
const createProject = async ({data}: CreateProjectInput) => {
@@ -21,7 +21,7 @@ const createProject = async ({data}: CreateProjectInput) => {
appName: name,
dryRun: false,
useTs: true,
- yarn: hasbin.sync('yarn'),
+ yarn: hasbin.sync("yarn"),
version: pkg.version,
skipInstall: false,
})
diff --git a/packages/gui/app/mutations/importProject.ts b/packages/gui/app/mutations/importProject.ts
index 37896264e..540950ec2 100644
--- a/packages/gui/app/mutations/importProject.ts
+++ b/packages/gui/app/mutations/importProject.ts
@@ -1,7 +1,7 @@
-import db, {ProjectCreateArgs} from 'db'
+import db, {ProjectCreateArgs} from "db"
type ImportProjectInput = {
- data: ProjectCreateArgs['data']
+ data: ProjectCreateArgs["data"]
}
const importProject = async ({data}: ImportProjectInput) => {
diff --git a/packages/gui/app/pages/_app.tsx b/packages/gui/app/pages/_app.tsx
index d57cb6c79..cebaaea7d 100644
--- a/packages/gui/app/pages/_app.tsx
+++ b/packages/gui/app/pages/_app.tsx
@@ -1,8 +1,8 @@
// import '@reach/tabs/styles.css'
-import 'tailwindcss/tailwind.css'
-import 'tippy.js/dist/tippy.css'
+import "tailwindcss/tailwind.css"
+import "tippy.js/dist/tippy.css"
-import {AppProps, Head} from 'blitz'
+import {AppProps, Head} from "blitz"
const MyApp = ({Component, pageProps}: AppProps): JSX.Element => (
<>
diff --git a/packages/gui/app/pages/import.tsx b/packages/gui/app/pages/import.tsx
index 4e1885a06..6d046bfbc 100644
--- a/packages/gui/app/pages/import.tsx
+++ b/packages/gui/app/pages/import.tsx
@@ -1,7 +1,7 @@
-import {BlitzPage} from 'blitz'
+import {BlitzPage} from "blitz"
-import {Sidebar} from 'app/components/Sidebar'
-import {NewView} from 'app/components/NewView'
+import {Sidebar} from "app/components/Sidebar"
+import {NewView} from "app/components/NewView"
const ImportPage: BlitzPage = () => (
<>
diff --git a/packages/gui/app/pages/index.tsx b/packages/gui/app/pages/index.tsx
index 040ded116..153bec189 100644
--- a/packages/gui/app/pages/index.tsx
+++ b/packages/gui/app/pages/index.tsx
@@ -1,8 +1,8 @@
-import {BlitzPage, useQuery, useRouter} from 'blitz'
-import {FC, Suspense, useEffect} from 'react'
+import {BlitzPage, useQuery, useRouter} from "blitz"
+import {FC, Suspense, useEffect} from "react"
-import {Sidebar} from 'app/components/Sidebar'
-import getProjects from 'app/queries/getProjects'
+import {Sidebar} from "app/components/Sidebar"
+import getProjects from "app/queries/getProjects"
const Stub: FC = () => {
const router = useRouter()
@@ -11,9 +11,9 @@ const Stub: FC = () => {
useEffect(() => {
if (projects.length > 0) {
- router.push('/p/[id]', `/p/${projects[0].id}`)
+ router.push("/p/[id]", `/p/${projects[0].id}`)
} else {
- router.push('/new')
+ router.push("/new")
}
}, [projects])
diff --git a/packages/gui/app/pages/new.tsx b/packages/gui/app/pages/new.tsx
index e38536bd7..91d8a0f23 100644
--- a/packages/gui/app/pages/new.tsx
+++ b/packages/gui/app/pages/new.tsx
@@ -1,7 +1,7 @@
-import {BlitzPage} from 'blitz'
+import {BlitzPage} from "blitz"
-import {Sidebar} from 'app/components/Sidebar'
-import {NewView} from 'app/components/NewView'
+import {Sidebar} from "app/components/Sidebar"
+import {NewView} from "app/components/NewView"
const NewPage: BlitzPage = () => (
<>
diff --git a/packages/gui/app/pages/p/[id]/index.tsx b/packages/gui/app/pages/p/[id]/index.tsx
index 7b56525b8..3298e2116 100644
--- a/packages/gui/app/pages/p/[id]/index.tsx
+++ b/packages/gui/app/pages/p/[id]/index.tsx
@@ -1,7 +1,7 @@
-import {BlitzPage} from 'blitz'
+import {BlitzPage} from "blitz"
-import {ProjectView} from 'app/components/ProjectView'
-import {Sidebar} from 'app/components/Sidebar'
+import {ProjectView} from "app/components/ProjectView"
+import {Sidebar} from "app/components/Sidebar"
const ProjectPage: BlitzPage = () => (
<>
diff --git a/packages/gui/app/pages/p/[id]/schema.tsx b/packages/gui/app/pages/p/[id]/schema.tsx
index 5684e2334..35a9e7bc3 100644
--- a/packages/gui/app/pages/p/[id]/schema.tsx
+++ b/packages/gui/app/pages/p/[id]/schema.tsx
@@ -1,13 +1,13 @@
-import {BlitzPage, useParam, useQuery, useRouter} from 'blitz'
-import {motion} from 'framer-motion'
-import {FC, useRef, Suspense} from 'react'
+import {BlitzPage, useParam, useQuery, useRouter} from "blitz"
+import {motion} from "framer-motion"
+import {FC, useRef, Suspense} from "react"
-import getProject from 'app/queries/getProject'
-import getSchema from 'app/queries/getSchema'
+import getProject from "app/queries/getProject"
+import getSchema from "app/queries/getSchema"
const SchemaView: FC = () => {
const router = useRouter()
- const id = useParam('id', 'string')
+ const id = useParam("id", "string")
const constraintsRef = useRef(null)
@@ -31,7 +31,8 @@ const SchemaView: FC = () => {
drag={true}
dragConstraints={constraintsRef}
dragMomentum={false}
- className="w-1/2 overflow-hidden bg-white border border-gray-200 rounded-lg ">
+ className="w-1/2 overflow-hidden bg-white border border-gray-200 rounded-lg "
+ >
{model.name}
diff --git a/packages/gui/app/pages/projects/[id].tsx b/packages/gui/app/pages/projects/[id].tsx
new file mode 100644
index 000000000..a769e9ff5
--- /dev/null
+++ b/packages/gui/app/pages/projects/[id].tsx
@@ -0,0 +1,62 @@
+import {BlitzPage, GetServerSideProps} from "blitz"
+import Error from "next/error"
+import {homedir} from "os"
+import {useState} from "react"
+
+import {Nav} from "app/components/Nav"
+import {CreateProjectModal} from "app/components/CreateProjectModal"
+import {ProjectHeader} from "app/components/ProjectHeader"
+import {ProjectModules} from "app/components/ProjectModules"
+import getProject from "app/queries/getProject"
+import {Project} from "db"
+import {getPages} from "utils/getPages"
+
+type ShowProjectPageProps = {
+ project: Project | null
+ homedir?: string
+ projectData?: {
+ pages: {route: string; link: string}[]
+ }
+}
+
+export const getServerSideProps: GetServerSideProps
= async ({query}) => {
+ const id = String(query.id)
+ const project = await getProject({where: {id}})
+
+ if (!project) {
+ return {
+ props: {project},
+ }
+ }
+
+ const pages = await getPages(project.path)
+
+ const projectData = {pages}
+
+ return {
+ props: {project, homedir: homedir(), projectData},
+ }
+}
+
+const ShowProjectPage: BlitzPage = ({project, homedir, projectData}) => {
+ const [isModalOpen, setIsModalOpen] = useState(false)
+
+ if (!project || !homedir || !projectData) {
+ return
+ }
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
+
+export default ShowProjectPage
diff --git a/packages/gui/app/queries/getCreateProjectStatus.ts b/packages/gui/app/queries/getCreateProjectStatus.ts
index bf4bde7bd..89bd8acda 100644
--- a/packages/gui/app/queries/getCreateProjectStatus.ts
+++ b/packages/gui/app/queries/getCreateProjectStatus.ts
@@ -1,6 +1,6 @@
-import {existsSync, promises} from 'fs'
+import {existsSync, promises} from "fs"
-import {CREATING_FILES, DONE, INSTALLING_DEPS, RETRIEVING_DEPS, UNKNOWN} from 'utils/status'
+import {CREATING_FILES, DONE, INSTALLING_DEPS, RETRIEVING_DEPS, UNKNOWN} from "utils/status"
type GetCreateProjectStatusInput = {
path: string
@@ -15,11 +15,11 @@ const getCreateProjectStatus = async ({path}: GetCreateProjectStatusInput) => {
if (!files) {
return CREATING_FILES
- } else if (!files.includes('node_modules')) {
+ } else if (!files.includes("node_modules")) {
return RETRIEVING_DEPS
- } else if (!files.includes('yarn.lock')) {
+ } else if (!files.includes("yarn.lock")) {
return INSTALLING_DEPS
- } else if (files.includes('yarn.lock')) {
+ } else if (files.includes("yarn.lock")) {
return DONE
}
diff --git a/packages/gui/app/queries/getDirectories.ts b/packages/gui/app/queries/getDirectories.ts
index 92f592c0e..d83737de6 100644
--- a/packages/gui/app/queries/getDirectories.ts
+++ b/packages/gui/app/queries/getDirectories.ts
@@ -1,5 +1,5 @@
-import {accessSync, constants, lstatSync, promises} from 'fs'
-import {join} from 'path'
+import {accessSync, constants, lstatSync, promises} from "fs"
+import {join} from "path"
const getIsReadable = (path: string) => {
try {
@@ -18,8 +18,8 @@ const getIsBlitz = async (path: string) => {
for await (const file of directory) {
if (
- (file.isFile() && file.name === 'blitz.config.js') ||
- (file.isDirectory() && file.name === '.blitz')
+ (file.isFile() && file.name === "blitz.config.js") ||
+ (file.isDirectory() && file.name === ".blitz")
) {
isBlitz = true
break
diff --git a/packages/gui/app/queries/getDirectory.ts b/packages/gui/app/queries/getDirectory.ts
index 5c50b5157..b62caf53a 100644
--- a/packages/gui/app/queries/getDirectory.ts
+++ b/packages/gui/app/queries/getDirectory.ts
@@ -1,9 +1,9 @@
-import * as fs from 'fs'
-import path from 'path'
+import * as fs from "fs"
+import path from "path"
enum ResponseStatus {
- Success = 'ok',
- Error = 'error',
+ Success = "ok",
+ Error = "error",
}
// type Status = 'ok' | 'error'
@@ -35,8 +35,8 @@ async function checkIfBlitzProject(path: string): Promise {
for await (const dirent of dir) {
if (
- (dirent.isFile() && dirent.name === 'blitz.config.js') ||
- (dirent.isDirectory() && dirent.name === '.blitz')
+ (dirent.isFile() && dirent.name === "blitz.config.js") ||
+ (dirent.isDirectory() && dirent.name === ".blitz")
) {
isBlitz = true
break
@@ -81,7 +81,7 @@ export default async function getDirectory(toRead?: string): Promise homedir()
diff --git a/packages/gui/app/queries/getPages.ts b/packages/gui/app/queries/getPages.ts
index 1b7c3d878..4e9bdc8db 100644
--- a/packages/gui/app/queries/getPages.ts
+++ b/packages/gui/app/queries/getPages.ts
@@ -1,21 +1,21 @@
-import glob from 'fast-glob'
+import glob from "fast-glob"
type GetPagesInput = {
path: string
}
const getPages = async ({path}: GetPagesInput) => {
- const entries = await glob('app/**/*.tsx', {cwd: path})
+ const entries = await glob("app/**/*.tsx", {cwd: path})
const routes = entries
- .filter((route) => route.includes('pages'))
- .filter((route) => !['app/pages/_app.tsx', 'app/pages/_document.tsx'].includes(route))
+ .filter((route) => route.includes("pages"))
+ .filter((route) => !["app/pages/_app.tsx", "app/pages/_document.tsx"].includes(route))
const links = routes.map((route) =>
route
- .split('pages')[1]
- .replace('.tsx', '')
- .replace(/index$/, ''),
+ .split("pages")[1]
+ .replace(".tsx", "")
+ .replace(/index$/, ""),
)
return routes.map((route, i) => ({route: route, link: links[i]}))
diff --git a/packages/gui/app/queries/getProject.ts b/packages/gui/app/queries/getProject.ts
index 44594da0b..78359db92 100644
--- a/packages/gui/app/queries/getProject.ts
+++ b/packages/gui/app/queries/getProject.ts
@@ -1,10 +1,10 @@
-import {existsSync} from 'fs'
+import {existsSync} from "fs"
-import db, {FindOneProjectArgs} from 'db'
-import {getDirMtime} from 'utils/getDirMtime'
+import db, {FindOneProjectArgs} from "db"
+import {getDirMtime} from "utils/getDirMtime"
type GetProjectInput = {
- where: FindOneProjectArgs['where']
+ where: FindOneProjectArgs["where"]
}
const getProject = async ({where}: GetProjectInput) => {
diff --git a/packages/gui/app/queries/getProjects.ts b/packages/gui/app/queries/getProjects.ts
index 823c1023b..420d5d91b 100644
--- a/packages/gui/app/queries/getProjects.ts
+++ b/packages/gui/app/queries/getProjects.ts
@@ -1,14 +1,14 @@
-import {existsSync} from 'fs'
+import {existsSync} from "fs"
-import db, {FindManyProjectArgs} from 'db'
-import {getDirMtime} from 'utils/getDirMtime'
+import db, {FindManyProjectArgs} from "db"
+import {getDirMtime} from "utils/getDirMtime"
type GetProjectsInput = {
- where?: FindManyProjectArgs['where']
- orderBy?: FindManyProjectArgs['orderBy']
- cursor?: FindManyProjectArgs['cursor']
- take?: FindManyProjectArgs['take']
- skip?: FindManyProjectArgs['skip']
+ where?: FindManyProjectArgs["where"]
+ orderBy?: FindManyProjectArgs["orderBy"]
+ cursor?: FindManyProjectArgs["cursor"]
+ take?: FindManyProjectArgs["take"]
+ skip?: FindManyProjectArgs["skip"]
}
const getProjects = async ({where, orderBy, cursor, take, skip}: GetProjectsInput) => {
diff --git a/packages/gui/app/queries/getSchema.ts b/packages/gui/app/queries/getSchema.ts
index 61932426c..e8278ce9f 100644
--- a/packages/gui/app/queries/getSchema.ts
+++ b/packages/gui/app/queries/getSchema.ts
@@ -1,7 +1,7 @@
// based on https://github.com/AhmedElywa/prisma-tools/blob/master/packages/schema
-import {existsSync, promises} from 'fs'
-import {join} from 'path'
+import {existsSync, promises} from "fs"
+import {join} from "path"
export type Field = {
name: string
@@ -10,7 +10,7 @@ export type Field = {
required: boolean
isId: boolean
unique: boolean
- kind: 'object' | 'enum' | 'scalar'
+ kind: "object" | "enum" | "scalar"
map?: string
relationField?: boolean
documentation?: string
@@ -33,8 +33,8 @@ export type SchemaObject = {models: Model[]; enums: Enums[]}
const lineArray = (line: string) =>
line
- .replace(/[\n\r]/g, '')
- .split(' ')
+ .replace(/[\n\r]/g, "")
+ .split(" ")
.filter((v) => v)
const getClassName = (lines: string[]) => lineArray(lines[0])[1]
@@ -43,7 +43,7 @@ const getMap = (line: string) => {
const value = line.match(/@map\((.*?)\)/)
if (value) {
- return value[1].replace(/name/, '').replace(':', '').replace(' ', '').replace(/"/g, '')
+ return value[1].replace(/name/, "").replace(":", "").replace(" ", "").replace(/"/g, "")
}
return undefined
@@ -53,7 +53,7 @@ const getRelation = (line: string) => {
const relationString = line.match(/@relation\((.*?)\)/)
if (relationString) {
- const relation: Field['relation'] = {}
+ const relation: Field["relation"] = {}
const name = relationString[1].match(/"(\w+)"/)
@@ -61,19 +61,19 @@ const getRelation = (line: string) => {
relation.name = name[1]
}
- ;['fields', 'references'].forEach((item) => {
+ ;["fields", "references"].forEach((item) => {
const pattern = new RegExp(`${item}:[\\s\\S]\\[(.*?)\\]`)
const values = relationString[1].match(pattern)
if (values) {
const asArray = values[1]
- .replace(/ /g, '')
- .split(',')
+ .replace(/ /g, "")
+ .split(",")
.filter((v) => v)
if (asArray.length > 0) {
- relation[item as 'fields' | 'references'] = asArray
+ relation[item as "fields" | "references"] = asArray
}
}
})
@@ -103,53 +103,53 @@ const getSchemaInObject = (data: string) => {
fields: [],
}
- let documentation = ''
+ let documentation = ""
for (let i = 1; i + 1 < lines.length; i++) {
const line = lineArray(lines[i])
- if (line[0].includes('//')) {
- documentation = documentation ? documentation + '\n' + line.join(' ') : line.join(' ')
- } else if (line[0].includes('@@')) {
+ if (line[0].includes("//")) {
+ documentation = documentation ? documentation + "\n" + line.join(" ") : line.join(" ")
+ } else if (line[0].includes("@@")) {
modelObject.map = getMap(lines[i])
} else {
- const type = line[1].replace('?', '').replace('[]', '')
+ const type = line[1].replace("?", "").replace("[]", "")
const field: Field = {
name: line[0],
type,
- isId: line.includes('@id'),
- unique: line.includes('@unique'),
- list: line[1].includes('[]'),
- required: !line[1].includes('[]') && !line[1].includes('?'),
+ isId: line.includes("@id"),
+ unique: line.includes("@unique"),
+ list: line[1].includes("[]"),
+ required: !line[1].includes("[]") && !line[1].includes("?"),
kind: data.includes(`enum ${type} `)
- ? 'enum'
+ ? "enum"
: data.includes(`model ${type} `)
- ? 'object'
- : 'scalar',
+ ? "object"
+ : "scalar",
documentation,
map: getMap(lines[i]),
}
- if (field.kind === 'object') {
+ if (field.kind === "object") {
field.relation = getRelation(lines[i])
}
modelObject.fields.push(field)
- documentation = ''
+ documentation = ""
}
}
modelObject.documentation = documentation
modelObject.fields
- .filter((item) => item.kind !== 'object')
+ .filter((item) => item.kind !== "object")
.forEach((item) => {
let relationField = false
modelObject.fields
- .filter((field) => field.kind === 'object')
+ .filter((field) => field.kind === "object")
.forEach((field) => {
if (!relationField) {
relationField = !!field.relation?.fields?.includes(item.name)
@@ -175,7 +175,7 @@ const getSchemaInObject = (data: string) => {
for (let i = 1; i + 1 < lines.length; i++) {
const line = lineArray(lines[i])
- !line[0].includes('//') && itemObject.fields.push(line[0])
+ !line[0].includes("//") && itemObject.fields.push(line[0])
}
modelsObject.enums.push({...itemObject})
@@ -190,13 +190,13 @@ type GetSchemaInput = {
}
const getSchema = async ({path}: GetSchemaInput) => {
- const schemaPath = join(path, 'db', 'schema.prisma')
+ const schemaPath = join(path, "db", "schema.prisma")
if (!existsSync(schemaPath)) {
return
}
- const data = await promises.readFile(schemaPath, 'utf-8')
+ const data = await promises.readFile(schemaPath, "utf-8")
return getSchemaInObject(data)
}
diff --git a/packages/gui/db/index.ts b/packages/gui/db/index.ts
index 6cdba9ff5..6b4ae88da 100644
--- a/packages/gui/db/index.ts
+++ b/packages/gui/db/index.ts
@@ -1,16 +1,16 @@
-import {PrismaClient} from '@prisma/client'
+import {PrismaClient} from "@prisma/client"
-export * from '@prisma/client'
+export * from "@prisma/client"
let prisma: PrismaClient
-if (process.env.NODE_ENV === 'production') {
+if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient()
} else {
// @ts-ignore
- global['prisma'] = global['prisma'] || new PrismaClient()
+ global["prisma"] = global["prisma"] || new PrismaClient()
// @ts-ignore
- prisma = global['prisma']
+ prisma = global["prisma"]
}
export default prisma
diff --git a/packages/gui/postcss.config.js b/packages/gui/postcss.config.js
index fd0648a7e..6efc41a52 100644
--- a/packages/gui/postcss.config.js
+++ b/packages/gui/postcss.config.js
@@ -1,3 +1,3 @@
module.exports = {
- plugins: ['tailwindcss'],
+ plugins: ["tailwindcss"],
}
diff --git a/packages/gui/tailwind.config.js b/packages/gui/tailwind.config.js
index d633e1695..98c68b7f9 100644
--- a/packages/gui/tailwind.config.js
+++ b/packages/gui/tailwind.config.js
@@ -1,4 +1,4 @@
-const defaultTheme = require('tailwindcss/defaultTheme')
+const defaultTheme = require("tailwindcss/defaultTheme")
module.exports = {
// ideally we should use this since the tailwind bundle is quite big,
@@ -8,15 +8,15 @@ module.exports = {
theme: {
extend: {
borderWidth: {
- 3: '3px',
+ 3: "3px",
},
fontFamily: {
- sans: ['Inter var', ...defaultTheme.fontFamily.sans],
+ sans: ["Inter var", ...defaultTheme.fontFamily.sans],
},
},
},
variants: {
- opacity: ['responsive', 'hover', 'focus', 'disabled'],
+ opacity: ["responsive", "hover", "focus", "disabled"],
},
- plugins: [require('@tailwindcss/ui')],
+ plugins: [require("@tailwindcss/ui")],
}
diff --git a/packages/gui/types/index.d.ts b/packages/gui/types/index.d.ts
index 5ca553356..74056fd3c 100644
--- a/packages/gui/types/index.d.ts
+++ b/packages/gui/types/index.d.ts
@@ -1 +1 @@
-declare module 'hasbin'
+declare module "hasbin"
diff --git a/packages/gui/utils/canUseDom.ts b/packages/gui/utils/canUseDom.ts
new file mode 100644
index 000000000..81ed967e5
--- /dev/null
+++ b/packages/gui/utils/canUseDom.ts
@@ -0,0 +1 @@
+export const canUseDOM = typeof window !== "undefined"
diff --git a/packages/gui/utils/dethunkify.ts b/packages/gui/utils/dethunkify.ts
new file mode 100644
index 000000000..eb5cb7124
--- /dev/null
+++ b/packages/gui/utils/dethunkify.ts
@@ -0,0 +1,2 @@
+export const dethunkify = (value: T | (() => T)): T =>
+ typeof value === "function" ? (value as () => T)() : value
diff --git a/packages/gui/utils/getDirMtime.ts b/packages/gui/utils/getDirMtime.ts
index dae246316..a6177166a 100644
--- a/packages/gui/utils/getDirMtime.ts
+++ b/packages/gui/utils/getDirMtime.ts
@@ -1,9 +1,9 @@
-import glob from 'fast-glob'
-import {lstatSync} from 'fs'
-import {join} from 'path'
+import glob from "fast-glob"
+import {lstatSync} from "fs"
+import {join} from "path"
export const getDirMtime = async (path: string) => {
- const files = await glob(join(path, '{,!(node_modules|.blitz|.git)/**/}*.*').replace(/\\/g, '/'))
+ const files = await glob(join(path, "{,!(node_modules|.blitz|.git)/**/}*.*").replace(/\\/g, "/"))
const sortedFiles = files
.filter((f) => lstatSync(f).isFile())
diff --git a/packages/gui/utils/hooks/state/useToggle.ts b/packages/gui/utils/hooks/state/useToggle.ts
index 8967ca1e7..e52a34b62 100644
--- a/packages/gui/utils/hooks/state/useToggle.ts
+++ b/packages/gui/utils/hooks/state/useToggle.ts
@@ -1,10 +1,9 @@
-import {useCallback} from 'react'
+import {useCallback} from "react"
-export const useToggle = ([value, setValue]: [boolean, React.Dispatch>]): [
+export const useToggle = ([value, setValue]: [
boolean,
React.Dispatch>,
- () => void,
-] => {
+]): [boolean, React.Dispatch>, () => void] => {
const toggleValue = useCallback(() => {
setValue((prevValue) => !prevValue)
}, [setValue])
diff --git a/packages/gui/utils/hooks/state/useUndoable.ts b/packages/gui/utils/hooks/state/useUndoable.ts
index 98ff1b214..8b108269e 100644
--- a/packages/gui/utils/hooks/state/useUndoable.ts
+++ b/packages/gui/utils/hooks/state/useUndoable.ts
@@ -1,6 +1,6 @@
-import {useCallback, useRef} from 'react'
+import {useCallback, useRef} from "react"
-import {MAX_SMALL_INTEGER} from './utils'
+import {MAX_SMALL_INTEGER} from "./utils"
export const useUndoable = (
[value, setValue]: [T, React.Dispatch>],
@@ -25,7 +25,7 @@ export const useUndoable = (
futureValuesRef.current = []
pastValuesRef.current = [...pastValuesRef.current, prevValue]
- return typeof update === 'function' ? (update as (prevValue: T) => T)(prevValue) : update
+ return typeof update === "function" ? (update as (prevValue: T) => T)(prevValue) : update
})
},
[setValue],
diff --git a/packages/gui/utils/hooks/web/useDelayUnmount.ts b/packages/gui/utils/hooks/web/useDelayUnmount.ts
new file mode 100644
index 000000000..436e6925d
--- /dev/null
+++ b/packages/gui/utils/hooks/web/useDelayUnmount.ts
@@ -0,0 +1,17 @@
+import {useEffect, useState} from "react"
+
+export const useDelayUnmount = (isMounted: boolean, delayMs: number) => {
+ const [shouldRender, setShouldRender] = useState(false)
+
+ useEffect(() => {
+ let timeoutId: number
+ if (isMounted && !shouldRender) {
+ setShouldRender(true)
+ } else if (!isMounted && shouldRender) {
+ // @ts-ignore
+ timeoutId = setTimeout(() => setShouldRender(false), delayMs)
+ }
+ return () => clearTimeout(timeoutId)
+ }, [isMounted, delayMs, shouldRender])
+ return shouldRender
+}
diff --git a/packages/gui/utils/hooks/web/useInterval.ts b/packages/gui/utils/hooks/web/useInterval.ts
index 2039449c3..3fa5c78b4 100644
--- a/packages/gui/utils/hooks/web/useInterval.ts
+++ b/packages/gui/utils/hooks/web/useInterval.ts
@@ -1,6 +1,6 @@
-import {useEffect} from 'react'
+import {useEffect} from "react"
-import {managedInterval, useEventCallback} from './utils'
+import {managedInterval, useEventCallback} from "./utils"
export const useInterval = (callback: () => void, delayMs: number | null): void => {
const savedCallback = useEventCallback(callback)
diff --git a/packages/gui/utils/hooks/web/useLocalStorage.ts b/packages/gui/utils/hooks/web/useLocalStorage.ts
new file mode 100644
index 000000000..ea95138b5
--- /dev/null
+++ b/packages/gui/utils/hooks/web/useLocalStorage.ts
@@ -0,0 +1,13 @@
+// based on https://github.com/kripod/react-hooks/blob/master/packages/web-api-hooks/src/useLocalStorage.ts
+
+import {JSONValue} from "utils/types/JSONValue"
+import {useStorage} from "utils/hooks/web/useStorage"
+
+const getLocalStorage = (): Storage => localStorage
+
+export const useLocalStorage = (
+ key: string,
+ initialValue: T | (() => T) | null = null,
+ errorCallback?: (error: DOMException | TypeError) => void,
+): [T, React.Dispatch>] =>
+ useStorage(getLocalStorage, key, initialValue, errorCallback)
diff --git a/packages/gui/utils/hooks/web/useNetworkAvailability.ts b/packages/gui/utils/hooks/web/useNetworkAvailability.ts
new file mode 100644
index 000000000..180663cb3
--- /dev/null
+++ b/packages/gui/utils/hooks/web/useNetworkAvailability.ts
@@ -0,0 +1,25 @@
+import {useEffect, useState} from "react"
+
+import {canUseDOM} from "utils/canUseDom"
+import {managedEventListener} from "utils/managedEventListener"
+
+export const useNetworkAvailability = (): boolean => {
+ const [online, setOnline] = useState(canUseDOM ? navigator.onLine : true)
+
+ useEffect(() => {
+ const cleanup1 = managedEventListener(window, "offline", () => {
+ setOnline(false)
+ })
+
+ const cleanup2 = managedEventListener(window, "online", () => {
+ setOnline(true)
+ })
+
+ return (): void => {
+ cleanup1()
+ cleanup2()
+ }
+ }, [])
+
+ return online
+}
diff --git a/packages/gui/utils/hooks/web/useStorage.ts b/packages/gui/utils/hooks/web/useStorage.ts
index 04f850bcf..99350984c 100644
--- a/packages/gui/utils/hooks/web/useStorage.ts
+++ b/packages/gui/utils/hooks/web/useStorage.ts
@@ -1,7 +1,7 @@
-import {Dispatch, SetStateAction, useEffect, useMemo, useState} from 'react'
+import {Dispatch, SetStateAction, useEffect, useMemo, useState} from "react"
-import {JSONValue} from './types'
-import {dethunkify} from './utils'
+import {JSONValue} from "./types"
+import {dethunkify} from "./utils"
export const useStorage = (
getStorage: () => Storage | null,
diff --git a/packages/gui/utils/hooks/web/utils.ts b/packages/gui/utils/hooks/web/utils.ts
index 5d5412fa1..d8a5512a0 100644
--- a/packages/gui/utils/hooks/web/utils.ts
+++ b/packages/gui/utils/hooks/web/utils.ts
@@ -1,11 +1,11 @@
-import {useCallback, useEffect, useRef} from 'react'
+import {useCallback, useEffect, useRef} from "react"
-import {EventMap} from './types'
+import {EventMap} from "./types"
-export const canUseDOM = typeof window !== 'undefined'
+export const canUseDOM = typeof window !== "undefined"
export const dethunkify = (value: T | (() => T)): T =>
- typeof value === 'function' ? (value as () => T)() : value
+ typeof value === "function" ? (value as () => T)() : value
export const managedEventListener = & string>(
target: T,
diff --git a/packages/gui/utils/managedEventListener.ts b/packages/gui/utils/managedEventListener.ts
new file mode 100644
index 000000000..92fd9c46b
--- /dev/null
+++ b/packages/gui/utils/managedEventListener.ts
@@ -0,0 +1,14 @@
+import {EventMap} from "utils/types/EventMap"
+
+export const managedEventListener = & string>(
+ target: T,
+ type: K,
+ callback: (event: EventMap[K]) => void,
+ options?: AddEventListenerOptions,
+): (() => void) => {
+ target.addEventListener(type, callback as EventListener, options)
+
+ return (): void => {
+ target.removeEventListener(type, callback as EventListener, options)
+ }
+}
diff --git a/packages/gui/utils/status.ts b/packages/gui/utils/status.ts
index 3841c1ee2..0f6a8c92c 100644
--- a/packages/gui/utils/status.ts
+++ b/packages/gui/utils/status.ts
@@ -1,5 +1,5 @@
-export const CREATING_FILES = 'creating-files'
-export const DONE = 'done'
-export const INSTALLING_DEPS = 'installing-deps'
-export const RETRIEVING_DEPS = 'retrieving-deps'
-export const UNKNOWN = 'unknown'
+export const CREATING_FILES = "creating-files"
+export const DONE = "done"
+export const INSTALLING_DEPS = "installing-deps"
+export const RETRIEVING_DEPS = "retrieving-deps"
+export const UNKNOWN = "unknown"
diff --git a/packages/gui/utils/string/findClosestStringMatch.ts b/packages/gui/utils/string/findClosestStringMatch.ts
index dd806a08f..019b37788 100644
--- a/packages/gui/utils/string/findClosestStringMatch.ts
+++ b/packages/gui/utils/string/findClosestStringMatch.ts
@@ -1,4 +1,4 @@
-import {orderBySimilarity} from './orderBySimilarity'
+import {orderBySimilarity} from "./orderBySimilarity"
export const findClosestStringMatch = (
name: string,
diff --git a/packages/gui/utils/string/orderBySimilarity.ts b/packages/gui/utils/string/orderBySimilarity.ts
index 955d0f649..4755480f2 100644
--- a/packages/gui/utils/string/orderBySimilarity.ts
+++ b/packages/gui/utils/string/orderBySimilarity.ts
@@ -19,8 +19,8 @@ const getMap = (
}
const compareTwoStrings = (aStr: string, bStr: string): number => {
- const a = aStr.replace(/\s+/g, '')
- const b = bStr.replace(/\s+/g, '')
+ const a = aStr.replace(/\s+/g, "")
+ const b = bStr.replace(/\s+/g, "")
if (!a.length && !b.length) {
return 1
@@ -50,7 +50,7 @@ const compareTwoStrings = (aStr: string, bStr: string): number => {
const count = firstBigrams.has(bigram) ? getMap(firstBigrams, bigram) + 1 : 1
if (count === undefined) {
- throw new Error('Already used has() above')
+ throw new Error("Already used has() above")
}
firstBigrams.set(bigram, count)
@@ -64,7 +64,7 @@ const compareTwoStrings = (aStr: string, bStr: string): number => {
const count = getMap(firstBigrams, bigram, 0)
if (count === undefined) {
- throw new Error('Already used has() above')
+ throw new Error("Already used has() above")
}
if (count > 0) {
diff --git a/packages/gui/utils/string/toKebabCase.ts b/packages/gui/utils/string/toKebabCase.ts
index fda7c02e4..3ce4f8153 100644
--- a/packages/gui/utils/string/toKebabCase.ts
+++ b/packages/gui/utils/string/toKebabCase.ts
@@ -1,5 +1,5 @@
export const toKebabCase = (str: string): string =>
str
- .replace(/([a-z])([A-Z])/g, '$1-$2')
- .replace(/[\s_]+/g, '-')
+ .replace(/([a-z])([A-Z])/g, "$1-$2")
+ .replace(/[\s_]+/g, "-")
.toLowerCase()
diff --git a/packages/gui/utils/timeDifference.ts b/packages/gui/utils/timeDifference.ts
new file mode 100644
index 000000000..7fc3cb667
--- /dev/null
+++ b/packages/gui/utils/timeDifference.ts
@@ -0,0 +1,56 @@
+// based on https://github.com/withspectrum/spectrum/blob/alpha/shared/time-difference.js
+
+export const timeDifference = (current: number, previous: number): string => {
+ const msPerMinute = 60 * 1000
+ const msPerHour = msPerMinute * 60
+ const msPerDay = msPerHour * 24
+ const msPerMonth = msPerDay * 30
+ const msPerYear = msPerDay * 365
+
+ let elapsed = current - previous
+
+ if (elapsed < msPerMinute) {
+ return "just now"
+ } else if (elapsed < msPerHour) {
+ const now = Math.round(elapsed / msPerMinute)
+ if (now === 1) {
+ return "1 minute ago"
+ } else {
+ return `${now} minutes ago`
+ }
+ } else if (elapsed < msPerDay) {
+ const now = Math.round(elapsed / msPerHour)
+ if (now === 1) {
+ return "1 hour ago"
+ } else {
+ return `${now} hours ago`
+ }
+ } else if (elapsed < msPerMonth) {
+ const now = Math.round(elapsed / msPerDay)
+ if (now === 1) {
+ return "yesterday"
+ } else if (now >= 7 && now <= 13) {
+ return "1 week ago"
+ } else if (now >= 14 && now <= 20) {
+ return "2 weeks ago"
+ } else if (now >= 21 && now <= 28) {
+ return "3 weeks ago"
+ } else {
+ return `${now} days ago`
+ }
+ } else if (elapsed < msPerYear) {
+ const now = Math.round(elapsed / msPerMonth)
+ if (now === 1) {
+ return "1 month ago"
+ } else {
+ return `${now} months ago`
+ }
+ } else {
+ const now = Math.round(elapsed / msPerYear)
+ if (now === 1) {
+ return "1 year ago"
+ } else {
+ return `${now} years ago`
+ }
+ }
+}
diff --git a/packages/gui/utils/types/JSONArray.ts b/packages/gui/utils/types/JSONArray.ts
new file mode 100644
index 000000000..d6af24661
--- /dev/null
+++ b/packages/gui/utils/types/JSONArray.ts
@@ -0,0 +1,3 @@
+import {JSONValue} from "utils/types/JSONValue"
+
+export interface JSONArray extends Array {}
diff --git a/packages/gui/utils/types/JSONObject.ts b/packages/gui/utils/types/JSONObject.ts
new file mode 100644
index 000000000..119c67ea3
--- /dev/null
+++ b/packages/gui/utils/types/JSONObject.ts
@@ -0,0 +1,5 @@
+import {JSONValue} from "utils/types/JSONValue"
+
+export interface JSONObject {
+ [key: string]: JSONValue
+}
diff --git a/packages/gui/utils/types/JSONValue.ts b/packages/gui/utils/types/JSONValue.ts
new file mode 100644
index 000000000..cebfa25d2
--- /dev/null
+++ b/packages/gui/utils/types/JSONValue.ts
@@ -0,0 +1,4 @@
+import {JSONArray} from "utils/types/JSONArray"
+import {JSONObject} from "utils/types/JSONObject"
+
+export type JSONValue = string | number | boolean | JSONArray | JSONObject | null
diff --git a/packages/gui/utils/useColor.ts b/packages/gui/utils/useColor.ts
index 827047e46..97877d14a 100644
--- a/packages/gui/utils/useColor.ts
+++ b/packages/gui/utils/useColor.ts
@@ -1,9 +1,9 @@
-import useSWR from 'swr'
+import useSWR from "swr"
-import {storage} from './storage'
+import {storage} from "./storage"
export const useColor = () => {
- const swr = useSWR<{color: string}>('color', storage)
+ const swr = useSWR<{color: string}>("color", storage)
return swr
}
diff --git a/packages/gui/utils/useEventCallback.ts b/packages/gui/utils/useEventCallback.ts
new file mode 100644
index 000000000..5637a849d
--- /dev/null
+++ b/packages/gui/utils/useEventCallback.ts
@@ -0,0 +1,11 @@
+import {useCallback, useEffect, useRef} from "react"
+
+export const useEventCallback = (callback: T): ((...args: unknown[]) => T) => {
+ const ref = useRef()
+
+ useEffect(() => {
+ ref.current = callback
+ }, [callback])
+
+ return useCallback((...args): T => ref.current!(...args), [ref])
+}
diff --git a/packages/gui/utils/useIcon.ts b/packages/gui/utils/useIcon.ts
index 7c1954cb7..3b55fc082 100644
--- a/packages/gui/utils/useIcon.ts
+++ b/packages/gui/utils/useIcon.ts
@@ -1,9 +1,9 @@
-import useSWR from 'swr'
+import useSWR from "swr"
-import {storage} from './storage'
+import {storage} from "./storage"
export const useIcon = () => {
- const swr = useSWR<{icon: string}>('icon', storage)
+ const swr = useSWR<{icon: string}>("icon", storage)
return swr
}
diff --git a/packages/gui/utils/useName.ts b/packages/gui/utils/useName.ts
index 0ccfb2705..0dd5247b5 100644
--- a/packages/gui/utils/useName.ts
+++ b/packages/gui/utils/useName.ts
@@ -3,12 +3,12 @@
// also, consider consolidating all these into a single hook.
-import useSWR from 'swr'
+import useSWR from "swr"
-import {storage} from './storage'
+import {storage} from "./storage"
export const useName = () => {
- const swr = useSWR<{name: string}>('name', storage)
+ const swr = useSWR<{name: string}>("name", storage)
return swr
}
diff --git a/packages/gui/utils/usePath.ts b/packages/gui/utils/usePath.ts
index 765a3e560..221357e53 100644
--- a/packages/gui/utils/usePath.ts
+++ b/packages/gui/utils/usePath.ts
@@ -1,9 +1,9 @@
-import useSWR from 'swr'
+import useSWR from "swr"
-import {storage} from './storage'
+import {storage} from "./storage"
export const usePath = () => {
- const swr = useSWR<{path: string}>('path', storage)
+ const swr = useSWR<{path: string}>("path", storage)
return swr
}
diff --git a/packages/installer/jest.config.js b/packages/installer/jest.config.js
index 9df39da96..f50cd02e9 100644
--- a/packages/installer/jest.config.js
+++ b/packages/installer/jest.config.js
@@ -1,11 +1,11 @@
module.exports = {
- preset: 'ts-jest',
- testEnvironment: 'node',
- moduleFileExtensions: ['ts', 'js', 'json'],
- coverageReporters: ['json', 'lcov', 'text', 'clover'],
+ preset: "ts-jest",
+ testEnvironment: "node",
+ moduleFileExtensions: ["ts", "js", "json"],
+ coverageReporters: ["json", "lcov", "text", "clover"],
// collectCoverage: !!`Boolean(process.env.CI)`,
- collectCoverageFrom: ['src/**/*.ts'],
- modulePathIgnorePatterns: ['/tmp', '/dist'],
+ collectCoverageFrom: ["src/**/*.ts"],
+ modulePathIgnorePatterns: ["/tmp", "/dist"],
// TODO enable threshold
// coverageThreshold: {
// global: {
@@ -17,8 +17,8 @@ module.exports = {
// },
globals: {
- 'ts-jest': {
- tsConfig: 'test/tsconfig.json',
+ "ts-jest": {
+ tsConfig: "test/tsconfig.json",
isolatedModules: true,
},
},
diff --git a/packages/installer/src/components/branded.tsx b/packages/installer/src/components/branded.tsx
index d6531e591..a3f2cbcc6 100644
--- a/packages/installer/src/components/branded.tsx
+++ b/packages/installer/src/components/branded.tsx
@@ -1,5 +1,5 @@
-import * as React from 'react'
-import {Color} from 'ink'
+import * as React from "react"
+import {Color} from "ink"
export const Branded: React.FC = ({children}) => (
diff --git a/packages/installer/src/components/newline.tsx b/packages/installer/src/components/newline.tsx
index c7f2dc5d7..c49f29922 100644
--- a/packages/installer/src/components/newline.tsx
+++ b/packages/installer/src/components/newline.tsx
@@ -1,5 +1,5 @@
-import * as React from 'react'
-import {Box} from 'ink'
+import * as React from "react"
+import {Box} from "ink"
export const Newline: React.FC<{count?: number}> = ({count = 1}) => {
return
diff --git a/packages/installer/src/executors/add-dependency-executor.tsx b/packages/installer/src/executors/add-dependency-executor.tsx
index 7f0553ad8..3eacaefbc 100644
--- a/packages/installer/src/executors/add-dependency-executor.tsx
+++ b/packages/installer/src/executors/add-dependency-executor.tsx
@@ -1,12 +1,12 @@
-import {ExecutorConfig, executorArgument, getExecutorArgument, Executor} from './executor'
-import * as fs from 'fs-extra'
-import * as path from 'path'
-import {spawn} from 'cross-spawn'
-import * as React from 'react'
-import {Box, Text} from 'ink'
-import {Newline} from '../components/newline'
-import Spinner from 'ink-spinner'
-import {useEnterToContinue} from '../utils/use-enter-to-continue'
+import {ExecutorConfig, executorArgument, getExecutorArgument, Executor} from "./executor"
+import * as fs from "fs-extra"
+import * as path from "path"
+import {spawn} from "cross-spawn"
+import * as React from "react"
+import {Box, Text} from "ink"
+import {Newline} from "../components/newline"
+import Spinner from "ink-spinner"
+import {useEnterToContinue} from "../utils/use-enter-to-continue"
interface NpmPackage {
name: string
@@ -24,13 +24,13 @@ export function isAddDependencyExecutor(executor: ExecutorConfig): executor is C
return (executor as Config).packages !== undefined
}
-export const type = 'add-dependency'
+export const type = "add-dependency"
function Package({pkg, loading}: {pkg: NpmPackage; loading: boolean}) {
return (
{` `}
- {loading ? : '📦'}
+ {loading ? : "📦"}
{` ${pkg.name}@${pkg.version}`}
)
@@ -68,7 +68,7 @@ const DependencyList = ({
)
}
-export const Propose: Executor['Propose'] = ({cliArgs, step, onProposalAccepted}) => {
+export const Propose: Executor["Propose"] = ({cliArgs, step, onProposalAccepted}) => {
useEnterToContinue(onProposalAccepted)
if (!isAddDependencyExecutor(step)) {
@@ -77,44 +77,44 @@ export const Propose: Executor['Propose'] = ({cliArgs, step, onProposalAccepted}
}
return (
)
}
function getPackageManager() {
- if (fs.existsSync(path.resolve('package-lock.json'))) {
- return 'npm'
+ if (fs.existsSync(path.resolve("package-lock.json"))) {
+ return "npm"
}
- return 'yarn'
+ return "yarn"
}
async function installPackages(packages: NpmPackage[], isDev = false) {
const packageManager = getPackageManager()
- const args: string[] = ['add']
+ const args: string[] = ["add"]
if (isDev) {
- args.push(packageManager === 'yarn' ? '-D' : '--save-dev')
+ args.push(packageManager === "yarn" ? "-D" : "--save-dev")
}
packages.forEach((pkg) => {
pkg.version ? args.push(`${pkg.name}@${pkg.version}`) : args.push(pkg.name)
})
await new Promise((resolve) => {
const cp = spawn(packageManager, args, {
- stdio: ['inherit', 'pipe', 'pipe'],
+ stdio: ["inherit", "pipe", "pipe"],
})
- cp.on('exit', resolve)
+ cp.on("exit", resolve)
})
}
-export const Commit: Executor['Commit'] = ({cliArgs, step, onChangeCommitted}) => {
+export const Commit: Executor["Commit"] = ({cliArgs, step, onChangeCommitted}) => {
const [depsInstalled, setDepsInstalled] = React.useState(false)
const [devDepsInstalled, setDevDepsInstalled] = React.useState(false)
const handleChangeCommitted = React.useCallback(() => {
const packages = (step as Config).packages
- const dependencies = packages.length === 1 ? 'dependency' : 'dependencies'
+ const dependencies = packages.length === 1 ? "dependency" : "dependencies"
onChangeCommitted(`Installed ${packages.length} ${dependencies}`)
}, [onChangeCommitted, step])
@@ -152,7 +152,7 @@ export const Commit: Executor['Commit'] = ({cliArgs, step, onChangeCommitted}) =
return (
<>
= (cliArgs: any) => T
-function isDynamicExecutorArgument(input: executorArgument): input is dynamicExecutorArgument {
- return typeof (input as dynamicExecutorArgument) === 'function'
+function isDynamicExecutorArgument(
+ input: executorArgument,
+): input is dynamicExecutorArgument {
+ return typeof (input as dynamicExecutorArgument) === "function"
}
export type executorArgument = T | dynamicExecutorArgument