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: drop urijs #167

Merged
merged 1 commit into from
Mar 23, 2022
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
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,17 @@
"test": "jest"
},
"dependencies": {
"@stoplight/json": "^3.10.2",
"@stoplight/json": "^3.17.1",
"@stoplight/types": "^12.4.0",
"@types/swagger-schema-official": "~2.0.21",
"@types/to-json-schema": "^0.2.0",
"@types/type-is": "^1.6.3",
"@types/urijs": "~1.19.9",
"json-schema": "^0.4.0",
"json-schema-generator": "^2.0.6",
"lodash": "^4.17.15",
"openapi3-ts": "^2.0.1",
"postman-collection": "^4.1.0",
"type-is": "^1.6.18",
"urijs": "~1.19.2"
"type-is": "^1.6.18"
},
"devDependencies": {
"@stoplight/eslint-config": "^1.1.0",
Expand Down
120 changes: 1 addition & 119 deletions src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,122 +1,4 @@
import * as urijs from 'urijs';

import { maybeResolveLocalRef, URI } from '../utils';

describe('URI()', () => {
it('instantiates from string', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).toString()).toEqual(url);
});

it('instantiates from urijs', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(urijs(url)).toString()).toEqual(url);
});

describe('type()', () => {
it('sets type', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).scheme('test2').toString()).toEqual('test2:///path/to/api.yaml#/the/pointer');
});
});

describe('host()', () => {
it('sets host', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).host('test2.com').toString()).toEqual('test://test2.com/path/to/api.yaml#/the/pointer');
});

it('sets host and port', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).host('test2:3000').toString()).toEqual('test://test2:3000/path/to/api.yaml#/the/pointer');
});

it('sets host and port (non-number port does not error)', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).host('test2:{$$.env.host}').toString()).toEqual(
'test://test2:{$$.env.host}/path/to/api.yaml#/the/pointer',
);
});
});

describe('port()', () => {
it('sets port', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).host('test2').port('3000').toString()).toEqual('test://test2:3000/path/to/api.yaml#/the/pointer');
});

it('does not error on invalid port', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).host('test2').port('invalid').toString()).toEqual('test://test2/path/to/api.yaml#/the/pointer');
});
});

describe('path()', () => {
it('sets path', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).path('/path/to/other/api.yaml').toString()).toEqual(
'test:///path/to/other/api.yaml#/the/pointer',
);
});
});

describe('pointer()', () => {
describe('pointer is a string', () => {
it('sets pointer', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).pointer('#/new/pointer').toString()).toEqual('test:///path/to/api.yaml#/new/pointer');
});
});

describe('pointer is a path', () => {
it('sets pointer', () => {
const url = 'test:///path/to/api.yaml#/the/pointer';

expect(URI(url).pointer(['new', 'pointer']).toString()).toEqual('test:///path/to/api.yaml#/new/pointer');
});
});
});

describe('append()', () => {
describe('append pointer to uri having a pointer', () => {
it('replaces pointer', () => {
expect(URI('file:///path/to/api.yaml#/some/pointer').append('#/some/other/pointer').toString()).toEqual(
'file:///path/to/api.yaml#/some/other/pointer',
);
});
});

describe('append element to uri having a pointer', () => {
it('appends element to pointer', () => {
expect(URI('file:///path/to/api.yaml#/some/pointer').append('inner').toString()).toEqual(
'file:///path/to/api.yaml#/some/pointer/inner',
);
});
});

describe('append pointer to uri not having a pointer', () => {
it('appends pointer to uri', () => {
expect(URI('file:///path/to/api.yaml').append('#/some').toString()).toEqual('file:///path/to/api.yaml#/some');
});
});

describe('append element to uri not having a pointer', () => {
it('appends element to uri', () => {
expect(URI('file:///path/to').append('api.yaml').toString()).toEqual('file:///path/to/api.yaml');
});
});
});
});
import { maybeResolveLocalRef } from '../utils';

