Giter VIP home page Giter VIP logo

standard_extension_template's Introduction

OCDS Extension Template Repository

OCDS extensions can be used to declare additional fields, objects and sections that will be included in an OCDS file, but which are not in the core schema, and to add or extend codelists. When any OCDS publication cites an extension in its' package metadata, it should be validated against the schema with that extension applied.

This repository provides a template of an extension that people can base their own on.

Getting started

To create an extension based on this template, you should:

  1. Download a zip file version of the template
  2. Extract it, and initialise it as a git repository (git init) †
  3. Update the README.md and extension.json files, and prepare any schema, codelist, documentation and test files
  4. Commit the files you have changed
  5. Delete files you have not changed
  6. Push to a new public git repository
  7. (For core or community extensions) Register this extension with the extensions registry

† Use of git for version control is recommended, but optional. Extensions can be hosted on any public HTTP server, providing the file structure matches that in this template repository.

Naming extension repositories

Names for extension repositories should conform to the following pattern:

ocds_[name]_extension

For example, ocds_additionalContactPoints_extension.

[name] should indicate the purpose of the extension, and/or the field or object being extended to aid self-documentation. This could be the JSON Pointer fragment for the name of the primary field or object that the extension introduces.

Extension repository structure

The structure of an extension repository should look like:

├── README.md (a full description of the extension in markdown - required)
├── extension.json (a json file giving metadata about the extension - required)
├── release-schema.json (JSON Merge Patch of release-schema.json)
└── codelists
    ├── emptyCodelist.csv (A new codelist)
    |__ +milestoneType.csv (Add values to the milestoneType codelist)
    └── milestoneType.csv (Overwrite the existing codelist - not recommended)

This copies the layout of the core standards repository.

Schema files

The extension template includes the following schema files:

  • release-schema.json

In most cases, the extension will have a release-schema.json with the minimal changes required to patch the schema. Empty schema files should not be included in the extension.

extension.json

This file is required. It provides information about the extension to be used by any OCDS automated tool.

This repository contains an example extension.json, whose format is described by extension-schema.json.

Required fields

  • name: An object mapping language codes to the title case name of the extension in the language
  • description: An object mapping language codes to the description of the extension in the language
  • documentationUrl: An object mapping language codes to the URL for documentation in the language, e.g. the extension's GitHub page
  • compatibility: An array of minor versions of the core standard that the extension is compatible with, e.g. [ "1.1" ]
  • contactPoint/name: The name of the contact point to communicate with the extension's authors or maintainers. It can be an individual or an organization.
  • contactPoint/email: The email address of the contact point.

Optional fields

  • schemas: An array of the filenames of the JSON Schema files in the extension's root directory, e.g. [ "release-schema.json" ]
  • codelists: An array of the filenames of the CSV files in the extension's codelists directory, e.g. [ "codelistName.csv", "+milestoneType.csv" ]
  • dependencies: An array of the URLs of other extensions whose definitions this extension $ref'erences, e.g. [ "http://path/to/extension/extension.json" ]

Description

Here are some guidelines for writing the text for the mandatory description field in extension.json :

  • There is no maximum length for the description, but you should try to keep it concise. In any case, do not sacrifice clarity for the sake of brevity.
  • Refer to the part(s) of the schema the extension is modifying.
  • Do not include in the description the development status of the extension (e.g. draft). If you need to add current status, do so in a README file, it will be much more visible and therefore less prone to be forgotten and not updated.
  • Avoid descriptions that simply duplicate or paraphrase the extension name.

For example, for ocds_performance_failures_extension, this wouldn't be a good description:

An extension covering performance failures in OCDS.

The actual description in the extension is much better:

Adds fields to the implementation section to allow disclosure of an array of contracting performance failures. Based on the performance failures reporting table defined in the World Bank Framework for Disclosure in PPPs.

Translation

To translate the name and description fields, and to provide documentationUrl in multiple languages, add additional key-value pairs for each language, for example:

{
  "description": {
    "es": "Descripción",
    "en": "Description"
  }
}

Codelists

As in the core standard repository, the extension template also includes a codelists folder to store extension-specific codelists.

Codelists are CSV files with camel case names, e.g. implementationStatus.csv. Be aware that a codelist in your extension using the same name as an existing codelist in the standard repository will override the existing codelist.

Prefixing a codelist name with + (e.g. +milestoneStatus.csv) indicates that contents of the codelist should be appended to an existing codelist of the same name.

How the extensions work

As of OCDS 1.1, the schema files from the core standard that extensions can extend are:

  • release-schema.json

In the extension some or all of these files can be used to do a JSON Merge Patch of the corresponding file.

A JSON Merge Patch is described by this RFC.

The patches are very simple. They just copy the same structure from the core schema and allow you add your extra fields or update existing fields just in the places the extension wants to change the schema.

