Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(esm): convert @redwoodjs/cli-helpers to ESM #9872

Merged
merged 6 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/cli-helpers/.babelrc.js

This file was deleted.

222 changes: 3 additions & 219 deletions packages/cli-helpers/__mocks__/fs.js
Original file line number Diff line number Diff line change
@@ -1,220 +1,4 @@
import path from 'path'
import * as memfs from 'memfs'

Josh-Walker-GM marked this conversation as resolved.
Show resolved Hide resolved
const fs = {
...jest.requireActual('fs'),
}

let mockFiles = {}

const pathSeparator = path.sep

const getParentDir = (path) => {
return path.substring(0, path.lastIndexOf(pathSeparator))
}

const makeParentDirs = (path) => {
const parentDir = getParentDir(path)
if (parentDir && !(parentDir in mockFiles)) {
mockFiles[parentDir] = undefined
makeParentDirs(parentDir)
}
}

/**
* This is a custom function that our tests can use during setup to specify
* what the files on the "mock" filesystem should look like when any of the
* `fs` APIs are used.
*
* Sets the state of the mocked file system
* @param newMockFiles - {[filepath]: contents}
*/
fs.__setMockFiles = (newMockFiles) => {
mockFiles = { ...newMockFiles }

// Generate all the directories which implicitly exist
Object.keys(mockFiles).forEach((mockPath) => {
if (mockPath.includes(pathSeparator)) {
makeParentDirs(mockPath)
}
})
}

fs.__getMockFiles = () => {
return mockFiles
}

fs.readFileSync = (path) => {
// In prisma v4.3.0, prisma format uses a Wasm module. See https://github.com/prisma/prisma/releases/tag/4.3.0.
// We shouldn't mock this, so we'll use the real fs.readFileSync.
if (path.includes('prisma_fmt_build_bg.wasm')) {
return jest.requireActual('fs').readFileSync(path)
}

if (path in mockFiles) {
return mockFiles[path]
} else {
const fakeError = new Error(
`Error: ENOENT: no such file or directory, open '${path}'`
)
fakeError.errno = -2
fakeError.syscall = 'open'
fakeError.code = 'ENOENT'
fakeError.path = path
throw fakeError
}
}

fs.writeFileSync = (path, contents) => {
const parentDir = getParentDir(path)
if (parentDir && !fs.existsSync(parentDir)) {
const fakeError = new Error(
`Error: ENOENT: no such file or directory, open '${path}'`
)
fakeError.errno = -2
fakeError.syscall = 'open'
fakeError.code = 'ENOENT'
fakeError.path = path
throw fakeError
}
mockFiles[path] = contents
}

fs.appendFileSync = (path, contents) => {
if (path in mockFiles) {
mockFiles[path] = mockFiles[path] + contents
} else {
fs.writeFileSync(path, contents)
}
}

fs.rmSync = (path, options = {}) => {
if (fs.existsSync(path)) {
if (options.recursive) {
Object.keys(mockFiles).forEach((mockedPath) => {
if (mockedPath.startsWith(path)) {
delete mockFiles[mockedPath]
}
})
} else {
if (mockFiles[path] === undefined) {
const children = fs.readdirSync(path)
if (children.length !== 0) {
const fakeError = new Error(
`NodeError [SystemError]: Path is a directory: rm returned EISDIR (is a directory) ${path}`
)
fakeError.errno = 21
fakeError.syscall = 'rm'
fakeError.code = 'ERR_FS_EISDIR'
fakeError.path = path
throw fakeError
}
}
delete mockFiles[path]
}
} else {
const fakeError = new Error(
`Error: ENOENT: no such file or directory, stat '${path}'`
)
fakeError.errno = -2
fakeError.syscall = 'stat'
fakeError.code = 'ENOENT'
fakeError.path = path
throw fakeError
}
}

fs.unlinkSync = (path) => {
if (path in mockFiles) {
delete mockFiles[path]
} else {
const fakeError = new Error(
`Error: ENOENT: no such file or directory, stat '${path}'`
)
fakeError.errno = -2
fakeError.syscall = 'unlink'
fakeError.code = 'ENOENT'
fakeError.path = path
throw fakeError
}
}

fs.existsSync = (path) => {
return path in mockFiles
}

