or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

detection.mdfile-classes.mdfilesystem.mdindex.mdlambda.mdscript-execution.md

detection.mddocs/

0

# Detection System

1

2

Automatic detection of project frameworks and appropriate builders for zero-configuration deployments.

3

4

## Capabilities

5

6

### Builder Detection

7

8

Automatically detect appropriate builders for a project based on its files and configuration.

9

10

```typescript { .api }

11

/**

12

* Detect appropriate builders for a project

13

* @param files - Array of file paths in the project

14

* @param pkg - Package.json contents (for npm projects)

15

* @param options - Detection options

16

* @returns Object containing detected builders, errors, and warnings

17

*/

18

function detectBuilders(

19

files: string[],

20

pkg?: PackageJson,

21

options?: Options

22

): { builders: Builder[]; errors: ErrorResponse[]; warnings: WarningResponse[] };

23

24

interface Options {

25

tag?: 'canary' | 'latest' | string;

26

functions?: BuilderFunctions;

27

ignoreBuildScript?: boolean;

28

projectSettings?: {

29

framework?: string | null;

30

devCommand?: string | null;

31

buildCommand?: string | null;

32

outputDirectory?: string | null;

33

};

34

}

35

36

interface Builder {

37

use: string;

38

src: string;

39

config?: Config;

40

}

41

42

interface ErrorResponse {

43

code: string;

44

message: string;

45

}

46

```

47

48

**Usage Examples:**

49

50

```typescript

51

import { detectBuilders } from "@now/build-utils";

52

53

// Detect builders for a Node.js project

54

const files = [

55

"index.js",

56

"package.json",

57

"api/users.js",

58

"api/posts.js",

59

"public/index.html"

60

];

61

62

const packageJson = {

63

name: "my-app",

64

scripts: {

65

build: "next build"

66

},

67

dependencies: {

68

next: "^12.0.0"

69

}

70

};

71

72

const result = detectBuilders(files, packageJson);

73

console.log("Detected builders:", result.builders);

74

// Output: [

75

// { use: "@vercel/next", src: "package.json" },

76

// { use: "@vercel/node", src: "api/**/*.js" }

77

// ]

78

79

// With custom options

80

const customResult = detectBuilders(files, packageJson, {

81

tag: "canary",

82

functions: {

83

"api/slow.js": { memory: 1024, maxDuration: 60 }

84

}

85

});

86

```

87

88

### Framework Detection

89

90

Detect which framework is being used in a project.

91

92

```typescript { .api }

93

/**

94

* Detect framework being used in a project

95

* @param options - Detection options with filesystem interface

96

* @returns Promise resolving to framework slug or null if none detected

97

*/

98

function detectFramework(options: DetectFrameworkOptions): Promise<string | null>;

99

100

interface DetectFrameworkOptions {

101

/** Filesystem interface for reading project files */

102

fs: DetectorFilesystem;

103

/** List of frameworks to check against */

104

frameworkList: Framework[];

105

}

106

107

interface Framework {

108

slug: string;

109

name: string;

110

detectors?: {

111

every?: FrameworkDetectionItem[];

112

some?: FrameworkDetectionItem[];

113

};

114

}

115

116

interface FrameworkDetectionItem {

117

path: string;

118

matchContent?: string;

119

}

120

```

121

122

**Usage Examples:**

123

124

```typescript

125

import { detectFramework } from "@now/build-utils";

126

127

// Implement filesystem interface

128

class ProjectFilesystem extends DetectorFilesystem {

129

protected async _hasPath(path: string): Promise<boolean> {

130

return fs.existsSync(path);

131

}

132

133

protected async _readFile(path: string): Promise<Buffer> {

134

return fs.readFileSync(path);

135

}

136

137

protected async _isFile(path: string): Promise<boolean> {

138

const stat = await fs.lstat(path);

139

return stat.isFile();

140

}

141

}

142

143

const framework = await detectFramework({

144

fs: new ProjectFilesystem(),

145

frameworkList: [

146

{

147

slug: "nextjs",

148

name: "Next.js",

149

detectors: {

150

some: [

151

{ path: "next.config.js" },

152

{ path: "package.json", matchContent: '"next"' }

153

]

154

}

155

}

156

]

157

});

158

159

console.log("Detected framework:", framework); // "nextjs" or null

160

```

161

162

### Route Detection

163

164

Detect API routes and generate routing configuration from filesystem structure.

165

166

```typescript { .api }

167

/**

168

* Detect API routes from filesystem

169

* @param filePaths - Array of file paths to analyze

170

* @param builders - Array of detected builders

171

* @param options - Route detection options

172

* @returns Array of detected routes

173

*/

174

function detectRoutes(

175

filePaths: string[],

176

builders: Builder[],

177

options?: DetectRoutesOptions

178

): Route[];

179

180

interface DetectRoutesOptions {

181

cleanUrls?: boolean;

182

trailingSlash?: boolean;

183

}

184

185

interface Route {

186

src: string;

187

dest?: string;

188

headers?: { [key: string]: string };

189

methods?: string[];

190

status?: number;

191

}

192

```

193

194

**Usage Examples:**

195

196

```typescript

197

import { detectRoutes } from "@now/build-utils";

198

199

const filePaths = [

200

"api/users/[id].js",

201

"api/posts/index.js",

202

"api/auth/login.js"

203

];

204

205

const builders = [

206

{ use: "@vercel/node", src: "api/**/*.js" }

207

];

208

209

const routes = detectRoutes(filePaths, builders, {

210

cleanUrls: true

211

});

212

213

console.log("Generated routes:", routes);

214

// Routes for dynamic routing, API endpoints, etc.

215

```

