Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.0.0 Release Notes #75

Closed
devinivy opened this issue Feb 2, 2021 · 0 comments
Closed

4.0.0 Release Notes #75

devinivy opened this issue Feb 2, 2021 · 0 comments

Comments

@devinivy
Copy link
Member

devinivy commented Feb 2, 2021

Note

The name of this module has switched from haute-couture to @hapipal/haute-couture on npm.

Summary

Haute-couture v4.0.0 is focused on modernization, intuitive default behavior, and a cleaner API. This release has also been published as @hapipal/haute-couture as part of an organization-wide effort to standardize the names and documentation for all hapi pal modules under the @hapipal npm scope.

  • Upgrade time: low to moderate - most users will be able to upgrade in a few hours or less (barring updates to node, hapi, or other peer dependencies). Could be closer to a day for users with custom amendments.
  • Complexity: low to moderate - the upgrade is straightforward for basic users, moderate for users of custom amendments, and moderate for library authors interoperating with haute-couture.
  • Risk: low to moderate - if some of the breaking changes are not heeded, it could cause issues that would not be caught during server initialization.
  • Dependencies: moderate - this release is not guaranteed to be compatible with certain versions of node, hapi, and other peer dependencies that were previously supported.

Breaking Changes

  • The package is now published as @hapipal/haute-couture rather than haute-couture.
  • Versions of node below v12 and versions of hapi below v19 are no longer supported.
  • Peer dependencies supported are now schwifty v6 (no longer v3-v5), schmervice v2 (no longer v1), vision v5 and v6, and nes v11 and v12 (no longer v10 and below). This only applies to built-in, officially supported peers: you may configure support for old versions through amenments.
  • HauteCouture.using(dirname, amendments) has been replaced with HauteCouture.composeWith({ dirname, amendments }), and more common usage is now HauteCouture.compose(server, options, { dirname, amendments }).
  • The format of amendments has changed to { [place]: amendment | false } rather than { add: [amendment], remove: [place] }.
  • The format of items in plugins/ has been simplified to { plugin, options } rather than { plugins: [{ plugin, options }], options }.
  • The manifest recursive option now defaults to true rather than false, so haute-couture will follow deeply-nested folders.
  • The amendment useFilename() args have changed to (value, filename, path) => ..., swapping the order of filename and path.
  • HauteCouture.manifest.create([amendments, [includeExtras]]) has been replaced with HauteCouture.manifest([amendments, [dirname]]) and HauteCouture.amendments([amendments]).

New Features

  • HauteCouture.amendment() simplifies overriding and extending default amendments.

  • Improved auto-configuration for decorations and extensions based on file path.

    • When a decoration contains server/, request/, response/, toolkit/, or handler/ in its file path, a default value for the decoration's type is inferred.
    • When an extension contains on-pre-start/, on-request/, on-pre-handler/, etc. in its file path, a default value for the extension's type is inferred.

Bug fixes

None

Migration Checklist

The content below is long and detailed with examples for your benefit, but for most users here's the shortlist:

  • Switch from the haute-couture package to @hapipal/haute-couture.
  • Ensure you're on node v12+, hapi v19+, and recent versions of schwifty, schmervice, vision, and nes.
  • In your plugin entrypoint (e.g. lib/index.js in the boilerplate) change await HauteCouture.using()(server, options) to await HauteCouture.compose(server, options).
  • Change files in plugins/ to export what is currently the contents of their plugins key, e.g. module.exports = { plugins: { plugin, options } } would become module.exports = { plugin, options }.
  • Note that haute-couture will find files deeply now by default. You could turn this off by adding the following config to your .hc.js file: module.exports = { $default: { recursive: false } }.

For more details, examples, and changes to amendments, see below.

Update to the new @hapipal/haute-couture package

The entire hapi pal ecosystem is in the process of moving to the @hapipal npm scope, so the package name has changed to @hapipal/haute-couture. You can find our organization on npm here.

Checklist:

  • In package.json replace "haute-couture": "3.x.x" (or similar) with "@hapipal/haute-couture": "4.x.x".
  • Update any places in your application where you require haute-couture to require('@hapipal/haute-couture').

Node, hapi, and other peer dependency versions

