import { AsyncFileSystem, FileSystem } from './fs' import { NowConfig } from './now-config' import readJson, { readJsonAsync } from './util/read-json' import { PackageJson } from 'type-fest' const listJoin = new Intl.ListFormat('default', { style: 'long', type: 'conjunction', }) export type App = { /** * The parsed package.json */ package: Package /** * SDK-specific configuration */ config: NowConfig /** * Root directory of the app */ rootDir: string } export type Package = PackageJson & { name: string version: string now?: NowConfig dependencies?: Record devDependencies?: Record } export async function parsePackageJsonAsync(rootDir: string, fs: AsyncFileSystem): Promise { return readJsonAsync(rootDir, 'package.json', fs) } export function parsePackageJson(rootDir: string, fs: FileSystem): Package { return readJson(rootDir, 'package.json', fs) } export function validateAppName(name: string | undefined): string | undefined { if (!name) { return `Invalid application name: cannot be empty` } if (name.length > 100) { return `Invalid application name: can be at most 100 characters long` } return undefined } // Scope checks from https://code.devsnc.com/dev/glide/blob/master/glide/src/com/glide/app_store/ScopeNameUtil.java#L112 export function validateScopeName(name: string | undefined, requiredPrefix?: string | undefined): string | undefined { const errors: string[] = [] if (!name) { return `Invalid scope: cannot be empty` } if (name.length > 18) { errors.push('must be less than 18 characters') } if (name.endsWith('_')) { errors.push('cannot end in an underscore') } if (name.includes('__')) { errors.push('cannot contain double underscore') } if (/[^a-z0-9_]/.test(name)) { errors.push('can only contain lowercase alphanumeric characters and underscores') } if (requiredPrefix) { if (name === requiredPrefix) { errors.push(`must not exactly match prefix "${requiredPrefix}"`) } if (!name.startsWith(requiredPrefix)) { errors.push(`must start with prefix "${requiredPrefix}"`) } } if (errors.length) { return `Invalid scope: ${listJoin.format(errors)}` } return undefined }