@platformatic/config
Advanced tools
Comparing version 0.21.1 to 0.22.0
66
index.js
@@ -9,4 +9,5 @@ 'use strict' | ||
const dotenv = require('dotenv') | ||
const { request } = require('undici') | ||
const { FileWatcher } = require('@platformatic/utils') | ||
const { getParser, analyze } = require('@platformatic/metaconfig') | ||
const { getParser, analyze, upgrade } = require('@platformatic/metaconfig') | ||
@@ -46,2 +47,3 @@ class ConfigManager extends EventEmitter { | ||
this.schemaOptions = opts.schemaOptions || {} | ||
this._providedSchema = !!opts.schema | ||
this._originalEnv = opts.env || {} | ||
@@ -139,5 +141,3 @@ this.env = this.purgeEnv(this._originalEnv) | ||
let meta = await analyze({ config: this.current }) | ||
while (typeof meta.up === 'function') { | ||
meta = meta.up() | ||
} | ||
meta = upgrade(meta) | ||
this.current = meta.config | ||
@@ -148,2 +148,17 @@ } catch { | ||
} | ||
if (!this._providedSchema && this.current.$schema) { | ||
// The user did not provide a schema, but we have a link to the schema | ||
// in $schema. Try to fetch the schema and ignore anything that goes | ||
// wrong. | ||
try { | ||
const { body, statusCode } = await request(this.current.$schema) | ||
if (statusCode === 200) { | ||
this.schema = await body.json() | ||
} | ||
} catch { | ||
// Ignore error. | ||
} | ||
} | ||
const validationResult = this.validate() | ||
@@ -181,2 +196,5 @@ if (!validationResult) { | ||
validate: (schema, path, parentSchema, data) => { | ||
if (typeof path !== 'string' || path.trim() === '') { | ||
return false | ||
} | ||
const resolved = resolve(this.dirname, path) | ||
@@ -228,4 +246,44 @@ data.parentData[data.parentDataProperty] = resolved | ||
} | ||
static listConfigFiles (type) { | ||
if (type) { | ||
// A config type (service, db, etc.) was explicitly provided. | ||
return [ | ||
`platformatic.${type}.json`, | ||
`platformatic.${type}.json5`, | ||
`platformatic.${type}.yaml`, | ||
`platformatic.${type}.yml`, | ||
`platformatic.${type}.toml`, | ||
`platformatic.${type}.tml` | ||
] | ||
} else { | ||
// A config type was not provided. Search for all known types and | ||
// formats. Unfortunately, this means the ConfigManager needs to be | ||
// aware of the different application types (but that should be small). | ||
return [ | ||
...this.listConfigFiles('service'), | ||
...this.listConfigFiles('db') | ||
] | ||
} | ||
} | ||
static async findConfigFile (directory, type) { | ||
directory ??= process.cwd() | ||
const configFileNames = this.listConfigFiles(type) | ||
const configFilesAccessibility = await Promise.all(configFileNames.map((fileName) => isFileAccessible(fileName, directory))) | ||
const accessibleConfigFilename = configFileNames.find((value, index) => configFilesAccessibility[index]) | ||
return accessibleConfigFilename | ||
} | ||
} | ||
async function isFileAccessible (filename, directory) { | ||
try { | ||
const filePath = resolve(directory, filename) | ||
await access(filePath) | ||
return true | ||
} catch (err) { | ||
return false | ||
} | ||
} | ||
module.exports = ConfigManager |
{ | ||
"name": "@platformatic/config", | ||
"version": "0.21.1", | ||
"version": "0.22.0", | ||
"description": "Platformatic DB Config Manager", | ||
@@ -17,9 +17,9 @@ "main": "index.js", | ||
"devDependencies": { | ||
"fastify": "^4.13.0", | ||
"@iarna/toml": "^2.2.5", | ||
"fastify": "^4.17.0", | ||
"json5": "^2.2.3", | ||
"snazzy": "^9.0.0", | ||
"standard": "^17.0.0", | ||
"json5": "^2.2.3", | ||
"yaml": "^2.2.1", | ||
"@iarna/toml": "^2.2.5", | ||
"tap": "^16.3.4" | ||
"tap": "^16.3.4", | ||
"yaml": "^2.2.2" | ||
}, | ||
@@ -30,4 +30,6 @@ "dependencies": { | ||
"pupa": "^3.1.0", | ||
"@platformatic/utils": "0.21.1", | ||
"@platformatic/metaconfig": "0.21.1" | ||
"semver": "^7.5.0", | ||
"undici": "^5.22.0", | ||
"@platformatic/metaconfig": "0.22.0", | ||
"@platformatic/utils": "0.22.0" | ||
}, | ||
@@ -34,0 +36,0 @@ "scripts": { |
'use strict' | ||
const { test } = require('tap') | ||
const { resolve } = require('path') | ||
const { join, resolve } = require('path') | ||
const ConfigManager = require('..') | ||
@@ -255,1 +255,69 @@ const path = require('path') | ||
}) | ||
test('ConfigManager.listConfigFiles() lists possible configs by type', async ({ plan, same }) => { | ||
plan(2) | ||
same(ConfigManager.listConfigFiles('db'), [ | ||
'platformatic.db.json', | ||
'platformatic.db.json5', | ||
'platformatic.db.yaml', | ||
'platformatic.db.yml', | ||
'platformatic.db.toml', | ||
'platformatic.db.tml' | ||
]) | ||
same(ConfigManager.listConfigFiles('service'), [ | ||
'platformatic.service.json', | ||
'platformatic.service.json5', | ||
'platformatic.service.yaml', | ||
'platformatic.service.yml', | ||
'platformatic.service.toml', | ||
'platformatic.service.tml' | ||
]) | ||
}) | ||
test('ConfigManager.listConfigFiles() lists all possible configs', async ({ plan, same }) => { | ||
plan(1) | ||
same(ConfigManager.listConfigFiles(), [ | ||
'platformatic.service.json', | ||
'platformatic.service.json5', | ||
'platformatic.service.yaml', | ||
'platformatic.service.yml', | ||
'platformatic.service.toml', | ||
'platformatic.service.tml', | ||
'platformatic.db.json', | ||
'platformatic.db.json5', | ||
'platformatic.db.yaml', | ||
'platformatic.db.yml', | ||
'platformatic.db.toml', | ||
'platformatic.db.tml' | ||
]) | ||
}) | ||
test('ConfigManager.findConfigFile() finds configs by type', async ({ plan, same }) => { | ||
plan(2) | ||
const fixturesDir = join(__dirname, 'fixtures') | ||
same( | ||
await ConfigManager.findConfigFile(fixturesDir, 'db'), | ||
'platformatic.db.json' | ||
) | ||
same( | ||
await ConfigManager.findConfigFile(fixturesDir, 'service'), | ||
'platformatic.service.json' | ||
) | ||
}) | ||
test('ConfigManager.findConfigFile() finds configs without type', async ({ plan, same }) => { | ||
plan(1) | ||
const fixturesDir = join(__dirname, 'fixtures') | ||
same( | ||
await ConfigManager.findConfigFile(fixturesDir), | ||
'platformatic.service.json' | ||
) | ||
}) | ||
test('ConfigManager.findConfigFile() searches cwd by default', async ({ plan, same }) => { | ||
plan(1) | ||
same( | ||
await ConfigManager.findConfigFile(), | ||
undefined | ||
) | ||
}) |
'use strict' | ||
const { test } = require('tap') | ||
const { resolve } = require('path') | ||
const { join, resolve } = require('path') | ||
const ConfigManager = require('..') | ||
const pkg = require('../package.json') | ||
const { MockAgent, setGlobalDispatcher, getGlobalDispatcher } = require('undici') | ||
const { schema } = require('../../db') // avoid circular dependency on pnpm | ||
@@ -114,8 +116,33 @@ test('should throw if file is not found', async ({ match, fail }) => { | ||
test('should automatically update', async ({ same }) => { | ||
test('should automatically update', async ({ same, teardown, pass, plan }) => { | ||
plan(2) | ||
const _agent = getGlobalDispatcher() | ||
const mockAgent = new MockAgent() | ||
setGlobalDispatcher(mockAgent) | ||
teardown(() => { | ||
setGlobalDispatcher(_agent) | ||
}) | ||
// Provide the base url to the request | ||
const mockPool = mockAgent.get('https://platformatic.dev') | ||
mockAgent.disableNetConnect() | ||
// intercept the request | ||
mockPool.intercept({ | ||
path: `/schemas/v${pkg.version.replace(/\.\d+$/, '.0')}/db`, | ||
method: 'GET' | ||
}).reply(404, () => { | ||
pass('should have called the mock server') | ||
return { | ||
message: 'not found' | ||
} | ||
}) | ||
const fixturesDir = join(__dirname, 'fixtures') | ||
const cm = new ConfigManager({ | ||
source: resolve(__dirname, './fixtures/db-0.16.0.json'), | ||
source: join(fixturesDir, 'db-0.16.0.json'), | ||
env: { PLT_FOOBAR: 'foobar' } | ||
}) | ||
await cm.parse() | ||
same(cm.current, { | ||
@@ -131,3 +158,6 @@ $schema: `https://platformatic.dev/schemas/v${pkg.version.replace(/\.\d+$/, '.0')}/db`, | ||
}, | ||
migrations: { dir: './demo/migrations', validateChecksums: false }, | ||
migrations: { | ||
dir: './demo/migrations', | ||
validateChecksums: false | ||
}, | ||
dashboard: { path: '/' }, | ||
@@ -137,1 +167,49 @@ authorization: { adminSecret: 'plt-db' } | ||
}) | ||
test('should use the remote schema', async ({ same, teardown, pass, plan }) => { | ||
plan(2) | ||
const _agent = getGlobalDispatcher() | ||
const mockAgent = new MockAgent() | ||
setGlobalDispatcher(mockAgent) | ||
teardown(() => { | ||
setGlobalDispatcher(_agent) | ||
}) | ||
// Provide the base url to the request | ||
const mockPool = mockAgent.get('https://platformatic.dev') | ||
mockAgent.disableNetConnect() | ||
// intercept the request | ||
mockPool.intercept({ | ||
path: `/schemas/v${pkg.version.replace(/\.\d+$/, '.0')}/db`, | ||
method: 'GET' | ||
}).reply(200, () => { | ||
pass('should have called the mock server') | ||
return JSON.stringify(schema) | ||
}) | ||
const fixturesDir = join(__dirname, 'fixtures') | ||
const cm = new ConfigManager({ | ||
source: join(fixturesDir, 'db-0.16.0.json'), | ||
env: { PLT_FOOBAR: 'foobar' } | ||
}) | ||
await cm.parse() | ||
same(cm.current, { | ||
$schema: `https://platformatic.dev/schemas/v${pkg.version.replace(/\.\d+$/, '.0')}/db`, | ||
server: { hostname: '127.0.0.1', port: '3042', logger: { level: 'info' } }, | ||
metrics: { auth: { username: 'plt-db', password: 'plt-db' } }, | ||
plugins: { paths: [join(fixturesDir, 'plugin-sum.js')] }, | ||
db: { | ||
connectionString: 'postgres://postgres:postgres@localhost:5432/postgres', | ||
graphiql: true, | ||
ignore: { versions: true } | ||
}, | ||
migrations: { | ||
dir: join(fixturesDir, 'demo', 'migrations'), | ||
validateChecksums: false | ||
}, | ||
dashboard: { path: '/' }, | ||
authorization: { adminSecret: 'plt-db' } | ||
}) | ||
}) |
@@ -7,3 +7,3 @@ 'use strict' | ||
test('do not emit event for not allowed files', async ({ teardown, equal, fail }) => { | ||
test('do not emit event for not allowed files', async ({ equal }) => { | ||
const configFile = path.join(__dirname, 'fixtures', 'onepath.json') | ||
@@ -28,1 +28,19 @@ const cm = new ConfigManager({ | ||
}) | ||
test('do not emit event for empty paths', async ({ equal }) => { | ||
const cm = new ConfigManager({ | ||
source: { path: '' }, | ||
schema: { | ||
type: 'object', | ||
properties: { | ||
path: { | ||
type: 'string', | ||
resolvePath: true | ||
} | ||
} | ||
} | ||
}) | ||
const parseResult = await cm.parse() | ||
equal(parseResult, false) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
53183
25
1430
7
+ Addedsemver@^7.5.0
+ Addedundici@^5.22.0
+ Added@fastify/busboy@2.1.1(transitive)
+ Added@platformatic/metaconfig@0.22.0(transitive)
+ Added@platformatic/utils@0.22.0(transitive)
+ Addedsemver@7.6.3(transitive)
+ Addedundici@5.28.4(transitive)
- Removed@platformatic/metaconfig@0.21.1(transitive)
- Removed@platformatic/utils@0.21.1(transitive)
Updated@platformatic/utils@0.22.0