Haute-couture interoperates Node and several packages. We've made an effort to maintain compatibility with older packages where applicable, but in some cases we have dropped support for old versions.

Checklist:

  • Make sure your node version is v12 or newer. This release is designed with language features in mind that are only available in node v12 or higher. Node v14 is the current LTS and the recommended version of node.
  • It is recommended to upgrade hapi v19 or v20, as these are the only officially supported versions of hapi.
  • If you use schwifty with haute-couture, upgrade to schwifty v6. You may alternately configure an amendment for an older version of schwifty. The main change is that schwifty v6 now uses server.registerModel() rather than server.schwifty() for registering models. The model example has also been updated (affects output of hpal make model).
  • If you use schmervice with haute-couture, upgrade to schmervice v2. You may alternately configure an amendment for an older version of schmervice. The main change is that the service example has been updated (affects output of hpal make service).
  • If you use nes with haute-couture, upgrade to nes v11 or above. The amendment has not changed, but earlier versions of nes are not officially compatible with hapi v19+ or node v12+.

New plugin composition entrypoint

Previously HauteCouture.using() was used as the entrypoint for composing a plugin. Due to its awkward usage for certain common use-cases and inspecific naming, we've introduced HauteCouture.compose() and HauteCouture.composeWith() to replace it.

Checklist:

  • Change any usage of the form HauteCouture.using(dirname, amendments)(server, options) to HauteCouture.compose(server, options, { dirname, amendments }).

    'use strict';
    
    const HauteCouture = require('@hapipal/haute-couture');
    
    exports.plugin = {
        name: 'my-plugin',
        register: async (server, options) => {
    
    -         await HauteCouture.using()(server, options);
    +         await HauteCouture.compose(server, options);
        }
    };
  • Change any usage of HauteCouture.using(dirname, amendments) where the function it returns it is not immediately invoked with HauteCouture.composeWith({ dirname, amendments }).

    'use strict';
    
    const HauteCouture = require('@hapipal/haute-couture');
    
    exports.plugin = {
        name: 'my-plugin',
    -    register: HauteCouture.using(`${__dirname}/my-plugin`)
    +    register: HauteCouture.composeWith({ dirname: `${__dirname}/my-plugin` })
    };

Amendments format

The format of amendments has changed to be more ergonomic. Rather than an instructional configuration { add, remove }, we have moved to a more declarative interface. Each amendment is keyed by its place directory, and there is a more straightforward way to extend/alter existing amendments. Note that the examples seen below demonstrate amendments placed in an .hc.js file, but they can also be passed directly to HauteCouture.compose().

Checklist:

  • Move any amendments in the add key into the new format keyed by place.

    'use strict'; // .hc.js
    
    module.exports = {
    -    add: [{
    -        place: 'lambdas',
    -        method: 'lambda',
    -        list: true
    -    }]
    +    lambdas: {
    +        method: 'lambda',
    +        list: true
    +    }
    };
  • Move any amendments in the remove key into the new format keyed by place with value set to false.

    'use strict'; // .hc.js
    
    module.exports = {
    -    remove: ['plugins', 'dependencies']
    +    plugins: false,
    +    dependencies: false
    };
  • Move amendment defaults under the '$default' or HauteCouture.default key.

    'use strict'; // .hc.js
    
    module.exports = {
    -    recursive: true,
    -    exclude: /utils/
    +    $default: {
    +        recursive: true,
    +        exclude: /utils/
    +    }
    };
  • If you use HauteCouture.manifest.create({}, true) to receive the default amendments for extension, you should now use HauteCouture.amendment():

    'use strict'; // .hc.js
    
    const HauteCouture = require('@hapipal/haute-couture');
    
    module.exports = {
        routes: HauteCouture.amendment('routes', {
            recursive: false
        })
    };
  • If you have a custom amendment using useFilename(), switch the argument order from (value, path, filename) => ... to (value, filename, path) => ....

Updated configuration for plugins/

We found that the contents of items within plugins/ were confusing for users. The source of the confusion is that hapi's server.plugin(plugins, options) receives two kinds of "options": 1. options to configure individual plugins and 2. registration options that tell hapi how to register the list of plugins, e.g. under a specific route prefix { route: { prefix: '/api' } }. The latter are not as commonly used, and in fact may be specified on a per-plugin basis anyway, so we removed support for these options.

