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

feat(boot): bind content of package.json to app context #1764

Merged
merged 1 commit into from
Oct 9, 2018

Conversation

raymondfeng
Copy link
Contributor

@raymondfeng raymondfeng commented Sep 26, 2018

See loopbackio/loopback4-example-shopping#16 (comment)

Checklist

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated
  • Documentation in /docs/site was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in examples/* were updated

@raymondfeng raymondfeng requested a review from bajtos as a code owner September 26, 2018 03:29
@@ -53,6 +55,11 @@ export function BootMixin<T extends Constructor<any>>(superClass: T) {
this.bind(BootBindings.BOOT_OPTIONS).toDynamicValue(
() => this.bootOptions,
);

this.bind(CoreBindings.APPLICATION_PACKAGE_JSON).toDynamicValue(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it not be better for this to be done via a Booter? This is not the intended usage of bootmixin and seems like concerns are being mixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind moving it to a application booter in the future once we figure out our configuration loading story, such as how to deal with env vars.

Copy link
Contributor

@virkt25 virkt25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall. i'm ok leaving out an ApplicationBooter till we have more stuff to add to it. Just one last comment and this can land imo.


this.bind(CoreBindings.APPLICATION_PACKAGE_JSON).toDynamicValue(() => {
const pkgFile = path.resolve(this.projectRoot, 'package.json');
return require(pkgFile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do a try/catch here in case package.json path is resolved incorrectly or the file doesn't exist (not sure why that may happen ... but in case it does).

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I would much rather see this functionality implemented as a new booter class.

As far as I understand the current design, BooterMixin is an optional helper that is not required for the booter component to work. Users should be able to use app.component(BooterComponent) and still get fully functional bootstrapper.

@@ -21,6 +23,15 @@ describe('controller booter acceptance tests', () => {

afterEach(stopApp);

it('binds package.json', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this test to a more appropriate file, maybe create a new test file in test/acceptance directory?

It looks wrong to me to see package.json-related tests inside controller booter acceptance tests.

(I think this is another clue that package.json should be handled by a new booter.)

@@ -192,6 +192,10 @@ export class Application extends Context {
const instance = this.getSync<Component>(componentKey);
mountComponent(this, instance);
}

public packageJson(pkg: PackageJson) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this name confusing for users and readers.

app.packageJson(/*...*/);

Can we find a better name, for example setApplicationMetadata? (I do realize this is not consistent with other API like app.component or app.controller.)

/**
* Type description for `package.json`
*/
export interface PackageJson {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON is a serialization format. Can we replace it with something else in the interface name please? How about PackageManifest, PackageMetadata or even ApplicationManifest/ApplicationMetadata?

I think I like ApplicationMetadata most.

version: string;
description: string;
// tslint:disable-next-line:no-any
[name: string]: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this data object is typically loaded from JSON, then I think we should restrict the allowed property types to number | string | object | array | null. JSON does not support functions and Dates for example. The current type definition makes it easy to accidentally treat a package.json property as a function and call it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this data object is typically loaded from JSON, then I think we should restrict the allowed property types to number | string | object | array | null. JSON does not support functions and Dates for example. The current type definition makes it easy to accidentally treat a package.json property as a function and call it.

This comment hasn't been addressed nor responded to, PTAL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@raymondfeng
Copy link
Contributor Author

@bajtos I added a application-metadata.booter and updated names. PTAL.

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch looks much better now!

@@ -192,6 +192,16 @@ export class Application extends Context {
const instance = this.getSync<Component>(componentKey);
mountComponent(this, instance);
}

/**
* Set application metadata. By default, the content of `package.json` is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"By defaults" implies to me that package.json metadata is populated by Application constructor, which is not true.

Can we make it more clear please that this metadata is empty by default but @loopback/boot populates is from package.json?

version: string;
description: string;
// tslint:disable-next-line:no-any
[name: string]: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this data object is typically loaded from JSON, then I think we should restrict the allowed property types to number | string | object | array | null. JSON does not support functions and Dates for example. The current type definition makes it easy to accidentally treat a package.json property as a function and call it.

This comment hasn't been addressed nor responded to, PTAL.

@raymondfeng raymondfeng force-pushed the bind-package-json branch 3 times, most recently from 65ba761 to 9424a11 Compare October 5, 2018 22:04
@raymondfeng
Copy link
Contributor Author

@bajtos Fixed. PTAL.

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Please double check that the tests are passing after rebasing your changes on top of the latest master.

@@ -33,6 +33,7 @@ describe('controller booter acceptance tests', () => {
});

async function getApp() {
await sandbox.copyFile(resolve(__dirname, '../fixtures/package.json'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will not work after the changes I made in #1824) - the package.json file is not going to be copied over from test to dist/test.

I think the easiest solution is to load the package json file from test/fixtures/application.ts:

import * as pkg from './package.json'

@raymondfeng raymondfeng merged commit 82f0ebe into master Oct 9, 2018
@raymondfeng raymondfeng deleted the bind-package-json branch October 9, 2018 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants