mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
feat(jsdoc-core): add Api class
Starting point for a public API for JSDoc.
This commit is contained in:
parent
5b11762b35
commit
865b9faa1e
@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable no-process-exit */
|
/* eslint-disable no-process-exit */
|
||||||
import EventEmitter from 'node:events';
|
import { Api } from '@jsdoc/core';
|
||||||
|
|
||||||
import { getLogFunctions } from '@jsdoc/util';
|
import { getLogFunctions } from '@jsdoc/util';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import ow from 'ow';
|
import ow from 'ow';
|
||||||
@ -130,7 +129,8 @@ export default class Engine {
|
|||||||
ow(opts.revision, ow.optional.date);
|
ow(opts.revision, ow.optional.date);
|
||||||
ow(opts.version, ow.any(ow.optional.string, ow.optional.object));
|
ow(opts.version, ow.any(ow.optional.string, ow.optional.object));
|
||||||
|
|
||||||
this.emitter = opts.emitter ?? new EventEmitter();
|
this.api = opts.api ?? new Api({ emitter: opts.emitter });
|
||||||
|
this.emitter = this.api.emitter;
|
||||||
this.flags = [];
|
this.flags = [];
|
||||||
this.log = opts.log ?? getLogFunctions(this.emitter);
|
this.log = opts.log ?? getLogFunctions(this.emitter);
|
||||||
this.#logger = new Logger({
|
this.#logger = new Logger({
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import EventEmitter from 'node:events';
|
||||||
|
|
||||||
import Engine from '../../../lib/engine.js';
|
import Engine from '../../../lib/engine.js';
|
||||||
import flags from '../../../lib/flags.js';
|
import flags from '../../../lib/flags.js';
|
||||||
import { LEVELS } from '../../../lib/logger.js';
|
import { LEVELS } from '../../../lib/logger.js';
|
||||||
@ -33,6 +35,14 @@ describe('@jsdoc/cli/lib/engine', () => {
|
|||||||
expect(Engine.LOG_LEVELS).toBeObject();
|
expect(Engine.LOG_LEVELS).toBeObject();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('has an `api` property that contains the API instance', () => {
|
||||||
|
expect(new Engine().api).toBeObject();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has an `emitter` property that contains a shared event emitter', () => {
|
||||||
|
expect(new Engine().emitter).toBeObject();
|
||||||
|
});
|
||||||
|
|
||||||
it('has an empty array of flags by default', () => {
|
it('has an empty array of flags by default', () => {
|
||||||
expect(new Engine().flags).toBeEmptyArray();
|
expect(new Engine().flags).toBeEmptyArray();
|
||||||
});
|
});
|
||||||
@ -97,6 +107,49 @@ describe('@jsdoc/cli/lib/engine', () => {
|
|||||||
expect(() => new Engine({ version: 1 })).toThrow();
|
expect(() => new Engine({ version: 1 })).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('emitter', () => {
|
||||||
|
it('creates an `EventEmitter` instance by default', () => {
|
||||||
|
expect(new Engine().emitter).toBeInstanceOf(EventEmitter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('lets you provide the emitter', () => {
|
||||||
|
const fakeEmitter = {
|
||||||
|
off: () => null,
|
||||||
|
on: () => null,
|
||||||
|
once: () => null,
|
||||||
|
};
|
||||||
|
const instance = new Engine({ emitter: fakeEmitter });
|
||||||
|
|
||||||
|
expect(instance.emitter).toBe(fakeEmitter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shares one emitter between the `Api` instance and the `Engine` instance', () => {
|
||||||
|
const instance = new Engine();
|
||||||
|
|
||||||
|
expect(instance.emitter).toBe(instance.api.emitter);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exit', () => {
|
||||||
|
// TODO: This is testing implementation details, not behavior. Refactor the method, then rewrite
|
||||||
|
// this test to test the behavior.
|
||||||
|
it('adds one listener for `exit` events if the exit code is 0', () => {
|
||||||
|
spyOn(process, 'on');
|
||||||
|
|
||||||
|
new Engine().exit(0);
|
||||||
|
|
||||||
|
expect(process.on).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds two listeners for `exit` events if the exit code is >0', () => {
|
||||||
|
spyOn(process, 'on');
|
||||||
|
|
||||||
|
new Engine().exit(1);
|
||||||
|
|
||||||
|
expect(process.on).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('help', () => {
|
describe('help', () => {
|
||||||
const instance = new Engine();
|
const instance = new Engine();
|
||||||
|
|
||||||
@ -132,26 +185,6 @@ describe('@jsdoc/cli/lib/engine', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('exit', () => {
|
|
||||||
// TODO: This is testing implementation details, not behavior. Refactor the method, then rewrite
|
|
||||||
// this test to test the behavior.
|
|
||||||
it('adds one listener for `exit` events if the exit code is 0', () => {
|
|
||||||
spyOn(process, 'on');
|
|
||||||
|
|
||||||
new Engine().exit(0);
|
|
||||||
|
|
||||||
expect(process.on).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('adds two listeners for `exit` events if the exit code is >0', () => {
|
|
||||||
spyOn(process, 'on');
|
|
||||||
|
|
||||||
new Engine().exit(1);
|
|
||||||
|
|
||||||
expect(process.on).toHaveBeenCalledTimes(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parseFlags', () => {
|
describe('parseFlags', () => {
|
||||||
it('throws with no input', () => {
|
it('throws with no input', () => {
|
||||||
expect(() => new Engine().parseFlags()).toThrow();
|
expect(() => new Engine().parseFlags()).toThrow();
|
||||||
|
|||||||
@ -19,10 +19,11 @@
|
|||||||
*
|
*
|
||||||
* @module @jsdoc/core
|
* @module @jsdoc/core
|
||||||
*/
|
*/
|
||||||
|
import Api from './lib/api.js';
|
||||||
import * as config from './lib/config.js';
|
import * as config from './lib/config.js';
|
||||||
import Env from './lib/env.js';
|
import Env from './lib/env.js';
|
||||||
import * as name from './lib/name.js';
|
import * as name from './lib/name.js';
|
||||||
import * as plugins from './lib/plugins.js';
|
import * as plugins from './lib/plugins.js';
|
||||||
|
|
||||||
export { config, Env, name, plugins };
|
export { Api, config, Env, name, plugins };
|
||||||
export default { config, Env, name, plugins };
|
export default { Api, config, Env, name, plugins };
|
||||||
|
|||||||
33
packages/jsdoc-core/lib/api.js
Normal file
33
packages/jsdoc-core/lib/api.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2023 the JSDoc Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import EventEmitter from 'node:events';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The API for programmatically generating documentation with JSDoc.
|
||||||
|
*/
|
||||||
|
export default class Api {
|
||||||
|
/**
|
||||||
|
* Creates an instance of the API.
|
||||||
|
*
|
||||||
|
* @param {?Object} opts - Options for the API instance.
|
||||||
|
* @param {?node:events.EventEmitter} opts.eventEmitter - The event emitter to use as a message
|
||||||
|
* bus for JSDoc.
|
||||||
|
*/
|
||||||
|
constructor(opts) {
|
||||||
|
this.emitter = opts?.emitter ?? new EventEmitter();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,12 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import core from '../../index.js';
|
import core from '../../index.js';
|
||||||
|
import Api from '../../lib/api.js';
|
||||||
import * as config from '../../lib/config.js';
|
import * as config from '../../lib/config.js';
|
||||||
import Env from '../../lib/env.js';
|
import Env from '../../lib/env.js';
|
||||||
import * as name from '../../lib/name.js';
|
import * as name from '../../lib/name.js';
|
||||||
import * as plugins from '../../lib/plugins.js';
|
import * as plugins from '../../lib/plugins.js';
|
||||||
|
|
||||||
describe('@jsdoc/core', () => {
|
describe('@jsdoc/core', () => {
|
||||||
|
describe('Api', () => {
|
||||||
|
it('is lib/api', () => {
|
||||||
|
expect(core.Api).toEqual(Api);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('config', () => {
|
describe('config', () => {
|
||||||
it('is lib/config', () => {
|
it('is lib/config', () => {
|
||||||
expect(core.config).toEqual(config);
|
expect(core.config).toEqual(config);
|
||||||
|
|||||||
53
packages/jsdoc-core/test/specs/lib/api.js
Normal file
53
packages/jsdoc-core/test/specs/lib/api.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2023 the JSDoc Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import EventEmitter from 'node:events';
|
||||||
|
|
||||||
|
import Api from '../../../lib/api.js';
|
||||||
|
|
||||||
|
describe('Api', () => {
|
||||||
|
let instance;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
instance = new Api();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is a constructor', () => {
|
||||||
|
function factory() {
|
||||||
|
return new Api();
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(factory).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has an `emitter` property', () => {
|
||||||
|
expect(instance.emitter).toBeObject();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('emitter', () => {
|
||||||
|
it('is an instance of `EventEmitter` by default', () => {
|
||||||
|
expect(instance.emitter).toBeInstanceOf(EventEmitter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('lets you provide your own emitter', () => {
|
||||||
|
const fakeEmitter = {};
|
||||||
|
|
||||||
|
instance = new Api({ emitter: fakeEmitter });
|
||||||
|
|
||||||
|
expect(instance.emitter).toBe(fakeEmitter);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user