Make service injection private
Tags: gulp, webdev, performance, angular
Published: 2020-07-14 15:00:41

This is part five of seven.

# Prerequisits
This part is very specific to how this project is set up and depends on what has been done in step four.

Our components/directives/services use the class syntax and bind the injected service to the class to keep the scope clean from services.
```javascript
class AwesomeComponent {
    constructor(MyService) {
        Object.assign(this, {MyService});
    }
}
```

# The bundle served
After the build process our code will look something like this:
```javascript
var AwesomeComponent = function() {
    AwesomeComponent.$inject = ['MyService'];

    function AwesomeComponent(MyService) {
        _classCallCheck(this, AwesomeComponent);
        Object.assign(this, {
            MyService: MyService
        });
    }
}
```
Some of you might already see the potential her 😉

# The way to privatization
In the last part we have looked at the possibility to minify our private methods (in my project I declare them with `_` in  the beginning). As our services are exclusively used within the component/directive/service, we could argue that they are injected private Methods.

So the way to optimize our class would be:
```javascript
class AwesomeComponent {
    constructor(MyService) {
        Object.assign(this, {
            _MyService: MyService,
        });
    }
}
```
It would be really boring and prone to mistakes to do all those changes by hand.

So here is my attempt to rework the services with a gulp task (once).
It follows those steps:
- get all js files
- look for the object assign pattern (objectAssignRegex)
- if we have no changes we continue without changes
- get all the services from the capture group and split them into an array
- map through the services and do the private method trick
- join the array with line breaks (`\n`)
- wrap them in formatted object assign wrapper
- Replace the old `Object.assign` contents with the generated string
- replace all `this.Service` with `this._Service` (careful of $)
- overwrite the contents

```javascript
// make services private
const tPrivateService = () => {
    const objectAssignRegex = /Object.assign\(this, \{(.+?)\}/m;
    return gulp
        .src(packagePath + '/**/*.js', {base: './'})
        .pipe(through.obj((file, _, cb) => {
            const newFile = file.clone();
            let string = newFile.contents.toString();

            const match = string.match(objectAssignRegex);
            if (match) {
                console.log('Working on ', file.basename);

                const services = match[1]
                    .split(', ')
                    .map((service) => service.trim());

                const newServices = services
                    .map((service) => `            _${service}: ${service},`).join('\n');

                const newObjectAssign = match[0]
                    .replace(match[1], newServices)
                    .replace('{', '{\n')
                    .replace('}', '\n        }');

                string = string.replace(objectAssignRegex, newObjectAssign);

                services.forEach((service) => {
                    string = string.replace(new RegExp(`this.${service.replace(/\$/g, '\\$')}`, 'gm'), `this._${service}`);
                });

                // overwrite contents of vinyl with new buffer
                newFile.contents = Buffer.from(string);
            }
            cb(null, newFile);
        }))
        .pipe(gulp.dest('./'));
};

exports.privateService = series(tPrivateService);
```

In my case, that worked for almost all files. In some cases I had the `Object.assign` implemented in a none standard way (with additional var declarations or line breaks).
Before you submit check all your changes.

Enjoy your privatized service injection 🎉

# Coming up next
- Privatize unused public methods in components/directives