Skip to content

Commit

Permalink
fix: support author parsing in d2.config.js [LIBS-347] (#747)
Browse files Browse the repository at this point in the history
  • Loading branch information
amcgee committed Sep 29, 2022
1 parent c64a082 commit e6838a7
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 35 deletions.
85 changes: 51 additions & 34 deletions cli/src/lib/parseConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,69 +26,86 @@ const parseAuthor = (author) => {

const validateConfig = (config) => {
if (!requiredConfigFields[config.type]) {
reporter.error(
`Unknown type ${chalk.bold(config.type)} specified in d2.config.js.`
throw new Error(
`Unknown type ${chalk.bold(
config.type
)} specified in d2.config.js.\n\tValid types: ${Object.keys(
requiredConfigFields
)}`
)
reporter.error(`\tValid types:`, Object.keys(requiredConfigFields))
process.exit(1)
}
requiredConfigFields[config.type].forEach((field) => {
if (!has(config, field)) {
reporter.error(
throw new Error(
`Required config field ${chalk.bold(
field
)} not found in d2.config.js or package.json`
)
process.exit(1)
}
})
return true
}

const parseConfigObjects = (
config = {},
pkg = {},
{ defaultsLib, defaultsApp, defaultsPWA } = {}
) => {
const type = config.type || 'app'
reporter.debug(`Type identified : ${chalk.bold(type)}`)

const defaults = type === 'lib' ? defaultsLib : defaultsApp
config = defaultsDeep(config, defaults)

// Add PWA defaults to apps
if (type === 'app') {
config = defaultsDeep(config, defaultsPWA)
}

config.name = config.name || pkg.name
config.version = config.version || pkg.version
config.author = parseAuthor(config.author || pkg.author)
if (config.author && !config.author.name) {
throw new Error('If author is specified, it must include a valid name')
}
config.description = config.description || pkg.description
config.title = config.title || config.name

reporter.debug('config loaded', config)

return config
}

const parseConfig = (paths) => {
try {
let config = {}
// if (!fs.existsSync(paths.config)) {
// reporter.error('Config file d2.config.js not found - use the init command to create one!')
// process.exit(1)
// }
let config
let pkg

if (fs.existsSync(paths.config)) {
reporter.debug('Loading d2 config at', paths.config)
config = require(paths.config)
reporter.debug('loaded', config)
}

const type = config.type || 'app'
reporter.debug(`Type identified : ${chalk.bold(type)}`)

const defaults =
type === 'lib' ? paths.configDefaultsLib : paths.configDefaultsApp
config = defaultsDeep(config, require(defaults))

// Add PWA defaults to apps
if (type === 'app') {
config = defaultsDeep(config, require(paths.configDefaultsPWA))
}

if (fs.existsSync(paths.package)) {
const pkg = fs.readJsonSync(paths.package)
config.name = config.name || pkg.name
config.version = config.version || pkg.version
config.author = config.author || parseAuthor(pkg.author)
config.description = config.description || pkg.description
pkg = fs.readJsonSync(paths.package)
}
config.title = config.title || config.name

validateConfig(config)
const parsedConfig = parseConfigObjects(config, pkg, {
defaultsLib: require(paths.configDefaultsLib),
defaultsApp: require(paths.configDefaultsApp),
defaultsPWA: require(paths.configDefaultsPWA),
})

reporter.debug('config loaded', config)
return config
validateConfig(parsedConfig)

return parsedConfig
} catch (e) {
reporter.error('Failed to load d2 config!')
reporter.debugErr(e)
reporter.error(e)
process.exit(1)
}
}

module.exports = parseConfig

module.exports.parseConfigObjects = parseConfigObjects
83 changes: 83 additions & 0 deletions cli/src/lib/parseConfig.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
const { parseConfigObjects } = require('./parseConfig.js')

describe('parseConfig', () => {
it('should correctly parse author fields', () => {
expect(
parseConfigObjects({ author: { name: 'Test Author' } }).author
).toMatchObject({ name: 'Test Author' })
expect(
parseConfigObjects({
author: {
name: 'Test Author',
email: '[email protected]',
url: 'https://author.com/test',
},
}).author
).toMatchObject({
name: 'Test Author',
email: '[email protected]',
url: 'https://author.com/test',
})
expect(
parseConfigObjects({
author: { name: 'Test Author', email: '[email protected]' },
}).author
).toMatchObject({ name: 'Test Author', email: '[email protected]' })
expect(
parseConfigObjects({
author: { name: 'Test Author', url: 'https://author.com/test' },
}).author
).toMatchObject({ name: 'Test Author', url: 'https://author.com/test' })

expect(
parseConfigObjects({ author: 'Test Author' }).author
).toMatchObject({ name: 'Test Author' })
expect(
parseConfigObjects({ author: 'Test Author <[email protected]>' })
.author
).toMatchObject({ name: 'Test Author', email: '[email protected]' })
expect(
parseConfigObjects({
author: 'Test Author <[email protected]> (https://author.com/test)',
}).author
).toMatchObject({
name: 'Test Author',
email: '[email protected]',
url: 'https://author.com/test',
})
expect(
parseConfigObjects({
author: 'Test Author (https://author.com/test)',
}).author
).toMatchObject({ name: 'Test Author', url: 'https://author.com/test' })

// missing name
expect(() =>
parseConfigObjects({
author: {
email: '[email protected]',
url: 'https://author.com/test',
},
})
).toThrow()
expect(
() =>
parseConfigObjects({ author: { email: '[email protected]' } })
.author
).toThrow()
expect(() =>
parseConfigObjects({ author: { url: 'https://author.com/test' } })
).toThrow()
expect(() =>
parseConfigObjects({ author: '(https://author.com/test)' })
).toThrow()
expect(() =>
parseConfigObjects({
author: '<[email protected]> (https://author.com/test)',
})
).toThrow()
expect(() =>
parseConfigObjects({ author: '<[email protected]>' })
).toThrow()
})
})
2 changes: 1 addition & 1 deletion docs/config/d2-config-js-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The following configuration properties are supported:
| **title** | _string_ | `config.name` | The human-readable application title, which will appear in the HeaderBar |
| **id** | _string_ | | The ID of the app on the [App Hub](https://apps.dhis2.org/). Used when publishing the app to the App Hub with [d2 app scripts publish](../scripts/publish). See [this guide](https://developers.dhis2.org/docs/guides/publish-apphub/) to learn how to set up continuous delivery. |
| **description** | _string_ | `pkg.description` | A full-length description of the application |
| **author** | _string_ | `pkg.author` | The name of the developer to include in the DHIS2 manifest |
| **author** | _string_ or _object_ | `pkg.author` | The name of the developer to include in the DHIS2 manifest, following [package.json author field syntax](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#people-fields-author-contributors). |
| **entryPoints.app** | _string_ | **./src/App** | The path to the application entrypoint (not used for libraries) |
| **entryPoints.lib** | _string_ or _object_ | **./src/index** | The path to the library entrypoint(s) (not used for applications). Supports [conditional exports](https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_conditional_exports) |
| **dataStoreNamespace** | _string_ | | The DataStore and UserDataStore namespace to reserve for this application. The reserved namespace **must** be suitably unique, as other apps will fail to install if they attempt to reserve the same namespace - see the [webapp manifest docs](https://docs.dhis2.org/en/develop/loading-apps.html) |
Expand Down

0 comments on commit e6838a7

Please sign in to comment.