fs.copyFileSync = (src, dist) => {
fs.writeFileSync(dist, fs.readFileSync(src))
}

fs.readdirSync = (path) => {
if (!fs.existsSync(path)) {
const fakeError = new Error(
`Error: ENOENT: no such file or directory, scandir '${path}'`
)
fakeError.errno = -2
fakeError.syscall = 'scandir'
fakeError.code = 'ENOENT'
fakeError.path = path
throw fakeError
}

if (mockFiles[path] !== undefined) {
const fakeError = new Error(
`Error: ENOTDIR: not a directory, scandir '${path}'`
)
fakeError.errno = -20
fakeError.syscall = 'scandir'
fakeError.code = 'ENOTDIR'
fakeError.path = path
throw fakeError
}

const content = []
Object.keys(mockFiles).forEach((mockedPath) => {
const childPath = mockedPath.substring(path.length + 1)
if (
mockedPath.startsWith(path) &&
!childPath.includes(pathSeparator) &&
childPath
) {
content.push(childPath)
}
})
return content
}

fs.mkdirSync = (path, options = {}) => {
if (options.recursive) {
makeParentDirs(path)
}
// Directories are represented as paths with an "undefined" value
fs.writeFileSync(path, undefined)
}

fs.rmdirSync = (path, options = {}) => {
if (!fs.existsSync(path)) {
const fakeError = new Error(
`Error: ENOENT: no such file or directory, rmdir '${path}'`
)
fakeError.errno = -2
fakeError.syscall = 'rmdir'
fakeError.code = 'ENOENT'
fakeError.path = path
throw fakeError
}

if (mockFiles[path] !== undefined) {
const fakeError = new Error(
`Error: ENOTDIR: not a directory, rmdir '${path}'`
)
fakeError.errno = -20
fakeError.syscall = 'rmdir'
fakeError.code = 'ENOTDIR'
fakeError.path = path
throw fakeError
}

fs.rmSync(path, options)
}

module.exports = fs
export * from 'memfs'
export default memfs.fs
26 changes: 26 additions & 0 deletions packages/cli-helpers/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as esbuild from 'esbuild'

const options = {
entryPoints: ['./src/index.ts'],
outdir: 'dist',

platform: 'node',
target: ['node20'],
bundle: true,
packages: 'external',

logLevel: 'info',
metafile: true,
}

await esbuild.build({
...options,
format: 'esm',
outExtension: { '.js': '.mjs' },
})

await esbuild.build({
...options,
format: 'cjs',
outExtension: { '.js': '.cjs' },
})
4 changes: 0 additions & 4 deletions packages/cli-helpers/jest.config.js

This file was deleted.

21 changes: 11 additions & 10 deletions packages/cli-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,32 @@
"directory": "packages/cli-helpers"
},
"license": "MIT",
"main": "./dist/index.js",
"type": "module",
"exports": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.cjs"
},
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "yarn build:js && yarn build:types",
"build:js": "babel src -d dist --extensions \".js,.jsx,.ts,.tsx\"",
"build": "yarn node ./build.js && yarn build:types",
"build:pack": "yarn pack -o redwoodjs-cli-helpers.tgz",
"build:types": "tsc --build --verbose",
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
"prepublishOnly": "NODE_ENV=production yarn build",
"test": "jest src",
"test:watch": "yarn test --watch"
"test": "vitest run",
"test:watch": "vitest watch"
},
"dependencies": {
"@babel/core": "^7.22.20",
"@babel/runtime-corejs3": "7.23.6",
"@iarna/toml": "2.2.5",
"@opentelemetry/api": "1.7.0",
"@redwoodjs/project-config": "6.0.7",
"@redwoodjs/telemetry": "6.0.7",
"chalk": "4.1.2",
"core-js": "3.34.0",
"dotenv": "16.3.1",
"execa": "5.1.1",
"listr2": "6.6.1",
Expand All @@ -41,12 +43,11 @@
"terminal-link": "2.1.1"
},
"devDependencies": {
"@babel/cli": "7.23.4",
"@types/lodash": "4.14.201",
"@types/pascalcase": "1.0.3",
"@types/yargs": "17.0.32",
"jest": "29.7.0",
"typescript": "5.3.3"
"typescript": "5.3.3",
"vitest": "1.2.1"
},
"gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1"
}
Loading
Loading