Skip to content
Merged
17 changes: 2 additions & 15 deletions src/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,6 @@ export class Bundler {
}
}

/**
* Copy files to destination directory
*/
async #copyFiles(files: string[], outDir: string) {
try {
await copyFiles(files, this.#cwdPath, outDir)
} catch (error) {
if (!error.message.includes("the file doesn't exist")) {
throw error
}
}
}

/**
* Copy meta files to the output directory
*/
Expand All @@ -116,7 +103,7 @@ export class Bundler {
.map((file) => file.pattern)
.concat(additionalFilesToCopy)

await this.#copyFiles(metaFiles, outDir)
await copyFiles(metaFiles, this.#cwdPath, outDir)
}

/**
Expand Down Expand Up @@ -189,7 +176,7 @@ export class Bundler {
*/
this.#logger.info('compiling typescript source', { suffix: 'tsc' })
const buildCompleted = await this.#runTsc(outDir)
await this.#copyFiles(['ace.js'], outDir)
await copyFiles(['ace.js'], this.#cwdPath, outDir)

/**
* Remove incomplete build directory when tsc build
Expand Down
36 changes: 26 additions & 10 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
* file that was distributed with this source code.
*/

import cpy from 'cpy'
import { isNotJunk } from 'junk'
import fastGlob from 'fast-glob'
import getRandomPort from 'get-port'
import { existsSync } from 'node:fs'
import type tsStatic from 'typescript'
import { fileURLToPath } from 'node:url'
import { execaNode, execa } from 'execa'
import { isAbsolute, relative } from 'node:path'
import { copyFile, mkdir } from 'node:fs/promises'
import { dirname, isAbsolute, join, relative } from 'node:path'
import { EnvLoader, EnvParser } from '@adonisjs/env'
import { ConfigParser, Watcher } from '@poppinss/chokidar-ts'

Expand Down Expand Up @@ -179,9 +180,18 @@ export async function copyFiles(files: string[], cwd: string, outDir: string) {
*/
const { paths, patterns } = files.reduce<{ patterns: string[]; paths: string[] }>(
(result, file) => {
/**
* If file is a glob pattern, then push it to patterns
*/
if (fastGlob.isDynamicPattern(file)) {
result.patterns.push(file)
} else {
return result
}

/**
* Otherwise, check if file exists and push it to paths to copy
*/
if (existsSync(join(cwd, file))) {
result.paths.push(file)
}

Expand All @@ -198,14 +208,20 @@ export async function copyFiles(files: string[], cwd: string, outDir: string) {
const filePaths = paths.concat(await fastGlob(patterns, { cwd }))

/**
* Computing relative destination. This is because, cpy is buggy when
* outDir is an absolute path.
* Finally copy files to the destination by keeping the same
* directory structure and ignoring junk files
*/
const destination = isAbsolute(outDir) ? relative(cwd, outDir) : outDir
debug('copying files %O to destination "%s"', filePaths, destination)
debug('copying files %O to destination "%s"', filePaths, outDir)
const copyPromises = filePaths.map(async (file) => {
const isJunkFile = !isNotJunk(file)
if (isJunkFile) return

return cpy(filePaths.filter(isNotJunk), destination, {
cwd: cwd,
flat: false,
const src = isAbsolute(file) ? file : join(cwd, file)
const dest = join(outDir, relative(cwd, src))

await mkdir(dirname(dest), { recursive: true })
return copyFile(src, dest)
})

return await Promise.all(copyPromises)
}
30 changes: 30 additions & 0 deletions tests/bundler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,34 @@ test.group('Bundler', () => {
assert.fileExists('./build/package-lock.json'),
])
})

test('should copy metafiles even if lock file is missing', async ({ assert, fs }) => {
await Promise.all([
fs.create(
'tsconfig.json',
JSON.stringify({ compilerOptions: { outDir: 'build', skipLibCheck: true } })
),
fs.create('adonisrc.ts', 'export default {}'),
fs.create('package.json', '{}'),

fs.create('resources/views/app.edge', ''),
])

const bundler = new Bundler(fs.baseUrl, ts, {
metaFiles: [
{
pattern: 'resources/views/**/*.edge',
reloadServer: false,
},
],
})

await bundler.bundle(true, 'npm')

await Promise.all([
assert.fileExists('./build/resources/views/app.edge'),
assert.fileExists('./build/package.json'),
assert.fileExists('./build/adonisrc.js'),
])
})
})
57 changes: 57 additions & 0 deletions tests/copy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { test } from '@japa/runner'
import { copyFiles } from '../src/helpers.js'
import { join } from 'node:path'

test.group('Copy files', () => {
test('match file patterns', async ({ fs }) => {
await fs.create('resources/views/welcome.edge', '')
await fs.create('resources/views/about.edge', '')
await fs.create('resources/views/contact/main.edge', '')

await fs.create('public/foo/test/a.json', '')
await fs.create('public/foo/test/b/a.json', '')

await copyFiles(
['resources/views/*.edge', 'public/**'],
fs.basePath,
join(fs.basePath, 'build')
)

await fs.exists('build/resources/views/welcome.edge')
await fs.exists('build/resources/views/about.edge')
await fs.exists('build/resources/views/contact/main.edge')

await fs.exists('build/public/foo/test/a.json')
await fs.exists('build/public/foo/test/b/a.json')
})

test('copy files that are not glob patterns', async ({ fs }) => {
await fs.create('resources/views/welcome.edge', '')
await fs.create('resources/views/about.edge', '')
await fs.create('package.json', '')

await copyFiles(
['resources/views/welcome.edge', 'resources/views/about.edge', 'package.json'],
fs.basePath,
join(fs.basePath, 'build')
)

await fs.exists('build/resources/views/welcome.edge')
await fs.exists('build/resources/views/about.edge')
await fs.exists('build/package.json')
})

test("copy files even if one path doesn't exist", async ({ fs }) => {
await fs.create('resources/views/welcome.edge', '')
await fs.create('resources/views/about.edge', '')

await copyFiles(
['resources/views/welcome.edge', 'resources/views/about.edge', 'package.json'],
fs.basePath,
join(fs.basePath, 'build')
)

await fs.exists('build/resources/views/welcome.edge')
await fs.exists('build/resources/views/about.edge')
})
})