Here are some simple examples of how this works. They are illustrative; any changes to existing fields should respect the Conformance documentation.

They all are examples of what could go in release-schema.json files in an extension.

Add a new field newField to the release.

{
  "properties": {
    "newField": {
      "title": "New field",
      "description": "A new field",
      "type": "string"
    }
  }
}

Add a new field newOrgField to the organization definition.

{
  "definitions": {
    "Organization": {
      "newOrgField": {
        "title": "New Org field",
        "description": "A new field",
        "type": "string"
      }
    }
  }
}

Best practice

It is possible to copy the whole of the schemas from the core, change them and as long as you have only added or changed properties the extension will work as expected. However doing it this way will mean that it will be hard to see what changes are made and will be much harder to track changes of the core schema (as every change in the core schema will need to be copied).

So it is best practice to just put in an extension the minimal changes that are required. However, it can be useful to work with the whole schema when developing an extension. In this case use the json-merge-patch library and it will generate the minimal patch for you by using the command line tool.

json-merge-patch create-patch core_schema.json new_modified_schema.json -o minimal_patch.json

You can also test your extension by:

json-merge-patch merge core_schema.json your_extension.json -o expected_output.json

standard_extension_template's People

Contributors

benvand avatar colinmaudry avatar dependabot[bot] avatar duncandewhurst avatar edugomez avatar jpmckinney avatar kindly avatar romifz avatar timgdavies avatar yolile avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

standard_extension_template's Issues

JSON Schema files optional?

The template has:

Extensions must include at least one of those files.

However, it's possible, as in https://github.com/INAImexico/ocds_extendedProcurementCategory_extension, to only have a modification to a codelist.

I suspect that the above phrase was written before codelist modification was specified. I propose removing the sentence, to make it allowed to only modify codelists.

Also, there is no consequence to 'no-op' extensions that modify nothing, so we don't need to specifically guard against that.

Agreed, @kindly @timgdavies @duncandewhurst?

cc @yolile

Changes for next major version

If there is a need for a next major version of this template, we could make the following changes:

  • Rename .babel_codelists and .babel_schema to babel_codelists.cfg and babel_schema.cfg. Most other projects use .cfg extensions rather than hidden files.
  • Rename codelists_text and jsonschema_text to ocds_codelists and ocds_schema, here and in setup.py in documentation-support. These entry points share the babel.extractors group, and therefore should be scoped to OCDS.

These are scheduled for a major version, as it's not worth the effort otherwise to rename things.

Document localized descriptions

Can we add to the readme a section to mention how the description and title fields can be localized?
Like:

"description" : 
[
    "es": "Descripción"
    "en": "Description"
]

Just for mention the format and correct form to do that and mention that this can be done.

Adding a script to test extensions

I would love to have a script as part of the standard template which I can use to test my extension against current version of OCDS.

E.g. before pushing it an updated version, I would run the test script which would:

  • Check my JSON was valid;
  • Grab the latest (or specified) version of the OCDS schema, and merge-patch it;
  • Present back the output in some meaningful way - possibly by building a little temporary docson viewer;

I've been meaning to write this myself, but not got to it yet, so logging here.

Declaring dependencies

One extension may depend on another.

For example, imagine two simple extensions. The first adds an object called 'extension', and then second adds a property called 'subExtension' to this object.

extension_one

{
    "properties":{
        "extension":{
               "type":"object"
         }
     }
}

extension_two

{
    "properties":
        "extension":{
             "properties": {
                   "subExtension":{ 
                       "type":"string"
                   }
               }
        }
}

If you try to use extension_two without extension_one you get invalid JSON Schema, because the information that extension is an 'object' was in extension_one.

Therefore, the extension.json for extension_two needs to declare it's dependency upon extension_one in order to tell applications/validators etc. that they MUST first apply extension_one before applying extension_two.

The question:

  • Should the extension.json for extension_two include (a) the extension registry slug of extension_one; or (b) a url to the extension.json for extension_one?

Issues to consider:

  • What if a new version of extension_one is entered into the extension registry in which extension is renamed to the_extension? How would a link to the registry slug indicate pinning of versions? Does it need to?

  • What if the location where extension_one is available for download changes? Would this require changes to any extensions that have it as a dependency? Or just to the registry?

  • What about dependencies between 'local extensions' which don't have an entry in the extensions registry? Do we support dependencies in this case?

  • Could there be a mixed approach? Either URL or slug?

An approach to extend existing codelists

For the PPP project we have an number of different extensions which want to add to an existing codelist. For example, adding to documentType.

The current approach lets us over-write codelists, but not add to them. This is a problem when you have multiple interacting codelists.

Could we develop an approach based on a syntax such as '_codeListName.csv' to append, and 'codeListName.csv' to over-write?

This depends on:

  • Firming up the CSV specification for our codelists (which are currently not terrible consistent and tidy)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.