1
0
Fork 0

feat: add join callback to include options

BREAKING CHANGE: usage of the include type now requires a join option
This commit is contained in:
ssube 2020-08-04 00:14:13 -05:00
parent dba9267828
commit 1d07d7c3ed
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
5 changed files with 37 additions and 29 deletions

View File

@ -9,5 +9,5 @@ The schema to be used for included files. This is necessary to work around circu
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
includeSchema: IncludeSchema includeOptions: IncludeOptions
``` ```

View File

@ -1,5 +1,5 @@
export { CONFIG_SCHEMA } from './schema'; export { CONFIG_SCHEMA } from './schema';
export { envType } from './type/Env'; export { envType } from './type/Env';
export { includeSchema, includeType } from './type/Include'; export { includeOptions as includeSchema, includeType } from './type/Include';
export { regexpType } from './type/Regexp'; export { regexpType } from './type/Regexp';
export { streamType } from './type/Stream'; export { streamType } from './type/Stream';

View File

@ -1,7 +1,7 @@
import { DEFAULT_SAFE_SCHEMA, Schema } from 'js-yaml'; import { DEFAULT_SAFE_SCHEMA, Schema } from 'js-yaml';
import { envType } from './type/Env'; import { envType } from './type/Env';
import { includeSchema, includeType } from './type/Include'; import { includeOptions, includeType } from './type/Include';
import { regexpType } from './type/Regexp'; import { regexpType } from './type/Regexp';
import { streamType } from './type/Stream'; import { streamType } from './type/Stream';
@ -17,4 +17,4 @@ export const CONFIG_SCHEMA = Schema.create([DEFAULT_SAFE_SCHEMA], [
streamType, streamType,
]); ]);
includeSchema.schema = CONFIG_SCHEMA; includeOptions.schema = CONFIG_SCHEMA;

View File

@ -1,15 +1,15 @@
import { InvalidArgumentError, NotFoundError } from '@apextoaster/js-utils'; import { InvalidArgumentError, NotFoundError, NotImplementedError } from '@apextoaster/js-utils';
import { SAFE_SCHEMA, safeLoad, Schema, Type as YamlType } from 'js-yaml'; import { SAFE_SCHEMA, safeLoad, Schema, Type as YamlType } from 'js-yaml';
import { join } from 'path';
export interface IncludeOptions { export interface ReaderOptions {
encoding: string; encoding: string;
} }
export type IncludeReader = (path: string, options: IncludeOptions) => string; export type IncludeReader = (path: string, options: ReaderOptions) => string;
export interface IncludeSchema { export interface IncludeOptions {
exists: (path: string) => boolean; exists: (path: string) => boolean;
join: (...path: Array<string>) => string;
read: IncludeReader; read: IncludeReader;
resolve: (path: string) => string; resolve: (path: string) => string;
schema: Schema; schema: Schema;
@ -20,13 +20,16 @@ export interface IncludeSchema {
* *
* @public * @public
*/ */
export const includeSchema: IncludeSchema = { export const includeOptions: IncludeOptions = {
exists: (path: string) => false, exists: (path: string) => false,
read: (path: string, encoding: IncludeOptions) => { join: (...path: Array<string>) => {
throw new Error('read stub'); throw new NotImplementedError('join stub');
},
read: (path: string, encoding: ReaderOptions) => {
throw new NotImplementedError('read stub');
}, },
resolve: (path: string) => { resolve: (path: string) => {
throw new Error('resolve stub'); throw new NotImplementedError('resolve stub');
}, },
schema: SAFE_SCHEMA, schema: SAFE_SCHEMA,
}; };
@ -40,7 +43,7 @@ export const includeType = new YamlType('!include', {
try { try {
const canonical = resolvePath(path); const canonical = resolvePath(path);
// throws in node 11+ // throws in node 11+
if (includeSchema.exists(canonical)) { if (includeOptions.exists(canonical)) {
return true; return true;
} else { } else {
throw new NotFoundError('included file does not exist'); throw new NotFoundError('included file does not exist');
@ -51,10 +54,10 @@ export const includeType = new YamlType('!include', {
}, },
construct(path: string): unknown { construct(path: string): unknown {
try { try {
return safeLoad(includeSchema.read(resolvePath(path), { return safeLoad(includeOptions.read(resolvePath(path), {
encoding: 'utf-8', encoding: 'utf-8',
}), { }), {
schema: includeSchema.schema, schema: includeOptions.schema,
}); });
} catch (err) { } catch (err) {
throw new InvalidArgumentError('error including file', err); throw new InvalidArgumentError('error including file', err);
@ -62,10 +65,13 @@ export const includeType = new YamlType('!include', {
}, },
}); });
/**
* @todo take root parameter instead of __dirname
*/
export function resolvePath(path: string): string { export function resolvePath(path: string): string {
if (path[0] === '.') { if (path[0] === '.') {
return includeSchema.resolve(join(__dirname, path)); return includeOptions.resolve(includeOptions.join(__dirname, path));
} else { } else {
return includeSchema.resolve(path); return includeOptions.resolve(path);
} }
} }

View File

@ -2,25 +2,27 @@ import { InvalidArgumentError, NotFoundError } from '@apextoaster/js-utils';
import { expect } from 'chai'; import { expect } from 'chai';
import { join } from 'path'; import { join } from 'path';
import { IncludeSchema, includeSchema, includeType } from '../../src/type/Include'; import { IncludeOptions, includeOptions, includeType } from '../../src/type/Include';
const TEST_ROOT = '../test/type'; const TEST_ROOT = '../test/type';
const ORIGINAL_SCHEMA: IncludeSchema = { const ORIGINAL_SCHEMA: IncludeOptions = {
...includeSchema, ...includeOptions,
}; };
describe('include config type', async () => { describe('include config type', async () => {
beforeEach(() => { beforeEach(() => {
includeSchema.exists = () => true; includeOptions.exists = () => true;
includeSchema.read = () => 'test'; includeOptions.join = (...path) => path.join('/');
includeSchema.resolve = (path: string) => path; includeOptions.read = () => 'test';
includeOptions.resolve = (path: string) => path;
}); });
afterEach(() => { afterEach(() => {
includeSchema.exists = ORIGINAL_SCHEMA.exists; includeOptions.exists = ORIGINAL_SCHEMA.exists;
includeSchema.read = ORIGINAL_SCHEMA.read; includeOptions.join = ORIGINAL_SCHEMA.join;
includeSchema.resolve = ORIGINAL_SCHEMA.resolve; includeOptions.read = ORIGINAL_SCHEMA.read;
includeOptions.resolve = ORIGINAL_SCHEMA.resolve;
}); });
it('should resolve existing files', async () => { it('should resolve existing files', async () => {
@ -28,7 +30,7 @@ describe('include config type', async () => {
}); });
it('should throw when resolving missing files', async () => { it('should throw when resolving missing files', async () => {
includeSchema.resolve = () => { includeOptions.resolve = () => {
throw new NotFoundError(); throw new NotFoundError();
}; };
@ -42,7 +44,7 @@ describe('include config type', async () => {
}); });
it('should throw when constructing missing files', async () => { it('should throw when constructing missing files', async () => {
includeSchema.read = () => { includeOptions.read = () => {
throw new InvalidArgumentError(); throw new InvalidArgumentError();
}; };