Skip to content

Commit

Permalink
fix(nango-yaml): allow endpoint to be reused across integration (#2365)
Browse files Browse the repository at this point in the history
## Describe your changes

Fixes
https://linear.app/nango/issue/NAN-1246/fix-cli-does-not-allow-endpoint-to-be-reused-across-integration

An oversight on my part when I rewrote this part, I moved the variable
on layer too high and didn't added unit test to ensure that.

- Allow endpoints to be reused across integration + unit test
  • Loading branch information
bodinsamuel authored Jun 18, 2024
1 parent e95ee6f commit 1d98584
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 31 deletions.
4 changes: 2 additions & 2 deletions packages/nango-yaml/lib/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ export abstract class NangoYamlParser {
return;
}

// check that every endpoint is unique across syncs and actions
const endpoints = new Set<string>();
for (const integration of this.parsed.integrations) {
// check that every endpoint is unique across syncs and actions per integration
const endpoints = new Set<string>();
// check that models are used only once per integration
const usedModels = new Set<string>();
const integrationName = integration.providerConfigKey;
Expand Down
91 changes: 62 additions & 29 deletions packages/nango-yaml/lib/parser.v2.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, describe, it } from 'vitest';
import { NangoYamlParserV2 } from './parser.v2.js';
import type { NangoYamlParsed, NangoYamlV2 } from '@nangohq/types';
import { ParserErrorMissingId, ParserErrorModelIsLiteral, ParserErrorModelNotFound } from './errors.js';
import { ParserErrorDuplicateEndpoint, ParserErrorMissingId, ParserErrorModelIsLiteral, ParserErrorModelNotFound } from './errors.js';

describe('parse', () => {
it('should parse', () => {
Expand Down Expand Up @@ -121,34 +121,67 @@ describe('parse', () => {
yamlVersion: 'v2'
});
});
describe('endpoints', () => {
it('should handle endpoint with model inside (found)', () => {
const v2: NangoYamlV2 = {
models: { Found: { id: 'string' } },
integrations: {
provider: { actions: { getGithubIssue: { endpoint: 'GET /ticketing/tickets/{Found:id}' } } }
}
};
const parser = new NangoYamlParserV2({ raw: v2 });
parser.parse();
expect(parser.errors).toStrictEqual([]);
expect(parser.warnings).toStrictEqual([]);
expect(parser.parsed?.integrations[0]?.actions).toMatchObject([
{
endpoint: { GET: '/ticketing/tickets/{Found:id}' }
}
]);
});

it('should handle endpoint with model inside (found)', () => {
const v2: NangoYamlV2 = {
models: { Found: { id: 'string' } },
integrations: {
provider: { actions: { getGithubIssue: { endpoint: 'GET /ticketing/tickets/{Found:id}' } } }
}
};
const parser = new NangoYamlParserV2({ raw: v2 });
parser.parse();
expect(parser.errors).toStrictEqual([]);
expect(parser.warnings).toStrictEqual([]);
expect(parser.parsed?.integrations[0]?.actions).toMatchObject([
{
endpoint: { GET: '/ticketing/tickets/{Found:id}' }
}
]);
});
it('should handle endpoint with model inside (missing)', () => {
const v2: NangoYamlV2 = {
models: {},
integrations: {
provider: { actions: { getGithubIssue: { endpoint: 'GET /ticketing/tickets/{Missing:id}' } } }
}
};
const parser = new NangoYamlParserV2({ raw: v2 });
parser.parse();
expect(parser.errors).toStrictEqual([new ParserErrorModelNotFound({ model: 'Missing', path: ['provider', 'syncs', 'getGithubIssue', '[endpoint]'] })]);
expect(parser.warnings).toStrictEqual([]);
it('should handle endpoint with model inside (missing)', () => {
const v2: NangoYamlV2 = {
models: {},
integrations: {
provider: { actions: { getGithubIssue: { endpoint: 'GET /ticketing/tickets/{Missing:id}' } } }
}
};
const parser = new NangoYamlParserV2({ raw: v2 });
parser.parse();
expect(parser.errors).toStrictEqual([
new ParserErrorModelNotFound({ model: 'Missing', path: ['provider', 'syncs', 'getGithubIssue', '[endpoint]'] })
]);
expect(parser.warnings).toStrictEqual([]);
});

it('should raise an error if endpoint is reused in an integration', () => {
const v2: NangoYamlV2 = {
models: {},
integrations: {
provider: { actions: { getGithubIssue: { endpoint: 'GET /issue' }, getTrelloIssue: { endpoint: 'GET /issue' } } }
}
};
const parser = new NangoYamlParserV2({ raw: v2 });
parser.parse();
expect(parser.errors).toStrictEqual([
new ParserErrorDuplicateEndpoint({ endpoint: 'GET /issue', path: ['provider', 'actions', 'getTrelloIssue', '[endpoint]'] })
]);
expect(parser.warnings).toStrictEqual([]);
});

it('should not raise an error if endpoint is reused across many integration', () => {
const v2: NangoYamlV2 = {
models: {},
integrations: {
providerA: { actions: { getGithubIssue: { endpoint: 'GET /issue' } } },
providerB: { actions: { getTrelloIssue: { endpoint: 'GET /issue' } } }
}
};
const parser = new NangoYamlParserV2({ raw: v2 });
parser.parse();
expect(parser.errors).toStrictEqual([]);
expect(parser.warnings).toStrictEqual([]);
});
});
});

0 comments on commit 1d98584

Please sign in to comment.