216

217

### Directory Detection

218

219

Detect specific directories and their purposes from builder configurations.

220

221

```typescript { .api }

222

/**

223

* Detect output directory from builders

224

* @param builders - Array of detected builders

225

* @returns Output directory path or null if not found

226

*/

227

function detectOutputDirectory(builders: Builder[]): string | null;

228

229

/**

230

* Detect API directory from builders

231

* @param builders - Array of detected builders

232

* @returns API directory path or null if not found

233

*/

234

function detectApiDirectory(builders: Builder[]): string | null;

235

236

/**

237

* Detect API file extensions from builders

238

* @param builders - Array of detected builders

239

* @returns Set of supported file extensions

240

*/

241

function detectApiExtensions(builders: Builder[]): Set<string>;

242

```

243

244

**Usage Examples:**

245

246

```typescript

247

import {

248

detectBuilders,

249

detectOutputDirectory,

250

detectApiDirectory,

251

detectApiExtensions

252

} from "@now/build-utils";

253

254

// First detect builders from project files

255

const files = [

256

"dist/index.html",

257

"dist/assets/style.css",

258

"api/hello.js",

259

"api/users.ts"

260

];

261

262

const builders = detectBuilders(files).builders;

263

264

// Then use builders to detect directories and extensions

265

const outputDir = detectOutputDirectory(builders);

266

console.log("Output directory:", outputDir); // "dist" or null

267

268

const apiDir = detectApiDirectory(builders);

269

console.log("API directory:", apiDir); // "api" or null

270

271

const apiExts = detectApiExtensions(builders);

272

console.log("API extensions:", apiExts); // Set([".js", ".ts"])

273

```

274

275

## Filesystem Detection Interface

276

277

### DetectorFilesystem

278

279

Abstract filesystem interface for framework detection that can be implemented for different storage backends.

280

281

```typescript { .api }

282

/**

283

* Abstract filesystem interface for framework detection

284

*/

285

abstract class DetectorFilesystem {

286

/** Check if a path exists */

287

hasPath(path: string): Promise<boolean>;

288

/** Check if a path represents a file */

289

isFile(path: string): Promise<boolean>;

290

/** Read file contents as Buffer */

291

readFile(path: string): Promise<Buffer>;

292

293

// Abstract methods that must be implemented

294

protected abstract _hasPath(path: string): Promise<boolean>;

295

protected abstract _readFile(path: string): Promise<Buffer>;

296

protected abstract _isFile(path: string): Promise<boolean>;

297

}

298

```

299

300

**Usage Examples:**

301

302

```typescript

303

import { DetectorFilesystem } from "@now/build-utils";

304

305

// Local filesystem implementation

306

class LocalFilesystem extends DetectorFilesystem {

307

constructor(private basePath: string) {

308

super();

309

}

310

311

protected async _hasPath(path: string): Promise<boolean> {

312

const fullPath = require('path').join(this.basePath, path);

313

return require('fs').existsSync(fullPath);

314

}

315

316

protected async _readFile(path: string): Promise<Buffer> {

317

const fullPath = require('path').join(this.basePath, path);

318

return require('fs').readFileSync(fullPath);

319

}

320

321

protected async _isFile(path: string): Promise<boolean> {

322

const fullPath = require('path').join(this.basePath, path);

323

const stat = await require('fs').promises.lstat(fullPath);

324

return stat.isFile();

325

}

326

}

327

328

// HTTP filesystem implementation

329

class HttpFilesystem extends DetectorFilesystem {

330

constructor(private baseUrl: string) {

331

super();

332

}

333

334

protected async _hasPath(path: string): Promise<boolean> {

335

try {

336

const response = await fetch(`${this.baseUrl}/${path}`, { method: 'HEAD' });

337

return response.ok;

338

} catch {

339

return false;

340

}

341

}

342

343

protected async _readFile(path: string): Promise<Buffer> {

344

const response = await fetch(`${this.baseUrl}/${path}`);

345

const arrayBuffer = await response.arrayBuffer();

346

return Buffer.from(arrayBuffer);

347

}

348

349

protected async _isFile(path: string): Promise<boolean> {

350

// Implementation depends on HTTP API capabilities

351

return this._hasPath(path);

352

}

353

}

354

```

355

356

## Detection Patterns

357

358

### Framework Detection Patterns

359

360

Common patterns used for framework detection:

361

362

```typescript

363

const frameworkPatterns = {

364

nextjs: {

365

some: [

366

{ path: "next.config.js" },

367

{ path: "next.config.ts" },

368

{ path: "package.json", matchContent: '"next"' }

369

]

370

},

371

nuxtjs: {

372

some: [

373

{ path: "nuxt.config.js" },

374

{ path: "nuxt.config.ts" },

375

{ path: "package.json", matchContent: '"nuxt"' }

376

]

377

},

378

gatsby: {

379

some: [

380

{ path: "gatsby-config.js" },

381

{ path: "gatsby-config.ts" },

382

{ path: "package.json", matchContent: '"gatsby"' }

383

]

384

}

385

};

386

```

387

388

### Builder Selection Logic

389

390

The detection system uses the following priority for selecting builders:

391

392

1. **API functions**: Files in `api/` directory get function builders

393

2. **Framework detection**: Detected frameworks get their specific builders

394

3. **Build scripts**: Projects with build scripts get static builders

395

4. **File extensions**: Fallback based on file types (.js, .ts, .py, etc.)

396

5. **Zero config**: Default builders for common patterns