Skip to content

Commit

Permalink
Add validate endpoint to check the data for errors without writing …
Browse files Browse the repository at this point in the history
…output files
  • Loading branch information
quincylvania committed Nov 23, 2020
1 parent 3fa9886 commit 9518d0a
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 45 deletions.
49 changes: 35 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ this to manage iD's tags. You can use it to create a custom schema for your own

### Building Data

To validate your source data and compile output files for iD:

```JS
const schemaBuilder = require('@ideditor/schema-builder');
schemaBuilder.build({
Expand All @@ -31,17 +33,36 @@ schemaBuilder.build({

The following options are optional:

- `inDirectory`, `string`: The relative directory of the source data files. Defaults to `data`.
- `outDirectory`, `string`: The relative directory of the built data files. Be aware that
- `inDirectory`: `string`, The relative directory of the source data files. Defaults to `data`.
- `outDirectory`: `string`, The relative directory of the built data files. Be aware that
everything in this directory will be overwritten when building. Defaults to `dist`.
- `sourceLocale`, `string`: The code of the language/locale used for the translatable strings in the data files. Defaults to `en`.
- `taginfoProjectInfo`, `object`: Project metadata required by TagInfo. If this info is not provided, the `taginfo.json` file will not be built. See the [schema](https://github.com/taginfo/taginfo-projects/blob/master/taginfo-project-schema.json) for more details.
- `processPresets`, `function(presets)`: An opportunity to edit the built presets.
- `processFields`, `function(fields)`: An opportunity to edit the built fields.
- `processCategories`, `function(categories)`: An opportunity to edit the built preset categories.
- `sourceLocale`: `string`, The code of the language/locale used for the translatable strings in the data files. Defaults to `en`.
- `taginfoProjectInfo`, `object`, Project metadata required by TagInfo. If this info is not provided, the `taginfo.json` file will not be built. See the [schema](https://github.com/taginfo/taginfo-projects/blob/master/taginfo-project-schema.json) for more details.
- `processPresets`: `function(presets)`, An opportunity to edit the built presets.
- `processFields`: `function(fields)`, An opportunity to edit the built fields.
- `processCategories`: `function(categories)`, An opportunity to edit the built preset categories.

### Validating Data

To validate your source data without compiling anything:

```JS
const schemaBuilder = require('@ideditor/schema-builder');
schemaBuilder.validate({
inDirectory: 'data'
});
```

The following options are identical to those for `schemaBuilder.build()`:
- `inDirectory`
- `processPresets`
- `processFields`
- `processCategories`

### Fetching Translations

To download locale files from Transfiex:

```JS
const schemaBuilder = require('@ideditor/schema-builder');
schemaBuilder.fetchTranslations({
Expand All @@ -56,20 +77,20 @@ schemaBuilder.fetchTranslations({

The following options are required:

- `organizationId`, `string`: The ID of the Transfiex organization where the translation project is hosted.
- `projectId`, `string`: The ID of the Transfiex project within the organization where the schema resource is translated.
- `organizationId`: `string`, The ID of the Transfiex organization where the translation project is hosted.
- `projectId`: `string`, The ID of the Transfiex project within the organization where the schema resource is translated.

The following options are optional:

- `resourceIds`, `[string]`: The IDs of the resources to download. Defaults to `['presets']`.
- `credentials`, `{ user: string, password: string }`: Your Transifex API credentials.
- `resourceIds`: `[string]`, The IDs of the resources to download. Defaults to `['presets']`.
- `credentials`: `{ user: string, password: string }`, Your Transifex API credentials.
Defaults to those stored as JSON in a `transifex.auth` file in your working directory.
- `reviewedOnly`, `boolean` or `[string]`: If `true`, only reviewed translations are included.
- `reviewedOnly`: `boolean` or `[string]`, If `true`, only reviewed translations are included.
If `false`, all translations are included. If an array of locale codes, only reviewed
translations are included for those specified locale codes, while all translations are included
for the remaining locales.
- `outDirectory`, `string`: Same as the `outDirectory` option for `schemaBuilder.build()`.
- `sourceLocale`, `string`: Same as the `sourceLocale` option for `schemaBuilder.build()`.
- `outDirectory`: `string`, Same as the `outDirectory` option for `schemaBuilder.build()`.
- `sourceLocale`: `string`, Same as the `sourceLocale` option for `schemaBuilder.build()`.

## Source Files

Expand Down
83 changes: 52 additions & 31 deletions lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,50 @@ const categorySchema = require('../schemas/preset_category.json');

let _currBuild = null;

function validateData(options) {
const START = '🔬 ' + colors.yellow('Validating schema...');
const END = '👍 ' + colors.green('schema okay');

function buildData(options) {
if (_currBuild) return _currBuild;
console.log('');
console.log(START);
console.time(END);

if (!options) options = {};
processData(options, false);

const dataDir = process.cwd() + '/' + (options.inDirectory || 'data');
const distDir = process.cwd() + '/' + (options.outDirectory || 'dist');
console.timeEnd(END);
console.log('');
}

function buildData(options) {

if (_currBuild) return _currBuild;

const START = '🏗 ' + colors.yellow('Building schema...');
const END = '👍 ' + colors.green('data built');
const START = '🏗 ' + colors.yellow('Validating and building schema...');
const END = '👍 ' + colors.green('schema built');

console.log('');
console.log(START);
console.time(END);

return _currBuild = processData(options, true)
.then(() => {
console.timeEnd(END);
console.log('');
_currBuild = null;
})
.catch((err) => {
console.error(err);
console.log('');
_currBuild = null;
process.exit(1);
});
}

function processData(options, write) {
if (!options) options = {};

const dataDir = process.cwd() + '/' + (options.inDirectory || 'data');

// Translation strings
let tstrings = {
categories: {},
Expand All @@ -39,15 +67,6 @@ function buildData(options) {
// all fields searchable under "add field"
let searchableFieldIDs = {};

if (!fs.existsSync(distDir)) {
fs.mkdirSync(distDir);
}

// Start clean
shell.rm('-rf', [
distDir + '/*'
]);

const deprecated = read(dataDir + '/deprecated.json');
if (deprecated) {
validateSchema(dataDir + '/deprecated.json', deprecated, require('../schemas/deprecated.json'));
Expand Down Expand Up @@ -77,16 +96,29 @@ function buildData(options) {
validateDefaults(defaults, categories, presets);
}

let translations = generateTranslations(fields, presets, tstrings, searchableFieldIDs);
let taginfo = generateTaginfo(presets, fields, deprecated, options.taginfoProjectInfo || {});
if (!write) return;

const distDir = process.cwd() + '/' + (options.outDirectory || 'dist');

if (!fs.existsSync(distDir)) {
fs.mkdirSync(distDir);
}

// Start clean
shell.rm('-rf', [
distDir + '/*'
]);

fs.writeFileSync(distDir + '/preset_categories.min.json', JSON.stringify(categories));
fs.writeFileSync(distDir + '/fields.min.json', JSON.stringify(fields));
fs.writeFileSync(distDir + '/presets.min.json', JSON.stringify(presets));

let taginfo = generateTaginfo(presets, fields, deprecated, options.taginfoProjectInfo || {});
if (taginfo) {
fs.writeFileSync(distDir + '/taginfo.min.json', JSON.stringify(taginfo));
}

let translations = generateTranslations(fields, presets, tstrings, searchableFieldIDs);
if (!fs.existsSync(distDir + '/translations')) {
fs.mkdirSync(distDir + '/translations');
}
Expand All @@ -108,19 +140,7 @@ function buildData(options) {
minifyJSON(dataDir + '/discarded.json', distDir + '/discarded.min.json'),
];

return _currBuild =
Promise.all(tasks)
.then(() => {
console.timeEnd(END);
console.log('');
_currBuild = null;
})
.catch((err) => {
console.error(err);
console.log('');
_currBuild = null;
process.exit(1);
});
return Promise.all(tasks);
}


Expand Down Expand Up @@ -625,3 +645,4 @@ function minifyJSON(inPath, outPath) {
}

module.exports.build = buildData;
module.exports.validate = validateData;
15 changes: 15 additions & 0 deletions tests/schema-builder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ describe('schema-builder', () => {
expect(schemaBuilder && schemaBuilder.fetchTranslations).not.toBeUndefined();
});

it('validates data', () => {
writeSourceData({
'data/presets/natural.json': {
tags: {
natural: '*'
},
geometry: ['point', 'vertex', 'line', 'area', 'relation'],
name: 'Natural Feature'
}
});
schemaBuilder.validate({
inDirectory: _workspace + '/data'
});
});

it('compiles data', () => {
writeSourceData({
'data/presets/natural.json': {
Expand Down

0 comments on commit 9518d0a

Please sign in to comment.