Checklist:

  • For each file in plugins/ used by haute-couture, move the contents of exports.plugins to exports.

    'use strict'; // plugins/my-plugin.js
    
    -module.exports = {
    -    plugins: require('any-hapi-plugin')
    -};
    +module.exports = require('any-hapi-plugin');
    'use strict'; // plugins/my-plugin.js
    
    -module.exports = {
    -    plugins: {
    -        plugin: require('any-hapi-plugin'),
    -        options: { some: 'option' }
    -    }
    -};
    +module.exports = {
    +    plugin: require('any-hapi-plugin'),
    +    options: { some: 'option' }
    +};
    'use strict'; // plugins/my-plugin.js
    
    -module.exports = {
    -    plugins: [
    -        require('any-hapi-plugin'),
    -        require('another-hapi-plugin')
    -    ]
    -};
    +module.exports = [
    +    require('any-hapi-plugin'),
    +    require('another-hapi-plugin')
    +];
    'use strict'; // plugins/@hapi.vision.js
    
    -module.exports = {
    -    plugins: {
    -        options: {
    -            engines: { html: require('handlebars') },
    -            path: __dirname + '/templates'
    -        }
    -    }
    -};
    +module.exports = {
    +    options: {
    +        engines: { html: require('handlebars') },
    +        path: __dirname + '/templates'
    +    }
    +};
  • For each file in plugins/ used by haute-couture that uses hapi registration options, move the options into each plugin's configuration.

    'use strict'; // plugins/my-plugin.js
    
    -module.exports = {
    -    plugins: require('any-hapi-plugin'),
    -    options: { routes: { prefix: '/api' } }
    -};
    +module.exports = {
    +    plugin: require('any-hapi-plugin'),
    +    routes: { prefix: '/api' }
    +};
    'use strict'; // plugins/my-plugin.js
    
    -module.exports = {
    -    plugins: [
    -        require('any-hapi-plugin'),
    -        {
    -            plugin: require('another-hapi-plugin'),
    -            options: { some: 'option' }
    -        }
    -    ],
    -    options: { routes: { prefix: '/api' } }
    -};
    +module.exports = [
    +    {
    +        plugin: require('any-hapi-plugin'),
    +        routes: { prefix: '/api' }
    +    }
    +    {
    +        plugin: require('another-hapi-plugin'),
    +        options: { some: 'option' }
    +        routes: { prefix: '/api' }
    +    }
    +];

New default of recursive: true

We found that most users find the recursive functionality more intuitive and often set it as the default in their projects, so it now defaults to true. This means that haute-couture will follow deeply-nested directories. For example, a route file routes/users/update.js will be found by haute-couture despite not living directly under routes/.

Checklist:

  • Check that each directory used by haute-couture (routes/, models/, etc.) does not contain any files under subdirectories that you want to be ignored by haute-couture.

    • Note that files under subdirectories named helpers/ are automatically ignored.
    • You may fine-tune haute-couture to ignore other files using the exclude amendment option.
    • Individual amendments may disable this feature. For example, to not treat the models/ directory recursively:
    'use strict'; // .hc.js
    
    const HauteCouture = require('@hapipal/haute-couture');
    
    module.exports = {
        models: HauteCouture.amendment('models', {
            recursive: false
        })
    };
  • Alternately, you may restore the v3 default functionality by setting the default value back to false in your project. To do so, update your amendments with the new default. For example, here is a .hc.js file restoring the former default value:

    'use strict'; // .hc.js
    
    module.exports = {
        $default: { recursive: false }
    };

Default amendments and generating haute manifests

If you're interoperating with haute-couture, you may want to generate an haute manifest yourself. In the past this was done with HauteCouture.manifest.create([amendments, [includeExtras]]), and now we have HauteCouture.amendments([amendments]) and HauteCouture.manifest([amendments, dirname]).

Checklist:

  • If you were using includeExtras, now use HauteCouture.amendments() to receive amendments keyed by their place. These amendments include before, after, etc.

    • You may also receive and patch a default amendment with HauteCouture.amendment().
  • If you were not using includeExtras, now use HauteCouture.manifest() to receive an array of haute manifest items. These items do not include before, after, etc., and may be passed directly to haute if configured with a dirname.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant