Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into nested-extended
Browse files Browse the repository at this point in the history
  • Loading branch information
skyqrose committed Oct 2, 2023
2 parents e432e6c + cdcfd4f commit 6bb66b5
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 192 deletions.
3 changes: 2 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2.1

orbs:
node: circleci/[email protected]
browser-tools: circleci/browser-tools@1.2.4
browser-tools: circleci/browser-tools@1.4.4

executors:
linux:
Expand Down Expand Up @@ -42,6 +42,7 @@ jobs:
node-version: << parameters.node-version >>.0
install-yarn: false
install-npm: true
npm-version: "9.7.1"
- install
- test-node

Expand Down
32 changes: 16 additions & 16 deletions .github/workflows/CI-CD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ jobs:
- macos-latest
- windows-latest
node:
- 10
- 12
- 14
- 16

steps:
- name: Checkout source
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Install Node ${{ matrix.node }}
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}

Expand All @@ -53,30 +53,30 @@ jobs:
run: npm run coverage:node

- name: Send code coverage results to Coveralls
uses: coverallsapp/github-action@v1.0.1
uses: coverallsapp/github-action@v1.1.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true

browser_tests:
name: Browser Tests
runs-on: ${{ matrix.os }}
timeout-minutes: 10
timeout-minutes: 15
strategy:
fail-fast: true
matrix:
os:
- ubuntu-latest # Chrome, Firefox, Safari (via SauceLabs), Edge (via SauceLabs)
- windows-latest # Internet Explorer
- ubuntu-latest # Chrome, Firefox
- windows-latest # Internet Explorer

steps:
- name: Checkout source
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Install Node
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: 12
node-version: 16

- name: Install dependencies
run: npm ci
Expand All @@ -94,21 +94,21 @@ jobs:
cat coverage/*/lcov.info > ./coverage/lcov.info
- name: Send code coverage results to Coveralls
uses: coverallsapp/github-action@v1.0.1
uses: coverallsapp/github-action@v1.1.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true

coverage:
name: Code Coverage
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 5
needs:
- node_tests
- browser_tests
steps:
- name: Let Coveralls know that all tests have finished
uses: coverallsapp/github-action@v1.0.1
uses: coverallsapp/github-action@v1.1.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
Expand All @@ -124,10 +124,10 @@ jobs:

steps:
- name: Checkout source
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Install Node
uses: actions/setup-node@v1
uses: actions/setup-node@v3

- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion lib/bundle/util/key-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { safePointerToPath, parse } = require("../../util/url");
const { basename, extname } = require("@stoplight/path");
const { get } = require("./object");

const MAX_ATTEMPTS = 20;
const MAX_ATTEMPTS = 1000;

function prettify (key) {
return capitalize(key.replace(/(?:\.|[\\/]+)([a-z])?/g, (_, letter, i) => {
Expand Down
50 changes: 38 additions & 12 deletions lib/resolve-external.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,22 @@ module.exports = resolveExternal;
* The promise resolves once all JSON references in the schema have been resolved,
* including nested references that are contained in externally-referenced files.
*/
function resolveExternal (parser, options) {
function resolveExternal(parser, options) {
if (!options.resolve.external) {
// Nothing to resolve, so exit early
return Promise.resolve();
}

try {
// console.log('Resolving $ref pointers in %s', parser.$refs._root$Ref.path);
let promises = crawl(parser.schema, parser.$refs._root$Ref.path + "#", parser.$refs, options);
let promises = crawl(
parser.schema,
parser.$refs._root$Ref.path + "#",
parser.$refs,
options
);
return Promise.all(promises);
}
catch (e) {
} catch (e) {
return Promise.reject(e);
}
}
Expand All @@ -44,24 +48,47 @@ function resolveExternal (parser, options) {
* @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
* @param {$Refs} $refs
* @param {$RefParserOptions} options
* @param {Set} seen - Internal.
*
* @returns {Promise[]}
* Returns an array of promises. There will be one promise for each JSON reference in `obj`.
* If `obj` does not contain any JSON references, then the array will be empty.
* If any of the JSON references point to files that contain additional JSON references,
* then the corresponding promise will internally reference an array of promises.
*/
function crawl (obj, path, $refs, options) {
function crawl(obj, path, $refs, options, external, seen) {
seen = seen || new Set();
let promises = [];

if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
if (
obj &&
typeof obj === "object" &&
!ArrayBuffer.isView(obj) &&
!seen.has(obj)
) {
seen.add(obj); // Track previously seen objects to avoid infinite recursion
if ($Ref.isExternal$Ref(obj)) {
promises.push(resolve$Ref(obj, path, $refs, options));
}
else {
if (external && $Ref.is$Ref(obj)) {
/* Correct the reference in the external document so we can resolve it */
let withoutHash = url.stripHash(path);
if (url.isFileSystemPath(withoutHash)) {
/* remove file:// from path */
withoutHash = url.toFileSystemPath(withoutHash);
}
obj.$ref = withoutHash + obj.$ref;
}
}

for (let key of Object.keys(obj)) {
let keyPath = Pointer.join(path, key);
let value = obj[key];
promises = promises.concat(crawl(value, keyPath, $refs, options));

promises = promises.concat(
crawl(value, keyPath, $refs, options, external, seen)
);
}
}

Expand All @@ -80,7 +107,7 @@ function crawl (obj, path, $refs, options) {
* The promise resolves once all JSON references in the object have been resolved,
* including nested references that are contained in externally-referenced files.
*/
async function resolve$Ref ($ref, path, $refs, options) {
async function resolve$Ref($ref, path, $refs, options) {
// console.log('Resolving $ref pointer "%s" at %s', $ref.$ref, path);

let resolvedPath = url.resolve(path, $ref.$ref);
Expand All @@ -99,17 +126,16 @@ async function resolve$Ref ($ref, path, $refs, options) {

// Crawl the parsed value
// console.log('Resolving $ref pointers in %s', withoutHash);
let promises = crawl(result, withoutHash + "#", $refs, options);
let promises = crawl(result, withoutHash + "#", $refs, options, true);

return Promise.all(promises);
}
catch (err) {
} catch (err) {
if (!options.continueOnError || !isHandledError(err)) {
throw err;
}

if ($refs._$refs[withoutHash]) {
err.source = url.stripHash(path);
err.source = decodeURI(url.stripHash(path));
err.path = url.safePointerToPath(url.getHash(path));
}

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 44 additions & 21 deletions test/specs/absolute-root/absolute-root.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,44 +47,65 @@ describe("When executed in the context of root directory", () => {
process.cwd = originalProcessCwd; // already restored by the finally block above, but just in case
});


it("should parse successfully from an absolute path", async () => {
let parser = new $RefParser();
const schema = await parser.parse(path.abs("specs/absolute-root/absolute-root.yaml"));
const schema = await parser.parse(
path.abs("specs/absolute-root/absolute-root.yaml")
);
expect(schema).to.equal(parser.schema);
expect(schema).to.deep.equal(parsedSchema.schema);
expect(parser.$refs.paths()).to.deep.equal([
path.abs("specs/absolute-root/absolute-root.yaml")
path.abs("specs/absolute-root/absolute-root.yaml"),
]);
});

it("should parse successfully from a url", async () => {
let parser = new $RefParser();
const schema = await parser.parse(path.url("specs/absolute-root/absolute-root.yaml"));
const schema = await parser.parse(
path.url("specs/absolute-root/absolute-root.yaml")
);
expect(schema).to.equal(parser.schema);
expect(schema).to.deep.equal(parsedSchema.schema);
expect(parser.$refs.paths()).to.deep.equal([path.url("specs/absolute-root/absolute-root.yaml")]);
expect(parser.$refs.paths()).to.deep.equal([
path.url("specs/absolute-root/absolute-root.yaml"),
]);
});

it("should resolve successfully from an absolute path", helper.testResolve(
path.abs("specs/absolute-root/absolute-root.yaml"),
path.abs("specs/absolute-root/absolute-root.yaml"), parsedSchema.schema,
path.abs("specs/absolute-root/definitions/definitions.json"), parsedSchema.definitions,
path.abs("specs/absolute-root/definitions/name.yaml"), parsedSchema.name,
path.abs("specs/absolute-root/definitions/required-string.yaml"), parsedSchema.requiredString
));
it(
"should resolve successfully from an absolute path",
helper.testResolve(
path.abs("specs/absolute-root/absolute-root.yaml"),
path.abs("specs/absolute-root/absolute-root.yaml"),
parsedSchema.schema,
path.abs("specs/absolute-root/definitions/definitions.json"),
parsedSchema.definitions,
path.abs("specs/absolute-root/definitions/name.yaml"),
parsedSchema.name,
path.abs("specs/absolute-root/definitions/required-string.yaml"),
parsedSchema.requiredString
)
);

it("should resolve successfully from a url", helper.testResolve(
path.url("specs/absolute-root/absolute-root.yaml"),
path.url("specs/absolute-root/absolute-root.yaml"), parsedSchema.schema,
path.url("specs/absolute-root/definitions/definitions.json"), parsedSchema.definitions,
path.url("specs/absolute-root/definitions/name.yaml"), parsedSchema.name,
path.url("specs/absolute-root/definitions/required-string.yaml"), parsedSchema.requiredString
));
it(
"should resolve successfully from a url",
helper.testResolve(
path.url("specs/absolute-root/absolute-root.yaml"),
path.url("specs/absolute-root/absolute-root.yaml"),
parsedSchema.schema,
path.url("specs/absolute-root/definitions/definitions.json"),
parsedSchema.definitions,
path.url("specs/absolute-root/definitions/name.yaml"),
parsedSchema.name,
path.url("specs/absolute-root/definitions/required-string.yaml"),
parsedSchema.requiredString
)
);

it("should dereference successfully", async () => {
let parser = new $RefParser();
const schema = await parser.dereference(path.abs("specs/absolute-root/absolute-root.yaml"));
const schema = await parser.dereference(
path.abs("specs/absolute-root/absolute-root.yaml")
);
expect(schema).to.equal(parser.schema);
expect(schema).to.deep.equal(dereferencedSchema);
// Reference equality
Expand All @@ -100,7 +121,9 @@ describe("When executed in the context of root directory", () => {

it("should bundle successfully", async () => {
let parser = new $RefParser();
const schema = await parser.bundle(path.abs("specs/absolute-root/absolute-root.yaml"));
const schema = await parser.bundle(
path.abs("specs/absolute-root/absolute-root.yaml")
);
expect(schema).to.equal(parser.schema);
expect(schema).to.deep.equal(bundledSchema);
});
Expand Down
Loading

0 comments on commit 6bb66b5

Please sign in to comment.