describe('maybeResolveLocalRef()', () => {
it('follows $refs', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './oas';
export * from './oas2';
export * from './oas3';
export * from './postman';
2 changes: 1 addition & 1 deletion src/oas2/guards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ export const isResponseObject = (maybeResponseObject: unknown): maybeResponseObj
'headers' in maybeResponseObject ||
'examples' in maybeResponseObject);

export function isValidScheme(scheme: unknown) {
export function isValidScheme(scheme: unknown): scheme is 'http' | 'https' | 'ws' | 'wss' {
return typeof scheme === 'string' && ['http', 'https', 'ws', 'wss'].includes(scheme);
}
14 changes: 8 additions & 6 deletions src/oas2/transformers/servers.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { DeepPartial, IServer } from '@stoplight/types';
import { Operation, Spec } from 'swagger-schema-official';

import { URI } from '../../utils';
import { isValidScheme } from '../guards';

export function translateToServers(spec: DeepPartial<Spec>, operation: DeepPartial<Operation>): IServer[] {
if (typeof spec.host !== 'string' || spec.host.length === 0) {
const { host } = spec;
if (typeof host !== 'string' || host.length === 0) {
return [];
}

Expand All @@ -14,13 +14,15 @@ export function translateToServers(spec: DeepPartial<Spec>, operation: DeepParti
return [];
}

const hasBasePath = typeof spec.basePath === 'string' && spec.basePath.length > 0;
const basePath = typeof spec.basePath === 'string' && spec.basePath.length > 0 ? spec.basePath : null;

return schemes.filter(isValidScheme).map(scheme => {
let uri = URI().scheme(scheme).host(spec.host);
const uri = new URL('https://localhost');
uri.host = host;
uri.protocol = `${scheme}:`;

if (hasBasePath) {
uri = uri.path(spec.basePath);
if (basePath !== null) {
uri.pathname = basePath;
}

return {
Expand Down
9 changes: 6 additions & 3 deletions src/postman/transformers/server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { IServer } from '@stoplight/types';
import { Url } from 'postman-collection';
import * as urijs from 'urijs';

export function transformServer(url: Url): IServer | undefined {
const origin = urijs(url.toString()).origin();
return origin ? { url: origin } : undefined;
try {
const origin = new URL(url.toString()).origin;
return origin ? { url: origin } : undefined;
} catch {
return undefined;
}
}
48 changes: 1 addition & 47 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,11 @@
import { hasRef, isLocalRef, pathToPointer, pointerToPath, resolveInlineRef } from '@stoplight/json';
import { hasRef, isLocalRef, resolveInlineRef } from '@stoplight/json';
import { Dictionary, Optional } from '@stoplight/types';
import { isObjectLike, map } from 'lodash';
import * as URIJS from 'urijs';

export function mapToKeys<T>(collection: Optional<T[]>) {
return map(collection, Object.keys);
}

// wraps urijs to handle edge cases that would normally error out or cause unexpected behavior
// in all funcs set a default empty string, since URI.func() !== URI.func(undefined) [<- undefined throw error in most cases]
// in all funcs set a default empty string, since URI.func('') will reset fields back to null while URI.func() will not
export function URI(url: string | URI = '') {
const uri: URI = !url || typeof url === 'string' ? new URIJS(url) : url;

return {
scheme: (type: string = '') => URI(uri.scheme(type)),

// if host includes a port that is not valid (a non-number) we encode the host to avoid errors and have it stored under uri.hostname
host: (host: string = '') =>
URI(uri.host(typeof host === 'string' && Number.isNaN(Number(host.split(':')[1])) ? URIJS.encode(host) : host)),

// if we try to set port directly and it is invalid (a non-number) reset the port to null
port: (port: string = '') => URI(uri.port(Number.isNaN(Number(port)) ? '' : port)),

path: (path: string = '') => URI(uri.path(path)),

pointer: (pathOrPointer: string | string[]) =>
URI(uri.hash(Array.isArray(pathOrPointer) ? pathToPointer(pathOrPointer) : pathOrPointer)),

// decode uri since some of the built in uri functions encode the args,
// normalize the uri to remove extra slash characters, and have uniform capitzalization where appropriate (schemes)
toString: () => URIJS.decode(uri.normalize().valueOf()),

append: (path: string = '') => {
const uri2 = new URIJS(path);

if (uri.fragment()) {
if (uri2.fragment()) {
return URI(uri.fragment(uri2.fragment()));
} else {
return URI(uri.hash(pathToPointer([...pointerToPath(uri.hash()), path])));
}
} else {
if (uri2.fragment()) {
return URI(uri.fragment(pathToPointer([path.split('#/')[1]])));
} else {
return URI(uri.segment([...uri.segment(), path]));
}
}
},
};
}

export const isDictionary = (maybeDictionary: unknown): maybeDictionary is Dictionary<unknown> =>
isObjectLike(maybeDictionary);

Expand Down
Loading