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

parse nested endpoint structure in root config #265

Merged
merged 1 commit into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/lib/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class Config {
}
}

keys(): Array<string> {
return Object.keys(this.config);
}

numberOpt(key: string): number | undefined {
const v = this.config[key];
if (v === undefined || typeof v === "number") {
Expand Down
53 changes: 48 additions & 5 deletions src/lib/config/root-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,29 @@ export class RootConfig {

constructor(config: Config) {
this.defaultEndpoint = config.strOpt("default");
this.endpoints = Object.fromEntries(
config
.allObjectsWhere((k) => k !== "default")
.map(([k, v]) => [k, Endpoint.fromConfig(v)])
);

/**
* Our updated config uses endpoint.<name> to reserve the endpoint namespace.
* It is possible prior users still have legacy config that has the endpoints at the top level.
* When config is updated, we will write the entire file, so it will either
* all be nested under endpoint or all legacy. The only time this wouldn't be
* the case is if a user manually modifies their file to have a top level
* endpoint after we have nested them all under endpoint. In that scenario,
* the added endpoint will not be recognized.
*/
if (RootConfig.configContainsNestedEndpointStructure(config)) {
this.endpoints = Object.fromEntries<Endpoint>(
config
.objectsIn("endpoint")
.map(([k, v]) => [k, Endpoint.fromConfig(v)])
);
} else {
this.endpoints = Object.fromEntries<Endpoint>(
config
.allObjectsWhere((k) => k !== "default")
.map(([k, v]) => [k, Endpoint.fromConfig(v)])
);
}

if (this.defaultEndpoint === "default") {
throw new InvalidConfigError(
Expand All @@ -26,6 +44,31 @@ export class RootConfig {
);
}
}

/**
* If there is an endpoint object in the config, and it has a
* object underneath it, we are saying that it uses the
*
* [endpoint.myacct]
* secret=***
*
* structure. This allows us to support a legacy config that has
* a top level endpoint named endpoint. Once we rewrite the config
* to be endpoint object based adding one manually like that
* will not be recognized.
*/
private static configContainsNestedEndpointStructure(
config: Config
): boolean {
if (config.objectExists("endpoint")) {
const endpointObj = config.object("endpoint");
return endpointObj.keys().some((key) => {
return endpointObj.objectExists(key);
});
Comment on lines +65 to +67
Copy link
Contributor

Choose a reason for hiding this comment

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

style (you can avoid the second return if you don't make a block):

Suggested change
return endpointObj.keys().some((key) => {
return endpointObj.objectExists(key);
});
return endpointObj.keys().some((key) => endpointObj.objectExists(key));

} else {
return false;
}
}
}

/**
Expand Down
37 changes: 37 additions & 0 deletions test/lib/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,43 @@ describe("root config", () => {
url: "http://localhost:8443",
});
});

it("supports config with endpoint nested", () => {
expect(
lookupEndpoint({
rootConfig: {
default: "other-endpoint",
endpoint: {
"my-endpoint": {
secret: "fn1234",
},
"other-endpoint": {
secret: "fn5678",
},
},
},
})
).to.deep.contain({
secret: "fn5678",
url: "https://db.fauna.com",
});
});

it("supports legacy top level endpoint", () => {
expect(
lookupEndpoint({
rootConfig: {
default: "endpoint",
endpoint: {
secret: "fn1234",
},
},
})
).to.deep.contain({
secret: "fn1234",
url: "https://db.fauna.com",
});
});
});

describe("root config with flags", () => {
Expand Down