From bffecd9ce1f61b0a98c24817cd60e1009671c7e8 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 8 Jun 2022 17:09:28 -0700 Subject: [PATCH 01/12] feat: support .aegir.ts config files Fix #943 --- .aegir.js => .aegir.ts | 3 +- README.md | 8 ++--- package.json | 1 + src/config/user.js | 74 +++++++++++++++++++++++++++++++----------- 4 files changed, 61 insertions(+), 25 deletions(-) rename .aegir.js => .aegir.ts (53%) diff --git a/.aegir.js b/.aegir.ts similarity index 53% rename from .aegir.js rename to .aegir.ts index be220ea36..20c6d9a84 100644 --- a/.aegir.js +++ b/.aegir.ts @@ -1,6 +1,5 @@ -/** @type {import("./src/types").PartialOptions} */ export default { docs: { entryPoint: 'utils' } -} +} as import("./src/types").PartialOptions diff --git a/README.md b/README.md index 5e16ad214..0ef6ace49 100644 --- a/README.md +++ b/README.md @@ -136,12 +136,12 @@ aegir test --ts-repo ## Release steps -1. Run linting +1. Run linting `npm run lint` 2. Run type check -3. Run tests +3. Run tests `npm run test` 4. Bump the version in `package.json` -5. Build everything -6. Update contributors based on the git history +5. Build everything `npm run build` +6. Update contributors based on the git history (deprecated?) 7. Generate a changelog based on the git log 8. Commit the version change & `CHANGELOG.md` 9. Create a git tag diff --git a/package.json b/package.json index 8d638c30e..9c0e65fc7 100644 --- a/package.json +++ b/package.json @@ -273,6 +273,7 @@ "strip-bom": "^5.0.0", "strip-json-comments": "^4.0.0", "tempy": "^2.0.0", + "ts-import": "^3.0.0-beta.3", "typescript": "^4.6.3", "uint8arrays": "^3.0.0", "undici": "^5.0.0", diff --git a/src/config/user.js b/src/config/user.js index 689a6cbc3..06e2dfa03 100644 --- a/src/config/user.js +++ b/src/config/user.js @@ -1,9 +1,9 @@ /* eslint-disable no-console */ - +// @ts-check import { lilconfig } from 'lilconfig' import merge from 'merge-options' import { pathToFileURL } from 'url' - +import tsImport from 'ts-import' /** * @typedef {import("./../types").Options} Options */ @@ -125,6 +125,54 @@ const defaults = { } } +/** + * @typedef {(filepath: string) => Promise} Loader + */ + +/** + * + * @param {{default?: Options} | Options} mod + * @returns {Options | {}} + */ +const handleConfigImport = (mod) => { + /** + * @type {*} + */ + const modWithDefaultExport = mod + if (modWithDefaultExport.default != null) { + return modWithDefaultExport.default + } + + if (typeof mod.toString === 'function') { + return mod + } + + // if there's no toString function, this was an ES module that didn't export anything + return {} +} + +/** + * @type {Loader} + */ +const loadEsm = async (filepath) => { + const res = await import(pathToFileURL(filepath).toString()) + + return handleConfigImport(res) +} + +/** + * @type {Loader} + */ +const loadTs = async (filepath) => { + try { + const res = await tsImport.load(filepath) + + return handleConfigImport(res) + } catch (err) { + return {} + } +} + /** * Search for local user config * @@ -132,32 +180,20 @@ const defaults = { * @returns {Promise} */ export const config = async (searchFrom) => { + console.log('searchFrom: ', searchFrom) let userConfig try { - const loadEsm = async (/** @type {string} */ filepath) => { - /** @type {any} */ - const res = await import(pathToFileURL(filepath).toString()) - - if (res.default != null) { - return res.default - } - - if (typeof res.toString === 'function') { - return res - } - - // if there's no toString function, this was an ES module that didn't export anything - return {} - } const loadedConfig = await lilconfig('aegir', { loaders: { '.js': loadEsm, - '.mjs': loadEsm + '.mjs': loadEsm, + '.ts': loadTs }, searchPlaces: [ 'package.json', '.aegir.js', - '.aegir.cjs' + '.aegir.cjs', + '.aegir.ts' ] }) .search(searchFrom) From eec2938f035e1b6ae5b5f07b4f12df8fb477fc1f Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 8 Jun 2022 17:10:48 -0700 Subject: [PATCH 02/12] docs: update release steps --- README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0ef6ace49..f9f10dfe9 100644 --- a/README.md +++ b/README.md @@ -137,18 +137,16 @@ aegir test --ts-repo ## Release steps 1. Run linting `npm run lint` -2. Run type check -3. Run tests `npm run test` -4. Bump the version in `package.json` -5. Build everything `npm run build` -6. Update contributors based on the git history (deprecated?) -7. Generate a changelog based on the git log -8. Commit the version change & `CHANGELOG.md` -9. Create a git tag -10. Run `git push` to `origin/master` -11. Publish a release to Github releases -12. Generate documentation and push to Github Pages -13. Publish to npm +1. Run tests `npm run test` +1. Bump the version in `package.json` +1. Build everything `npm run build` +1. Generate a changelog based on the git log (missing command?) +1. Commit the version change & `CHANGELOG.md` +1. Create a git tag +1. Run `git push` to `origin/master` +1. Publish a release to Github releases +1. Generate documentation and push to Github Pages +1. Publish to npm ```bash aegir release --help From a17e4c7f11da9b8bae51db8deac9decfd3e5adc4 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 8 Jun 2022 17:17:02 -0700 Subject: [PATCH 03/12] chore: remove dev comment --- src/config/user.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config/user.js b/src/config/user.js index 06e2dfa03..a24a7b892 100644 --- a/src/config/user.js +++ b/src/config/user.js @@ -180,7 +180,6 @@ const loadTs = async (filepath) => { * @returns {Promise} */ export const config = async (searchFrom) => { - console.log('searchFrom: ', searchFrom) let userConfig try { const loadedConfig = await lilconfig('aegir', { From eacb4637a913cae8aa5071939796f66865bdfb2a Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 9 Jun 2022 14:42:15 -0700 Subject: [PATCH 04/12] revert README.md changes --- README.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f9f10dfe9..5e16ad214 100644 --- a/README.md +++ b/README.md @@ -136,17 +136,19 @@ aegir test --ts-repo ## Release steps -1. Run linting `npm run lint` -1. Run tests `npm run test` -1. Bump the version in `package.json` -1. Build everything `npm run build` -1. Generate a changelog based on the git log (missing command?) -1. Commit the version change & `CHANGELOG.md` -1. Create a git tag -1. Run `git push` to `origin/master` -1. Publish a release to Github releases -1. Generate documentation and push to Github Pages -1. Publish to npm +1. Run linting +2. Run type check +3. Run tests +4. Bump the version in `package.json` +5. Build everything +6. Update contributors based on the git history +7. Generate a changelog based on the git log +8. Commit the version change & `CHANGELOG.md` +9. Create a git tag +10. Run `git push` to `origin/master` +11. Publish a release to Github releases +12. Generate documentation and push to Github Pages +13. Publish to npm ```bash aegir release --help From 8b6ac5109e05db1fd8e5f221097de6c20575f602 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 9 Jun 2022 14:50:30 -0700 Subject: [PATCH 05/12] feat: eslint checks .aegir.ts --- .aegir.ts | 12 +++++++----- .eslintignore | 1 + tsconfig.json | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 .eslintignore diff --git a/.aegir.ts b/.aegir.ts index 20c6d9a84..3b9838f81 100644 --- a/.aegir.ts +++ b/.aegir.ts @@ -1,5 +1,7 @@ -export default { - docs: { - entryPoint: 'utils' - } -} as import("./src/types").PartialOptions +const options: import('./src/types').PartialOptions = { + docs: { + entryPoint: 'utils' + } +} + +export default options diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..8d5fa662a --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +!.aegir.ts diff --git a/tsconfig.json b/tsconfig.json index ca16e19bc..9f5dfc01d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "emitDeclarationOnly": true }, "include": [ + ".aegir.ts", "package.json", "src", "test", From 934927cf935ff89d7053bc7590d6464f504a01e4 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 9 Jun 2022 14:50:54 -0700 Subject: [PATCH 06/12] remove @ts-check pragma --- src/config/user.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config/user.js b/src/config/user.js index a24a7b892..8dfe215af 100644 --- a/src/config/user.js +++ b/src/config/user.js @@ -1,5 +1,4 @@ /* eslint-disable no-console */ -// @ts-check import { lilconfig } from 'lilconfig' import merge from 'merge-options' import { pathToFileURL } from 'url' From 8bc09caf1a8a778ee620ba7e664a883a1fae3c5f Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 13 Jun 2022 12:19:23 -0700 Subject: [PATCH 07/12] feat: invalid aegir config throws errors --- src/config/defaults.js | 122 +++++++++++ src/config/user.js | 189 +++++------------- src/{types.ts => types.d.ts} | 0 .../config-with-invalid-export/.aegir.js | 5 + .../config-with-invalid-export/package.json | 4 + .../fixtures/config-without-export/.aegir.js | 3 + .../config-without-export/package.json | 4 + .../fixtures/custom-ts-config/.aegir.ts | 12 ++ .../fixtures/custom-ts-config/.eslintignore | 1 + .../fixtures/custom-ts-config/.eslintrc.js | 8 + .../fixtures/custom-ts-config/package.json | 3 + .../fixtures/custom-ts-config/tsconfig.json | 10 + test/config/user.js | 38 +++- .../with-aegir-config/.aegir.js | 2 + 14 files changed, 257 insertions(+), 144 deletions(-) create mode 100644 src/config/defaults.js rename src/{types.ts => types.d.ts} (100%) create mode 100644 test/config/fixtures/config-with-invalid-export/.aegir.js create mode 100644 test/config/fixtures/config-with-invalid-export/package.json create mode 100644 test/config/fixtures/config-without-export/.aegir.js create mode 100644 test/config/fixtures/config-without-export/package.json create mode 100644 test/config/fixtures/custom-ts-config/.aegir.ts create mode 100644 test/config/fixtures/custom-ts-config/.eslintignore create mode 100644 test/config/fixtures/custom-ts-config/.eslintrc.js create mode 100644 test/config/fixtures/custom-ts-config/package.json create mode 100644 test/config/fixtures/custom-ts-config/tsconfig.json diff --git a/src/config/defaults.js b/src/config/defaults.js new file mode 100644 index 000000000..d260a32e2 --- /dev/null +++ b/src/config/defaults.js @@ -0,0 +1,122 @@ +/** + * @typedef {import("./../types").Options} Options + */ + +/** @type {Omit} */ +const defaults = { + // global options + debug: false, + // test cmd options + test: { + build: false, + runner: 'node', + target: ['node', 'browser', 'webworker'], + watch: false, + files: [], + timeout: 60000, + grep: '', + bail: false, + progress: false, + cov: false, + browser: { + config: { + buildConfig: { + conditions: ['production'] + } + } + }, + before: async () => { return undefined }, + after: async () => {} + }, + // build cmd options + build: { + bundle: true, + bundlesize: false, + bundlesizeMax: '100kB', + types: true, + config: {} + }, + // linter cmd options + lint: { + silent: false, + fix: false, + files: [ + '*.{js,ts}', + 'bin/**', + 'config/**/*.{js,ts}', + 'test/**/*.{js,ts}', + 'src/**/*.{js,ts}', + 'tasks/**/*.{js,ts}', + 'benchmarks/**/*.{js,ts}', + 'utils/**/*.{js,ts}', + '!**/node_modules/**' + ] + }, + // docs cmd options + docs: { + publish: false, + entryPoint: 'src/index.js' + }, + // ts cmd options + ts: { + preset: undefined, + include: [] + }, + // release cmd options + release: { + build: true, + types: true, + test: true, + lint: true, + contributors: true, + bump: true, + changelog: true, + publish: true, + commit: true, + tag: true, + push: true, + ghrelease: true, + docs: true, + ghtoken: '', + type: 'patch', + preid: undefined, + distTag: 'latest', + remote: 'origin' + }, + // dependency check cmd options + dependencyCheck: { + input: [ + 'package.json', + '.aegir.js', + '.aegir.cjs', + 'src/**/*.js', + 'src/**/*.cjs', + 'test/**/*.js', + 'test/**/*.cjs', + 'dist/**/*.js', + 'benchmarks/**/*.js', + 'benchmarks/**/*.cjs', + 'utils/**/*.js', + 'utils/**/*.cjs', + '!./test/fixtures/**/*.js', + '!./test/fixtures/**/*.cjs', + '!./dist/test/fixtures/**/*.js', + '!./dist/test/fixtures/**/*.cjs', + '!**/*.min.js' + ], + productionOnly: false, + productionInput: [ + 'package.json', + 'src/**/*.js', + 'src/**/*.cjs', + 'dist/src/**/*.js', + 'utils/**/*.js', + 'utils/**/*.cjs' + ], + ignore: [ + '@types/*' + ] + } +} + +export { defaults } diff --git a/src/config/user.js b/src/config/user.js index 8dfe215af..22b7edf17 100644 --- a/src/config/user.js +++ b/src/config/user.js @@ -3,182 +3,91 @@ import { lilconfig } from 'lilconfig' import merge from 'merge-options' import { pathToFileURL } from 'url' import tsImport from 'ts-import' -/** - * @typedef {import("./../types").Options} Options - */ -/** @type {Omit} */ -const defaults = { - // global options - debug: false, - // test cmd options - test: { - build: false, - runner: 'node', - target: ['node', 'browser', 'webworker'], - watch: false, - files: [], - timeout: 60000, - grep: '', - bail: false, - progress: false, - cov: false, - browser: { - config: { - buildConfig: { - conditions: ['production'] - } - } - }, - before: async () => { return undefined }, - after: async () => {} - }, - // build cmd options - build: { - bundle: true, - bundlesize: false, - bundlesizeMax: '100kB', - types: true, - config: {} - }, - // linter cmd options - lint: { - silent: false, - fix: false, - files: [ - '*.{js,ts}', - 'bin/**', - 'config/**/*.{js,ts}', - 'test/**/*.{js,ts}', - 'src/**/*.{js,ts}', - 'tasks/**/*.{js,ts}', - 'benchmarks/**/*.{js,ts}', - 'utils/**/*.{js,ts}', - '!**/node_modules/**' - ] - }, - // docs cmd options - docs: { - publish: false, - entryPoint: 'src/index.js' - }, - // ts cmd options - ts: { - preset: undefined, - include: [] - }, - // release cmd options - release: { - build: true, - types: true, - test: true, - lint: true, - contributors: true, - bump: true, - changelog: true, - publish: true, - commit: true, - tag: true, - push: true, - ghrelease: true, - docs: true, - ghtoken: '', - type: 'patch', - preid: undefined, - distTag: 'latest', - remote: 'origin' - }, - // dependency check cmd options - dependencyCheck: { - input: [ - 'package.json', - '.aegir.js', - '.aegir.cjs', - 'src/**/*.js', - 'src/**/*.cjs', - 'test/**/*.js', - 'test/**/*.cjs', - 'dist/**/*.js', - 'benchmarks/**/*.js', - 'benchmarks/**/*.cjs', - 'utils/**/*.js', - 'utils/**/*.cjs', - '!./test/fixtures/**/*.js', - '!./test/fixtures/**/*.cjs', - '!./dist/test/fixtures/**/*.js', - '!./dist/test/fixtures/**/*.cjs', - '!**/*.min.js' - ], - productionOnly: false, - productionInput: [ - 'package.json', - 'src/**/*.js', - 'src/**/*.cjs', - 'dist/src/**/*.js', - 'utils/**/*.js', - 'utils/**/*.cjs' - ], - ignore: [ - '@types/*' - ] - } -} +import { defaults } from './defaults.js' /** - * @typedef {(filepath: string) => Promise} Loader + * @typedef {import('../types').Options} Options + * @typedef {import('../types').PartialOptions} PartialOptions + * @typedef {(filepath: string) => Promise} Loader */ /** * - * @param {{default?: Options} | Options} mod - * @returns {Options | {}} + * @param {{default?: PartialOptions} | PartialOptions} mod + * @param {string} configFilePath + * + * @returns {PartialOptions | null} */ -const handleConfigImport = (mod) => { - /** - * @type {*} - */ - const modWithDefaultExport = mod +const handleConfigImport = (mod, configFilePath) => { + const modWithDefaultExport = /** @type {{default?: PartialOptions}} */(mod) if (modWithDefaultExport.default != null) { return modWithDefaultExport.default } if (typeof mod.toString === 'function') { - return mod + return /** @type {PartialOptions} */(mod) + } + + if (typeof mod === 'object' && typeof mod.toString === 'undefined' && Object.keys(mod).length === 0) { + // nothing is exported. + throw new Error(`Nothing is exported in your config file '${configFilePath}'. Please export your configuration as the default export`) } - // if there's no toString function, this was an ES module that didn't export anything - return {} + throw new Error(`Incorrectly exported configuration from '${configFilePath}'`) } /** * @type {Loader} */ const loadEsm = async (filepath) => { - const res = await import(pathToFileURL(filepath).toString()) + let res + try { + res = await import(pathToFileURL(filepath).toString()) + } catch (err) { + console.error('Unexpected error while importing your config file') + throw err + } - return handleConfigImport(res) + return handleConfigImport(res, filepath) } /** * @type {Loader} */ const loadTs = async (filepath) => { + let res try { - const res = await tsImport.load(filepath) - - return handleConfigImport(res) + res = await tsImport.load(filepath) } catch (err) { - return {} + console.error('Unexpected error while loading your config file') + throw err } + + return handleConfigImport(res, filepath) } +/** + * We should only be grabbing the config once per search location + * + * @type {Map} + */ +const cachedConfig = new Map() + /** * Search for local user config * * @param {string | undefined} [searchFrom] + * * @returns {Promise} */ export const config = async (searchFrom) => { + if (cachedConfig.has(searchFrom)) { + return /** @type {Options} */(cachedConfig.get(searchFrom)) + } + /** + * @type {PartialOptions} + */ let userConfig try { const loadedConfig = await lilconfig('aegir', { @@ -202,8 +111,8 @@ export const config = async (searchFrom) => { userConfig = {} } } catch (err) { - console.error(err) - throw new Error('Error finding your config file.') + console.error('Unexpected error loading aegir config') + throw err } const conf = /** @type {Options} */(merge( @@ -211,7 +120,9 @@ export const config = async (searchFrom) => { userConfig )) + cachedConfig.set(searchFrom, conf) + return conf } -export const loadUserConfig = () => config() +export const loadUserConfig = config diff --git a/src/types.ts b/src/types.d.ts similarity index 100% rename from src/types.ts rename to src/types.d.ts diff --git a/test/config/fixtures/config-with-invalid-export/.aegir.js b/test/config/fixtures/config-with-invalid-export/.aegir.js new file mode 100644 index 000000000..c1dfcb0f6 --- /dev/null +++ b/test/config/fixtures/config-with-invalid-export/.aegir.js @@ -0,0 +1,5 @@ +const config = { + +}; + +export { config } diff --git a/test/config/fixtures/config-with-invalid-export/package.json b/test/config/fixtures/config-with-invalid-export/package.json new file mode 100644 index 000000000..3f7c1f148 --- /dev/null +++ b/test/config/fixtures/config-with-invalid-export/package.json @@ -0,0 +1,4 @@ +{ + "name": "config-with-invalid-export", + "type": "module" +} diff --git a/test/config/fixtures/config-without-export/.aegir.js b/test/config/fixtures/config-without-export/.aegir.js new file mode 100644 index 000000000..2ebf6c253 --- /dev/null +++ b/test/config/fixtures/config-without-export/.aegir.js @@ -0,0 +1,3 @@ +const options = { + +}; diff --git a/test/config/fixtures/config-without-export/package.json b/test/config/fixtures/config-without-export/package.json new file mode 100644 index 000000000..56ccf1572 --- /dev/null +++ b/test/config/fixtures/config-without-export/package.json @@ -0,0 +1,4 @@ +{ + "name": "config-without-export", + "type": "module" +} diff --git a/test/config/fixtures/custom-ts-config/.aegir.ts b/test/config/fixtures/custom-ts-config/.aegir.ts new file mode 100644 index 000000000..39b0457b8 --- /dev/null +++ b/test/config/fixtures/custom-ts-config/.aegir.ts @@ -0,0 +1,12 @@ +import type { PartialOptions } from '../../../../src/types'; + +const config: PartialOptions = { + debug: true, + test: { + before: async (opts) => { + return { env: { res: '1234' } } + } + } +} + +export default config diff --git a/test/config/fixtures/custom-ts-config/.eslintignore b/test/config/fixtures/custom-ts-config/.eslintignore new file mode 100644 index 000000000..8d5fa662a --- /dev/null +++ b/test/config/fixtures/custom-ts-config/.eslintignore @@ -0,0 +1 @@ +!.aegir.ts diff --git a/test/config/fixtures/custom-ts-config/.eslintrc.js b/test/config/fixtures/custom-ts-config/.eslintrc.js new file mode 100644 index 000000000..75d65f2cf --- /dev/null +++ b/test/config/fixtures/custom-ts-config/.eslintrc.js @@ -0,0 +1,8 @@ +export default { + "extends": "../../../../package.json", + "parserOptions": { + "sourceType": "module", + "project": ["./tsconfig.json"] + }, + "parser": "@typescript-eslint/parser", +} diff --git a/test/config/fixtures/custom-ts-config/package.json b/test/config/fixtures/custom-ts-config/package.json new file mode 100644 index 000000000..1503ae7af --- /dev/null +++ b/test/config/fixtures/custom-ts-config/package.json @@ -0,0 +1,3 @@ +{ + "name": "custom-config" +} \ No newline at end of file diff --git a/test/config/fixtures/custom-ts-config/tsconfig.json b/test/config/fixtures/custom-ts-config/tsconfig.json new file mode 100644 index 000000000..8dd070dc5 --- /dev/null +++ b/test/config/fixtures/custom-ts-config/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../../src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist", + "noEmit": true + }, + "include": [ + ".aegir.ts", + ] +} diff --git a/test/config/user.js b/test/config/user.js index 4af2ae3ce..e585b7afc 100644 --- a/test/config/user.js +++ b/test/config/user.js @@ -2,14 +2,21 @@ import { expect } from '../../utils/chai.js' import { config } from '../../src/config/user.js' -import path from 'path' +import { dirname, join } from 'path' import { fileURLToPath } from 'url' -const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const __dirname = dirname(fileURLToPath(import.meta.url)) + +/** + * + * @param {string} searchPath + * @returns string + */ +const getConfigSearchPath = (searchPath) => join(__dirname, ...searchPath.split('/')) describe('config - user', () => { it('custom config', async () => { - const conf = await config(path.join(__dirname, 'fixtures/custom-config')) + const conf = await config(getConfigSearchPath('fixtures/custom-config')) expect(conf).to.have.property('debug').eql(false) expect(conf).to.have.nested.property('test.before') expect(conf).to.have.nested.property('test.after') @@ -19,8 +26,20 @@ describe('config - user', () => { expect(res).to.eql(undefined) }) + it('custom ts config', async () => { + const conf = await config(getConfigSearchPath('fixtures/custom-ts-config')) + expect(conf).to.have.property('debug').eql(true) + expect(conf).to.have.nested.property('test.before') + expect(conf).to.have.nested.property('test.after') + + // @ts-ignore + const res = await conf.test.before() + expect(res).not.to.be.undefined() + expect(res && res.env?.res).to.eql('1234') + }) + it('supports async hooks', async () => { - const conf = await config(path.join(__dirname, 'fixtures/custom-user-async-hooks')) + const conf = await config(getConfigSearchPath('fixtures/custom-user-async-hooks')) // @ts-ignore expect(await conf.test.before()).to.eql('pre done async') // @ts-ignore @@ -28,7 +47,16 @@ describe('config - user', () => { }) it('supports package.json aegir property', async () => { - const conf = await config(path.join(__dirname, 'fixtures/custom-config-package-json')) + const conf = await config(getConfigSearchPath('fixtures/custom-config-package-json')) expect(conf.debug).to.ok() }) + + // Error cases + it('throws an error when config has no exports', async () => { + await expect(config(getConfigSearchPath('fixtures/config-without-export'))).to.be.rejectedWith(/^Nothing is exported in your config file/) + }) + + it('throws an error when config has invalid exports', async () => { + await expect(config(getConfigSearchPath('fixtures/config-with-invalid-export'))).to.be.rejectedWith(/^Incorrectly exported configuration/) + }) }) diff --git a/test/fixtures/dependency-check/with-aegir-config/.aegir.js b/test/fixtures/dependency-check/with-aegir-config/.aegir.js index ae1fc38a6..a5687b1bf 100644 --- a/test/fixtures/dependency-check/with-aegir-config/.aegir.js +++ b/test/fixtures/dependency-check/with-aegir-config/.aegir.js @@ -1,3 +1,5 @@ /* eslint-disable no-unused-vars */ import { execa } from 'execa' + +export default {} From 94d16beb1289986da3e389dbf88282cbcb1d0f53 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 13 Jun 2022 12:20:06 -0700 Subject: [PATCH 08/12] feat: support .aegir config files without extension --- src/config/user.js | 22 +++++++++++++++++- .../fixtures/custom-config-no-ext/.aegir | 3 +++ .../custom-config-no-ext/package.json | 3 +++ .../fixtures/custom-ts-no-ext-config/.aegir | 12 ++++++++++ .../custom-ts-no-ext-config/.eslintignore | 1 + .../custom-ts-no-ext-config/.eslintrc.json | 8 +++++++ .../fixtures/custom-ts-no-ext-config/index.ts | 1 + .../custom-ts-no-ext-config/package.json | 4 ++++ .../custom-ts-no-ext-config/tsconfig.json | 11 +++++++++ test/config/user.js | 23 +++++++++++++++++++ 10 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/config/fixtures/custom-config-no-ext/.aegir create mode 100644 test/config/fixtures/custom-config-no-ext/package.json create mode 100644 test/config/fixtures/custom-ts-no-ext-config/.aegir create mode 100644 test/config/fixtures/custom-ts-no-ext-config/.eslintignore create mode 100644 test/config/fixtures/custom-ts-no-ext-config/.eslintrc.json create mode 100644 test/config/fixtures/custom-ts-no-ext-config/index.ts create mode 100644 test/config/fixtures/custom-ts-no-ext-config/package.json create mode 100644 test/config/fixtures/custom-ts-no-ext-config/tsconfig.json diff --git a/src/config/user.js b/src/config/user.js index 22b7edf17..d92a804fc 100644 --- a/src/config/user.js +++ b/src/config/user.js @@ -67,6 +67,25 @@ const loadTs = async (filepath) => { return handleConfigImport(res, filepath) } +/** + * @type {Loader} + */ +const noExt = async (filepath) => { + console.log('noExt') + try { + return await loadEsm(filepath) + } catch (err) { + try { + return await loadTs(filepath) + } catch (err) { + console.error(`Could not load your config file at '${filepath}'`) + console.error(err, err) + } + } + + return null +} + /** * We should only be grabbing the config once per search location * @@ -94,7 +113,8 @@ export const config = async (searchFrom) => { loaders: { '.js': loadEsm, '.mjs': loadEsm, - '.ts': loadTs + '.ts': loadTs, + noExt }, searchPlaces: [ 'package.json', diff --git a/test/config/fixtures/custom-config-no-ext/.aegir b/test/config/fixtures/custom-config-no-ext/.aegir new file mode 100644 index 000000000..a07a84c50 --- /dev/null +++ b/test/config/fixtures/custom-config-no-ext/.aegir @@ -0,0 +1,3 @@ +module.exports = { + +}; diff --git a/test/config/fixtures/custom-config-no-ext/package.json b/test/config/fixtures/custom-config-no-ext/package.json new file mode 100644 index 000000000..1503ae7af --- /dev/null +++ b/test/config/fixtures/custom-config-no-ext/package.json @@ -0,0 +1,3 @@ +{ + "name": "custom-config" +} \ No newline at end of file diff --git a/test/config/fixtures/custom-ts-no-ext-config/.aegir b/test/config/fixtures/custom-ts-no-ext-config/.aegir new file mode 100644 index 000000000..39b0457b8 --- /dev/null +++ b/test/config/fixtures/custom-ts-no-ext-config/.aegir @@ -0,0 +1,12 @@ +import type { PartialOptions } from '../../../../src/types'; + +const config: PartialOptions = { + debug: true, + test: { + before: async (opts) => { + return { env: { res: '1234' } } + } + } +} + +export default config diff --git a/test/config/fixtures/custom-ts-no-ext-config/.eslintignore b/test/config/fixtures/custom-ts-no-ext-config/.eslintignore new file mode 100644 index 000000000..c49db0865 --- /dev/null +++ b/test/config/fixtures/custom-ts-no-ext-config/.eslintignore @@ -0,0 +1 @@ +!.aegir diff --git a/test/config/fixtures/custom-ts-no-ext-config/.eslintrc.json b/test/config/fixtures/custom-ts-no-ext-config/.eslintrc.json new file mode 100644 index 000000000..d6e753c88 --- /dev/null +++ b/test/config/fixtures/custom-ts-no-ext-config/.eslintrc.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../../package.json", + "parserOptions": { + "sourceType": "module", + "project": ["./tsconfig.json"] + }, + "parser": "@typescript-eslint/parser" +} diff --git a/test/config/fixtures/custom-ts-no-ext-config/index.ts b/test/config/fixtures/custom-ts-no-ext-config/index.ts new file mode 100644 index 000000000..336ce12bb --- /dev/null +++ b/test/config/fixtures/custom-ts-no-ext-config/index.ts @@ -0,0 +1 @@ +export {} diff --git a/test/config/fixtures/custom-ts-no-ext-config/package.json b/test/config/fixtures/custom-ts-no-ext-config/package.json new file mode 100644 index 000000000..80612d988 --- /dev/null +++ b/test/config/fixtures/custom-ts-no-ext-config/package.json @@ -0,0 +1,4 @@ +{ + "name": "custom-config", + "type": "module" +} diff --git a/test/config/fixtures/custom-ts-no-ext-config/tsconfig.json b/test/config/fixtures/custom-ts-no-ext-config/tsconfig.json new file mode 100644 index 000000000..cc66116b5 --- /dev/null +++ b/test/config/fixtures/custom-ts-no-ext-config/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../../src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist", + "noEmit": true + }, + "include": [ + "./.aegir", + "./index.ts" + ] +} diff --git a/test/config/user.js b/test/config/user.js index e585b7afc..a07293409 100644 --- a/test/config/user.js +++ b/test/config/user.js @@ -26,6 +26,17 @@ describe('config - user', () => { expect(res).to.eql(undefined) }) + it('custom config without extension', async () => { + const conf = await config(getConfigSearchPath('fixtures/custom-config')) + expect(conf).to.have.property('debug').eql(false) + expect(conf).to.have.nested.property('test.before') + expect(conf).to.have.nested.property('test.after') + + // @ts-ignore + const res = await conf.test.before() + expect(res).to.eql(undefined) + }) + it('custom ts config', async () => { const conf = await config(getConfigSearchPath('fixtures/custom-ts-config')) expect(conf).to.have.property('debug').eql(true) @@ -38,6 +49,18 @@ describe('config - user', () => { expect(res && res.env?.res).to.eql('1234') }) + it('custom ts config without extension', async () => { + const conf = await config(getConfigSearchPath('fixtures/custom-ts-no-ext-config')) + expect(conf).to.have.property('debug').eql(true) + expect(conf).to.have.nested.property('test.before') + expect(conf).to.have.nested.property('test.after') + + // @ts-ignore + const res = await conf.test.before() + expect(res).not.to.be.undefined() + expect(res && res.env?.res).to.eql('1234') + }) + it('supports async hooks', async () => { const conf = await config(getConfigSearchPath('fixtures/custom-user-async-hooks')) // @ts-ignore From 05f95aa520d1ca2376b51c2f955c363b4e54bef8 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 14 Jun 2022 10:54:51 -0700 Subject: [PATCH 09/12] fix: use correct fixture directory --- test/config/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/config/user.js b/test/config/user.js index a07293409..20ecf326d 100644 --- a/test/config/user.js +++ b/test/config/user.js @@ -27,7 +27,7 @@ describe('config - user', () => { }) it('custom config without extension', async () => { - const conf = await config(getConfigSearchPath('fixtures/custom-config')) + const conf = await config(getConfigSearchPath('fixtures/custom-config-no-ext')) expect(conf).to.have.property('debug').eql(false) expect(conf).to.have.nested.property('test.before') expect(conf).to.have.nested.property('test.after') From b62bef6a96dbd1cb289ca7d21faabdabcd8e79b4 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 14 Jun 2022 11:05:22 -0700 Subject: [PATCH 10/12] fix: no extension .aegir files work again --- src/config/user.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/config/user.js b/src/config/user.js index d92a804fc..3f091d6dc 100644 --- a/src/config/user.js +++ b/src/config/user.js @@ -71,7 +71,6 @@ const loadTs = async (filepath) => { * @type {Loader} */ const noExt = async (filepath) => { - console.log('noExt') try { return await loadEsm(filepath) } catch (err) { @@ -80,10 +79,9 @@ const noExt = async (filepath) => { } catch (err) { console.error(`Could not load your config file at '${filepath}'`) console.error(err, err) + throw new Error(`Could not load your no-extension aegir config file at '${filepath}' as ESM nor TS`) } } - - return null } /** @@ -120,7 +118,8 @@ export const config = async (searchFrom) => { 'package.json', '.aegir.js', '.aegir.cjs', - '.aegir.ts' + '.aegir.ts', + '.aegir' ] }) .search(searchFrom) From 3afe11937c6598029e988eb2fa66e244c6d348cb Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 23 Jun 2022 14:12:34 -0700 Subject: [PATCH 11/12] fix: correct .aegir.ts options type --- .aegir.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.aegir.ts b/.aegir.ts index 3b9838f81..ccd349295 100644 --- a/.aegir.ts +++ b/.aegir.ts @@ -1,4 +1,6 @@ -const options: import('./src/types').PartialOptions = { +import type { PartialOptions } from './src/types.js' + +const options: PartialOptions = { docs: { entryPoint: 'utils' } From 2cbe5c6536ce42fc8689cb1a798c7c646a2916a8 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 23 Jun 2022 14:13:18 -0700 Subject: [PATCH 12/12] chore: add test for .aegir.ts config with ESM import --- .../custom-ts-config-with-esm-import/.aegir.ts | 15 +++++++++++++++ .../.eslintignore | 1 + .../custom-ts-config-with-esm-import/.eslintrc.js | 8 ++++++++ .../custom-ts-config-with-esm-import/package.json | 3 +++ .../tsconfig.json | 10 ++++++++++ test/config/user.js | 12 ++++++++++++ 6 files changed, 49 insertions(+) create mode 100644 test/config/fixtures/custom-ts-config-with-esm-import/.aegir.ts create mode 100644 test/config/fixtures/custom-ts-config-with-esm-import/.eslintignore create mode 100644 test/config/fixtures/custom-ts-config-with-esm-import/.eslintrc.js create mode 100644 test/config/fixtures/custom-ts-config-with-esm-import/package.json create mode 100644 test/config/fixtures/custom-ts-config-with-esm-import/tsconfig.json diff --git a/test/config/fixtures/custom-ts-config-with-esm-import/.aegir.ts b/test/config/fixtures/custom-ts-config-with-esm-import/.aegir.ts new file mode 100644 index 000000000..b623f0a96 --- /dev/null +++ b/test/config/fixtures/custom-ts-config-with-esm-import/.aegir.ts @@ -0,0 +1,15 @@ +import { isWritableStream } from 'is-stream' + +import type { PartialOptions } from '../../../../src/types'; + +const config: PartialOptions = { + debug: true, + test: { + before: async (opts) => { + console.log('isWritableStream: ', isWritableStream) + return { env: { res: '4321' } } + } + } +} + +export default config diff --git a/test/config/fixtures/custom-ts-config-with-esm-import/.eslintignore b/test/config/fixtures/custom-ts-config-with-esm-import/.eslintignore new file mode 100644 index 000000000..8d5fa662a --- /dev/null +++ b/test/config/fixtures/custom-ts-config-with-esm-import/.eslintignore @@ -0,0 +1 @@ +!.aegir.ts diff --git a/test/config/fixtures/custom-ts-config-with-esm-import/.eslintrc.js b/test/config/fixtures/custom-ts-config-with-esm-import/.eslintrc.js new file mode 100644 index 000000000..75d65f2cf --- /dev/null +++ b/test/config/fixtures/custom-ts-config-with-esm-import/.eslintrc.js @@ -0,0 +1,8 @@ +export default { + "extends": "../../../../package.json", + "parserOptions": { + "sourceType": "module", + "project": ["./tsconfig.json"] + }, + "parser": "@typescript-eslint/parser", +} diff --git a/test/config/fixtures/custom-ts-config-with-esm-import/package.json b/test/config/fixtures/custom-ts-config-with-esm-import/package.json new file mode 100644 index 000000000..1503ae7af --- /dev/null +++ b/test/config/fixtures/custom-ts-config-with-esm-import/package.json @@ -0,0 +1,3 @@ +{ + "name": "custom-config" +} \ No newline at end of file diff --git a/test/config/fixtures/custom-ts-config-with-esm-import/tsconfig.json b/test/config/fixtures/custom-ts-config-with-esm-import/tsconfig.json new file mode 100644 index 000000000..8dd070dc5 --- /dev/null +++ b/test/config/fixtures/custom-ts-config-with-esm-import/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../../src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist", + "noEmit": true + }, + "include": [ + ".aegir.ts", + ] +} diff --git a/test/config/user.js b/test/config/user.js index 20ecf326d..ecd3e7ef3 100644 --- a/test/config/user.js +++ b/test/config/user.js @@ -49,6 +49,18 @@ describe('config - user', () => { expect(res && res.env?.res).to.eql('1234') }) + it('custom ts config with ESM import', async () => { + const conf = await config(getConfigSearchPath('fixtures/custom-ts-config-with-esm-import')) + expect(conf).to.have.property('debug').eql(true) + expect(conf).to.have.nested.property('test.before') + expect(conf).to.have.nested.property('test.after') + + // @ts-ignore + const res = await conf.test.before() + expect(res).not.to.be.undefined() + expect(res && res.env?.res).to.eql('4321') + }) + it('custom ts config without extension', async () => { const conf = await config(getConfigSearchPath('fixtures/custom-ts-no-ext-config')) expect(conf).to.have.property('debug').eql(true)