forked from defunkt/toes
Centralize VALID_NAME regex into shared types
This commit is contained in:
parent
e7dd220106
commit
0af360cef2
|
|
@ -1,6 +1,6 @@
|
||||||
import { Hype } from '@because/hype'
|
import { Hype } from '@because/hype'
|
||||||
import { define, stylesToCSS } from '@because/forge'
|
import { define, stylesToCSS } from '@because/forge'
|
||||||
import { baseStyles, ToolScript, theme, on } from '@because/toes/tools'
|
import { baseStyles, ToolScript, theme, on, VALID_NAME } from '@because/toes/tools'
|
||||||
import { mkdirSync } from 'fs'
|
import { mkdirSync } from 'fs'
|
||||||
import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'fs/promises'
|
import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'fs/promises'
|
||||||
import { join, resolve } from 'path'
|
import { join, resolve } from 'path'
|
||||||
|
|
@ -13,7 +13,6 @@ const DATA_ROOT = process.env.DATA_ROOT!
|
||||||
const TOES_URL = process.env.TOES_URL!
|
const TOES_URL = process.env.TOES_URL!
|
||||||
|
|
||||||
const REPOS_DIR = resolve(DATA_ROOT, 'repos')
|
const REPOS_DIR = resolve(DATA_ROOT, 'repos')
|
||||||
const VALID_NAME = /^[a-zA-Z0-9._-]+$/
|
|
||||||
const VISIBILITY_PATH = join(DATA_DIR, 'visibility.json')
|
const VISIBILITY_PATH = join(DATA_DIR, 'visibility.json')
|
||||||
|
|
||||||
const TOGGLE_SCRIPT = `
|
const TOGGLE_SCRIPT = `
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { VALID_NAME } from '../../shared/types'
|
||||||
import { closeModal, openModal, renderModal } from '../components/modal'
|
import { closeModal, openModal, renderModal } from '../components/modal'
|
||||||
import { navigate } from '../router'
|
import { navigate } from '../router'
|
||||||
import { apps } from '../state'
|
import { apps } from '../state'
|
||||||
|
|
@ -20,7 +21,7 @@ async function createNewApp() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/^[a-z][a-z0-9.-]*$/.test(name)) {
|
if (!VALID_NAME.test(name)) {
|
||||||
newAppError = 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens'
|
newAppError = 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens'
|
||||||
renderModal()
|
renderModal()
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import type { App } from '../../shared/types'
|
import type { App } from '../../shared/types'
|
||||||
|
import { VALID_NAME } from '../../shared/types'
|
||||||
import { closeModal, openModal, renderModal } from '../components/modal'
|
import { closeModal, openModal, renderModal } from '../components/modal'
|
||||||
import { navigate } from '../router'
|
import { navigate } from '../router'
|
||||||
import { apps } from '../state'
|
import { apps } from '../state'
|
||||||
|
|
@ -19,7 +20,7 @@ async function doRenameApp(input: HTMLInputElement) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/^[a-z][a-z0-9.-]*$/.test(newName)) {
|
if (!VALID_NAME.test(newName)) {
|
||||||
renameAppError = 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens'
|
renameAppError = 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens'
|
||||||
renderModal()
|
renderModal()
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { buildAppUrl } from '@urls'
|
||||||
import { isTunnelsAvailable, shareApp, unshareApp } from '../tunnels'
|
import { isTunnelsAvailable, shareApp, unshareApp } from '../tunnels'
|
||||||
import type { App as BackendApp } from '$apps'
|
import type { App as BackendApp } from '$apps'
|
||||||
import type { App as SharedApp } from '@types'
|
import type { App as SharedApp } from '@types'
|
||||||
|
import { VALID_NAME } from '@types'
|
||||||
import { generateTemplates, type TemplateType } from '%templates'
|
import { generateTemplates, type TemplateType } from '%templates'
|
||||||
import { Hype } from '@because/hype'
|
import { Hype } from '@because/hype'
|
||||||
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'
|
||||||
|
|
@ -120,7 +121,7 @@ router.post('/', async c => {
|
||||||
const name = body.name?.trim().toLowerCase().replace(/\s+/g, '-')
|
const name = body.name?.trim().toLowerCase().replace(/\s+/g, '-')
|
||||||
if (!name) return c.json({ ok: false, error: 'App name is required' }, 400)
|
if (!name) return c.json({ ok: false, error: 'App name is required' }, 400)
|
||||||
|
|
||||||
if (!/^[a-z][a-z0-9.-]*$/.test(name)) {
|
if (!VALID_NAME.test(name)) {
|
||||||
return c.json({ ok: false, error: 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens' }, 400)
|
return c.json({ ok: false, error: 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens' }, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { App as SharedApp, AppState } from '@types'
|
import type { App as SharedApp, AppState } from '@types'
|
||||||
import type { ToesEvent, ToesEventInput, ToesEventType } from '../shared/events'
|
import type { ToesEvent, ToesEventInput, ToesEventType } from '../shared/events'
|
||||||
import type { Subprocess } from 'bun'
|
import type { Subprocess } from 'bun'
|
||||||
import { DEFAULT_EMOJI } from '@types'
|
import { DEFAULT_EMOJI, VALID_NAME } from '@types'
|
||||||
import { buildAppUrl, toSubdomain } from '@urls'
|
import { buildAppUrl, toSubdomain } from '@urls'
|
||||||
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'fs'
|
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'fs'
|
||||||
import { LOCAL_HOST } from '%config'
|
import { LOCAL_HOST } from '%config'
|
||||||
|
|
@ -176,7 +176,7 @@ export async function renameApp(oldName: string, newName: string): Promise<{ ok:
|
||||||
|
|
||||||
if (_apps.has(newName)) return { ok: false, error: 'An app with that name already exists' }
|
if (_apps.has(newName)) return { ok: false, error: 'An app with that name already exists' }
|
||||||
|
|
||||||
if (!/^[a-z][a-z0-9.-]*$/.test(newName)) {
|
if (!VALID_NAME.test(newName)) {
|
||||||
return { ok: false, error: 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens' }
|
return { ok: false, error: 'Name must start with a letter and contain only lowercase letters, numbers, dots, and hyphens' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
export const DEFAULT_EMOJI = '🖥️'
|
export const DEFAULT_EMOJI = '🖥️'
|
||||||
|
export const VALID_NAME = /^[a-z][a-z0-9.-]*$/
|
||||||
|
|
||||||
export interface FileInfo {
|
export interface FileInfo {
|
||||||
hash: string
|
hash: string
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
export { VALID_NAME } from '../shared/types'
|
||||||
export { theme } from '../client/themes'
|
export { theme } from '../client/themes'
|
||||||
export { loadAppEnv } from './env'
|
export { loadAppEnv } from './env'
|
||||||
export type { ToesEvent, ToesEventType } from './events'
|
export type { ToesEvent, ToesEventType } from './events'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user